diff --git a/Assets/Editor/Presets/GeomCache/game.cbc b/Assets/Editor/Presets/GeomCache/game.cbc deleted file mode 100644 index 9b98f3460f..0000000000 --- a/Assets/Editor/Presets/GeomCache/game.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/game_lz4hc.cbc b/Assets/Editor/Presets/GeomCache/game_lz4hc.cbc deleted file mode 100644 index dbd0499175..0000000000 --- a/Assets/Editor/Presets/GeomCache/game_lz4hc.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/game_z_up.cbc b/Assets/Editor/Presets/GeomCache/game_z_up.cbc deleted file mode 100644 index ec2555a3e3..0000000000 --- a/Assets/Editor/Presets/GeomCache/game_z_up.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/game_z_up_lz4hc.cbc b/Assets/Editor/Presets/GeomCache/game_z_up_lz4hc.cbc deleted file mode 100644 index c2e30a6386..0000000000 --- a/Assets/Editor/Presets/GeomCache/game_z_up_lz4hc.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/prerendered.cbc b/Assets/Editor/Presets/GeomCache/prerendered.cbc deleted file mode 100644 index c09785111d..0000000000 --- a/Assets/Editor/Presets/GeomCache/prerendered.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/prerendered_z_up.cbc b/Assets/Editor/Presets/GeomCache/prerendered_z_up.cbc deleted file mode 100644 index e42a915e58..0000000000 --- a/Assets/Editor/Presets/GeomCache/prerendered_z_up.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/rigids_only.cbc b/Assets/Editor/Presets/GeomCache/rigids_only.cbc deleted file mode 100644 index e8620bc11e..0000000000 --- a/Assets/Editor/Presets/GeomCache/rigids_only.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/rigids_only_z_up.cbc b/Assets/Editor/Presets/GeomCache/rigids_only_z_up.cbc deleted file mode 100644 index d1f8bc2db3..0000000000 --- a/Assets/Editor/Presets/GeomCache/rigids_only_z_up.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/uncompressed.cbc b/Assets/Editor/Presets/GeomCache/uncompressed.cbc deleted file mode 100644 index e21d52d9d1..0000000000 --- a/Assets/Editor/Presets/GeomCache/uncompressed.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Editor/Presets/GeomCache/uncompressed_z_up.cbc b/Assets/Editor/Presets/GeomCache/uncompressed_z_up.cbc deleted file mode 100644 index 273ce1fbb1..0000000000 --- a/Assets/Editor/Presets/GeomCache/uncompressed_z_up.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.abc b/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.abc deleted file mode 100644 index 8ca759d342..0000000000 --- a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.abc +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9c36d7bc993ddf616f478115a123efabda5b4b833a4e6524312f43c228ae0902 -size 487003 diff --git a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.cbc b/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.cbc deleted file mode 100644 index 3c99ab1627..0000000000 --- a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.cbc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.ma b/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.ma deleted file mode 100644 index 65aade11a0..0000000000 --- a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.ma +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:96a21446422b834ea90a5d38eaaca309fdee31dc3cc03c0e9c094b39ec3a459d -size 4715164 diff --git a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.mtl b/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.mtl deleted file mode 100644 index 05dfe70b09..0000000000 --- a/Assets/Engine/EngineAssets/GeomCaches/defaultGeomCache.mtl +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake index 4d5680a30d..f9d1e60dda 100644 --- a/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Mac/runtime_dependencies.cmake @@ -8,3 +8,8 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +set(GEM_DEPENDENCIES + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Null.Private +) \ No newline at end of file diff --git a/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake b/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake index 4d5680a30d..ee7be9ac6d 100644 --- a/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake +++ b/AutomatedTesting/Gem/Code/Platform/Mac/tool_dependencies.cmake @@ -8,3 +8,10 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # + +set(GEM_DEPENDENCIES + Gem::Atom_RHI_Null.Private + Gem::Atom_RHI_Null.Builders + Gem::Atom_RHI_Metal.Private + Gem::Atom_RHI_Metal.Builders +) \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/CryMaterialsCommands_test.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/CryMaterialsCommands_test.py deleted file mode 100755 index 41ae0608a4..0000000000 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/CryMaterialsCommands_test.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -its licensors. - -For complete copyright and license terms please see the LICENSE at the root of this -distribution (the "License"). All use of this software is governed by the License, -or, if provided, by the license below or the license accompanying this file. Do not -remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -""" - -# -# This is a pytest module to test the in-Editor Python API from ViewPane.h -# -import pytest -pytest.importorskip('ly_test_tools') - -import sys -import os -sys.path.append(os.path.dirname(__file__)) -from hydra_utils import launch_test_case - - -@pytest.mark.SUITE_sandbox -@pytest.mark.parametrize('launcher_platform', ['windows_editor']) -@pytest.mark.parametrize('project', ['AutomatedTesting']) -@pytest.mark.parametrize('level', ['auto_test']) -class TestLegacyCryMaterialsCommandsAutomation(object): - - def test_Legacy_CryMaterials(self, request, editor, level, launcher_platform): - - unexpected_lines=[] - expected_lines = [ - # "Material Settings/Shader updated correctly", # Disabled, SPEC-3590 - # "Material Settings/Surface Type updated correctly", # Disabled, SPEC-3590 - "Texture Maps/Diffuse/Tiling/IsTileU updated correctly", - "Texture Maps/Diffuse/Tiling/TileU updated correctly", - "Texture Maps/Diffuse/Rotator/Type updated correctly", - "Texture Maps/Diffuse/Rotator/Amplitude updated correctly", - "Texture Maps/Diffuse/Oscillator/AmplitudeU updated correctly", - "Opacity Settings/Opacity updated correctly", - "Opacity Settings/AlphaTest updated correctly", - "Opacity Settings/Additive updated correctly", - "Lighting Settings/Diffuse Color updated correctly", - "Lighting Settings/Specular Color updated correctly", - "Lighting Settings/Emissive Intensity updated correctly", - "Lighting Settings/Emissive Color updated correctly", - "Advanced/Allow layer activation updated correctly", - "Advanced/2 Sided updated correctly", - "Advanced/No Shadow updated correctly", - "Advanced/Use Scattering updated correctly", - "Advanced/Hide After Breaking updated correctly", - "Advanced/Fog Volume Shading Quality High updated correctly", - "Advanced/Blend Terrain Color updated correctly", - "Advanced/Voxel Coverage updated correctly", - "Advanced/Propagate Opacity Settings updated correctly", - "Advanced/Propagate Lighting Settings updated correctly", - "Advanced/Propagate Advanced Settings updated correctly", - "Advanced/Propagate Texture Maps updated correctly", - "Advanced/Propagate Shader Params updated correctly", - "Advanced/Propagate Shader Generation updated correctly", - "Advanced/Propagate Vertex Deformation updated correctly", - # "Shader Params/Blend Factor updated correctly", # Disabled, SPEC-3590 - # "Shader Params/Indirect bounce color updated correctly", # Disabled, SPEC-3590 - "Vertex Deformation/Type updated correctly", - "Vertex Deformation/Wave Length X updated correctly", - "Vertex Deformation/Wave X/Level updated correctly", - "Vertex Deformation/Wave X/Amplitude updated correctly", - "Vertex Deformation/Wave X/Phase updated correctly", - "Vertex Deformation/Wave X/Frequency updated correctly" - ] - - test_case_file = os.path.join(os.path.dirname(__file__), 'CryMaterialsCommands_test_case.py') - launch_test_case(editor, test_case_file, expected_lines, unexpected_lines) - diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/CryMaterialsCommands_test_case.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/CryMaterialsCommands_test_case.py deleted file mode 100755 index 913b1ace24..0000000000 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/CryMaterialsCommands_test_case.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -its licensors. - -For complete copyright and license terms please see the LICENSE at the root of this -distribution (the "License"). All use of this software is governed by the License, -or, if provided, by the license below or the license accompanying this file. Do not -remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -""" - -# Tests the legacy Python API for CryMaterials while the Editor is running - -import azlmbr.bus as bus -import azlmbr.editor as editor -import azlmbr.legacy.material as material -import azlmbr.math as math - -materialName = 'materials/ter_layer_green' -print(f'Starting CryMaterial test case using material {materialName}') - - -def MaterialPropertyTest(property, value, doReset=True): - try: - # get old value and attempt to set new value - oldValue = material.get_property(materialName, property) - if oldValue == value: - print(f'>>> `{property}` already set to {oldValue}') - return - material.set_property(materialName, property, value) - - # test that the set new value worked - newValue = material.get_property(materialName, property) - if oldValue != newValue: - print(f"{property} updated correctly") - - # reset back to old value - if doReset: - material.set_property(materialName, property, oldValue) - except: - print(f'!!! hit an exception when setting `{property}` to {value}') - - -color = math.Color() -color.r = 255.0 -color.g = 128.0 -color.b = 64.0 -color.a = 0.0 - -# Material Settings -# MaterialPropertyTest("Material Settings/Shader", "Geometrybeam") # Disabled, SPEC-3590 -# MaterialPropertyTest("Material Settings/Surface Type", "grass") # Disabled, SPEC-3590 - -# Texture Maps -MaterialPropertyTest("Texture Maps/Diffuse/Tiling/IsTileU", False) -MaterialPropertyTest("Texture Maps/Diffuse/Tiling/IsTileV", False) -MaterialPropertyTest("Texture Maps/Diffuse/Tiling/TileU", 0.42) -MaterialPropertyTest("Texture Maps/Diffuse/Rotator/Type", 'Oscillated Rotation') -MaterialPropertyTest("Texture Maps/Diffuse/Rotator/Amplitude", 42.0) -MaterialPropertyTest("Texture Maps/Diffuse/Oscillator/TypeU", 'Fixed Moving') -MaterialPropertyTest("Texture Maps/Diffuse/Oscillator/AmplitudeU", 42.0) - -# Vertex Deformation -MaterialPropertyTest("Vertex Deformation/Type", 'Sin Wave') -MaterialPropertyTest("Vertex Deformation/Wave Length X", 42.0) -MaterialPropertyTest("Vertex Deformation/Type", 'Perlin 3D') -MaterialPropertyTest("Vertex Deformation/Noise Scale", math.Vector3(1.1, 2.2, 3.3)) - -# Opacity Settings -MaterialPropertyTest("Opacity Settings/Opacity", 42) -MaterialPropertyTest("Opacity Settings/AlphaTest", 2) -MaterialPropertyTest("Opacity Settings/Additive", True) - -# Lighting Settings -MaterialPropertyTest("Lighting Settings/Diffuse Color", color) -MaterialPropertyTest("Lighting Settings/Specular Color", color) -MaterialPropertyTest("Lighting Settings/Emissive Intensity", 42.0) -MaterialPropertyTest("Lighting Settings/Emissive Color", color) -MaterialPropertyTest("Lighting Settings/Specular Level", 2.0) - -# Advanced -MaterialPropertyTest("Advanced/Allow layer activation", False) -MaterialPropertyTest("Advanced/2 Sided", True) -MaterialPropertyTest("Advanced/No Shadow", True) -MaterialPropertyTest("Advanced/Use Scattering", True) -MaterialPropertyTest("Advanced/Hide After Breaking", True) -MaterialPropertyTest("Advanced/Fog Volume Shading Quality High", True) -MaterialPropertyTest("Advanced/Blend Terrain Color", True) -MaterialPropertyTest("Advanced/Voxel Coverage", 0.42) -# --- MaterialPropertyTest("Advanced/Link to Material", "materials/ter_layer_blue") # Works, but clears on UI refresh -MaterialPropertyTest("Advanced/Propagate Opacity Settings", True) -MaterialPropertyTest("Advanced/Propagate Lighting Settings", True) -MaterialPropertyTest("Advanced/Propagate Advanced Settings", True) -MaterialPropertyTest("Advanced/Propagate Texture Maps", True) -MaterialPropertyTest("Advanced/Propagate Shader Params", True) -MaterialPropertyTest("Advanced/Propagate Shader Generation", True) -MaterialPropertyTest("Advanced/Propagate Vertex Deformation", True) - -# Shader parameters vary with each Shader, just testing a couple of them... -# MaterialPropertyTest("Shader Params/Blend Factor", 7.0, False) # Disabled, SPEC-3590 -# MaterialPropertyTest("Shader Params/Indirect bounce color", color, False) # Disabled, SPEC-3590 - -### These values are reset to False when set. Left them here commented for reference. -# MaterialPropertyTest("Shader Generation Params/Dust & Turbulence", True) -# MaterialPropertyTest("Shader Generation Params/Receive Shadows", True) -# MaterialPropertyTest("Shader Generation Params/UV Vignetting", True) - -# Vertex Deformation -MaterialPropertyTest("Vertex Deformation/Type", "Sin Wave") -MaterialPropertyTest("Vertex Deformation/Wave Length X", 42.0) -MaterialPropertyTest("Vertex Deformation/Wave X/Level", 42.0) -MaterialPropertyTest("Vertex Deformation/Wave X/Amplitude", 42.0) -MaterialPropertyTest("Vertex Deformation/Wave X/Phase", 42.0) -MaterialPropertyTest("Vertex Deformation/Wave X/Frequency", 42.0) - -editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'ExitNoPrompt') diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py index 062c449ab7..e701ff8d16 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py @@ -161,20 +161,6 @@ def run(): # Deletion/Undo/Redo test verify_deletion_undo_redo(self.component_name, entity_obj) - # Area Light Component - area_light = "Area Light" - ComponentTests( - area_light, lambda entity_obj: verify_required_component_addition( - entity_obj, ["Capsule Shape"], area_light)) - - # Decal Component - material_asset_path = os.path.join("AutomatedTesting", "Materials", "basic_grey.material") - material_asset = asset.AssetCatalogRequestBus( - bus.Broadcast, "GetAssetIdByPath", material_asset_path, math.Uuid(), False) - ComponentTests( - "Decal (Atom)", lambda entity_obj: verify_set_property( - entity_obj, "Controller|Configuration|Material", material_asset)) - # DepthOfField Component camera_entity = hydra.Entity("camera_entity") camera_entity.create_entity(math.Vector3(512.0, 512.0, 34.0), ["Camera"]) @@ -185,6 +171,14 @@ def run(): lambda entity_obj: verify_set_property( entity_obj, "Controller|Configuration|Camera Entity", camera_entity.id)) + # Decal Component + material_asset_path = os.path.join("AutomatedTesting", "Materials", "basic_grey.material") + material_asset = asset.AssetCatalogRequestBus( + bus.Broadcast, "GetAssetIdByPath", material_asset_path, math.Uuid(), False) + ComponentTests( + "Decal (Atom)", lambda entity_obj: verify_set_property( + entity_obj, "Controller|Configuration|Material", material_asset)) + # Directional Light Component ComponentTests( "Directional Light", @@ -213,9 +207,6 @@ def run(): # Physical Sky Component ComponentTests("Physical Sky") - # Point Light Component - ComponentTests("Point Light") - # PostFX Layer Component ComponentTests("PostFX Layer") diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py index 16139e3f66..aafa2ff9b7 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py @@ -27,194 +27,6 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts") @pytest.mark.parametrize("level", ["auto_test"]) class TestAtomEditorComponentsMain(object): - @pytest.mark.test_case_id( - "C32078117", # Area Light - "C32078130", # Display Mapper - "C32078129", # Light - "C32078131", # Radius Weight Modifier - "C32078127", # PostFX Layer - "C32078126", # Point Light - "C32078125", # Physical Sky - "C32078115", # Global Skylight (IBL) - "C32078121", # Exposure Control - "C32078120", # Directional Light - "C32078119", # DepthOfField - "C32078118") # Decal - def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform): - cfg_args = [level] - - expected_lines = [ - # Area Light Component - "Area Light Entity successfully created", - "Area Light_test: Component added to the entity: True", - "Area Light_test: Component removed after UNDO: True", - "Area Light_test: Component added after REDO: True", - "Area Light_test: Entered game mode: True", - "Area Light_test: Entity enabled after adding required components: True", - "Area Light_test: Entity is hidden: True", - "Area Light_test: Entity is shown: True", - "Area Light_test: Entity deleted: True", - "Area Light_test: UNDO entity deletion works: True", - "Area Light_test: REDO entity deletion works: True", - # Decal Component - "Decal (Atom) Entity successfully created", - "Decal (Atom)_test: Component added to the entity: True", - "Decal (Atom)_test: Component removed after UNDO: True", - "Decal (Atom)_test: Component added after REDO: True", - "Decal (Atom)_test: Entered game mode: True", - "Decal (Atom)_test: Exit game mode: True", - "Decal (Atom) Controller|Configuration|Material: SUCCESS", - "Decal (Atom)_test: Entity is hidden: True", - "Decal (Atom)_test: Entity is shown: True", - "Decal (Atom)_test: Entity deleted: True", - "Decal (Atom)_test: UNDO entity deletion works: True", - "Decal (Atom)_test: REDO entity deletion works: True", - # DepthOfField Component - "DepthOfField Entity successfully created", - "DepthOfField_test: Component added to the entity: True", - "DepthOfField_test: Component removed after UNDO: True", - "DepthOfField_test: Component added after REDO: True", - "DepthOfField_test: Entered game mode: True", - "DepthOfField_test: Exit game mode: True", - "DepthOfField_test: Entity disabled initially: True", - "DepthOfField_test: Entity enabled after adding required components: True", - "DepthOfField Controller|Configuration|Camera Entity: SUCCESS", - "DepthOfField_test: Entity is hidden: True", - "DepthOfField_test: Entity is shown: True", - "DepthOfField_test: Entity deleted: True", - "DepthOfField_test: UNDO entity deletion works: True", - "DepthOfField_test: REDO entity deletion works: True", - # Directional Light Component - "Directional Light Entity successfully created", - "Directional Light_test: Component added to the entity: True", - "Directional Light_test: Component removed after UNDO: True", - "Directional Light_test: Component added after REDO: True", - "Directional Light_test: Entered game mode: True", - "Directional Light_test: Exit game mode: True", - "Directional Light Controller|Configuration|Shadow|Camera: SUCCESS", - "Directional Light_test: Entity is hidden: True", - "Directional Light_test: Entity is shown: True", - "Directional Light_test: Entity deleted: True", - "Directional Light_test: UNDO entity deletion works: True", - "Directional Light_test: REDO entity deletion works: True", - # Exposure Control Component - "Exposure Control Entity successfully created", - "Exposure Control_test: Component added to the entity: True", - "Exposure Control_test: Component removed after UNDO: True", - "Exposure Control_test: Component added after REDO: True", - "Exposure Control_test: Entered game mode: True", - "Exposure Control_test: Exit game mode: True", - "Exposure Control_test: Entity disabled initially: True", - "Exposure Control_test: Entity enabled after adding required components: True", - "Exposure Control_test: Entity is hidden: True", - "Exposure Control_test: Entity is shown: True", - "Exposure Control_test: Entity deleted: True", - "Exposure Control_test: UNDO entity deletion works: True", - "Exposure Control_test: REDO entity deletion works: True", - # Global Skylight (IBL) Component - "Global Skylight (IBL) Entity successfully created", - "Global Skylight (IBL)_test: Component added to the entity: True", - "Global Skylight (IBL)_test: Component removed after UNDO: True", - "Global Skylight (IBL)_test: Component added after REDO: True", - "Global Skylight (IBL)_test: Entered game mode: True", - "Global Skylight (IBL)_test: Exit game mode: True", - "Global Skylight (IBL) Controller|Configuration|Diffuse Image: SUCCESS", - "Global Skylight (IBL) Controller|Configuration|Specular Image: SUCCESS", - "Global Skylight (IBL)_test: Entity is hidden: True", - "Global Skylight (IBL)_test: Entity is shown: True", - "Global Skylight (IBL)_test: Entity deleted: True", - "Global Skylight (IBL)_test: UNDO entity deletion works: True", - "Global Skylight (IBL)_test: REDO entity deletion works: True", - # Physical Sky Component - "Physical Sky Entity successfully created", - "Physical Sky component was added to entity", - "Entity has a Physical Sky component", - "Physical Sky_test: Component added to the entity: True", - "Physical Sky_test: Component removed after UNDO: True", - "Physical Sky_test: Component added after REDO: True", - "Physical Sky_test: Entered game mode: True", - "Physical Sky_test: Exit game mode: True", - "Physical Sky_test: Entity is hidden: True", - "Physical Sky_test: Entity is shown: True", - "Physical Sky_test: Entity deleted: True", - "Physical Sky_test: UNDO entity deletion works: True", - "Physical Sky_test: REDO entity deletion works: True", - # Point Light Component - "Point Light Entity successfully created", - "Point Light_test: Component added to the entity: True", - "Point Light_test: Component removed after UNDO: True", - "Point Light_test: Component added after REDO: True", - "Point Light_test: Entered game mode: True", - "Point Light_test: Exit game mode: True", - "Point Light_test: Entity is hidden: True", - "Point Light_test: Entity is shown: True", - "Point Light_test: Entity deleted: True", - "Point Light_test: UNDO entity deletion works: True", - "Point Light_test: REDO entity deletion works: True", - # PostFX Layer Component - "PostFX Layer Entity successfully created", - "PostFX Layer_test: Component added to the entity: True", - "PostFX Layer_test: Component removed after UNDO: True", - "PostFX Layer_test: Component added after REDO: True", - "PostFX Layer_test: Entered game mode: True", - "PostFX Layer_test: Exit game mode: True", - "PostFX Layer_test: Entity is hidden: True", - "PostFX Layer_test: Entity is shown: True", - "PostFX Layer_test: Entity deleted: True", - "PostFX Layer_test: UNDO entity deletion works: True", - "PostFX Layer_test: REDO entity deletion works: True", - # Radius Weight Modifier Component - "Radius Weight Modifier Entity successfully created", - "Radius Weight Modifier_test: Component added to the entity: True", - "Radius Weight Modifier_test: Component removed after UNDO: True", - "Radius Weight Modifier_test: Component added after REDO: True", - "Radius Weight Modifier_test: Entered game mode: True", - "Radius Weight Modifier_test: Exit game mode: True", - "Radius Weight Modifier_test: Entity is hidden: True", - "Radius Weight Modifier_test: Entity is shown: True", - "Radius Weight Modifier_test: Entity deleted: True", - "Radius Weight Modifier_test: UNDO entity deletion works: True", - "Radius Weight Modifier_test: REDO entity deletion works: True", - # Light Component - "Light Entity successfully created", - "Light_test: Component added to the entity: True", - "Light_test: Component removed after UNDO: True", - "Light_test: Component added after REDO: True", - "Light_test: Entered game mode: True", - "Light_test: Exit game mode: True", - "Light_test: Entity is hidden: True", - "Light_test: Entity is shown: True", - "Light_test: Entity deleted: True", - "Light_test: UNDO entity deletion works: True", - "Light_test: REDO entity deletion works: True", - # Display Mapper Component - "Display Mapper Entity successfully created", - "Display Mapper_test: Component added to the entity: True", - "Display Mapper_test: Component removed after UNDO: True", - "Display Mapper_test: Component added after REDO: True", - "Display Mapper_test: Entered game mode: True", - "Display Mapper_test: Exit game mode: True", - "Display Mapper_test: Entity is hidden: True", - "Display Mapper_test: Entity is shown: True", - "Display Mapper_test: Entity deleted: True", - "Display Mapper_test: UNDO entity deletion works: True", - "Display Mapper_test: REDO entity deletion works: True", - ] - - unexpected_lines = [ - "failed to open", - "Traceback (most recent call last):", - ] - - hydra.launch_and_validate_results( - request, - TEST_DIRECTORY, - editor, - "hydra_AtomEditorComponents_AddedToEntity.py", - timeout=EDITOR_TIMEOUT, - expected_lines=expected_lines, - unexpected_lines=unexpected_lines, - halt_on_unexpected=True, - null_renderer=True, - cfg_args=cfg_args, - ) + # It requires at least one test + def test_Dummy(self, request, editor, level, workspace, project, launcher_platform): + pass diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_SandboxSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_SandboxSuite.py index 0fb873e677..8ca5b5aa31 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_SandboxSuite.py +++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_SandboxSuite.py @@ -19,6 +19,170 @@ import pytest @pytest.mark.parametrize("level", ["auto_test"]) class TestAtomEditorComponentsSandbox(object): - # It requires at least one test - def test_Dummy(self, request, editor, level, workspace, project, launcher_platform): - pass + @pytest.mark.test_case_id( + "C32078117", # Area Light + "C32078130", # Display Mapper + "C32078129", # Light + "C32078131", # Radius Weight Modifier + "C32078127", # PostFX Layer + "C32078126", # Point Light + "C32078125", # Physical Sky + "C32078115", # Global Skylight (IBL) + "C32078121", # Exposure Control + "C32078120", # Directional Light + "C32078119", # DepthOfField + "C32078118") # Decal + def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform): + cfg_args = [level] + + expected_lines = [ + # Decal Component + "Decal (Atom) Entity successfully created", + "Decal (Atom)_test: Component added to the entity: True", + "Decal (Atom)_test: Component removed after UNDO: True", + "Decal (Atom)_test: Component added after REDO: True", + "Decal (Atom)_test: Entered game mode: True", + "Decal (Atom)_test: Exit game mode: True", + "Decal (Atom) Controller|Configuration|Material: SUCCESS", + "Decal (Atom)_test: Entity is hidden: True", + "Decal (Atom)_test: Entity is shown: True", + "Decal (Atom)_test: Entity deleted: True", + "Decal (Atom)_test: UNDO entity deletion works: True", + "Decal (Atom)_test: REDO entity deletion works: True", + # DepthOfField Component + "DepthOfField Entity successfully created", + "DepthOfField_test: Component added to the entity: True", + "DepthOfField_test: Component removed after UNDO: True", + "DepthOfField_test: Component added after REDO: True", + "DepthOfField_test: Entered game mode: True", + "DepthOfField_test: Exit game mode: True", + "DepthOfField_test: Entity disabled initially: True", + "DepthOfField_test: Entity enabled after adding required components: True", + "DepthOfField Controller|Configuration|Camera Entity: SUCCESS", + "DepthOfField_test: Entity is hidden: True", + "DepthOfField_test: Entity is shown: True", + "DepthOfField_test: Entity deleted: True", + "DepthOfField_test: UNDO entity deletion works: True", + "DepthOfField_test: REDO entity deletion works: True", + # Directional Light Component + "Directional Light Entity successfully created", + "Directional Light_test: Component added to the entity: True", + "Directional Light_test: Component removed after UNDO: True", + "Directional Light_test: Component added after REDO: True", + "Directional Light_test: Entered game mode: True", + "Directional Light_test: Exit game mode: True", + "Directional Light Controller|Configuration|Shadow|Camera: SUCCESS", + "Directional Light_test: Entity is hidden: True", + "Directional Light_test: Entity is shown: True", + "Directional Light_test: Entity deleted: True", + "Directional Light_test: UNDO entity deletion works: True", + "Directional Light_test: REDO entity deletion works: True", + # Exposure Control Component + "Exposure Control Entity successfully created", + "Exposure Control_test: Component added to the entity: True", + "Exposure Control_test: Component removed after UNDO: True", + "Exposure Control_test: Component added after REDO: True", + "Exposure Control_test: Entered game mode: True", + "Exposure Control_test: Exit game mode: True", + "Exposure Control_test: Entity disabled initially: True", + "Exposure Control_test: Entity enabled after adding required components: True", + "Exposure Control_test: Entity is hidden: True", + "Exposure Control_test: Entity is shown: True", + "Exposure Control_test: Entity deleted: True", + "Exposure Control_test: UNDO entity deletion works: True", + "Exposure Control_test: REDO entity deletion works: True", + # Global Skylight (IBL) Component + "Global Skylight (IBL) Entity successfully created", + "Global Skylight (IBL)_test: Component added to the entity: True", + "Global Skylight (IBL)_test: Component removed after UNDO: True", + "Global Skylight (IBL)_test: Component added after REDO: True", + "Global Skylight (IBL)_test: Entered game mode: True", + "Global Skylight (IBL)_test: Exit game mode: True", + "Global Skylight (IBL) Controller|Configuration|Diffuse Image: SUCCESS", + "Global Skylight (IBL) Controller|Configuration|Specular Image: SUCCESS", + "Global Skylight (IBL)_test: Entity is hidden: True", + "Global Skylight (IBL)_test: Entity is shown: True", + "Global Skylight (IBL)_test: Entity deleted: True", + "Global Skylight (IBL)_test: UNDO entity deletion works: True", + "Global Skylight (IBL)_test: REDO entity deletion works: True", + # Physical Sky Component + "Physical Sky Entity successfully created", + "Physical Sky component was added to entity", + "Entity has a Physical Sky component", + "Physical Sky_test: Component added to the entity: True", + "Physical Sky_test: Component removed after UNDO: True", + "Physical Sky_test: Component added after REDO: True", + "Physical Sky_test: Entered game mode: True", + "Physical Sky_test: Exit game mode: True", + "Physical Sky_test: Entity is hidden: True", + "Physical Sky_test: Entity is shown: True", + "Physical Sky_test: Entity deleted: True", + "Physical Sky_test: UNDO entity deletion works: True", + "Physical Sky_test: REDO entity deletion works: True", + # PostFX Layer Component + "PostFX Layer Entity successfully created", + "PostFX Layer_test: Component added to the entity: True", + "PostFX Layer_test: Component removed after UNDO: True", + "PostFX Layer_test: Component added after REDO: True", + "PostFX Layer_test: Entered game mode: True", + "PostFX Layer_test: Exit game mode: True", + "PostFX Layer_test: Entity is hidden: True", + "PostFX Layer_test: Entity is shown: True", + "PostFX Layer_test: Entity deleted: True", + "PostFX Layer_test: UNDO entity deletion works: True", + "PostFX Layer_test: REDO entity deletion works: True", + # Radius Weight Modifier Component + "Radius Weight Modifier Entity successfully created", + "Radius Weight Modifier_test: Component added to the entity: True", + "Radius Weight Modifier_test: Component removed after UNDO: True", + "Radius Weight Modifier_test: Component added after REDO: True", + "Radius Weight Modifier_test: Entered game mode: True", + "Radius Weight Modifier_test: Exit game mode: True", + "Radius Weight Modifier_test: Entity is hidden: True", + "Radius Weight Modifier_test: Entity is shown: True", + "Radius Weight Modifier_test: Entity deleted: True", + "Radius Weight Modifier_test: UNDO entity deletion works: True", + "Radius Weight Modifier_test: REDO entity deletion works: True", + # Light Component + "Light Entity successfully created", + "Light_test: Component added to the entity: True", + "Light_test: Component removed after UNDO: True", + "Light_test: Component added after REDO: True", + "Light_test: Entered game mode: True", + "Light_test: Exit game mode: True", + "Light_test: Entity is hidden: True", + "Light_test: Entity is shown: True", + "Light_test: Entity deleted: True", + "Light_test: UNDO entity deletion works: True", + "Light_test: REDO entity deletion works: True", + # Display Mapper Component + "Display Mapper Entity successfully created", + "Display Mapper_test: Component added to the entity: True", + "Display Mapper_test: Component removed after UNDO: True", + "Display Mapper_test: Component added after REDO: True", + "Display Mapper_test: Entered game mode: True", + "Display Mapper_test: Exit game mode: True", + "Display Mapper_test: Entity is hidden: True", + "Display Mapper_test: Entity is shown: True", + "Display Mapper_test: Entity deleted: True", + "Display Mapper_test: UNDO entity deletion works: True", + "Display Mapper_test: REDO entity deletion works: True", + ] + + unexpected_lines = [ + "failed to open", + "Traceback (most recent call last):", + ] + + hydra.launch_and_validate_results( + request, + TEST_DIRECTORY, + editor, + "hydra_AtomEditorComponents_AddedToEntity.py", + timeout=EDITOR_TIMEOUT, + expected_lines=expected_lines, + unexpected_lines=unexpected_lines, + halt_on_unexpected=True, + null_renderer=True, + cfg_args=cfg_args, + ) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py index d8e0a6769c..60fa9dc44d 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py @@ -20,7 +20,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. class Tests(): enter_game_mode = ("Entered game mode", "Failed to enter game mode") find_cylinder = ("Cylinder entity found", "Cylinder entity not found") - find_terrain = ("Terrain found", "Terrain not found") + create_terrain = ("Terrain entity created successfully", "Failed to create Terrain Entity") + find_terrain = ("Terrain entity found", "Terrain entity not found") + add_physx_shape_collider = ("Added PhysX Shape Collider", "Failed to add PhysX Shape Collider") + add_box_shape = ("Added Box Shape", "Failed to add Box Shape") cylinder_above_terrain = ("Cylinder position above ground", "Cylinder is not above the ground") time_out = ("No time out occurred", "A time out occurred, please validate level setup") touched_ground = ("Touched ground before time out", "Did not touch ground before time out") @@ -40,11 +43,12 @@ def C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(): Once game mode is entered, the cylinder should fall toward and collide with the terrain. Steps: - 1) Open level and enter game mode - 2) Retrieve entities and positions - 3) Wait for cylinder to collide with terrain OR time out - 4) Exit game mode - 5) Close the editor + 1) Open level and create terrain Entity. + 2) Enter Game Mode. + 3) Retrieve entities and positions + 4) Wait for cylinder to collide with terrain OR time out + 5) Exit game mode + 6) Close the editor :return: """ @@ -54,29 +58,48 @@ def C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(): import ImportPathHelper as imports imports.init() - + from editor_python_test_tools.editor_entity_utils import EditorEntity import azlmbr.legacy.general as general import azlmbr.bus + import azlmbr.math as math from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper # Global time out TIME_OUT = 1.0 - # 1) Open level / Enter game mode + # 1) Open level helper.init_idle() helper.open_level("Physics", "C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain") + + # Create terrain entity + terrain = EditorEntity.create_editor_entity_at([30.0, 30.0, 33.96], "Terrain") + Report.result(Tests.create_terrain, terrain.id.IsValid()) + + terrain.add_component("PhysX Shape Collider") + Report.result(Tests.add_physx_shape_collider, terrain.has_component("PhysX Shape Collider")) + + box_shape_component = terrain.add_component("Box Shape") + Report.result(Tests.add_box_shape, terrain.has_component("Box Shape")) + + box_shape_component.set_component_property_value("Box Shape|Box Configuration|Dimensions", + math.Vector3(1024.0, 1024.0, 0.01)) + + # 2)Enter game mode helper.enter_game_mode(Tests.enter_game_mode) - # 2) Retrieve entities and positions + # 3) Retrieve entities and positions cylinder_id = general.find_game_entity("PhysX_Cylinder") Report.critical_result(Tests.find_cylinder, cylinder_id.IsValid()) + + + terrain_id = general.find_game_entity("Terrain") + Report.critical_result(Tests.find_terrain, terrain_id.IsValid()) - terrain_id = general.find_game_entity("PhysX_Terrain") - Report.critical_result(Tests.find_terrain, terrain_id.IsValid()) - cylinder_pos = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTM", cylinder_id).GetPosition() - terrain_pos = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTM", terrain_id).GetPosition() + cylinder_pos = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", cylinder_id) + #Cylinder position is 64,84,35 + terrain_pos = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", terrain_id) Report.info_vector3(cylinder_pos, "Cylinder:") Report.info_vector3(terrain_pos, "Terrain:") Report.critical_result( @@ -104,13 +127,13 @@ def C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(): handler.connect(cylinder_id) handler.add_callback("OnCollisionBegin", on_collision_begin) - # 3) Wait for the cylinder to hit the ground OR time out + # 4) Wait for the cylinder to hit the ground OR time out test_completed = helper.wait_for_condition((lambda: TouchGround.value), TIME_OUT) Report.critical_result(Tests.time_out, test_completed) Report.result(Tests.touched_ground, TouchGround.value) - # 4) Exit game mode + # 5) Exit game mode helper.exit_game_mode(Tests.exit_game_mode) diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py index 67e855a00e..f81445fe03 100644 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Main.py @@ -34,4 +34,61 @@ class TestAutomation(TestAutomationBase): def test_C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC(self, request, workspace, editor, launcher_platform): from . import C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(self, request, workspace, editor, launcher_platform): + from . import C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C4044459_Material_DynamicFriction(self, request, workspace, editor, launcher_platform): + from . import C4044459_Material_DynamicFriction as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C15425929_Undo_Redo(self, request, workspace, editor, launcher_platform): + from . import C15425929_Undo_Redo as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C4976243_Collision_SameCollisionGroupDiffCollisionLayers(self, request, workspace, editor, + launcher_platform): + from . import C4976243_Collision_SameCollisionGroupDiffCollisionLayers as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C14654881_CharacterController_SwitchLevels(self, request, workspace, editor, launcher_platform): + from . import C14654881_CharacterController_SwitchLevels as test_module + self._run_test(request, workspace, editor, test_module) + + def test_C17411467_AddPhysxRagdollComponent(self, request, workspace, editor, launcher_platform): + from . import C17411467_AddPhysxRagdollComponent as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C12712453_ScriptCanvas_MultipleRaycastNode(self, request, workspace, editor, launcher_platform): + from . import C12712453_ScriptCanvas_MultipleRaycastNode as test_module + # Fixme: unexpected_lines = ["Assert"] + test_module.Lines.unexpected + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C4982593_PhysXCollider_CollisionLayer.setreg', 'AutomatedTesting/Registry') + def test_C4982593_PhysXCollider_CollisionLayerTest(self, request, workspace, editor, launcher_platform): + from . import C4982593_PhysXCollider_CollisionLayerTest as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C18243586_Joints_HingeLeadFollowerCollide(self, request, workspace, editor, launcher_platform): + from . import C18243586_Joints_HingeLeadFollowerCollide as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C4982803_Enable_PxMesh_Option(self, request, workspace, editor, launcher_platform): + from . import C4982803_Enable_PxMesh_Option as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(self, request, workspace, editor, launcher_platform): + from . import C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain as test_module self._run_test(request, workspace, editor, test_module) \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py index 39ed85a65a..4f91f539ee 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Periodic.py @@ -52,11 +52,6 @@ class TestAutomation(TestAutomationBase): from . import C4976207_PhysXRigidBodies_KinematicBehavior as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(self, request, workspace, editor, launcher_platform): - from . import C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C5932042_PhysXForceRegion_LinearDamping(self, request, workspace, editor, launcher_platform): from . import C5932042_PhysXForceRegion_LinearDamping as test_module @@ -92,11 +87,6 @@ class TestAutomation(TestAutomationBase): from . import C4976194_RigidBody_PhysXComponentIsValid as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C4044459_Material_DynamicFriction(self, request, workspace, editor, launcher_platform): - from . import C4044459_Material_DynamicFriction as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C5932045_ForceRegion_Spline(self, request, workspace, editor, launcher_platform): from . import C5932045_ForceRegion_Spline as test_module @@ -208,26 +198,11 @@ class TestAutomation(TestAutomationBase): from . import C18981526_Material_RestitutionCombinePriority as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C15425929_Undo_Redo(self, request, workspace, editor, launcher_platform): - from . import C15425929_Undo_Redo as test_module - self._run_test(request, workspace, editor, test_module) - - @revert_physics_config - def test_C15308217_NoCrash_LevelSwitch(self, request, workspace, editor, launcher_platform): - from . import C15308217_NoCrash_LevelSwitch as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C12868580_ForceRegion_SplineModifiedTransform(self, request, workspace, editor, launcher_platform): from . import C12868580_ForceRegion_SplineModifiedTransform as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C4976243_Collision_SameCollisionGroupDiffCollisionLayers(self, request, workspace, editor, launcher_platform): - from . import C4976243_Collision_SameCollisionGroupDiffCollisionLayers as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C12712455_ScriptCanvas_ShapeCastVerification(self, request, workspace, editor, launcher_platform): from . import C12712455_ScriptCanvas_ShapeCastVerification as test_module @@ -248,17 +223,6 @@ class TestAutomation(TestAutomationBase): from . import C6131473_StaticSlice_OnDynamicSliceSpawn as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C4982798_Collider_ColliderRotationOffset(self, request, workspace, editor, launcher_platform): - from . import C4982798_Collider_ColliderRotationOffset as test_module - self._run_test(request, workspace, editor, test_module) - - @revert_physics_config - def test_C12712453_ScriptCanvas_MultipleRaycastNode(self, request, workspace, editor, launcher_platform): - from . import C12712453_ScriptCanvas_MultipleRaycastNode as test_module - # Fixme: unexpected_lines = ["Assert"] + test_module.Lines.unexpected - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C5959808_ForceRegion_PositionOffset(self, request, workspace, editor, launcher_platform): from . import C5959808_ForceRegion_PositionOffset as test_module @@ -275,7 +239,7 @@ class TestAutomation(TestAutomationBase): def test_C13895144_Ragdoll_ChangeLevel(self, request, workspace, editor, launcher_platform): from . import C13895144_Ragdoll_ChangeLevel as test_module self._run_test(request, workspace, editor, test_module) - + @revert_physics_config def test_C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody(self, request, workspace, editor, launcher_platform): from . import C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody as test_module @@ -305,11 +269,6 @@ class TestAutomation(TestAutomationBase): from . import C5296614_PhysXMaterial_ColliderShape as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C6090547_ForceRegion_ParentChildForceRegions(self, request, workspace, editor, launcher_platform): - from . import C6090547_ForceRegion_ParentChildForceRegions as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C4982595_Collider_TriggerDisablesCollision(self, request, workspace, editor, launcher_platform): from . import C4982595_Collider_TriggerDisablesCollision as test_module @@ -320,11 +279,6 @@ class TestAutomation(TestAutomationBase): from . import C14976307_Gravity_SetGravityWorks as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C14654881_CharacterController_SwitchLevels(self, request, workspace, editor, launcher_platform): - from . import C14654881_CharacterController_SwitchLevels as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(self, request, workspace, editor, launcher_platform): from . import C15556261_PhysXMaterials_CharacterControllerMaterialAssignment as test_module @@ -374,18 +328,6 @@ class TestAutomation(TestAutomationBase): from . import C4044461_Material_Restitution as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - @fm.file_override('physxsystemconfiguration.setreg','C4982593_PhysXCollider_CollisionLayer.setreg', 'AutomatedTesting/Registry') - def test_C4982593_PhysXCollider_CollisionLayerTest(self, request, workspace, editor, launcher_platform): - from . import C4982593_PhysXCollider_CollisionLayerTest as test_module - self._run_test(request, workspace, editor, test_module) - - @revert_physics_config - @fm.file_override('physxsystemconfiguration.setreg','C3510644_Collider_CollisionGroups.setreg', 'AutomatedTesting/Registry') - def test_C3510644_Collider_CollisionGroups(self, request, workspace, editor, launcher_platform): - from . import C3510644_Collider_CollisionGroups as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config @fm.file_override('physxdefaultsceneconfiguration.setreg','C14902097_ScriptCanvas_PreUpdateEvent.setreg', 'AutomatedTesting/Registry') def test_C14902097_ScriptCanvas_PreUpdateEvent(self, request, workspace, editor, launcher_platform): @@ -415,11 +357,6 @@ class TestAutomation(TestAutomationBase): from . import C18243589_Joints_BallSoftLimitsConstrained as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C18243586_Joints_HingeLeadFollowerCollide(self, request, workspace, editor, launcher_platform): - from . import C18243586_Joints_HingeLeadFollowerCollide as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C18243591_Joints_BallLeadFollowerCollide(self, request, workspace, editor, launcher_platform): from . import C18243591_Joints_BallLeadFollowerCollide as test_module @@ -441,21 +378,11 @@ class TestAutomation(TestAutomationBase): from . import C14861500_DefaultSetting_ColliderShape as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C19578021_ShapeCollider_CanBeAdded(self, request, workspace, editor, launcher_platform): - from . import C19578021_ShapeCollider_CanBeAdded as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C19723164_ShapeCollider_WontCrashEditor(self, request, workspace, editor, launcher_platform): from . import C19723164_ShapeColliders_WontCrashEditor as test_module self._run_test(request, workspace, editor, test_module) - @revert_physics_config - def test_C4982803_Enable_PxMesh_Option(self, request, workspace, editor, launcher_platform): - from . import C4982803_Enable_PxMesh_Option as test_module - self._run_test(request, workspace, editor, test_module) - @revert_physics_config def test_C4982800_PhysXColliderShape_CanBeSelected(self, request, workspace, editor, launcher_platform): from . import C4982800_PhysXColliderShape_CanBeSelected as test_module @@ -471,10 +398,6 @@ class TestAutomation(TestAutomationBase): from . import C4982802_PhysXColliderShape_CanBeSelected as test_module self._run_test(request, workspace, editor, test_module) - def test_C17411467_AddPhysxRagdollComponent(self, request, workspace, editor, launcher_platform): - from . import C17411467_AddPhysxRagdollComponent as test_module - self._run_test(request, workspace, editor, test_module) - def test_C12905528_ForceRegion_WithNonTriggerCollider(self, request, workspace, editor, launcher_platform): from . import C12905528_ForceRegion_WithNonTriggerCollider as test_module # Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"] @@ -522,4 +445,35 @@ class TestAutomation(TestAutomationBase): def test_C100000_RigidBody_EnablingGravityWorksPoC(self, request, workspace, editor, launcher_platform): from . import C100000_RigidBody_EnablingGravityWorksPoC as test_module - self._run_test(request, workspace, editor, test_module) \ No newline at end of file + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + @fm.file_override('physxsystemconfiguration.setreg','C3510644_Collider_CollisionGroups.setreg', 'AutomatedTesting/Registry') + def test_C3510644_Collider_CollisionGroups(self, request, workspace, editor, launcher_platform): + from . import C3510644_Collider_CollisionGroups as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C4982798_Collider_ColliderRotationOffset(self, request, workspace, editor, launcher_platform): + from . import C4982798_Collider_ColliderRotationOffset as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C15308217_NoCrash_LevelSwitch(self, request, workspace, editor, launcher_platform): + from . import C15308217_NoCrash_LevelSwitch as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C6090547_ForceRegion_ParentChildForceRegions(self, request, workspace, editor, launcher_platform): + from . import C6090547_ForceRegion_ParentChildForceRegions as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C19578021_ShapeCollider_CanBeAdded(self, request, workspace, editor, launcher_platform): + from . import C19578021_ShapeCollider_CanBeAdded as test_module + self._run_test(request, workspace, editor, test_module) + + @revert_physics_config + def test_C15425929_Undo_Redo(self, request, workspace, editor, launcher_platform): + from . import C15425929_Undo_Redo as test_module + self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py index 39bc4c8188..e829726ba9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py +++ b/AutomatedTesting/Gem/PythonTests/physics/TestSuite_Sandbox.py @@ -1,49 +1,49 @@ -""" -All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -its licensors. - -For complete copyright and license terms please see the LICENSE at the root of this -distribution (the "License"). All use of this software is governed by the License, -or, if provided, by the license below or the license accompanying this file. Do not -remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - -""" - -# This suite consists of all test cases that are passing and have been verified. - -import pytest -import os -import sys - -from .FileManagement import FileManagement as fm -from ly_test_tools import LAUNCHERS - -sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') - -from base import TestAutomationBase - - -revert_physics_config = fm.file_revert_list(['physxdebugconfiguration.setreg', 'physxdefaultsceneconfiguration.setreg', 'physxsystemconfiguration.setreg'], 'AutomatedTesting/Registry') - - -@pytest.mark.SUITE_sandbox -@pytest.mark.parametrize("launcher_platform", ['windows_editor']) -@pytest.mark.parametrize("project", ["AutomatedTesting"]) -class TestAutomation(TestAutomationBase): - - ## Seems to be flaky, need to investigate - def test_C19536274_GetCollisionName_PrintsName(self, request, workspace, editor, launcher_platform): - from . import C19536274_GetCollisionName_PrintsName as test_module - # Fixme: expected_lines=["Layer Name: Right"] - self._run_test(request, workspace, editor, test_module) - - ## Seems to be flaky, need to investigate - def test_C19536277_GetCollisionName_PrintsNothing(self, request, workspace, editor, launcher_platform): - from . import C19536277_GetCollisionName_PrintsNothing as test_module - # All groups present in the PhysX Collider that could show up in test - # Fixme: collision_groups = ["All", "None", "All_NoTouchBend", "All_3", "None_1", "All_NoTouchBend_1", "All_2", "None_1_1", "All_NoTouchBend_1_1", "All_1", "None_1_1_1", "All_NoTouchBend_1_1_1", "All_4", "None_1_1_1_1", "All_NoTouchBend_1_1_1_1", "GroupLeft", "GroupRight"] - # Fixme: for group in collision_groups: - # Fixme: unexpected_lines.append(f"GroupName: {group}") - # Fixme: expected_lines=["GroupName: "] - self._run_test(request, workspace, editor, test_module) \ No newline at end of file +""" +All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +its licensors. + +For complete copyright and license terms please see the LICENSE at the root of this +distribution (the "License"). All use of this software is governed by the License, +or, if provided, by the license below or the license accompanying this file. Do not +remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +""" + +# This suite consists of all test cases that are passing and have been verified. + +import pytest +import os +import sys + +from .FileManagement import FileManagement as fm +from ly_test_tools import LAUNCHERS + +sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../automatedtesting_shared') + +from base import TestAutomationBase + + +revert_physics_config = fm.file_revert_list(['physxdebugconfiguration.setreg', 'physxdefaultsceneconfiguration.setreg', 'physxsystemconfiguration.setreg'], 'AutomatedTesting/Registry') + + +@pytest.mark.SUITE_sandbox +@pytest.mark.parametrize("launcher_platform", ['windows_editor']) +@pytest.mark.parametrize("project", ["AutomatedTesting"]) +class TestAutomation(TestAutomationBase): + + ## Seems to be flaky, need to investigate + def test_C19536274_GetCollisionName_PrintsName(self, request, workspace, editor, launcher_platform): + from . import C19536274_GetCollisionName_PrintsName as test_module + # Fixme: expected_lines=["Layer Name: Right"] + self._run_test(request, workspace, editor, test_module) + + ## Seems to be flaky, need to investigate + def test_C19536277_GetCollisionName_PrintsNothing(self, request, workspace, editor, launcher_platform): + from . import C19536277_GetCollisionName_PrintsNothing as test_module + # All groups present in the PhysX Collider that could show up in test + # Fixme: collision_groups = ["All", "None", "All_NoTouchBend", "All_3", "None_1", "All_NoTouchBend_1", "All_2", "None_1_1", "All_NoTouchBend_1_1", "All_1", "None_1_1_1", "All_NoTouchBend_1_1_1", "All_4", "None_1_1_1_1", "All_NoTouchBend_1_1_1_1", "GroupLeft", "GroupRight"] + # Fixme: for group in collision_groups: + # Fixme: unexpected_lines.append(f"GroupName: {group}") + # Fixme: expected_lines=["GroupName: "] + self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Levels/Physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.ly b/AutomatedTesting/Levels/Physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.ly index ba141251d5..d618bf1873 100644 --- a/AutomatedTesting/Levels/Physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.ly +++ b/AutomatedTesting/Levels/Physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:231d5ac32c95334eeb1cbf77ea0bceae1d8010de3290dfdbd991abb46d18bae6 -size 6844 +oid sha256:83af66a6db4ff2b4df7212099b661a96668cfb326d8984e41b16506ec0062141 +size 5844 diff --git a/AutomatedTesting/Registry/assets_scan_folders.setreg b/AutomatedTesting/Registry/assets_scan_folders.setreg index 5394d381a3..91061f3337 100644 --- a/AutomatedTesting/Registry/assets_scan_folders.setreg +++ b/AutomatedTesting/Registry/assets_scan_folders.setreg @@ -38,6 +38,13 @@ "Gems/PrimitiveAssets" ] }, + "MaterialEditor": + { + "SourcePaths": + [ + "Gems/Atom/Tools/MaterialEditor" + ] + }, "UiBasics": { "SourcePaths": diff --git a/CMakeLists.txt b/CMakeLists.txt index cefbcf2ef4..ae8a7a05f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,9 @@ foreach(restricted_platform ${PAL_RESTRICTED_PLATFORMS}) endif() endforeach() -add_subdirectory(scripts) +if(NOT INSTALLED_ENGINE) + add_subdirectory(scripts) +endif() # SPEC-1417 will investigate and fix this if(NOT PAL_PLATFORM_NAME STREQUAL "Mac") @@ -125,5 +127,5 @@ if(NOT INSTALLED_ENGINE) ly_setup_o3de_install() # IMPORTANT: must be included last - include(cmake/CPack.cmake) + include(cmake/Packaging.cmake) endif() diff --git a/Code/CryEngine/CMakeLists.txt b/Code/CryEngine/CMakeLists.txt index 38fcbf4a27..96f6427268 100644 --- a/Code/CryEngine/CMakeLists.txt +++ b/Code/CryEngine/CMakeLists.txt @@ -10,5 +10,4 @@ # add_subdirectory(CryCommon) -add_subdirectory(CryFont) add_subdirectory(CrySystem) diff --git a/Code/CryEngine/CryCommon/CREVolumeObject.h b/Code/CryEngine/CryCommon/CREVolumeObject.h index d84c7b3e50..2137053a8e 100644 --- a/Code/CryEngine/CryCommon/CREVolumeObject.h +++ b/Code/CryEngine/CryCommon/CREVolumeObject.h @@ -55,7 +55,7 @@ public: Matrix34 m_matInv; Vec3 m_eyePosInWS; Vec3 m_eyePosInOS; - Plane m_volumeTraceStartPlane; + Plane_tpl m_volumeTraceStartPlane; AABB m_renderBoundsOS; bool m_viewerInsideVolume; bool m_nearPlaneIntersectsVolume; diff --git a/Code/CryEngine/CryCommon/CREWaterOcean.h b/Code/CryEngine/CryCommon/CREWaterOcean.h index 784588309f..e8ca310d41 100644 --- a/Code/CryEngine/CryCommon/CREWaterOcean.h +++ b/Code/CryEngine/CryCommon/CREWaterOcean.h @@ -25,7 +25,7 @@ public: virtual void mfPrepare(bool bCheckOverflow); virtual bool mfDraw(CShader* ef, SShaderPass* sfm); - virtual void mfGetPlane(Plane& pl); + virtual void mfGetPlane(Plane_tpl& pl); virtual void Create(uint32 nVerticesCount, SVF_P3F_C4B_T2F* pVertices, uint32 nIndicesCount, const void* pIndices, uint32 nIndexSizeof); void ReleaseOcean(); diff --git a/Code/CryEngine/CryCommon/CREWaterVolume.h b/Code/CryEngine/CryCommon/CREWaterVolume.h index 3e7a0636e6..89102e3097 100644 --- a/Code/CryEngine/CryCommon/CREWaterVolume.h +++ b/Code/CryEngine/CryCommon/CREWaterVolume.h @@ -27,7 +27,7 @@ public: virtual ~CREWaterVolume(); virtual void mfPrepare(bool bCheckOverflow); virtual bool mfDraw(CShader* ef, SShaderPass* sfm); - virtual void mfGetPlane(Plane& pl); + virtual void mfGetPlane(Plane_tpl& pl); virtual void mfCenter(Vec3& vCenter, CRenderObject* pObj); virtual void GetMemoryUsage(ICrySizer* pSizer) const @@ -69,7 +69,7 @@ public: Vec3 m_center; AABB m_WSBBox; - Plane m_fogPlane; + Plane_tpl m_fogPlane; float m_fogDensity; Vec3 m_fogColor; bool m_fogColorAffectedBySun; diff --git a/Code/CryEngine/CryCommon/CryFontBus.h b/Code/CryEngine/CryCommon/CryFontBus.h deleted file mode 100644 index 9922193f42..0000000000 --- a/Code/CryEngine/CryCommon/CryFontBus.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - */ - -#pragma once - -#include - -#include - -namespace AZ -{ - /*! - * Signal LY to create an ICryFont - */ - class CryFontCreationRequests - : public AZ::EBusTraits - { - public: - using MutexType = AZStd::recursive_mutex; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - virtual bool CreateCryFont([[maybe_unused]] SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) {return false;} //! return false to fall back to default CryFont initialization - }; - using CryFontCreationRequestBus = AZ::EBus; - -} diff --git a/Code/CryEngine/CryCommon/Cry_Camera.h b/Code/CryEngine/CryCommon/Cry_Camera.h index a744d7335f..56a764d897 100644 --- a/Code/CryEngine/CryCommon/Cry_Camera.h +++ b/Code/CryEngine/CryCommon/Cry_Camera.h @@ -594,7 +594,7 @@ public: ILINE const Vec3& GetFPVertex(int nId) const; //get far-plane vertices ILINE const Vec3& GetPPVertex(int nId) const; //get projection-plane vertices - ILINE const Plane* GetFrustumPlane(int numplane) const { return &m_fp[numplane]; } + ILINE const Plane_tpl* GetFrustumPlane(int numplane) const { return &m_fp[numplane]; } ////////////////////////////////////////////////////////////////////////// // Z-Buffer ranges. @@ -720,7 +720,7 @@ private: Vec3 m_cltn, m_crtn, m_clbn, m_crbn; //this are the 4 vertices of the near-plane in cam-space Vec3 m_cltf, m_crtf, m_clbf, m_crbf; //this are the 4 vertices of the farclip-plane in cam-space - Plane m_fp [FRUSTUM_PLANES]; // + Plane_tpl m_fp [FRUSTUM_PLANES]; // uint32 m_idx1[FRUSTUM_PLANES], m_idy1[FRUSTUM_PLANES], m_idz1[FRUSTUM_PLANES]; // uint32 m_idx2[FRUSTUM_PLANES], m_idy2[FRUSTUM_PLANES], m_idz2[FRUSTUM_PLANES]; // @@ -742,7 +742,7 @@ public: m_crtp = arrvVerts[2]; m_crbp = arrvVerts[3]; } - inline void SetFrustumPlane(int i, const Plane& plane) + inline void SetFrustumPlane(int i, const Plane_tpl& plane) { m_fp[i] = plane; //do not break strict aliasing rules, use union instead of reinterpret_casts @@ -1180,12 +1180,12 @@ inline void CCamera::UpdateFrustum() //------------------------------------------------------------------------------- //--- calculate the six frustum-planes using the frustum edges in world-space --- //------------------------------------------------------------------------------- - m_fp[FR_PLANE_NEAR ] = Plane::CreatePlane(m_crtn + GetPosition(), m_cltn + GetPosition(), m_crbn + GetPosition()); - m_fp[FR_PLANE_RIGHT ] = Plane::CreatePlane(m_crbf + GetPosition(), m_crtf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_LEFT ] = Plane::CreatePlane(m_cltf + GetPosition(), m_clbf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_TOP ] = Plane::CreatePlane(m_crtf + GetPosition(), m_cltf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_BOTTOM] = Plane::CreatePlane(m_clbf + GetPosition(), m_crbf + GetPosition(), GetPosition()); - m_fp[FR_PLANE_FAR ] = Plane::CreatePlane(m_crtf + GetPosition(), m_crbf + GetPosition(), m_cltf + GetPosition()); //clip-plane + m_fp[FR_PLANE_NEAR ] = Plane_tpl::CreatePlane(m_crtn + GetPosition(), m_cltn + GetPosition(), m_crbn + GetPosition()); + m_fp[FR_PLANE_RIGHT ] = Plane_tpl::CreatePlane(m_crbf + GetPosition(), m_crtf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_LEFT ] = Plane_tpl::CreatePlane(m_cltf + GetPosition(), m_clbf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_TOP ] = Plane_tpl::CreatePlane(m_crtf + GetPosition(), m_cltf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_BOTTOM] = Plane_tpl::CreatePlane(m_clbf + GetPosition(), m_crbf + GetPosition(), GetPosition()); + m_fp[FR_PLANE_FAR ] = Plane_tpl::CreatePlane(m_crtf + GetPosition(), m_crbf + GetPosition(), m_cltf + GetPosition()); //clip-plane uint32 rh = m_Matrix.IsOrthonormalRH(); if (rh == 0) diff --git a/Code/CryEngine/CryCommon/Cry_GeoDistance.h b/Code/CryEngine/CryCommon/Cry_GeoDistance.h index 92c1f65d87..47794c7671 100644 --- a/Code/CryEngine/CryCommon/Cry_GeoDistance.h +++ b/Code/CryEngine/CryCommon/Cry_GeoDistance.h @@ -1168,17 +1168,6 @@ namespace Distance { return fDist2; } - // Compute both the min and max distances of a box to a plane, in the sense of the plane normal. - inline void AABB_Plane(float* pfDistMin, float* pfDistMax, const AABB& box, const Plane& pl) - { - float fDist0 = pl.DistFromPlane(box.min), - fDistX = (box.max.x - box.min.x) * pl.n.x, - fDistY = (box.max.y - box.min.y) * pl.n.y, - fDistZ = (box.max.z - box.min.z) * pl.n.z; - *pfDistMin = fDist0 + min(fDistX, 0.f) + min(fDistY, 0.f) + min(fDistZ, 0.f); - *pfDistMax = fDist0 + max(fDistX, 0.f) + max(fDistY, 0.f) + max(fDistZ, 0.f); - } - //---------------------------------------------------------------------------------- // Distance: Sphere_Triangle //---------------------------------------------------------------------------------- diff --git a/Code/CryEngine/CryCommon/Cry_GeoIntersect.h b/Code/CryEngine/CryCommon/Cry_GeoIntersect.h index c2f556c4b7..89f6d8ebaf 100644 --- a/Code/CryEngine/CryCommon/Cry_GeoIntersect.h +++ b/Code/CryEngine/CryCommon/Cry_GeoIntersect.h @@ -22,7 +22,7 @@ #include namespace Intersect { - inline bool Ray_Plane(const Ray& ray, const Plane& plane, Vec3& output, bool bSingleSidePlane = true) + inline bool Ray_Plane(const Ray& ray, const Plane_tpl& plane, Vec3& output, bool bSingleSidePlane = true) { float cosine = plane.n | ray.direction; @@ -49,7 +49,7 @@ namespace Intersect { return true; //intersection occurred } - inline bool Line_Plane(const Line& line, const Plane& plane, Vec3& output, bool bSingleSidePlane = true) + inline bool Line_Plane(const Line& line, const Plane_tpl& plane, Vec3& output, bool bSingleSidePlane = true) { float cosine = plane.n | line.direction; diff --git a/Code/CryEngine/CryCommon/Cry_GeoOverlap.h b/Code/CryEngine/CryCommon/Cry_GeoOverlap.h index 3f2c7081d7..ab560b7518 100644 --- a/Code/CryEngine/CryCommon/Cry_GeoOverlap.h +++ b/Code/CryEngine/CryCommon/Cry_GeoOverlap.h @@ -945,29 +945,6 @@ namespace Overlap { } } - - /*! - * - * we use the SEPARATING-AXIS-TEST for OBB/Plane overlap. - * - * Example: - * bool result=Overlap::OBB_Plane( pos,obb, plane ); - * - */ - inline bool OBB_Plane(const Vec3& pos, const OBB& obb, const Plane& plane) - { - //the new center-position in world-space - Vec3 p = obb.m33 * obb.c + pos; - //extract the orientation-vectors from the columns of the 3x3 matrix - //and scale them by the half-lengths - Vec3 ax = Vec3(obb.m33.m00, obb.m33.m10, obb.m33.m20) * obb.h.x; - Vec3 ay = Vec3(obb.m33.m01, obb.m33.m11, obb.m33.m21) * obb.h.y; - Vec3 az = Vec3(obb.m33.m02, obb.m33.m12, obb.m33.m22) * obb.h.z; - //check OBB against Plane, using the plane-normal as separating axis - return fabsf(plane | p) < (fabsf(plane.n | ax) + fabsf(plane.n | ay) + fabsf(plane.n | az)); - } - - /*! * * we use the SEPARATING AXIS TEST to check if a triangle and AABB overlap. @@ -1214,7 +1191,7 @@ namespace Overlap { //test if the box intersects the plane of the triangle //compute plane equation of triangle: normal*x+d=0 - Plane plane = Plane::CreatePlane((e0 % e1), v0); + Plane_tpl plane = Plane_tpl::CreatePlane((e0 % e1), v0); Vec3 vmin, vmax; if (plane.n.x > 0.0f) @@ -1505,7 +1482,7 @@ namespace Overlap { //test if the box overlaps the plane of the triangle //compute plane equation of triangle: normal*x+d=0 - Plane plane = Plane::CreatePlane((e0 % e1), v0); + Plane_tpl plane = Plane_tpl::CreatePlane((e0 % e1), v0); Vec3 vmin, vmax; if (plane.n.x > 0.0f) diff --git a/Code/CryEngine/CryCommon/I3DEngine.h b/Code/CryEngine/CryCommon/I3DEngine.h index 8d3801ecb4..883b0a6d3b 100644 --- a/Code/CryEngine/CryCommon/I3DEngine.h +++ b/Code/CryEngine/CryCommon/I3DEngine.h @@ -458,7 +458,7 @@ struct SClipVolumeBlendInfo { static const int BlendPlaneCount = 2; - Plane blendPlanes[BlendPlaneCount]; + Plane_tpl blendPlanes[BlendPlaneCount]; struct IClipVolume* blendVolumes[BlendPlaneCount]; }; diff --git a/Code/CryEngine/CryCommon/IEntityRenderState.h b/Code/CryEngine/CryCommon/IEntityRenderState.h index 912f4632ab..92ff354eff 100644 --- a/Code/CryEngine/CryCommon/IEntityRenderState.h +++ b/Code/CryEngine/CryCommon/IEntityRenderState.h @@ -731,8 +731,8 @@ struct IWaterVolumeRenderNode virtual void SetAuxPhysParams(pe_params_area*) = 0; virtual void CreateOcean(uint64 volumeID, /* TBD */ bool keepSerializationParams = false) = 0; - virtual void CreateArea(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; - virtual void CreateRiver(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; + virtual void CreateArea(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale, const Plane_tpl& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; + virtual void CreateRiver(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale, const Plane_tpl& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; virtual void CreateRiver(uint64 volumeID, const AZStd::vector& verticies, const AZ::Transform& transform, float uTexCoordBegin, float uTexCoordEnd, const AZ::Vector2& surfUVScale, const AZ::Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0; virtual void SetAreaPhysicsArea(const Vec3* pVertices, unsigned int numVertices, bool keepSerializationParams = false) = 0; diff --git a/Code/CryEngine/CryCommon/IShader.h b/Code/CryEngine/CryCommon/IShader.h index 1e8553ac57..7fcbdefebb 100644 --- a/Code/CryEngine/CryCommon/IShader.h +++ b/Code/CryEngine/CryCommon/IShader.h @@ -52,7 +52,6 @@ struct SShaderItem; class ITexture; struct IMaterial; struct SParam; -class CMaterial; struct SShaderSerializeContext; struct IAnimNode; struct SSkinningData; diff --git a/Code/CryEngine/CryCommon/RendElement.h b/Code/CryEngine/CryCommon/RendElement.h index c3dc1c080d..41bcf2bf67 100644 --- a/Code/CryEngine/CryCommon/RendElement.h +++ b/Code/CryEngine/CryCommon/RendElement.h @@ -119,7 +119,7 @@ struct IRenderElement virtual void mfCenter(Vec3& centr, CRenderObject* pObj) = 0; virtual void mfGetBBox(Vec3& vMins, Vec3& vMaxs) = 0; virtual void mfReset() = 0; - virtual void mfGetPlane(Plane& pl) = 0; + virtual void mfGetPlane(Plane_tpl& pl) = 0; virtual void mfExport(struct SShaderSerializeContext& SC) = 0; virtual void mfImport(struct SShaderSerializeContext& SC, uint32& offset) = 0; virtual void mfPrecache(const SShaderItem& SH) = 0; @@ -265,7 +265,7 @@ public: void mfPrecache([[maybe_unused]] const SShaderItem& SH) override {} void mfExport([[maybe_unused]] struct SShaderSerializeContext& SC) override { CryFatalError("mfExport has not been implemented for this render element type"); } void mfImport([[maybe_unused]] struct SShaderSerializeContext& SC, [[maybe_unused]] uint32& offset) override { CryFatalError("mfImport has not been implemented for this render element type"); } - void mfGetPlane(Plane& pl) override; + void mfGetPlane(Plane_tpl& pl) override; void* mfGetPointer([[maybe_unused]] ESrcPointer ePT, [[maybe_unused]] int* Stride, [[maybe_unused]] EParamType Type, [[maybe_unused]] ESrcPointer Dst, [[maybe_unused]] int Flags) override { return nullptr; } uint16 mfGetFlags() override { return m_Flags; } diff --git a/Code/CryEngine/CryFont/CryFont.cpp b/Code/CryEngine/CryFont/CryFont.cpp deleted file mode 100644 index ab39a0fa4d..0000000000 --- a/Code/CryEngine/CryFont/CryFont.cpp +++ /dev/null @@ -1,845 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : CCryFont class. - - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "CryFont.h" -#include "CryPath.h" -#include "FFont.h" -#include "FontTexture.h" -#include "FontRenderer.h" -#include "ILocalizationManager.h" - -#include -#include - -// Static member definitions -const Vec2i CCryFont::defaultGlyphSize = Vec2i(ICryFont::defaultGlyphSizeX, ICryFont::defaultGlyphSizeY); - -#if !defined(_RELEASE) -static void DumpFontTexture(IConsoleCmdArgs* pArgs) -{ - if (pArgs->GetArgCount() != 2) - { - return; - } - - const char* pFontName = pArgs->GetArg(1); - - if (pFontName && *pFontName && *pFontName != '0') - { - string fontFile("@devroot@/"); - fontFile += pFontName; - fontFile += ".bmp"; - - CFFont* pFont = (CFFont*) gEnv->pCryFont->GetFont(pFontName); - if (pFont) - { - pFont->GetFontTexture()->WriteToFile(fontFile.c_str()); - gEnv->pLog->LogWithType(IMiniLog::eInputResponse, "Dumped \"%s\" texture to \"%s\"!", pFontName, fontFile.c_str()); - } - } -} - -static void DumpFontNames([[maybe_unused]] IConsoleCmdArgs* pArgs) -{ - string names = gEnv->pCryFont->GetLoadedFontNames(); - gEnv->pLog->LogWithType(IMiniLog::eInputResponse, "Currently loaded fonts: %s", names.c_str()); -} - -static void ReloadFonts([[maybe_unused]] IConsoleCmdArgs* pArgs) -{ - gEnv->pCryFont->ReloadAllFonts(); -} -#endif - -namespace -{ - //! Stores paths to styled font assets for a given set of languages - //! This struct stores the XML data contained within the tag of - //! an enclosing definition: - //! - //! - //! - //! - //! - //! - //! - //! - //! - struct FontTagXml - { - //! \return True if all font asset paths are non-empty, false otherwise - bool IsValid() const - { - // Note that "lang" can be empty - return !m_fontFilename.empty() - && !m_boldFontFilename.empty() - && !m_italicFontFilename.empty() - && !m_boldItalicFontFilename.empty(); - } - - string m_lang; //!< Stores a comma-separated list of languages this collection of fonts applies to. - //!< If this is an empty string, it implies that these set of fonts will be applied - //!< by default (when a language is being used but no fonts in the font family are - //!< mapped to that language). - - string m_fontFilename; //!< Font used when no styling is applied. - string m_boldFontFilename; //!< Bold-styled font - string m_italicFontFilename; //!< Italic-styled font - string m_boldItalicFontFilename; //!< Bold-italic-styled font - }; - - //! Stores parsed font family XML data. - //! This struct contains the name of the font family and a list of font - //! file XML data for all the language-specific mappings of this - //! font family. - //! - //! Example XML: - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - //! - struct FontFamilyTagXml - { - //! Returns true if all font file fields were parsed, false otherwise. - bool IsValid() const - { - for (const FontTagXml& fontTagXml : m_fontTagsXml) - { - if (!fontTagXml.IsValid()) - { - return false; - } - } - - // Every font family must have a name - return !m_fontFamilyName.empty(); - } - - string m_fontFamilyName; //!< Value of the "name" font-family tag attribute - AZStd::list m_fontTagsXml; //!< List of child tag data. - }; - - //! Returns true if the XML tree was traversed successfully, false otherwise. - //! - //! Note that, if this function returns true, it simply means that there were - //! no unexpected structure issues with the given XML tree, it doesn't - //! necessarily mean that all the required fields were parsed. - bool ParseFontFamilyXml(const XmlNodeRef& node, FontFamilyTagXml& xmlData) - { - if (!node) - { - return false; - } - - // - if (AZStd::string(node->getTag()) == "fontfamily") - { - const int numAttributes = node->getNumAttributes(); - - if (numAttributes <= 0) - { - // Expecting at least one attribute - return false; - } - - string name; - - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - if (string(key) == "name") - { - name = value; - } - else - { - // Unexpected font tag attribute - return false; - } - } - } - - name.Trim(); - if (!name.empty()) - { - xmlData.m_fontFamilyName = name; - } - else - { - // Font family must have a name - return false; - } - } - - // - if (AZStd::string(node->getTag()) == "font") - { - xmlData.m_fontTagsXml.push_back(FontTagXml()); - - string lang; - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - if (string(key) == "lang") - { - lang = value; - } - else - { - // Unexpected font tag attribute - return false; - } - } - } - - lang.Trim(); - if (!lang.empty()) - { - xmlData.m_fontTagsXml.back().m_lang = lang; - } - } - - // - else if (AZStd::string(node->getTag()) == "file") - { - const int numAttributes = node->getNumAttributes(); - - if (numAttributes <= 0) - { - // Expecting at least one attribute - return false; - } - - string path; - string tags; - - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - if (string(key) == "path") - { - path = value; - } - else if (string(key) == "tags") - { - tags = value; - } - else - { - // Unexpected font tag attribute - return false; - } - } - } - - tags.Trim(); - if (tags.empty()) - { - xmlData.m_fontTagsXml.back().m_fontFilename = path; - } - else if (tags == "b") - { - xmlData.m_fontTagsXml.back().m_boldFontFilename = path; - } - else if (tags == "i") - { - xmlData.m_fontTagsXml.back().m_italicFontFilename = path; - } - else - { - // We'll just assume any other tag indicates bold italic - xmlData.m_fontTagsXml.back().m_boldItalicFontFilename = path; - } - } - - for (int i = 0, count = node->getChildCount(); i < count; ++i) - { - XmlNodeRef child = node->getChild(i); - if (!ParseFontFamilyXml(child, xmlData)) - { - return false; - } - } - - return true; - } - - //! Only attempt XML file load if file exists. - //! There are use-cases where the XML path is not fully known (such as - //! when referencing font family names from font family XML files), and - //! attempting to load the XML files directly via ISystem() methods can - //! produce a lot of warning noise. - XmlNodeRef SafeLoadXmlFromFile(const string& xmlPath) - { - if (gEnv->pCryPak->IsFileExist(xmlPath.c_str())) - { - return GetISystem()->LoadXmlFromFile(xmlPath.c_str()); - } - - return XmlNodeRef(); - } - -} - -CCryFont::CCryFont(ISystem* pSystem) - : m_pSystem(pSystem) - , m_fonts() - , m_rndPropIsRGBA(false) - , m_rndPropHalfTexelOffset(0.5f) -{ - assert(m_pSystem); - - CryLogAlways("Using FreeType %d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH); - - // Persist fonts for application lifetime to prevent unnecessary work - REGISTER_CVAR(r_persistFontFamilies, r_persistFontFamilies, VF_NULL, "Persist loaded font families for lifetime of application."); - -#if !defined(_RELEASE) - REGISTER_COMMAND("r_DumpFontTexture", DumpFontTexture, 0, - "Dumps the specified font's texture to a bitmap file\n" - "Use r_DumpFontTexture to get the loaded font names\n" - "Usage: r_DumpFontTexture "); - REGISTER_COMMAND("r_DumpFontNames", DumpFontNames, 0, - "Logs a list of fonts currently loaded"); - REGISTER_COMMAND("r_ReloadFonts", ReloadFonts, VF_NULL, - "Reload all fonts"); -#endif -} - -CCryFont::~CCryFont() -{ - // Persist fonts for application lifetime to prevent unnecessary work - m_persistedFontFamilies.clear(); - - for (FontMapItor it = m_fonts.begin(), itEnd = m_fonts.end(); it != itEnd; ) - { - CFFont* pFont = it->second; - ++it; // iterate as Release() below will remove font from the map - SAFE_RELEASE(pFont); - } -} - -void CCryFont::Release() -{ - delete this; -} - -IFFont* CCryFont::NewFont(const char* pFontName) -{ - string name = pFontName; - name.MakeLower(); - - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(name.c_str())); - if (it != m_fonts.end()) - { - return it->second; - } - - CFFont* pFont = new CFFont(m_pSystem, this, name.c_str()); - m_fonts.insert(FontMapItor::value_type(name, pFont)); - return pFont; -} - -IFFont* CCryFont::GetFont(const char* pFontName) const -{ - FontMapConstItor it = m_fonts.find(CONST_TEMP_STRING(string(pFontName).MakeLower())); - return it != m_fonts.end() ? it->second : 0; -} - -FontFamilyPtr CCryFont::LoadFontFamily(const char* pFontFamilyName) -{ - FontFamilyPtr fontFamily(nullptr); - string fontFamilyPath; - string fontFamilyFullPath; - - XmlNodeRef root = LoadFontFamilyXml(pFontFamilyName, fontFamilyPath, fontFamilyFullPath); - - if (root) - { - FontFamilyTagXml xmlData; - const bool parseSuccess = ParseFontFamilyXml(root, xmlData); - if (parseSuccess && xmlData.IsValid()) - { - const char* currentLanguage = gEnv->pSystem->GetLocalizationManager()->GetLanguage(); - FontTagXml* defaultFont = nullptr; - FontTagXml* langSpecificFont = nullptr; - - // Note that we don't break out of this for-loop early because we - // want to find both the default font family and the - // language-specific font family. We prefer the lang-specific - // family but will fall back on the default if it doesn't exist. - for (FontTagXml& fontTagXml : xmlData.m_fontTagsXml) - { - if (fontTagXml.m_lang.empty()) - { - defaultFont = &fontTagXml; - } - else - { - int searchPos = 0; - string langToken; - - // "lang" font-tag attribute could be comma-separated - while (!(langToken = fontTagXml.m_lang.Tokenize(",", searchPos)).empty()) - { - if (langToken.Trim() == currentLanguage) - { - langSpecificFont = &fontTagXml; - break; - } - } - } - } - - if (langSpecificFont || defaultFont) - { - // Prefer lang-specific font-family over default, if it exists - FontTagXml* fontTagXml = langSpecificFont ? langSpecificFont : defaultFont; - - // Pre-pend font family's path to make font family XML paths - // relative to font family file - fontTagXml->m_fontFilename = fontFamilyPath + fontTagXml->m_fontFilename; - fontTagXml->m_boldFontFilename = fontFamilyPath + fontTagXml->m_boldFontFilename; - fontTagXml->m_italicFontFilename = fontFamilyPath + fontTagXml->m_italicFontFilename; - fontTagXml->m_boldItalicFontFilename = fontFamilyPath + fontTagXml->m_boldItalicFontFilename; - - IFFont* normal = LoadFont(fontTagXml->m_fontFilename.c_str()); - IFFont* bold = LoadFont(fontTagXml->m_boldFontFilename.c_str()); - IFFont* italic = LoadFont(fontTagXml->m_italicFontFilename.c_str()); - IFFont* boldItalic = LoadFont(fontTagXml->m_boldItalicFontFilename.c_str()); - - // Only continue if all fonts were created successfully - if (normal && bold && italic && boldItalic) - { - fontFamily.reset(new FontFamily(), - [this](FontFamily* pFontFamily) - { - ReleaseFontFamily(pFontFamily); - }); - - // Map the font family name both by path and by name defined - // within the Font Family XML itself. This allows font - // families to also be referenced simply by name. - if (!AddFontFamilyToMaps(fontFamilyFullPath, xmlData.m_fontFamilyName, fontFamily)) - { - SAFE_RELEASE(normal); - SAFE_RELEASE(bold); - SAFE_RELEASE(italic); - SAFE_RELEASE(boldItalic); - - return nullptr; - } - - fontFamily->familyName = xmlData.m_fontFamilyName; - fontFamily->normal = normal; - fontFamily->bold = bold; - fontFamily->italic = italic; - fontFamily->boldItalic = boldItalic; - } - else - { - SAFE_RELEASE(normal); - SAFE_RELEASE(bold); - SAFE_RELEASE(italic); - SAFE_RELEASE(boldItalic); - } - } - } - } - - if (!fontFamily) - { - // Unable to load font family XML, so load font normally and associate - // it with a font family - IFFont* pFont = LoadFont(pFontFamilyName); - - if (pFont) - { - // Create a font family from a single font by assigning all the - // font family stylings to the same font - fontFamily.reset(new FontFamily(), - [this](FontFamily* pFontFamily) - { - ReleaseFontFamily(pFontFamily); - }); - - // Use filepath as familyName so font loading/unloading doesn't break with duplicate file names - fontFamily->familyName = pFontFamilyName; - - if (!AddFontFamilyToMaps(pFontFamilyName, fontFamily->familyName, fontFamily)) - { - SAFE_RELEASE(pFont); - - return nullptr; - } - - // Assign all stylings to the same font - fontFamily->normal = pFont; - fontFamily->bold = pFont; - fontFamily->italic = pFont; - fontFamily->boldItalic = pFont; - - // The other three stylings need to have their ref count - // incremented (even though in this particular case its all the - // same font) because when ReleaseFontFamily executes all fonts - // in the family will be (corresondingly) Release'd. - fontFamily->bold->AddRef(); - fontFamily->italic->AddRef(); - fontFamily->boldItalic->AddRef(); - } - } - - // Persist fonts for application lifetime to prevent unnecessary work - if (r_persistFontFamilies > 0) - { - m_persistedFontFamilies.emplace_back(FontFamilyPtr(fontFamily)); - } - - return fontFamily; -} - -FontFamilyPtr CCryFont::GetFontFamily(const char* pFontFamilyName) -{ - FontFamilyPtr fontFamily = nullptr; - - // The given string could either be: a font family name (defined in font - // family XML), a file path (for regular fonts mapped as font families), - // or just the filename of a font itself. Fonts are mapped by font family - // name or by filepath, so attempt lookup using the map first since it's - // the fastest. - string loweredName = string(pFontFamilyName).Trim().MakeLower(); - auto it = m_fontFamilies.find(PathUtil::MakeGamePath(loweredName).c_str()); - if (it != m_fontFamilies.end()) - { - fontFamily = FontFamilyPtr(it->second); - } - else - { - // Iterate through all fonts, returning the first match where simply - // the filename of a font could be a match. This case will likely be - // hit when text markup references a font that doesn't belong to a - // font family. - for (const auto& fontFamilyIter : m_fontFamilies) - { - const AZStd::string& mappedFontFamilyName = fontFamilyIter.first; - string mappedFilenameNoExtension = PathUtil::GetFileName(mappedFontFamilyName.c_str()); - - string searchStringFilenameNoExtension = PathUtil::GetFileName(loweredName); - - if (mappedFilenameNoExtension == searchStringFilenameNoExtension) - { - fontFamily = FontFamilyPtr(fontFamilyIter.second); - break; - } - } - } - - return fontFamily; -} - -void CCryFont::AddCharsToFontTextures(FontFamilyPtr pFontFamily, const char* pChars, int glyphSizeX, int glyphSizeY) -{ - pFontFamily->normal->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); - pFontFamily->bold->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); - pFontFamily->italic->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); - pFontFamily->boldItalic->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY); -} - -void CCryFont::SetRendererProperties(IRenderer* pRenderer) -{ - if (pRenderer) - { - m_rndPropIsRGBA = (pRenderer->GetFeatures() & RFT_RGBA) != 0; - m_rndPropHalfTexelOffset = 0.0f; - } -} - -void CCryFont::GetMemoryUsage(ICrySizer* pSizer) const -{ - if (!pSizer->Add(*this)) - { - return; - } - - pSizer->AddObject(m_fonts); -} - -string CCryFont::GetLoadedFontNames() const -{ - string ret; - for (FontMapConstItor it = m_fonts.begin(), itEnd = m_fonts.end(); it != itEnd; ++it) - { - CFFont* pFont = it->second; - if (pFont) - { - if (!ret.empty()) - { - ret += ","; - } - ret += pFont->GetName(); - } - } - return ret; -} - -void CCryFont::OnLanguageChanged() -{ - ReloadAllFonts(); - - EBUS_EVENT(LanguageChangeNotificationBus, LanguageChanged); -} - -void CCryFont::ReloadAllFonts() -{ - // Persist fonts for application lifetime to prevent unnecessary work - m_persistedFontFamilies.clear(); - - AZStd::list fontFamilyFilenames; - AZStd::list fontFamilyWeakPtrs; - - // Iterate through all currently loaded font families - for (auto it : m_fontFamilyReverseLookup) - { - fontFamilyWeakPtrs.push_back(it.first); - fontFamilyFilenames.push_back(it.second->first); - } - - // Release font-family resources and unmap them - for (auto fontFamily : fontFamilyWeakPtrs) - { - ReleaseFontFamily(fontFamily); - } - - // Reload the font families - for (auto familyFilename : fontFamilyFilenames) - { - LoadFontFamily(familyFilename.c_str()); - } - - // All UI text components need to reload their font assets (both in-game - // and in-editor). - EBUS_EVENT(FontNotificationBus, OnFontsReloaded); -} - -void CCryFont::UnregisterFont(const char* pFontName) -{ - FontMapItor it = m_fonts.find(CONST_TEMP_STRING(pFontName)); - -#if defined(AZ_ENABLE_TRACING) - IFFont* fontPtr = it->second; -#endif - - if (it != m_fonts.end()) - { - m_fonts.erase(it); - } - -#if defined(AZ_ENABLE_TRACING) - // Make sure the font being released isn't currently in use by a font family. - // If it is, the FontFamily will have a dangling pointer and will cause a - // crash when the FontFamily eventually gets released. - for (auto reverseMapEntry : m_fontFamilyReverseLookup) - { - FontFamily* fontFamily = reverseMapEntry.first; - AZ_Assert(fontFamily->normal != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - AZ_Assert(fontFamily->italic != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - AZ_Assert(fontFamily->bold != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - AZ_Assert(fontFamily->boldItalic != fontPtr, - "The following font is being freed but still in use by a FontFamily: %s", - pFontName); - } -#endif -} - -IFFont* CCryFont::LoadFont(const char* pFontName) -{ - string fontName = pFontName; - fontName.MakeLower(); - - IFFont* font = GetFont(fontName); - if (font) - { - font->AddRef(); // use existing loaded font - } - else - { - // attempt to create and load a new font, use the font pathname as the font name - font = NewFont(fontName); - if (!font) - { - string errorMsg = "Error creating a new font named "; - errorMsg += fontName; - errorMsg += "."; - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg.c_str()); - } - else - { - // creating font adds one to its refcount so no need for AddRef here - if (!font->Load(fontName)) - { - string errorMsg = "Error loading a font from "; - errorMsg += fontName; - errorMsg += "."; - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg); - font->Release(); - font = nullptr; - } - } - } - - return font; -} - -void CCryFont::ReleaseFontFamily(FontFamily* pFontFamily) -{ - // Ensure that Font Family was mapped prior to destruction - const bool isMapped = m_fontFamilyReverseLookup.find(pFontFamily) != m_fontFamilyReverseLookup.end(); - if (!isMapped) - { - return; - } - - // Note that the FontFamily is mapped both by filename and by "family name" - auto it = m_fontFamilyReverseLookup[pFontFamily]; - m_fontFamilies.erase(it); - string familyName(pFontFamily->familyName); - m_fontFamilies.erase(familyName.MakeLower().c_str()); - - // Reverse lookup is used to avoid needing to store filename path with - // the font family, so we need to remove that entry also. - m_fontFamilyReverseLookup.erase(pFontFamily); - - SAFE_RELEASE(pFontFamily->normal); - SAFE_RELEASE(pFontFamily->bold); - SAFE_RELEASE(pFontFamily->italic); - SAFE_RELEASE(pFontFamily->boldItalic); -} - -bool CCryFont::AddFontFamilyToMaps(const char* pFontFamilyFilename, const char* pFontFamilyName, FontFamilyPtr fontFamily) -{ - if (!pFontFamilyFilename || !pFontFamilyName || !fontFamily.get()) - { - return false; - } - - // We don't support "updating" mapped values. - AZStd::string loweredFilename(PathUtil::MakeGamePath(string(pFontFamilyFilename)).c_str()); - AZStd::to_lower(loweredFilename.begin(), loweredFilename.end()); - if (m_fontFamilies.find(loweredFilename) != m_fontFamilies.end()) - { - string warnMsg; - warnMsg.Format("Couldn't load Font Family '%s': already loaded", pFontFamilyFilename); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str()); - return false; - } - - // Similarly, we don't support Font Family XMLs that have the same font - // family name (we assume all Font Family names are unique). - AZStd::string loweredFontFamilyName(pFontFamilyName); - AZStd::to_lower(loweredFontFamilyName.begin(), loweredFontFamilyName.end()); - if (m_fontFamilies.find(loweredFontFamilyName) != m_fontFamilies.end()) - { - string warnMsg; - warnMsg.Format("Couldn't load Font Family '%s': already loaded", pFontFamilyName); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str()); - return false; - } - - // First, insert by filename - AZStd::pair> insertPair(loweredFilename, fontFamily); - auto iterPosition = m_fontFamilies.insert(insertPair).first; - m_fontFamilyReverseLookup[fontFamily.get()] = iterPosition; - - // Then, by Font Family name - AZStd::pair> nameInsertPair(loweredFontFamilyName, fontFamily); - m_fontFamilies.insert(nameInsertPair); - - return true; -} - -XmlNodeRef CCryFont::LoadFontFamilyXml(const char* pFontFamilyName, string& outputDirectory, string& outputFullPath) -{ - outputFullPath = pFontFamilyName; - outputDirectory = PathUtil::GetPath(pFontFamilyName); - XmlNodeRef root = SafeLoadXmlFromFile(outputFullPath); - - // When parsing a tag in markup, only the font name is given and - // not a path, so we try to build a "best guess" path from the name. - if (!root) - { - string fileNoExtension(PathUtil::GetFileName(pFontFamilyName)); - string fileExtension(PathUtil::GetExt(pFontFamilyName)); - - if (fileExtension.empty()) - { - fileExtension = ".fontfamily"; - } - - // Try: "fonts/fontName.fontfamily" - outputDirectory = string("fonts/"); - outputFullPath = outputDirectory + fileNoExtension + fileExtension; - root = SafeLoadXmlFromFile(outputFullPath); - - // Finally, try: "fonts/fontName/fontName.fontfamily" - if (!root) - { - outputDirectory = string("fonts/") + fileNoExtension + "/"; - outputFullPath = outputDirectory + fileNoExtension + fileExtension; - root = SafeLoadXmlFromFile(outputFullPath); - } - } - - return root; -} - -#endif - diff --git a/Code/CryEngine/CryFont/CryFont.def b/Code/CryEngine/CryFont/CryFont.def deleted file mode 100644 index 43bfe0b13d..0000000000 --- a/Code/CryEngine/CryFont/CryFont.def +++ /dev/null @@ -1,3 +0,0 @@ -EXPORTS - ModuleInitISystem @2 - CryModuleGetMemoryInfo @8 diff --git a/Code/CryEngine/CryFont/CryFont.h b/Code/CryEngine/CryFont/CryFont.h deleted file mode 100644 index 726818f5a7..0000000000 --- a/Code/CryEngine/CryFont/CryFont.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYFONT_CRYFONT_H -#define CRYINCLUDE_CRYFONT_CRYFONT_H -#pragma once - - -#if !defined(USE_NULLFONT_ALWAYS) - -#include -#include -#include -#include - -class CFFont; - - -class CCryFont - : public ICryFont -{ - friend class CFFont; - -public: - - static const Vec2i defaultGlyphSize; //!< Default glyph size indicates that glyphs in the font texture - //!< should be rendered at the maximum resolution supported by - //!< the font texture's glyph cell/slot configuration (configured - //!< via font XML). - -public: - CCryFont(ISystem* pSystem); - virtual ~CCryFont(); - - virtual void Release(); - virtual IFFont* NewFont(const char* pFontName); - virtual IFFont* GetFont(const char* pFontName) const; - virtual FontFamilyPtr LoadFontFamily(const char* pFontFamilyName) override; - virtual FontFamilyPtr GetFontFamily(const char* pFontFamilyName) override; - virtual void AddCharsToFontTextures(FontFamilyPtr pFontFamily, const char* pChars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override; - virtual void SetRendererProperties(IRenderer* pRenderer); - virtual void GetMemoryUsage(ICrySizer* pSizer) const; - virtual string GetLoadedFontNames() const; - virtual void OnLanguageChanged() override; - virtual void ReloadAllFonts() override; - -public: - void UnregisterFont(const char* pFontName); - bool RndPropIsRGBA() const { return m_rndPropIsRGBA; } - float RndPropHalfTexelOffset() const { return m_rndPropHalfTexelOffset; } - -private: - typedef std::map FontMap; - typedef FontMap::iterator FontMapItor; - typedef FontMap::const_iterator FontMapConstItor; - - typedef AZStd::map> FontFamilyMap; - typedef AZStd::map FontFamilyReverseLookupMap; - -private: - //! Convenience method for loading fonts - IFFont* LoadFont(const char* fontName); - - //! Called when final FontFamily shared_ptr is destroyed; do not call directly. - void ReleaseFontFamily(FontFamily* pFontFamily); - - //! Adds new entries into both font family maps for the given font family - //! - //! Note that it's not possible to update Font Family mappings with this - //! method. The only way to do that would be to release the font family - //! and re-load it with the new values. - //! - //! \return True only if the Font Family was added to the maps, false for all other cases (such as - //! when the font family is already mapped). - bool AddFontFamilyToMaps(const char* pFontFamilyFilename, const char* pFontFamilyName, FontFamilyPtr fontFamily); - - //! Internal method that (possibly) makes several attempts at locating and loading a given font family XML. - //! \param pFontFamilyName The name of the font family, or path to a font family file. - //! \param outputDirectory Path to loaded font family (no filename), may need resolving with PathUtil::MakeGamePath. - //! \param outputFullPath Full path to loaded font family, may need resolving with PathUtil::MakeGamePath. - XmlNodeRef LoadFontFamilyXml(const char* pFontFamilyName, string& outputDirectory, string& outputFullPath); - -private: - FontMap m_fonts; - FontFamilyMap m_fontFamilies; //!< Map font family names to weak ptrs so we can construct shared_ptrs but not keep a ref ourselves. - FontFamilyReverseLookupMap m_fontFamilyReverseLookup; // m_persistedFontFamilies; //!< Stores persisted fonts (if "persist font families" is enabled) - -}; - -#endif - -#endif // CRYINCLUDE_CRYFONT_CRYFONT_H diff --git a/Code/CryEngine/CryFont/CryFont.rc b/Code/CryEngine/CryFont/CryFont.rc deleted file mode 100644 index 5730d0a537..0000000000 --- a/Code/CryEngine/CryFont/CryFont.rc +++ /dev/null @@ -1,111 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Russian resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) -#ifdef _WIN32 -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT -#pragma code_page(1251) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // Russian resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000904b0" - BEGIN - VALUE "CompanyName", "Amazon.com, Inc." - VALUE "FileVersion", "1, 0, 0, 1" - VALUE "LegalCopyright", "Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates." - VALUE "ProductName", "Lumberyard" - VALUE "ProductVersion", "1, 0, 0, 1" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x9, 1200 - END -END - -#endif // German (Germany) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/Code/CryEngine/CryFont/CryFont_precompiled.cpp b/Code/CryEngine/CryFont/CryFont_precompiled.cpp deleted file mode 100644 index 235fe8e053..0000000000 --- a/Code/CryEngine/CryFont/CryFont_precompiled.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CryFont_precompiled.h" diff --git a/Code/CryEngine/CryFont/CryFont_precompiled.h b/Code/CryEngine/CryFont/CryFont_precompiled.h deleted file mode 100644 index e37845aa35..0000000000 --- a/Code/CryEngine/CryFont/CryFont_precompiled.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once - -#include - -#define CRYFONT_EXPORTS - -#include - -#include - -#include -#include -#include -#include - -#define USE_NULLFONT - -#if defined(DEDICATED_SERVER) -#define USE_NULLFONT_ALWAYS 1 -#endif - diff --git a/Code/CryEngine/CryFont/FBitmap.h b/Code/CryEngine/CryFont/FBitmap.h deleted file mode 100644 index 93f5505726..0000000000 --- a/Code/CryEngine/CryFont/FBitmap.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once -#ifndef CRYINCLUDE_CRYFONT_FBITMAP_H -#define CRYINCLUDE_CRYFONT_FBITMAP_H - - -class CFBitmap -{ -public: - CFBitmap(); - ~CFBitmap(); - - int Blur(int iIterations); - int Scale(float fScaleX, float fScaleY); - - int BlitFrom(CFBitmap* pSrc, int iSX, int iSY, int iDX, int iDY, int iW, int iH); - int BlitTo(CFBitmap* pDst, int iDX, int iDY, int iSX, int iSY, int iW, int iH); - - int Create(int iWidth, int iHeight); - int Release(); - - int SaveBitmap(const string& szFileName); - int Get32Bpp(unsigned int** pBuffer) - { - (*pBuffer) = new unsigned int[m_iWidth * m_iHeight]; - - if (!(*pBuffer)) - { - return 0; - } - - int iDataSize = m_iWidth * m_iHeight; - - for (int i = 0; i < iDataSize; i++) - { - (*pBuffer)[i] = (m_pData[i] << 24) | (m_pData[i] << 16) | (m_pData[i] << 8) | (m_pData[i]); - } - - return 1; - } - - int GetWidth() { return m_iWidth; } - int GetHeight() { return m_iHeight; } - - void SetRenderData(void* pRenderData) { m_pIRenderData = pRenderData; }; - void* GetRenderData() { return m_pIRenderData; }; - - void GetMemoryUsage (class ICrySizer* pSizer); - - unsigned char* GetData() { return m_pData; } - -public: - - int m_iWidth; - int m_iHeight; - - unsigned char* m_pData; - void* m_pIRenderData; -}; - - -#endif // CRYINCLUDE_CRYFONT_FBITMAP_H diff --git a/Code/CryEngine/CryFont/FFont.cpp b/Code/CryEngine/CryFont/FFont.cpp deleted file mode 100644 index c028a0827e..0000000000 --- a/Code/CryEngine/CryFont/FFont.cpp +++ /dev/null @@ -1,1550 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Font class. - - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FFont.h" -#include "CryFont.h" -#include "FontTexture.h" -#include "UnicodeIterator.h" - -#include -#include - -static ColorB ColorTable[10] = -{ - ColorB(0x00, 0x00, 0x00), // black - ColorB(0xff, 0xff, 0xff), // white - ColorB(0x00, 0x00, 0xff), // blue - ColorB(0x00, 0xff, 0x00), // green - ColorB(0xff, 0x00, 0x00), // red - ColorB(0x00, 0xff, 0xff), // cyan - ColorB(0xff, 0xff, 0x00), // yellow - ColorB(0xff, 0x00, 0xff), // purple - ColorB(0xff, 0x80, 0x00), // orange - ColorB(0x8f, 0x8f, 0x8f), // grey -}; - -static const int TabCharCount = 4; -static const size_t MsgBufferSize = 1024; -static const size_t MaxDrawVBQuads = 128; - -CFFont::CFFont(ISystem* pSystem, CCryFont* pCryFont, const char* pFontName) - : m_name(pFontName) - , m_curPath("") - , m_pFontTexture(0) - , m_fontBufferSize(0) - , m_pFontBuffer(0) - , m_texID(-1) - , m_textureVersion(0) - , m_pSystem(pSystem) - , m_pCryFont(pCryFont) - , m_fontTexDirty(false) - , m_effects() - , m_pDrawVB(0) - , m_nRefCount(0) - , m_monospacedFont(false) -{ - assert(m_name.c_str()); - assert(m_pSystem); - assert(m_pCryFont); - - // create default effect - SEffect* pEffect = AddEffect("default"); - pEffect->AddPass(); - - m_pDrawVB = new SVF_P3F_C4B_T2F[MaxDrawVBQuads * 6]; - - AddRef(); -} - -CFFont::~CFFont() -{ - // The font should already be unregistered through a call to - // CFFont::Release() at this point. - CRY_ASSERT(m_pCryFont == nullptr); - - Free(); - - SAFE_DELETE_ARRAY(m_pDrawVB); -} - -int32 CFFont::AddRef() -{ - int32 nRef = CryInterlockedIncrement(&m_nRefCount); - return nRef; -} - -int32 CFFont::Release() -{ - if (m_nRefCount > 0) - { - int32 nRef = CryInterlockedDecrement(&m_nRefCount); - if (nRef < 0) - { - CryFatalError("CBaseResource::Release() called more than once!"); - } - - if (nRef <= 0) - { - if (m_pCryFont) - { - AZStd::lock_guard locker(m_fontMutex); - - // Unregister font so no one can increase it's ref count while it is queued for deletion - m_pCryFont->UnregisterFont(m_name); - m_pCryFont = nullptr; - } - - if (gEnv->pRenderer) - { - gEnv->pRenderer->DeleteFont(this); - } - return 0; - } - return nRef; - } - return 0; -} - -// Load a font from a TTF file -bool CFFont::Load(const char* pFontFilePath, unsigned int width, unsigned int height, unsigned int widthNumSlots, unsigned int heightNumSlots, unsigned int flags, float sizeRatio) -{ - if (!pFontFilePath) - { - return false; - } - - Free(); - - auto pPak = gEnv->pCryPak; - - string fullFile; - if (pPak->IsAbsPath(pFontFilePath)) - { - fullFile = pFontFilePath; - } - else - { - fullFile = m_curPath + pFontFilePath; - } - - int iSmoothMethod = (flags & TTFFLAG_SMOOTH_MASK) >> TTFFLAG_SMOOTH_SHIFT; - int iSmoothAmount = (flags & TTFFLAG_SMOOTH_AMOUNT_MASK) >> TTFFLAG_SMOOTH_AMOUNT_SHIFT; - - AZ::IO::HandleType fileHandle = pPak->FOpen(fullFile.c_str(), "rb"); - if (fileHandle == AZ::IO::InvalidHandle) - { - return false; - } - - size_t fileSize = pPak->FGetSize(fileHandle); - if (!fileSize) - { - pPak->FClose(fileHandle); - return false; - } - - unsigned char* pBuffer = new unsigned char[fileSize]; - if (!pPak->FReadRaw(pBuffer, fileSize, 1, fileHandle)) - { - pPak->FClose(fileHandle); - delete [] pBuffer; - return false; - } - - pPak->FClose(fileHandle); - - if (!m_pFontTexture) - { - m_pFontTexture = new CFontTexture(); - } - - if (!m_pFontTexture || !m_pFontTexture->CreateFromMemory(pBuffer, (int)fileSize, width, height, iSmoothMethod, iSmoothAmount, widthNumSlots, heightNumSlots, sizeRatio)) - { - delete [] pBuffer; - return false; - } - - m_monospacedFont = m_pFontTexture->GetMonospaced(); - m_pFontBuffer = pBuffer; - m_fontBufferSize = fileSize; - m_fontTexDirty = false; - m_sizeRatio = sizeRatio; - - InitCache(); - - return true; -} - - -void CFFont::Free() -{ - IRenderer* pRenderer = gEnv->pRenderer; - if (m_texID >= 0 && pRenderer) - { - pRenderer->RemoveTexture(m_texID); - m_texID = -1; - m_textureVersion = 0; - } - - delete m_pFontTexture; - m_pFontTexture = 0; - - delete [] m_pFontBuffer; - m_pFontBuffer = 0; -} - -void CFFont::DrawString(float x, float y, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr, 0) - { - return; - } - - DrawStringUInternal(x, y, 1.0f, pStr, asciiMultiLine, ctx); -} - -void CFFont::DrawString(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr, 0) - { - return; - } - - DrawStringUInternal(x, y, z, pStr, asciiMultiLine, ctx); -} - -void CFFont::DrawStringUInternal(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr || !m_pFontTexture || ctx.m_fxIdx >= m_effects.size() || m_effects[ctx.m_fxIdx].m_passes.empty(), 0) - { - return; - } - - AZStd::lock_guard locker(m_fontMutex); - - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - pRenderer->DrawStringU(this, x, y, z, pStr, asciiMultiLine, ctx); -} - -ILINE uint32 COLCONV(uint32 clr) -{ - return ((clr & 0xff00ff00) | ((clr & 0xff0000) >> 16) | ((clr & 0xff) << 16)); -} - -void CFFont::RenderCallback(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - AZStd::lock_guard locker(m_fontMutex); - - const size_t fxSize = m_effects.size(); - - IF (fxSize && m_texID == -1 && !InitTexture(), 0) - { - return; - } - - // if the font is about to be deleted then m_pCryFont can be nullptr - if (!m_pCryFont) - { - return; - } - - SVF_P3F_C4B_T2F* pVertex = m_pDrawVB; - size_t vbOffset = 0; - - bool isFontRenderStateSet = false; - TransformationMatrices backupSceneMatrices; - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - int baseState = ctx.m_baseState; - bool overrideViewProjMatrices = ctx.m_overrideViewProjMatrices; - int texId = m_texID; - - // Local function to share code needed when we render the vertex buffer so far - AZStd::function RenderVB = [&pVertex, &vbOffset, pRenderer] - { - gEnv->pRenderer->DrawDynVB(pVertex, 0, vbOffset, 0, prtTriangleList); - vbOffset = 0; - }; - - // Local function that is passed into CreateQuadsForText as the AddQuad function - AddFunction AddQuad = [&pVertex, &vbOffset, RenderVB] - (const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, const Vec2& tc0, const Vec2& tc1, const Vec2& tc2, const Vec2& tc3, uint32 packedColor) - { - // define char quad - pVertex[vbOffset].xyz = v0; - pVertex[vbOffset].color.dcolor = packedColor; - pVertex[vbOffset].st = tc0; - - pVertex[vbOffset + 1].xyz = v1; - pVertex[vbOffset + 1].color.dcolor = packedColor; - pVertex[vbOffset + 1].st = tc1; - - pVertex[vbOffset + 2].xyz = v2; - pVertex[vbOffset + 2].color.dcolor = packedColor; - pVertex[vbOffset + 2].st = tc2; - - pVertex[vbOffset + 3].xyz = v2; - pVertex[vbOffset + 3].color.dcolor = packedColor; - pVertex[vbOffset + 3].st = tc2; - - pVertex[vbOffset + 4].xyz = v3; - pVertex[vbOffset + 4].color.dcolor = packedColor; - pVertex[vbOffset + 4].st = tc3; - - pVertex[vbOffset + 5].xyz = v0; - pVertex[vbOffset + 5].color.dcolor = packedColor; - pVertex[vbOffset + 5].st = tc0; - - vbOffset += 6; - - if (vbOffset >= MaxDrawVBQuads * 6) - { - RenderVB(); - } - }; - - // Local function that is passed into CreateQuadsForText as the BeginPass function - BeginPassFunction BeginPass = [&pVertex, &vbOffset, &isFontRenderStateSet, &backupSceneMatrices, texId, pRenderer, baseState, RenderVB, overrideViewProjMatrices] - (const SRenderingPass* pPass) - { - // We don't want to set this state before the call to CreateQuadsForText since that calls Prepare, - // which is needed before FontSetTexture - if (!isFontRenderStateSet) - { - pRenderer->FontSetTexture(texId, FILTER_TRILINEAR); - pRenderer->FontSetRenderingState(overrideViewProjMatrices, backupSceneMatrices); - gEnv->pRenderer->FontSetBlending(pPass->m_blendSrc, pPass->m_blendDest, baseState); - isFontRenderStateSet = true; - } - - if (vbOffset > 0) - { - RenderVB(); - } - - gEnv->pRenderer->FontSetBlending(pPass->m_blendSrc, pPass->m_blendDest, baseState); - }; - - CreateQuadsForText(x, y, z, pStr, asciiMultiLine, ctx, AddQuad, BeginPass); - - if (vbOffset > 0) - { - RenderVB(); - } - - // restore the old states - if (isFontRenderStateSet) - { - pRenderer->FontRestoreRenderingState(overrideViewProjMatrices, backupSceneMatrices); - } -} - -Vec2 CFFont::GetTextSize(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - IF (!pStr, 0) - { - return Vec2(0.0f, 0.0f); - } - - return GetTextSizeUInternal(pStr, asciiMultiLine, ctx); -} - -Vec2 CFFont::GetTextSizeUInternal(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - const size_t fxSize = m_effects.size(); - - IF (!pStr || !m_pFontTexture || !fxSize, 0) - { - return Vec2(0, 0); - } - - AZStd::lock_guard locker(m_fontMutex); - - Prepare(pStr, false, ctx.m_requestSize); - - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - // This is the "logical" size of the font (in pixels). The actual size of - // the glyphs in the font texture may have additional scaling applied or - // could have been re-rendered at a different size. - Vec2 size = ctx.m_size; - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(size.x, size.y); - } - - // This scaling takes into account the logical size of the font relative - // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - - float maxW = 0; - float maxH = 0; - - const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0; - const SEffect& fx = m_effects[fxIdx]; - - for (size_t i = 0, numPasses = fx.m_passes.size(); i < numPasses; ++i) - { - const SRenderingPass* pPass = &fx.m_passes[numPasses - i - 1]; - - // gather pass data - Vec2 offset = pPass->m_posOffset; - - float charX = offset.x; - float charY = offset.y + size.y; - - if (charY > maxH) - { - maxH = charY; - } - - // parse the string, ignoring control characters - uint32_t nextCh = 0; - Unicode::CIterator pChar(pStr); - while (uint32_t ch = *pChar) - { - ++pChar; - nextCh = *pChar; - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - - ++pChar; - } - case '\n': - { - if (charX > maxW) - { - maxW = charX; - } - - charX = offset.x; - charY += size.y; - - if (charY > maxH) - { - maxH = charY; - } - - continue; - } - break; - case '\r': - { - if (charX > maxW) - { - maxW = charX; - } - - charX = offset.x; - continue; - } - break; - case '\t': - { - if (ctx.m_proportional) - { - charX += TabCharCount * size.x * FONT_SPACE_SIZE; - } - else - { - charX += TabCharCount * size.x * ctx.m_widthScale; - } - continue; - } - break; - case '$': - { - if (ctx.m_processSpecialChars) - { - if (*pChar == '$') - { - ++pChar; - } - else if (isdigit(*pChar)) - { - ++pChar; - continue; - } - else if (*pChar == 'O' || *pChar == 'o') - { - ++pChar; - continue; - } - } - } - break; - default: - break; - } - - const bool rerenderGlyphs = m_sizeBehavior == SizeBehavior::Rerender; - const Vec2i requestSize = rerenderGlyphs ? ctx.m_requestSize : CCryFont::defaultGlyphSize; - int horizontalAdvance = m_pFontTexture->GetHorizontalAdvance(ch, requestSize); - float advance; - - if (ctx.m_proportional) - { - advance = horizontalAdvance * scaleInfo.scale.x; - } - else - { - advance = size.x * ctx.m_widthScale; - } - - // Adjust "advance" here for kerning purposes - Vec2 kerningOffset(Vec2_Zero); - if (ctx.m_kerningEnabled && nextCh) - { - kerningOffset = m_pFontTexture->GetKerning(ch, nextCh) * scaleInfo.scale.x; - } - - // Adjust char width with tracking only if there is a next character - if (nextCh) - { - charX += ctx.m_tracking; - } - - charX += advance + kerningOffset.x; - } - - if (charX > maxW) - { - maxW = charX; - } - } - - return Vec2(maxW, maxH); -} - -uint32 CFFont::GetNumQuadsForText(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - uint32 numQuads = 0; - - const size_t fxSize = m_effects.size(); - const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0; - const SEffect& fx = m_effects[fxIdx]; - - for (size_t j = 0, numPasses = fx.m_passes.size(); j < numPasses; ++j) - { - size_t i = numPasses - j - 1; - bool drawFrame = ctx.m_framed && i == numPasses - 1; - - if (drawFrame) - { - ++numQuads; - } - - uint32_t nextCh = 0; - Unicode::CIterator pChar(pStr); - while (uint32_t ch = *pChar) - { - ++pChar; - nextCh = *pChar; - - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - ++pChar; - } - case '\n': - { - continue; - } - break; - case '\r': - { - continue; - } - break; - case '\t': - { - continue; - } - break; - case '$': - { - if (ctx.m_processSpecialChars) - { - if (*pChar == '$') - { - ++pChar; - } - else if (isdigit(*pChar)) - { - ++pChar; - continue; - } - else if (*pChar == 'O' || *pChar == 'o') - { - ++pChar; - continue; - } - } - } - break; - default: - break; - } - - ++numQuads; - } - } - - return numQuads; -} - -uint32 CFFont::WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16* indices, uint32 maxQuads, float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) -{ - AZStd::lock_guard locker(m_fontMutex); - - uint32 numQuadsWritten = 0; - - const size_t fxSize = m_effects.size(); - IF (fxSize && m_texID == -1 && !InitTexture(), 0) - { - return numQuadsWritten; - } - - // if the font is about to be deleted then m_pCryFont can be nullptr - if (!m_pCryFont) - { - return numQuadsWritten; - } - - SVF_P2F_C4B_T2F_F4B* pVertex = verts; - uint16* pIndex = indices; - size_t vbOffset = 0; - size_t ibOffset = 0; - - // Local function that is passed into CreateQuadsForText as the AddQuad function - AddFunction AddQuad = [&pVertex, &pIndex, &vbOffset, &ibOffset, maxQuads, &numQuadsWritten] - (const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, const Vec2& tc0, const Vec2& tc1, const Vec2& tc2, const Vec2& tc3, uint32 packedColor) - { - Vec2 xy0(v0); - Vec2 xy1(v1); - Vec2 xy2(v2); - Vec2 xy3(v3); - - AZ_Assert(vbOffset + 3 < maxQuads * 4, "Vertex buffer overflow"); - AZ_Assert(ibOffset + 5 < maxQuads * 6, "Index buffer overflow"); - - // This should never happen but for safety make sure we never write off end of buffers (should hit asserts above if this is the case) - if (numQuadsWritten < maxQuads) - { - // define char quad - pVertex[vbOffset].xy = xy0; - pVertex[vbOffset].color.dcolor = packedColor; - pVertex[vbOffset].st = tc0; - pVertex[vbOffset].texIndex = 0; - pVertex[vbOffset].texHasColorChannel = 0; - pVertex[vbOffset].texIndex2 = 0; - pVertex[vbOffset].pad = 0; - - pVertex[vbOffset + 1].xy = xy1; - pVertex[vbOffset + 1].color.dcolor = packedColor; - pVertex[vbOffset + 1].st = tc1; - pVertex[vbOffset + 1].texIndex = 0; - pVertex[vbOffset + 1].texHasColorChannel = 0; - pVertex[vbOffset + 1].texIndex2 = 0; - pVertex[vbOffset + 1].pad = 0; - - pVertex[vbOffset + 2].xy = xy2; - pVertex[vbOffset + 2].color.dcolor = packedColor; - pVertex[vbOffset + 2].st = tc2; - pVertex[vbOffset + 2].texIndex = 0; - pVertex[vbOffset + 2].texHasColorChannel = 0; - pVertex[vbOffset + 2].texIndex2 = 0; - pVertex[vbOffset + 2].pad = 0; - - pVertex[vbOffset + 3].xy = xy3; - pVertex[vbOffset + 3].color.dcolor = packedColor; - pVertex[vbOffset + 3].st = tc3; - pVertex[vbOffset + 3].texIndex = 0; - pVertex[vbOffset + 3].texHasColorChannel = 0; - pVertex[vbOffset + 3].texIndex2 = 0; - pVertex[vbOffset + 3].pad = 0; - - pIndex[ibOffset] = vbOffset; - pIndex[ibOffset + 1] = vbOffset + 1; - pIndex[ibOffset + 2] = vbOffset + 2; - pIndex[ibOffset + 3] = vbOffset + 2; - pIndex[ibOffset + 4] = vbOffset + 3; - pIndex[ibOffset + 5] = vbOffset + 0; - - vbOffset += 4; - ibOffset += 6; - - ++numQuadsWritten; - } - }; - - // Local function that is passed into CreateQuadsForText as the BeginPass function - BeginPassFunction BeginPass = [] - (const SRenderingPass* /* pPass */) - { - }; - - - CreateQuadsForText(x, y, z, pStr, asciiMultiLine, ctx, AddQuad, BeginPass); - - return numQuadsWritten; -} - -int CFFont::GetFontTextureId() -{ - if (m_texID == -1 && !InitTexture()) - { - return -1; - } - - return m_texID; -} - -uint32 CFFont::GetFontTextureVersion() -{ - return m_textureVersion; -} - -void CFFont::CreateQuadsForText(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx, - AddFunction AddQuad, BeginPassFunction BeginPass) -{ - const size_t fxSize = m_effects.size(); - - Prepare(pStr, true, ctx.m_requestSize); - - const size_t fxIdx = ctx.m_fxIdx < fxSize ? ctx.m_fxIdx : 0; - const SEffect& fx = m_effects[fxIdx]; - - bool isRGB = m_pCryFont->RndPropIsRGBA(); - - float halfTexelShift = m_pCryFont->RndPropHalfTexelOffset(); - - bool passZeroColorOverridden = ctx.IsColorOverridden(); - - uint32 alphaBlend = passZeroColorOverridden ? ctx.m_colorOverride.a : fx.m_passes[0].m_color.a; - if (alphaBlend > 128) - { - ++alphaBlend; // 0..256 for proper blending - } - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - // This is the "logical" size of the font (in pixels). The actual size of - // the glyphs in the font texture may have additional scaling applied or - // could have been re-rendered at a different size. - Vec2 size = ctx.m_size; - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(size.x, size.y); - } - - // This scaling takes into account the logical size of the font relative - // to any additional scaling applied (such as from "size ratio"). - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - - Vec2 baseXY = Vec2(x, y); // in pixels - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(baseXY.x, baseXY.y); - } - - // Apply overscan border - const int flags = ctx.GetFlags(); - if ((flags & eDrawText_2D) && !(flags & eDrawText_IgnoreOverscan)) - { - Vec2 overscanBorder = Vec2(0.0f, 0.0f); - pRenderer->EF_Query(EFQ_OverscanBorders, overscanBorder); - - const float screenWidth = (float)pRenderer->GetOverlayWidth(); - const float screenHeight = (float)pRenderer->GetOverlayHeight(); - Vec2 overscanBorderOffset = ZERO; - if (!(flags & eDrawText_Center)) - { - overscanBorderOffset.x = (overscanBorder.x * screenWidth); - } - if (!(flags & eDrawText_CenterV)) - { - overscanBorderOffset.y = (overscanBorder.y * screenHeight); - } - if (flags & eDrawText_Right) - { - overscanBorderOffset.x = -overscanBorderOffset.x; - } - if (flags & eDrawText_Bottom) - { - overscanBorderOffset.y = -overscanBorderOffset.y; - } - baseXY += overscanBorderOffset; - } - - // snap for pixel perfect rendering (better quality for text) - if (ctx.m_pixelAligned) - { - baseXY.x = floor(baseXY.x); - baseXY.y = floor(baseXY.y); - - // for smaller fonts (half res or less) it's better to average multiple pixels (we don't miss lines) - if (scaleInfo.scale.x < 0.9f) - { - baseXY.x += 0.5f; // try to average two columns (for exact half res) - } - if (scaleInfo.scale.y < 0.9f) - { - baseXY.y += 0.25f; // hand tweaked value to get a good result with tiny font (640x480 underscore in console) - } - } - - for (size_t j = 0, numPasses = fx.m_passes.size(); j < numPasses; ++j) - { - size_t i = numPasses - j - 1; - - const SRenderingPass* pPass = &fx.m_passes[i]; - - if (!i) - { - alphaBlend = 256; - } - - ColorB passColor = !i && passZeroColorOverridden ? ctx.m_colorOverride : fx.m_passes[i].m_color; - - // gather pass data - Vec2 offset = pPass->m_posOffset; // in pixels - - float charX = baseXY.x + offset.x; // in pixels - float charY = baseXY.y + offset.y; // in pixels - - ColorB color = passColor; - - bool drawFrame = ctx.m_framed && i == numPasses - 1; - - BeginPass(pPass); - - if (drawFrame) - { - ColorB tempColor(255, 255, 255, 255); - uint32 frameColor = tempColor.pack_abgr8888(); - if (!isRGB) - { - frameColor = COLCONV(frameColor); - } - - Vec2 textSize = GetTextSizeUInternal(pStr, asciiMultiLine, ctx); - - float x0 = baseXY.x - 12; - float y0 = baseXY.y - 6; - float x1 = baseXY.x + textSize.x + 12; - float y1 = baseXY.y + textSize.y + 6; - - bool culled = false; - IF (ctx.m_clippingEnabled, 0) - { - float clipX = ctx.m_clipX; - float clipY = ctx.m_clipY; - float clipR = ctx.m_clipX + ctx.m_clipWidth; - float clipB = ctx.m_clipY + ctx.m_clipHeight; - - if ((x0 >= clipR) || (y0 >= clipB) || (x1 < clipX) || (y1 < clipY)) - { - culled = true; - } - - x0 = max(clipX, x0); - y0 = max(clipY, y0); - x1 = min(clipR, x1); - y1 = min(clipB, y1); - - //if (!culled && ((x1 - x0 <= 0.0f) || (y1 - y0 <= 0.0f))) - // culled = true; - } - - IF (!culled, 1) - { - Vec3 v0(x0, y0, z); - Vec3 v2(x1, y1, z); - Vec3 v1(v2.x, v0.y, v0.z); // to avoid float->half conversion - Vec3 v3(v0.x, v2.y, v0.z); // to avoid float->half conversion - - if (ctx.m_drawTextFlags & eDrawText_UseTransform) - { - v0 = ctx.m_transform * v0; - v2 = ctx.m_transform * v2; - v1 = ctx.m_transform * v1; - v3 = ctx.m_transform * v3; - } - - Vec2 gradientUvMin, gradientUvMax; - GetGradientTextureCoord(gradientUvMin.x, gradientUvMin.y, gradientUvMax.x, gradientUvMax.y); - - // define the frame quad - Vec2 uv(gradientUvMin.x, gradientUvMax.y); - AddQuad(v0, v1, v2, v3, uv, uv, uv, uv, frameColor); - } - } - - // parse the string, ignoring control characters - uint32_t nextCh = 0; - Unicode::CIterator pChar(pStr); - while (uint32_t ch = *pChar) - { - ++pChar; - nextCh = *pChar; - - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - ++pChar; - } - case '\n': - { - charX = baseXY.x + offset.x; - charY += size.y; - continue; - } - break; - case '\r': - { - charX = baseXY.x + offset.x; - continue; - } - break; - case '\t': - { - if (ctx.m_proportional) - { - charX += TabCharCount * size.x * FONT_SPACE_SIZE; - } - else - { - charX += TabCharCount * size.x * ctx.m_widthScale; - } - continue; - } - break; - case '$': - { - if (ctx.m_processSpecialChars) - { - if (*pChar == '$') - { - ++pChar; - } - else if (isdigit(*pChar)) - { - if (!i) - { - int colorIndex = (*pChar) - '0'; - ColorB newColor = ColorTable[colorIndex]; - color.r = newColor.r; - color.g = newColor.g; - color.b = newColor.b; - // Leave alpha at original value! - } - ++pChar; - continue; - } - else if (*pChar == 'O' || *pChar == 'o') - { - if (!i) - { - color = passColor; - } - ++pChar; - continue; - } - } - } - break; - default: - break; - } - - // get texture coordinates - float texCoord[4]; - - int charOffsetX, charOffsetY; // in font texels - int charSizeX, charSizeY; // in font texels - const bool rerenderGlyphs = m_sizeBehavior == SizeBehavior::Rerender; - const Vec2i requestSize = rerenderGlyphs ? ctx.m_requestSize : CCryFont::defaultGlyphSize; - m_pFontTexture->GetTextureCoord(m_pFontTexture->GetCharSlot(ch, requestSize), texCoord, charSizeX, charSizeY, charOffsetX, charOffsetY, requestSize); - - int horizontalAdvance = m_pFontTexture->GetHorizontalAdvance(ch, requestSize); - float advance; - - if (ctx.m_proportional) - { - advance = horizontalAdvance * scaleInfo.scale.x; - } - else - { - advance = size.x * ctx.m_widthScale; - } - - Vec2 kerningOffset(Vec2_Zero); - if (ctx.m_kerningEnabled && nextCh) - { - kerningOffset = m_pFontTexture->GetKerning(ch, nextCh) * scaleInfo.scale.x; - } - - float trackingOffset = 0.0f; - if (nextCh) - { - trackingOffset = ctx.m_tracking; - } - - float px = charX + charOffsetX * scaleInfo.scale.x; // in pixels - float py = charY + charOffsetY * scaleInfo.scale.y; // in pixels - float pr = px + charSizeX * scaleInfo.scale.x; - float pb = py + charSizeY * scaleInfo.scale.y; - - // compute clipping - float newX = px; // in pixels - float newY = py; // in pixels - float newR = pr; // in pixels - float newB = pb; // in pixels - - if (ctx.m_clippingEnabled) - { - float clipX = ctx.m_clipX; - float clipY = ctx.m_clipY; - float clipR = ctx.m_clipX + ctx.m_clipWidth; - float clipB = ctx.m_clipY + ctx.m_clipHeight; - - // clip non visible - if ((px >= clipR) || (py >= clipB) || (pr < clipX) || (pb < clipY)) - { - charX += advance + kerningOffset.x + trackingOffset; - continue; - } - // clip partially visible - else - { - float width = horizontalAdvance * scaleInfo.rcpCellWidth; - if ((width <= 0.0f) || (size.y <= 0.0f)) - { - charX += advance + kerningOffset.x + trackingOffset; - continue; - } - - // clip the image to the scissor rect - newX = max(clipX, px); - newY = max(clipY, py); - newR = min(clipR, pr); - newB = min(clipB, pb); - - float rcpWidth = 1.0f / width; - float rcpHeight = 1.0f / size.y; - - float texW = texCoord[2] - texCoord[0]; - float texH = texCoord[3] - texCoord[1]; - - // clip horizontal - texCoord[0] = texCoord[0] + texW * (newX - px) * rcpWidth; - texCoord[2] = texCoord[2] + texW * (newR - pr) * rcpWidth; - - // clip vertical - texCoord[1] = texCoord[1] + texH * (newY - py) * rcpHeight; - texCoord[3] = texCoord[3] + texH * (newB - pb) * rcpHeight; - } - } - - newX += halfTexelShift; - newY += halfTexelShift; - newR += halfTexelShift; - newB += halfTexelShift; - - //int offset = vbLen * 6; - - Vec3 v0(newX, newY, z); - Vec3 v2(newR, newB, z); - Vec3 v1(v2.x, v0.y, v0.z); // to avoid float->half conversion - Vec3 v3(v0.x, v2.y, v0.z); // to avoid float->half conversion - - Vec2 tc0(texCoord[0], texCoord[1]); - Vec2 tc2(texCoord[2], texCoord[3]); - Vec2 tc1(tc2.x, tc0.y); // to avoid float->half conversion - Vec2 tc3(tc0.x, tc2.y); // to avoid float->half conversion - - uint32 packedColor = 0; - { - ColorB tempColor = color; - tempColor.a = ((uint32) tempColor.a * alphaBlend) >> 8; - packedColor = tempColor.pack_abgr8888(); - - if (!isRGB) - { - packedColor = COLCONV(packedColor); - } - } - - if (ctx.m_drawTextFlags & eDrawText_UseTransform) - { - v0 = ctx.m_transform * v0; - v2 = ctx.m_transform * v2; - v1 = ctx.m_transform * v1; - v3 = ctx.m_transform * v3; - } - - AddQuad(v0, v1, v2, v3, tc0, tc1, tc2, tc3, packedColor); - - charX += advance + kerningOffset.x + trackingOffset; - } - } -} - -CFFont::TextScaleInfoInternal CFFont::CalculateScaleInternal(const STextDrawContext& ctx) const -{ - Vec2 size = GetRestoredFontSize(ctx); // in pixel - - IRenderer* pRenderer = gEnv->pRenderer; - AZ_Assert(pRenderer, "gEnv->pRenderer is NULL"); - - if (ctx.m_sizeIn800x600) - { - pRenderer->ScaleCoord(size.x, size.y); - } - - float rcpCellWidth; - Vec2 scale; - - int fontTextureCellWidth = GetFontTexture()->GetCellWidth(); - int fontTextureCellHeight = GetFontTexture()->GetCellHeight(); - - if (ctx.m_proportional) - { - rcpCellWidth = (1.0f / static_cast(fontTextureCellWidth)) * size.x; - scale = Vec2(rcpCellWidth * ctx.m_widthScale, size.y / static_cast(fontTextureCellHeight)); - } - else - { - rcpCellWidth = size.x / 16.0f; - scale = Vec2(rcpCellWidth * ctx.m_widthScale, size.y * ctx.m_widthScale / 16.0f); - } - - return TextScaleInfoInternal(scale, rcpCellWidth); -} - -size_t CFFont::GetTextLength(const char* pStr, const bool asciiMultiLine) const -{ - size_t len = 0; - - // parse the string, ignoring control characters - const char* pChar = pStr; - while (char ch = *pChar++) - { - if ((ch & 0xC0) == 0x80) - { - continue; // Skip UTF-8 continuation bytes, we count only the first byte of a code-point - } - switch (ch) - { - case '\\': - { - if (*pChar != 'n' || !asciiMultiLine) - { - break; - } - ++pChar; - } - case '\n': - case '\r': - case '\t': - { - continue; - } - break; - case '$': - { - if (*pChar == '$') - { - ++pChar; - } - else if (*pChar) - { - ++pChar; - continue; - } - } - break; - default: - break; - } - ++len; - } - - return len; -} - -void CFFont::WrapText(string& result, float maxWidth, const char* pStr, const STextDrawContext& ctx) -{ - result = pStr; - - if (ctx.m_sizeIn800x600) - { - maxWidth = gEnv->pRenderer->ScaleCoordX(maxWidth); - } - - Vec2 strSize = GetTextSizeUInternal(result.c_str(), true, ctx); - - if (strSize.x <= maxWidth) - { - return; - } - - // Assume a given string has multiple lines of text if it's height is - // greater than the height of its font. - const bool multiLine = strSize.y > GetRestoredFontSize(ctx).y; - - int lastSpace = -1; - const char* pLastSpace = NULL; - float lastSpaceWidth = 0.0f; - - float curCharWidth = 0.0f; - float curLineWidth = 0.0f; - float biggestLineWidth = 0.0f; - float widthSum = 0.0f; - - int curChar = 0; - Unicode::CIterator pChar(result.c_str()); - while (uint32_t ch = *pChar) - { - // Dollar sign escape codes. The following scenarios can happen with dollar signs embedded in a string. - // The following character is... - // 1. ... a digit, 'O' or 'o' which indicates a color code. Both characters a skipped in the width calculation. - // 2. ... another dollar sign. Only 1 dollar sign is skipped in the width calculation. - // 3. ... anything else. The dollar sign is processed in the width calculation. - if (ctx.m_processSpecialChars && ch == '$') - { - ++pChar; - char nextChar = *pChar; - - if (isdigit(nextChar) || nextChar == 'O' || nextChar == 'o') - { - ++pChar; - continue; - } - else if (nextChar != '$') - { - --pChar; - } - } - - // get char width and sum it to the line width - // Note: This is not unicode compatible, since char-width depends on surrounding context (ie, combining diacritics etc) - char codepoint[5]; - Unicode::Convert(codepoint, ch); - curCharWidth = GetTextSizeUInternal(codepoint, true, ctx).x; - - // keep track of spaces - // they are good for splitting the string - if (ch == ' ') - { - lastSpace = curChar; - lastSpaceWidth = curLineWidth + curCharWidth; - pLastSpace = pChar.GetPosition(); - assert(*pLastSpace == ' '); - } - - bool prevCharWasNewline = false; - const bool notFirstChar = pChar.GetPosition() != result.c_str(); - if (*pChar && notFirstChar) - { - const char* pPrevCharStr = pChar.GetPosition() - 1; - prevCharWasNewline = pPrevCharStr[0] == '\n'; - } - - // if line exceed allowed width, split it - if (prevCharWasNewline || (curLineWidth + curCharWidth >= maxWidth && (*pChar))) - { - if (prevCharWasNewline) - { - // Reset the current line width to account for newline - curLineWidth = curCharWidth; - widthSum += curLineWidth; - } - else if ((lastSpace > 0) && ((curChar - lastSpace) < 16) && (curChar - lastSpace >= 0)) // 16 is the default threshold - { - *(char*)pLastSpace = '\n'; // This is safe inside UTF-8 because space is single-byte codepoint - - if (lastSpaceWidth > biggestLineWidth) - { - biggestLineWidth = lastSpaceWidth; - } - - curLineWidth = curLineWidth - lastSpaceWidth + curCharWidth; - widthSum += curLineWidth; - } - else - { - const char* pBuf = pChar.GetPosition(); - size_t bytesProcessed = pBuf - result.c_str(); - result.insert(bytesProcessed, '\n'); // Insert the newline, this invalidates the iterator - pBuf = result.c_str() + bytesProcessed; // In case reallocation occurs, we ensure we are inside the new buffer - assert(*pBuf == '\n'); - pChar.SetPosition(pBuf); // pChar once again points inside the target string, at the current character - assert(*pChar == ch); - ++pChar; - ++curChar; - - if (curLineWidth > biggestLineWidth) - { - biggestLineWidth = curLineWidth; - } - - widthSum += curLineWidth; - curLineWidth = curCharWidth; - } - - // if we don't need any more line breaks, then just stop, but for - // multiple lines we can't assume that there aren't any more - // strings to wrap, so continue - if (strSize.x - widthSum <= maxWidth && !multiLine) - { - break; - } - - lastSpaceWidth = 0; - lastSpace = 0; - } - else - { - curLineWidth += curCharWidth; - } - - ++curChar; - ++pChar; - } -} - -void CFFont::GetMemoryUsage (ICrySizer* pSizer) const -{ - pSizer->AddObject(m_name); - pSizer->AddObject(m_curPath); - pSizer->AddObject(m_pFontTexture); - pSizer->AddObject(m_pFontBuffer, m_fontBufferSize); - pSizer->AddObject(m_effects); - pSizer->AddObject(m_pDrawVB, sizeof(SVF_P3F_C4B_T2F) * MaxDrawVBQuads * 6); -} - -void CFFont::GetGradientTextureCoord(float& minU, float& minV, float& maxU, float& maxV) const -{ - const CTextureSlot* pSlot = m_pFontTexture->GetGradientSlot(); - assert(pSlot); - - float invWidth = 1.0f / (float) m_pFontTexture->GetWidth(); - float invHeight = 1.0f / (float) m_pFontTexture->GetHeight(); - - // deflate by one pixel to avoid bilinear filtering on the borders - minU = pSlot->vTexCoord[0] + invWidth; - minV = pSlot->vTexCoord[1] + invHeight; - maxU = pSlot->vTexCoord[0] + (pSlot->iCharWidth - 1) * invWidth; - maxV = pSlot->vTexCoord[1] + (pSlot->iCharHeight - 1) * invHeight; -} - -unsigned int CFFont::GetEffectId(const char* pEffectName) const -{ - if (pEffectName) - { - for (size_t i = 0, numEffects = m_effects.size(); i < numEffects; ++i) - { - if (!strcmp(m_effects[i].m_name.c_str(), pEffectName)) - { - return i; - } - } - } - - return 0; -} - -unsigned int CFFont::GetNumEffects() const -{ - return m_effects.size(); -} - -const char* CFFont::GetEffectName(unsigned int effectId) const -{ - return (effectId < m_effects.size()) ? m_effects[effectId].m_name.c_str() : nullptr; -} - -Vec2 CFFont::GetMaxEffectOffset(unsigned int effectId) const -{ - Vec2 maxOffset(0.0f, 0.0f); - - if (effectId < m_effects.size()) - { - const SEffect& fx = m_effects[effectId]; - - for (size_t i = 0, numPasses = fx.m_passes.size(); i < numPasses; ++i) - { - const SRenderingPass* pPass = &fx.m_passes[numPasses - i - 1]; - - // gather pass data - Vec2 offset = pPass->m_posOffset; - - if (maxOffset.x < offset.x) - { - maxOffset.x = offset.x; - } - - if (maxOffset.y < offset.y) - { - maxOffset.y = offset.y; - } - } - } - - return maxOffset; -} - -bool CFFont::DoesEffectHaveTransparency(unsigned int effectId) const -{ - const size_t fxSize = m_effects.size(); - const size_t fxIdx = effectId < fxSize ? effectId : 0; - const SEffect& fx = m_effects[fxIdx]; - - for (auto& pass : fx.m_passes) - { - // if the alpha is not 255 then there is transparency - if (pass.m_color.a != 255) - { - return true; - } - } - - return false; -} - -void CFFont::AddCharsToFontTexture(const char* pChars, int glyphSizeX, int glyphSizeY) -{ - AZStd::lock_guard locker(m_fontMutex); - Vec2i glyphSize(glyphSizeX, glyphSizeY); - Prepare(pChars, false, glyphSize); -} - -Vec2 CFFont::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const STextDrawContext& ctx) const -{ - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - return m_pFontTexture->GetKerning(leftGlyph, rightGlyph) * scaleInfo.scale.x; -} - -float CFFont::GetAscender(const STextDrawContext& ctx) const -{ - return (ctx.m_size.y * m_pFontTexture->GetAscenderToHeightRatio()); -} - -float CFFont::GetBaseline(const STextDrawContext& ctx) const -{ - const TextScaleInfoInternal scaleInfo(CalculateScaleInternal(ctx)); - // Calculate baseline the same way as the font renderer which uses the glyph height * size ratio. - // Adding 1 because FontTexture always adds 1 to the char height in GetTextureCoord - return (round(m_pFontTexture->GetCellHeight() * GetSizeRatio()) + 1.0f) * scaleInfo.scale.y; -} - -bool CFFont::InitTexture() -{ - m_texID = gEnv->pRenderer->FontCreateTexture(m_pFontTexture->GetWidth(), m_pFontTexture->GetHeight(), (uint8*)m_pFontTexture->GetBuffer(), eTF_A8, IRenderer::FontCreateTextureGenMipsDefaultValue, m_name.c_str()); - m_textureVersion = 0; - return m_texID >= 0; -} - -bool CFFont::InitCache() -{ - m_pFontTexture->CreateGradientSlot(); - - // precache (not required but for faster printout later) - const char first = ' '; - const char last = '~'; - char buf[last - first + 2]; - char* p = buf; - - // precache all [normal] printable characters to the string (missing ones are updated on demand) - for (int i = first; i <= last; ++i) - { - *p++ = i; - } - *p = 0; - - Prepare(buf, false); - - return true; -} - -CFFont::SEffect* CFFont::AddEffect(const char* pEffectName) -{ - m_effects.push_back(SEffect(pEffectName)); - return &m_effects[m_effects.size() - 1]; -} - -CFFont::SEffect* CFFont::GetDefaultEffect() -{ - return &m_effects[0]; -} - -void CFFont::Prepare(const char* pStr, bool updateTexture, const Vec2i& glyphSize) -{ - const bool rerenderGlyphs = m_sizeBehavior == SizeBehavior::Rerender; - const Vec2i usedGlyphSize = rerenderGlyphs ? glyphSize : CCryFont::defaultGlyphSize; - bool texUpdateNeeded = m_pFontTexture->PreCacheString(pStr, nullptr, m_sizeRatio, usedGlyphSize, m_fontHintParams) == 1 || m_fontTexDirty; - if (updateTexture && texUpdateNeeded && m_texID >= 0) - { - gEnv->pRenderer->FontUpdateTexture(m_texID, 0, 0, m_pFontTexture->GetWidth(), m_pFontTexture->GetHeight(), (unsigned char*)m_pFontTexture->GetBuffer()); - m_fontTexDirty = false; - ++m_textureVersion; - - // Let any listeners know that the font texture has changed - EBUS_EVENT(FontNotificationBus, OnFontTextureUpdated, this); - } - else - { - m_fontTexDirty = texUpdateNeeded; - } -} - -Vec2 CFFont::GetRestoredFontSize(const STextDrawContext& ctx) const -{ - // Calculate the scale that we need to apply to the text size to ensure - // it's on-screen size is the same regardless of the slot scaling needed - // to fit the glyphs of the font within the font texture slots. - float restoringScale = IFFontConstants::defaultSizeRatio / m_sizeRatio; - return Vec2(ctx.m_size.x * restoringScale, ctx.m_size.y * restoringScale); -} - -#endif - diff --git a/Code/CryEngine/CryFont/FFont.h b/Code/CryEngine/CryFont/FFont.h deleted file mode 100644 index c2eddd7b1d..0000000000 --- a/Code/CryEngine/CryFont/FFont.h +++ /dev/null @@ -1,234 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Font class. - - -#ifndef CRYINCLUDE_CRYFONT_FFONT_H -#define CRYINCLUDE_CRYFONT_FFONT_H -#pragma once - - -#if !defined(USE_NULLFONT_ALWAYS) - -#include -#include -#include -#include -#include "CryFont.h" - -#include - -struct ISystem; -class CFontTexture; - - -class CFFont - : public IFFont - , public IFFont_RenderProxy -{ -public: - //! Determines how characters of different sizes should be handled during render. - enum class SizeBehavior - { - Scale, //!< Default behavior; glyphs rendered at different sizes are rendered on scaled geometry - Rerender //!< Similar to Scale, but the glyph in the font texture is re-rendered to match the target - //!< size, as long as the size isn't greater than the maximum glyph/slot resolution as - //!< configured for the font texture in the font XML. - }; - - //! The hinting visual algorithm to be used (when hinting is enabled) - enum class HintStyle - { - Normal, //!< Default hinting behavior provided by font renderer - Light //!< Produces fuzzier glyphs but more accurately tracks glyph shape - }; - - //! Chooses whether hinting info should be obtained from the font, turned off entirely, or automatically generated - enum class HintBehavior - { - Default, //!< Obtain hinting data from font itself - AutoHint, //!< Procedurally derive hinting information from glyph - NoHinting, //!< Disable hinting entirely - }; - - //! Simple struct used to communicate font hinting parameters to font renderer. - struct FontHintParams - { - FontHintParams() : hintStyle(HintStyle::Normal), hintBehavior(HintBehavior::Default) { } - - HintStyle hintStyle; - HintBehavior hintBehavior; - }; - - struct SRenderingPass - { - ColorB m_color; - Vec2 m_posOffset; - int m_blendSrc; - int m_blendDest; - - SRenderingPass() - : m_color(255, 255, 255, 255) - , m_posOffset(0, 0) - , m_blendSrc(GS_BLSRC_SRCALPHA) - , m_blendDest(GS_BLDST_ONEMINUSSRCALPHA) - { - } - - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - }; - - struct SEffect - { - string m_name; - std::vector m_passes; - - SEffect(const char* name) - : m_name(name) - { - assert(name); - } - - SRenderingPass* AddPass() - { - m_passes.push_back(SRenderingPass()); - return &m_passes[m_passes.size() - 1]; - } - - void ClearPasses() - { - m_passes.resize(0); - } - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_name); - pSizer->AddObject(m_passes); - } - }; - - typedef std::vector Effects; - typedef Effects::iterator EffectsIt; - -public: - virtual int32 AddRef() override; - virtual int32 Release() override; - virtual bool Load(const char* pFontFilePath, unsigned int width, unsigned int height, unsigned int widthNumSlots, unsigned int heightNumSlots, unsigned int flags, float sizeRatio); - virtual bool Load(const char* pXMLFile); - virtual void Free(); - virtual void DrawString(float x, float y, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual void DrawString(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual Vec2 GetTextSize(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual size_t GetTextLength(const char* pStr, const bool asciiMultiLine) const; - virtual void WrapText(string& result, float maxWidth, const char* pStr, const STextDrawContext& ctx); - virtual void GetMemoryUsage(ICrySizer* pSizer) const; - virtual void GetGradientTextureCoord(float& minU, float& minV, float& maxU, float& maxV) const; - virtual unsigned int GetEffectId(const char* pEffectName) const; - virtual unsigned int GetNumEffects() const; - virtual const char* GetEffectName(unsigned int effectId) const; - virtual Vec2 GetMaxEffectOffset(unsigned int effectId) const; - virtual bool DoesEffectHaveTransparency(unsigned int effectId) const; - virtual void AddCharsToFontTexture(const char* pChars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override; - virtual Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const STextDrawContext& ctx) const override; - virtual float GetAscender(const STextDrawContext& ctx) const override; - virtual float GetBaseline(const STextDrawContext& ctx) const override; - - virtual uint32 GetNumQuadsForText(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual uint32 WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16* indices, uint32 maxQuads, float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - virtual int GetFontTextureId(); - virtual uint32 GetFontTextureVersion(); - - virtual float GetSizeRatio() const override { return m_sizeRatio; } - -public: - virtual void RenderCallback(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - -public: - CFFont(ISystem* pSystem, CCryFont* pCryFont, const char* pFontName); - - bool InitTexture(); - bool InitCache(); - - CFontTexture* GetFontTexture() const { return m_pFontTexture; } - const string& GetName() const { return m_name; } - - SEffect* AddEffect(const char* pEffectName); - SEffect* GetDefaultEffect(); - -private: - virtual ~CFFont(); - - void Prepare(const char* pStr, bool updateTexture, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - void DrawStringUInternal(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - Vec2 GetTextSizeUInternal(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx); - - using AddFunction = AZStd::function; - using BeginPassFunction = AZStd::function; - - //! This function is used by both RenderCallback and WriteTextQuadsToBuffers - //! To do this is takes two function pointers that implement the appropriate AddQuad and BeginPass behavior - void CreateQuadsForText(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx, - AddFunction AddQuad, BeginPassFunction BeginPass); - - struct TextScaleInfoInternal - { - TextScaleInfoInternal(const Vec2& _scale, float _rcpCellWidth) - : scale(_scale), rcpCellWidth(_rcpCellWidth) { } - - Vec2 scale; - float rcpCellWidth; - }; - - TextScaleInfoInternal CalculateScaleInternal(const STextDrawContext& ctx) const; - - Vec2 GetRestoredFontSize(const STextDrawContext& ctx) const; - -private: - string m_name; - string m_curPath; - - CFontTexture* m_pFontTexture; - - size_t m_fontBufferSize; - unsigned char* m_pFontBuffer; - - int m_texID; - uint32 m_textureVersion; - - ISystem* m_pSystem; - - AZStd::recursive_mutex m_fontMutex; //!< Controls access between main and render threads. It's common for one thread - //!< to add un-cached glyphs to the font texture while another is accessing the - //!< font texture. - - CCryFont* m_pCryFont; - - bool m_fontTexDirty; - - Effects m_effects; - - SVF_P3F_C4B_T2F* m_pDrawVB; - - volatile int32 m_nRefCount; - - bool m_monospacedFont; //!< True if this font is fixed/monospaced, false otherwise (obtained from FreeType) - - float m_sizeRatio = IFFontConstants::defaultSizeRatio; - SizeBehavior m_sizeBehavior = SizeBehavior::Scale; //!< Changes how glyphs rendered at different sizes are rendered. - FontHintParams m_fontHintParams; //!< How the font should be hinted when its loaded and rendered to the font texture -}; - -#endif - -#endif // CRYINCLUDE_CRYFONT_FFONT_H diff --git a/Code/CryEngine/CryFont/FFontXML.cpp b/Code/CryEngine/CryFont/FFontXML.cpp deleted file mode 100644 index 1fdd84994e..0000000000 --- a/Code/CryEngine/CryFont/FFontXML.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : XML parsing to load a font. - - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FFont.h" -#include "FontTexture.h" -#include -#include - -#if defined(WIN32) || defined(WIN64) -# include -# include -#endif - -////////////////////////////////////////////////////////////////////////// -// Xml parser implementation - -enum -{ - - ELEMENT_UNKNOWN = 0, - ELEMENT_FONT = 1, - ELEMENT_EFFECT = 2, - ELEMENT_EFFECTFILE = 3, - ELEMENT_PASS = 4, - ELEMENT_PASS_COLOR = 5, - ELEMENT_PASS_POSOFFSET = 12, - ELEMENT_PASS_BLEND = 14 -}; - -static inline int GetBlendModeFromString(const string& str, bool dst) -{ - int blend = GS_BLSRC_ONE; - - if (str == "zero") - { - blend = dst ? GS_BLDST_ZERO : GS_BLSRC_ZERO; - } - else if (str == "one") - { - blend = dst ? GS_BLDST_ONE : GS_BLSRC_ONE; - } - else if (str == "srcalpha" || - str == "src_alpha") - { - blend = dst ? GS_BLDST_SRCALPHA : GS_BLSRC_SRCALPHA; - } - else if (str == "invsrcalpha" || - str == "inv_src_alpha") - { - blend = dst ? GS_BLDST_ONEMINUSSRCALPHA : GS_BLSRC_ONEMINUSSRCALPHA; - } - else if (str == "dstalpha" || - str == "dst_alpha") - { - blend = dst ? GS_BLDST_DSTALPHA : GS_BLSRC_DSTALPHA; - } - else if (str == "invdstalpha" || - str == "inv_dst_alpha") - { - blend = dst ? GS_BLDST_ONEMINUSDSTALPHA : GS_BLSRC_ONEMINUSDSTALPHA; - } - else if (str == "dstcolor" || - str == "dst_color") - { - blend = GS_BLSRC_DSTCOL; - } - else if (str == "srccolor" || - str == "src_color") - { - blend = GS_BLDST_SRCCOL; - } - else if (str == "invdstcolor" || - str == "inv_dst_color") - { - blend = GS_BLSRC_ONEMINUSDSTCOL; - } - else if (str == "invsrccolor" || - str == "inv_src_color") - { - blend = GS_BLDST_ONEMINUSSRCCOL; - } - - return blend; -} - -class CXmlFontShader -{ -public: - CXmlFontShader(CFFont* pFont) - { - m_pFont = pFont; - m_nElement = ELEMENT_UNKNOWN; - m_pEffect = NULL; - m_pPass = NULL; - m_FontTexSize.set(0, 0); - - static const int defaultSlotWidthSize = 16; - static const int defaultSlotHeightSize = 8; - m_SlotSizes.set(defaultSlotWidthSize, defaultSlotHeightSize); - - m_FontSmoothAmount = 0; - m_FontSmoothMethod = FONT_SMOOTH_NONE; - } - - ~CXmlFontShader() - { - } - - void ScanXmlNodesRecursively(XmlNodeRef node) - { - if (!node) - { - return; - } - - FoundElement(node->getTag()); - - for (int i = 0, count = node->getNumAttributes(); i < count; ++i) - { - const char* key = ""; - const char* value = ""; - if (node->getAttributeByIndex(i, &key, &value)) - { - FoundAttribute(key, value); - } - } - - for (int i = 0, count = node->getChildCount(); i < count; ++i) - { - XmlNodeRef child = node->getChild(i); - ScanXmlNodesRecursively(child); - } - } - -private: - // notify methods - void FoundElement(const string& name) - { - //MessageBox(NULL, string("[" + name + "]").c_str(), "FoundElement", MB_OK); - // process the previous element - switch (m_nElement) - { - case ELEMENT_FONT: - { - if (!m_FontTexSize.x || !m_FontTexSize.y) - { - m_FontTexSize.set(512, 512); - } - - bool fontLoaded = m_pFont->Load(m_strFontPath.c_str(), m_FontTexSize.x, m_FontTexSize.y, m_SlotSizes.x, m_SlotSizes.y, TTFFLAG_CREATE(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio); -#if defined(WIN32) || defined(WIN64) - if (!fontLoaded) - { - TCHAR sysFontPath[MAX_PATH]; - if (SUCCEEDED(SHGetFolderPath(0, CSIDL_FONTS, 0, SHGFP_TYPE_DEFAULT, sysFontPath))) - { - const char* pFontPath = m_strFontPath.c_str(); - const char* pFontName = CryStringUtils::FindFileNameInPath(pFontPath); - - string newFontPath(sysFontPath); - newFontPath += "/"; - newFontPath += pFontName; - m_pFont->Load(newFontPath, m_FontTexSize.x, m_FontTexSize.y, m_SlotSizes.x, m_SlotSizes.y, TTFFLAG_CREATE(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio); - } - } -#endif - } - break; - - default: - break; - } - - // Translate the m_nElement name to a define - if (name == "font") - { - m_nElement = ELEMENT_FONT; - } - else if (name == "effect") - { - m_nElement = ELEMENT_EFFECT; - } - else if (name == "effectfile") - { - m_nElement = ELEMENT_EFFECTFILE; - } - else if (name == "pass") - { - m_pPass = NULL; - m_nElement = ELEMENT_PASS; - if (m_pEffect) - { - m_pPass = m_pEffect->AddPass(); - } - } - else if (name == "color") - { - m_nElement = ELEMENT_PASS_COLOR; - } - else if (name == "pos" || - name == "offset") - { - m_nElement = ELEMENT_PASS_POSOFFSET; - } - else if (name == "blend" || - name == "blending") - { - m_nElement = ELEMENT_PASS_BLEND; - } - else - { - m_nElement = ELEMENT_UNKNOWN; - } - } - - void FoundAttribute(const string& name, const string& value) - { - //MessageBox(NULL, string(name + "\n" + value).c_str(), "FoundAttribute", MB_OK); - switch (m_nElement) - { - case ELEMENT_FONT: - if (name == "path") - { - m_strFontPath = value; - } - else if (name == "w") - { - m_FontTexSize.x = (long)atof(value.c_str()); - } - else if (name == "h") - { - m_FontTexSize.y = (long)atof(value.c_str()); - } - else if (name == "widthslots") - { - m_SlotSizes.x = (int)atoi(value.c_str()); - } - else if (name == "heightslots") - { - m_SlotSizes.y = (int)atoi(value.c_str()); - } - else if (name == "sizeratio") - { - m_SizeRatio = static_cast(atof(value.c_str())); - } - else if (name == "smooth") - { - if (value == "blur") - { - m_FontSmoothMethod = FONT_SMOOTH_BLUR; - } - else if (value == "supersample") - { - m_FontSmoothMethod = FONT_SMOOTH_SUPERSAMPLE; - } - else if (value == "none") - { - m_FontSmoothMethod = FONT_SMOOTH_NONE; - } - } - else if (name == "smooth_amount") - { - m_FontSmoothAmount = (long)atof(value.c_str()); - } - break; - - case ELEMENT_EFFECT: - if (name == "name") - { - if (value == "default") - { - m_pEffect = m_pFont->GetDefaultEffect(); - m_pEffect->ClearPasses(); - } - else - { - m_pEffect = m_pFont->AddEffect(value.c_str()); - } - } - break; - - case ELEMENT_EFFECTFILE: - if (name == "path") - { - m_strFontEffectPath = value; - } - break; - - case ELEMENT_PASS_COLOR: - if (!m_pPass) - { - break; - } - if (name == "r") - { - m_pPass->m_color.r = (uint8)((float)atof(value.c_str()) * 255.0f); - } - else if (name == "g") - { - m_pPass->m_color.g = (uint8)((float)atof(value.c_str()) * 255.0f); - } - else if (name == "b") - { - m_pPass->m_color.b = (uint8)((float)atof(value.c_str()) * 255.0f); - } - else if (name == "a") - { - m_pPass->m_color.a = (uint8)((float)atof(value.c_str()) * 255.0f); - } - break; - - case ELEMENT_PASS_POSOFFSET: - if (!m_pPass) - { - break; - } - if (name == "x") - { - m_pPass->m_posOffset.x = (float)atoi(value.c_str()); - } - else if (name == "y") - { - m_pPass->m_posOffset.y = (float)atoi(value.c_str()); - } - break; - - case ELEMENT_PASS_BLEND: - if (!m_pPass) - { - break; - } - if (name == "src") - { - m_pPass->m_blendSrc = GetBlendModeFromString(value, false); - } - else if (name == "dst") - { - m_pPass->m_blendDest = GetBlendModeFromString(value, true); - } - else if (name == "type") - { - if (value == "modulate") - { - m_pPass->m_blendSrc = GS_BLSRC_SRCALPHA; - m_pPass->m_blendDest = GS_BLDST_ONEMINUSSRCALPHA; - } - else if (value == "additive") - { - m_pPass->m_blendSrc = GS_BLSRC_SRCALPHA; - m_pPass->m_blendDest = GS_BLDST_ONE; - } - } - break; - - default: - case ELEMENT_UNKNOWN: - break; - } - } - -public: - CFFont* m_pFont; - - unsigned long m_nElement; - - CFFont::SEffect* m_pEffect; - CFFont::SRenderingPass* m_pPass; - - string m_strFontPath; - string m_strFontEffectPath; - vector2l m_FontTexSize; - Vec2i m_SlotSizes; - float m_SizeRatio = IFFontConstants::defaultSizeRatio; - - int m_FontSmoothMethod; - int m_FontSmoothAmount; -}; - -////////////////////////////////////////////////////////////////////////// -// Main loading function -bool CFFont::Load(const char* pXMLFile) -{ - m_curPath = ""; - if (pXMLFile) - { - m_curPath = PathUtil::GetPath(pXMLFile); - } - - XmlNodeRef root = GetISystem()->LoadXmlFromFile(pXMLFile); - if (!root) - { - return false; - } - - CXmlFontShader xmlfs(this); - xmlfs.ScanXmlNodesRecursively(root); - - // if this was not a valid font XML file then return false - if (!m_pFontTexture || !m_pFontBuffer) - { - return false; - } - - // if there was a font effect file then parse that for effects - if (!xmlfs.m_strFontEffectPath.empty()) - { - XmlNodeRef fontEffectRoot = GetISystem()->LoadXmlFromFile(xmlfs.m_strFontEffectPath.c_str()); - if (!fontEffectRoot) - { - AZ_Warning("Font", false, "Error parsing font file %s, 'effectfile' pathname %s could not be found.", - pXMLFile, xmlfs.m_strFontEffectPath.c_str()); - return false; - } - - if (m_effects.size() > 1 || (m_effects.size() == 1 && (m_effects[0].m_name != "default" || m_effects[0].m_passes.size() > 1))) - { - AZ_Warning("Font", false, "Error parsing font file %s, 'effectfile' and 'effect' cannot both be used in the same font file.", - pXMLFile); - m_effects.clear(); - } - - // parse the font effects file, adding to this font object - CXmlFontShader xmlfsEffect(this); - xmlfsEffect.ScanXmlNodesRecursively(fontEffectRoot); - } - - return true; -} - -#endif - diff --git a/Code/CryEngine/CryFont/FontRenderer.cpp b/Code/CryEngine/CryFont/FontRenderer.cpp deleted file mode 100644 index 2cf160896b..0000000000 --- a/Code/CryEngine/CryFont/FontRenderer.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// -// Purpose: -// - Render a glyph outline into a bitmap using FreeType 2 - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FontRenderer.h" - -#include -#include -#include - -#include - -// Sizes are defined in in 26.6 fixed float format (TT_F26Dot6), where -// 1 unit is 1/64 of a pixel. -static const int fractionalPixelUnits = 64; - -namespace -{ - FT_Int32 GetLoadFlags(CFFont::HintBehavior hintBehavior) - { - switch (hintBehavior) - { - case CFFont::HintBehavior::NoHinting: - { - return FT_LOAD_NO_HINTING; - break; - } - case CFFont::HintBehavior::AutoHint: - { - return FT_LOAD_FORCE_AUTOHINT; - break; - } - } - return FT_LOAD_DEFAULT; - } - - FT_Int32 GetLoadTarget(CFFont::HintStyle hintStyle) - { - if (hintStyle == CFFont::HintStyle::Light) - { - return FT_LOAD_TARGET_LIGHT; - } - - return FT_LOAD_TARGET_NORMAL; - } - - FT_Render_Mode GetRenderMode(CFFont::HintStyle hintStyle) - { - // We use the hint style to drive the render mode also. These should - // usually be correlated with each other for best results, even though - // they could technically be different. - if (hintStyle == CFFont::HintStyle::Light) - { - return FT_RENDER_MODE_LIGHT; - } - - return FT_RENDER_MODE_NORMAL; - } -} - -//------------------------------------------------------------------------------------------------- -CFontRenderer::CFontRenderer() - : m_pLibrary(0) - , m_pFace(0) - , m_pGlyph(0) - , m_fSizeRatio(IFFontConstants::defaultSizeRatio) - , m_pEncoding(FONT_ENCODING_UNICODE) - , m_iGlyphBitmapWidth(0) - , m_iGlyphBitmapHeight(0) -{ -} - -//------------------------------------------------------------------------------------------------- -CFontRenderer::~CFontRenderer() -{ - FT_Done_Face(m_pFace); - ; - FT_Done_FreeType(m_pLibrary); - m_pFace = NULL; - m_pLibrary = NULL; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::LoadFromFile(const string& szFileName) -{ - int iError = FT_Init_FreeType(&m_pLibrary); - - if (iError) - { - return 0; - } - - if (m_pFace) - { - FT_Done_Face(m_pFace); - m_pFace = 0; - } - - iError = FT_New_Face(m_pLibrary, szFileName.c_str(), 0, &m_pFace); - - if (iError) - { - return 0; - } - - SetEncoding(FONT_ENCODING_UNICODE); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::LoadFromMemory(unsigned char* pBuffer, int iBufferSize) -{ - int iError = FT_Init_FreeType(&m_pLibrary); - - if (iError) - { - return 0; - } - - if (m_pFace) - { - FT_Done_Face(m_pFace); - m_pFace = 0; - } - iError = FT_New_Memory_Face(m_pLibrary, pBuffer, iBufferSize, 0, &m_pFace); - - if (iError) - { - return 0; - } - - SetEncoding(FONT_ENCODING_UNICODE); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::Release() -{ - FT_Done_Face(m_pFace); - ; - FT_Done_FreeType(m_pLibrary); - m_pFace = NULL; - m_pLibrary = NULL; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::SetGlyphBitmapSize(int iWidth, int iHeight, float sizeRatio) -{ - m_iGlyphBitmapWidth = iWidth; - m_iGlyphBitmapHeight = iHeight; - - // Assign the given scale for texture slots as long as its positive - m_fSizeRatio = sizeRatio > 0.0f ? sizeRatio : m_fSizeRatio; - - FT_Set_Pixel_Sizes(m_pFace, (int)(m_iGlyphBitmapWidth * m_fSizeRatio), (int)(m_iGlyphBitmapHeight * m_fSizeRatio)); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::GetGlyphBitmapSize(int* pWidth, int* pHeight) -{ - if (pWidth) - { - *pWidth = m_iGlyphBitmapWidth; - } - - if (pHeight) - { - *pHeight = m_iGlyphBitmapHeight; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontRenderer::SetEncoding(FT_Encoding pEncoding) -{ - if (FT_Select_Charmap(m_pFace, pEncoding)) - { - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -int CFontRenderer::GetGlyph(CGlyphBitmap* pGlyphBitmap, int* iHoriAdvance, uint8* iGlyphWidth, uint8* iGlyphHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, int iX, int iY, int iCharCode, const CFFont::FontHintParams& fontHintParams) -{ - FT_Int32 loadFlags = GetLoadFlags(fontHintParams.hintBehavior); - loadFlags |= GetLoadTarget(fontHintParams.hintStyle); - - int iError = FT_Load_Char(m_pFace, iCharCode, loadFlags); - - if (iError) - { - return 0; - } - - FT_Render_Mode renderMode = GetRenderMode(fontHintParams.hintStyle); - - m_pGlyph = m_pFace->glyph; - - iError = FT_Render_Glyph(m_pGlyph, renderMode); - - if (iError) - { - return 0; - } - - if (iHoriAdvance) - { - *iHoriAdvance = m_pGlyph->metrics.horiAdvance / fractionalPixelUnits; - } - - if (iGlyphWidth) - { - *iGlyphWidth = m_pGlyph->bitmap.width; - } - - if (iGlyphHeight) - { - *iGlyphHeight = m_pGlyph->bitmap.rows; - } - - unsigned char* pBuffer = pGlyphBitmap->GetBuffer(); - AZ_Assert(pBuffer, "CGlyphBitmap: bad buffer"); - - uint32 dwGlyphWidth = pGlyphBitmap->GetWidth(); - iCharOffsetX = m_pGlyph->bitmap_left; - iCharOffsetY = (static_cast(round(m_iGlyphBitmapHeight * m_fSizeRatio)) - m_pGlyph->bitmap_top); - - const int textureSlotBufferWidth = pGlyphBitmap->GetWidth(); - const int textureSlotBufferHeight = pGlyphBitmap->GetHeight(); - - // might happen if font characters are too big or cache dimenstions in font.xml is too small "" - const bool charWidthFits = iX + m_pGlyph->bitmap.width <= textureSlotBufferWidth; - const bool charHeightFits = iY + m_pGlyph->bitmap.rows <= textureSlotBufferHeight; - const bool charFitsInSlot = charWidthFits && charHeightFits; - AZ_Error("Font", charFitsInSlot, "Character code %d doesn't fit in font texture; check 'sizeRatio' attribute in font XML or adjust this character's sizing in the font.", iCharCode); - - // Since we might be re-rendering/overwriting a glyph that already exists - // in the font texture, clear the contents of this particular slot so no - // artifacts of the previous glyph remain. - pGlyphBitmap->Clear(); - - // Restrict iteration to smallest of either the texture slot or glyph - // bitmap buffer ranges - const int bufferMaxIterWidth = AZStd::GetMin(textureSlotBufferWidth, m_pGlyph->bitmap.width); - const int bufferMaxIterHeight = AZStd::GetMin(textureSlotBufferHeight, m_pGlyph->bitmap.rows); - - for (int i = 0; i < bufferMaxIterHeight; i++) - { - int iNewY = i + iY; - - for (int j = 0; j < bufferMaxIterWidth; j++) - { - unsigned char cColor = m_pGlyph->bitmap.buffer[(i * m_pGlyph->bitmap.width) + j]; - int iOffset = iNewY * dwGlyphWidth + iX + j; - - if (iOffset >= (int)dwGlyphWidth * m_iGlyphBitmapHeight) - { - continue; - } - - pBuffer[iOffset] = cColor; - // pBuffer[iOffset] = cColor/2+32; // debug - visualize character in a block - } - } - - return 1; -} - -int CFontRenderer::GetGlyphScaled([[maybe_unused]] CGlyphBitmap* pGlyphBitmap, [[maybe_unused]] int* iGlyphWidth, [[maybe_unused]] int* iGlyphHeight, [[maybe_unused]] int iX, [[maybe_unused]] int iY, [[maybe_unused]] float fScaleX, [[maybe_unused]] float fScaleY, [[maybe_unused]] int iCharCode) -{ - return 1; -} - -Vec2 CFontRenderer::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) -{ - FT_Vector kerningOffsets; - kerningOffsets.x = kerningOffsets.y = 0; - - if (FT_HAS_KERNING(m_pFace)) - { - const FT_UInt leftGlyphIndex = FT_Get_Char_Index(m_pFace, leftGlyph); - const FT_UInt rightGlyphIndex = FT_Get_Char_Index(m_pFace, rightGlyph); - - [[maybe_unused]] FT_Error ftError = FT_Get_Kerning(m_pFace, leftGlyphIndex, rightGlyphIndex, FT_KERNING_DEFAULT, &kerningOffsets); - -#if !defined(_RELEASE) - if (0 != ftError) - { - string warnMsg; - warnMsg.Format("FT_Get_Kerning returned %d", ftError); - CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str()); - } -#endif - } - - return Vec2(azlossy_cast(kerningOffsets.x / fractionalPixelUnits), azlossy_cast(kerningOffsets.y / fractionalPixelUnits)); -} - -float CFontRenderer::GetAscenderToHeightRatio() -{ - return (static_cast(m_pFace->ascender) / static_cast(m_pFace->height)); -} - -//------------------------------------------------------------------------------------------------- -/* -int CFontRenderer::FT_GetIndex(int iCharCode) -{ -if (iCharCode < 256) -{ -int iIndex = 0; -int iUnicode; - -// try unicode -for (int i = 0; i < m_pFace->num_charmaps; i++) -{ -if ((m_pFace->charmaps[i]->platform_id == 3) && (m_pFace->charmaps[i]->encoding_id == 1)) -{ -iUnicode = i; - -FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]); - -iIndex = FT_Get_Char_Index(m_pFace, iCharCode); - -// not unicode, try ascii -if (iIndex == 0) -{ -for (int i = 0; i < m_pFace->num_charmaps; i++) -{ -if ((m_pFace->charmaps[i]->platform_id == 0) && (m_pFace->charmaps[i]->encoding_id == 0)) -{ -FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]); - -iIndex = FT_Get_Char_Index(m_pFace, iCharCode); - -// not ascii either, reuse unicode default "missing char" -if (iIndex == 0) -{ -FT_Set_Charmap(m_pFace, m_pFace->charmaps[iUnicode]); - -return FT_Get_Char_Index(m_pFace, iCharCode); -} -} -} -} - -return iIndex; -} -} - -return 0; -} -else -{ -for (int i = 0; i < m_pFace->num_charmaps; i++) -{ -if ((m_pFace->charmaps[i]->platform_id == 3) && (m_pFace->charmaps[i]->encoding_id == 1)) -{ -FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]); - -return FT_Get_Char_Index(m_pFace, iCharCode); -} -} - -return 0; -} - -return 0; -} -*/ - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/FontRenderer.h b/Code/CryEngine/CryFont/FontRenderer.h deleted file mode 100644 index aca26a1e04..0000000000 --- a/Code/CryEngine/CryFont/FontRenderer.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Render a glyph outline into a bitmap using FreeType 2 - -#if !defined(USE_NULLFONT_ALWAYS) - -#ifndef CRYINCLUDE_CRYFONT_FONTRENDERER_H -#define CRYINCLUDE_CRYFONT_FONTRENDERER_H -#pragma once - - - -#include "GlyphBitmap.h" -#include "FFont.h" -#include -#pragma push_macro("generic") -#define generic GenericFromFreeTypeLibrary -#include -#undef generic -#pragma pop_macro("generic") - - -// Corresponds to the Unicode character set. This value covers all versions of the Unicode repertoire, -// including ASCII and Latin-1. Most fonts include a Unicode charmap, but not all of them. -#define FONT_ENCODING_UNICODE (FT_ENCODING_UNICODE) - -// Corresponds to the Microsoft Symbol encoding, used to encode mathematical symbols in the 32..255 character code range. -// For more information, see `http://www.ceviz.net/symbol.htm'. -#define FONT_ENCODING_SYMBOL (FT_ENCODING_MS_SYMBOL) - -// Corresponds to Microsoft's Japanese SJIS encoding. -// More info at `http://langsupport.japanreference.com/encoding.shtml'. See note on multi-byte encodings below. -#define FONT_ENCODING_SJIS (FT_ENCODING_MS_SJIS) - -// Corresponds to the encoding system for Simplified Chinese, as used in China. Only found in some TrueType fonts. -#define FONT_ENCODING_GB2312 (FT_ENCODING_MS_GB2312) - -// Corresponds to the encoding system for Traditional Chinese, as used in Taiwan and Hong Kong. Only found in some TrueType fonts. -#define FONT_ENCODING_BIG5 (FT_ENCODING_MS_BIG5) - -// Corresponds to the Korean encoding system known as Wansung. -// This is a Microsoft encoding that is only found in some TrueType fonts. -// For more information, see `http://www.microsoft.com/typography/unicode/949.txt'. -#define FONT_ENCODING_WANSUNG (FT_ENCODING_MS_WANSUNG) - -// The Korean standard character set (KS C-5601-1992), which corresponds to Windows code page 1361. -// This character set includes all possible Hangeul character combinations. Only found on some rare TrueType fonts. -#define FONT_ENCODING_JOHAB (FT_ENCODING_MS_JOHAB) - - - -//------------------------------------------------------------------------------------ -class CFontRenderer -{ -public: - - CFontRenderer(); - ~CFontRenderer(); - - int LoadFromFile(const string& szFileName); - int LoadFromMemory(unsigned char* pBuffer, int iBufferSize); - int Release(); - - int SetGlyphBitmapSize(int iWidth, int iHeight, float sizeRatio); - int GetGlyphBitmapSize(int* pWidth, int* pHeight); - - int SetSizeRatio(float fSizeRatio) { m_fSizeRatio = fSizeRatio; return 1; }; - float GetSizeRatio() { return m_fSizeRatio; }; - - int SetEncoding(FT_Encoding pEncoding); - FT_Encoding GetEncoding() { return m_pEncoding; }; - - //! Populates the given pGlyphBitmap's buffer from the FreeType bitmap buffer - //! \param iCharCode Used as a character index to retrieve the FreeType glyph and it's associated bitmap buffer for the character - //! \param pGlyphBitmap The FreeType glyph buffer is essentially copied into this CGlyphBitmap buffer - int GetGlyph(CGlyphBitmap* pGlyphBitmap, int* iHoriAdvance, uint8* iGlyphWidth, uint8* iGlyphHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, int iX, int iY, int iCharCode, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - int GetGlyphScaled(CGlyphBitmap* pGlyphBitmap, int* iGlyphWidth, int* iGlyphHeight, int iX, int iY, float fScaleX, float fScaleY, int iCharCode); - - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - - bool GetMonospaced() const { return FT_IS_FIXED_WIDTH(m_pFace) != 0; } - - Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph); - - float GetAscenderToHeightRatio(); - -private: - - FT_Library m_pLibrary; - FT_Face m_pFace; - FT_GlyphSlot m_pGlyph; - float m_fSizeRatio; - - FT_Encoding m_pEncoding; - - int m_iGlyphBitmapWidth; - int m_iGlyphBitmapHeight; -}; - -#endif // CRYINCLUDE_CRYFONT_FONTRENDERER_H - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/FontTexture.cpp b/Code/CryEngine/CryFont/FontTexture.cpp deleted file mode 100644 index 8db7484d59..0000000000 --- a/Code/CryEngine/CryFont/FontTexture.cpp +++ /dev/null @@ -1,633 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose: -// - Create and update a texture with the most recently used glyphs - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "FontTexture.h" -#include "UnicodeIterator.h" -#include - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#undef GetCharWidth -#endif - -//------------------------------------------------------------------------------------------------- -CFontTexture::CFontTexture() - : m_wSlotUsage(1) - , m_iWidth(0) - , m_iHeight(0) - , m_fInvWidth(0.0f) - , m_fInvHeight(0.0f) - , m_iCellWidth(0) - , m_iCellHeight(0) - , m_fTextureCellWidth(0) - , m_fTextureCellHeight(0) - , m_iWidthCellCount(0) - , m_iHeightCellCount(0) - , m_nTextureSlotCount(0) - , m_pBuffer(0) - , m_iSmoothMethod(FONT_SMOOTH_NONE) - , m_iSmoothAmount(FONT_SMOOTH_AMOUNT_NONE) -{ -} - -//------------------------------------------------------------------------------------------------- -CFontTexture::~CFontTexture() -{ - Release(); -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::CreateFromFile(const string& szFileName, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount) -{ - if (!m_pGlyphCache.LoadFontFromFile(szFileName)) - { - Release(); - - return 0; - } - - if (!Create(iWidth, iHeight, iSmoothMethod, iSmoothAmount, iWidthCellCount, iHeightCellCount)) - { - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::CreateFromMemory(unsigned char* pFileData, int iDataSize, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount, float sizeRatio) -{ - if (!m_pGlyphCache.LoadFontFromMemory(pFileData, iDataSize)) - { - Release(); - - return 0; - } - - if (!Create(iWidth, iHeight, iSmoothMethod, iSmoothAmount, iWidthCellCount, iHeightCellCount, sizeRatio)) - { - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::Create(int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount, float sizeRatio) -{ - m_pBuffer = new FONT_TEXTURE_TYPE[iWidth * iHeight]; - if (!m_pBuffer) - { - return 0; - } - - memset(m_pBuffer, 0, iWidth * iHeight * sizeof(FONT_TEXTURE_TYPE)); - - if (!(iWidthCellCount * iHeightCellCount)) - { - return 0; - } - - m_iWidth = iWidth; - m_iHeight = iHeight; - m_fInvWidth = 1.0f / (float)iWidth; - m_fInvHeight = 1.0f / (float)iHeight; - - m_iWidthCellCount = iWidthCellCount; - m_iHeightCellCount = iHeightCellCount; - m_nTextureSlotCount = m_iWidthCellCount * m_iHeightCellCount; - - m_iSmoothMethod = iSmoothMethod; - m_iSmoothAmount = iSmoothAmount; - - m_iCellWidth = m_iWidth / m_iWidthCellCount; - m_iCellHeight = m_iHeight / m_iHeightCellCount; - - m_fTextureCellWidth = m_iCellWidth * m_fInvWidth; - m_fTextureCellHeight = m_iCellHeight * m_fInvHeight; - - if (!m_pGlyphCache.Create(FONT_GLYPH_CACHE_SIZE, m_iCellWidth, m_iCellHeight, iSmoothMethod, iSmoothAmount, sizeRatio)) - { - Release(); - - return 0; - } - - if (!CreateSlotList(m_nTextureSlotCount)) - { - Release(); - - return 0; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::Release() -{ - delete[] m_pBuffer; - m_pBuffer = 0; - - ReleaseSlotList(); - - m_pSlotTable.clear(); - - m_pGlyphCache.Release(); - - m_iWidthCellCount = 0; - m_iHeightCellCount = 0; - m_nTextureSlotCount = 0; - - m_iWidth = 0; - m_iHeight = 0; - m_fInvWidth = 0.0f; - m_fInvHeight = 0.0f; - - m_iCellWidth = 0; - m_iCellHeight = 0; - - m_iSmoothMethod = 0; - m_iSmoothAmount = 0; - - m_fTextureCellWidth = 0.0f; - m_fTextureCellHeight = 0.0f; - - m_wSlotUsage = 1; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -uint32 CFontTexture::GetSlotChar(int iSlot) const -{ - return m_pSlotList[iSlot]->cCurrentChar; -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetCharSlot(uint32 cChar, const Vec2i& glyphSize) -{ - CryFont::FontTexture::CTextureSlotKey slotKey = GetTextureSlotKey(cChar, glyphSize); - CTextureSlotTableItor pItor = m_pSlotTable.find(slotKey); - - if (pItor != m_pSlotTable.end()) - { - return pItor->second; - } - - return 0; -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetLRUSlot() -{ - uint16 wMaxSlotAge = 0; - CTextureSlot* pLRUSlot = 0; - CTextureSlot* pSlot; - - CTextureSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->wSlotUsage == 0) - { - return pSlot; - } - else - { - uint16 slotAge = m_wSlotUsage - pSlot->wSlotUsage; - if (slotAge > wMaxSlotAge) - { - pLRUSlot = pSlot; - wMaxSlotAge = slotAge; - } - } - - ++pItor; - } - - return pLRUSlot; -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetMRUSlot() -{ - uint16 wMinSlotAge = 0xFFFF; - CTextureSlot* pMRUSlot = 0; - CTextureSlot* pSlot; - - CTextureSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->wSlotUsage != 0) - { - uint16 slotAge = m_wSlotUsage - pSlot->wSlotUsage; - if (slotAge > wMinSlotAge) - { - pMRUSlot = pSlot; - wMinSlotAge = slotAge; - } - } - - ++pItor; - } - - return pMRUSlot; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::PreCacheString(const char* szString, int* pUpdated, float sizeRatio, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - Vec2i clampedGlyphSize = ClampGlyphSize(glyphSize, m_iCellWidth, m_iCellHeight); - - uint16 wSlotUsage = m_wSlotUsage++; - int iUpdated = 0; - - uint32 cChar; - for (Unicode::CIterator it(szString); *it; ++it) - { - cChar = *it; - CTextureSlot* pSlot = GetCharSlot(cChar, clampedGlyphSize); - - if (!pSlot) - { - pSlot = GetLRUSlot(); - - if (!pSlot) - { - return 0; - } - - if (!UpdateSlot(pSlot->iTextureSlot, wSlotUsage, cChar, sizeRatio, clampedGlyphSize, fontHintParams)) - { - return 0; - } - - ++iUpdated; - } - else - { - pSlot->wSlotUsage = wSlotUsage; - } - } - - if (pUpdated) - { - *pUpdated = iUpdated; - } - - if (iUpdated) - { - return 1; - } - - return 2; -} - -//------------------------------------------------------------------------------------------------- -void CFontTexture::GetTextureCoord(CTextureSlot* pSlot, float texCoords[4], - int& iCharSizeX, int& iCharSizeY, int& iCharOffsetX, int& iCharOffsetY, - const Vec2i& glyphSize) const -{ - if (!pSlot) - { - return; // expected behavior - } - - // Re-rendered glyphs are stored at smaller sizes than glyphs rendered at - // the (maximum) font texture slot resolution. We scale the returned width - // and height of the (actual) rendered glyph sizes so its transparent to - // callers that the glyph is actually smaller (from being re-rendered). - const float requestSizeWidthScale = AZ::GetMin(1.0f, GetRequestSizeWidthScale(glyphSize)); - const float requestSizeHeightScale = AZ::GetMin(1.0f, GetRequestSizeHeightScale(glyphSize)); - const float invRequestSizeWidthScale = 1.0f / requestSizeWidthScale; - const float invRequestSizeHeightScale = 1.0f / requestSizeHeightScale; - - // The inverse scale grows as the glyph size decreases. Once the glyph size - // reaches the font texture's max slot dimensions, we cap width/height scale - // since the text draw context will apply normal (as opposed to re-rendered) - // scaling. - int iChWidth = static_cast(pSlot->iCharWidth * invRequestSizeWidthScale); - int iChHeight = static_cast(pSlot->iCharHeight * invRequestSizeHeightScale); - - float slotCoord0 = pSlot->vTexCoord[0]; - float slotCoord1 = pSlot->vTexCoord[1]; - texCoords[0] = slotCoord0 - m_fInvWidth; // extra pixel for nicer bilinear filter - texCoords[1] = slotCoord1 - m_fInvHeight; // extra pixel for nicer bilinear filter - - // UV coordinates also must be scaled relative to the re-rendered glyph size - // as well. Width scale must be capped at 1.0f since glyph can't grow - // beyond the slot's resolution. - texCoords[2] = slotCoord0 + (((float)iChWidth * m_fInvWidth) * requestSizeWidthScale); - texCoords[3] = slotCoord1 + (((float)iChHeight * m_fInvHeight) * requestSizeHeightScale); - - iCharSizeX = iChWidth + 1; // extra pixel for nicer bilinear filter - iCharSizeY = iChHeight + 1; // extra pixel for nicer bilinear filter - - // Offsets are scaled accordingly when the rendered glyph size is smaller - // than the glyph/slot dimensions, but otherwise we expect the text draw - // context to apply scaling beyond that. - iCharOffsetX = static_cast(pSlot->iCharOffsetX * invRequestSizeWidthScale); - iCharOffsetY = static_cast(pSlot->iCharOffsetY * invRequestSizeHeightScale); -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::GetCharacterWidth(uint32 cChar) const -{ - CTextureSlotTableItorConst pItor = m_pSlotTable.find(GetTextureSlotKey(cChar)); - - if (pItor == m_pSlotTable.end()) - { - return 0; - } - - const CTextureSlot& rSlot = *pItor->second; - - // For proportional fonts, add one pixel of spacing for aesthetic reasons - int proportionalOffset = GetMonospaced() ? 0 : 1; - - return rSlot.iCharWidth + proportionalOffset; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::GetHorizontalAdvance(uint32 cChar, const Vec2i& glyphSize) const -{ - CTextureSlotTableItorConst pItor = m_pSlotTable.find(GetTextureSlotKey(cChar, glyphSize)); - - if (pItor == m_pSlotTable.end()) - { - return 0; - } - - const CTextureSlot& rSlot = *pItor->second; - - // Re-rendered glyphs are stored at smaller sizes than glyphs rendered at - // the (maximum) font texture slot resolution. We scale the returned width - // and height of the (actual) rendered glyph sizes so its transparent to - // callers that the glyph is actually smaller (from being re-rendered). - const float requestSizeWidthScale = GetRequestSizeWidthScale(glyphSize); - const float invRequestSizeWidthScale = 1.0f / requestSizeWidthScale; - - // Only multiply by 1.0f when glyphsize is greater than cell width because we assume that callers - // will use the font draw text context to scale the value appropriately. - return static_cast(rSlot.iHoriAdvance * AZ::GetMax(1.0f, invRequestSizeWidthScale)); -} - -//------------------------------------------------------------------------------------------------- -/* -int CFontTexture::GetCharHeightByChar(wchar_t cChar) -{ -CTextureSlotTableItor pItor = m_pSlotTable.find(cChar); - -if (pItor != m_pSlotTable.end()) -{ -return pItor->second->iCharHeight; -} - -return 0; -} -*/ - -//------------------------------------------------------------------------------------------------- -int CFontTexture::WriteToFile([[maybe_unused]] const string& szFileName) -{ -#ifdef WIN32 - AZ::IO::FileIOStream outputFile(szFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary); - - if (!outputFile.IsOpen()) - { - return 0; - } - - BITMAPFILEHEADER pHeader; - BITMAPINFOHEADER pInfoHeader; - - memset(&pHeader, 0, sizeof(BITMAPFILEHEADER)); - memset(&pInfoHeader, 0, sizeof(BITMAPINFOHEADER)); - - pHeader.bfType = 0x4D42; - pHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + m_iWidth * m_iHeight * 3; - pHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - - pInfoHeader.biSize = sizeof(BITMAPINFOHEADER); - pInfoHeader.biWidth = m_iWidth; - pInfoHeader.biHeight = m_iHeight; - pInfoHeader.biPlanes = 1; - pInfoHeader.biBitCount = 24; - pInfoHeader.biCompression = 0; - pInfoHeader.biSizeImage = m_iWidth * m_iHeight * 3; - - outputFile.Write(sizeof(BITMAPFILEHEADER), &pHeader); - outputFile.Write(sizeof(BITMAPINFOHEADER), &pInfoHeader); - - unsigned char cRGB[3]; - - for (int i = m_iHeight - 1; i >= 0; i--) - { - for (int j = 0; j < m_iWidth; j++) - { - cRGB[0] = m_pBuffer[(i * m_iWidth) + j]; - cRGB[1] = *cRGB; - - cRGB[2] = *cRGB; - - outputFile.Write(3, cRGB); - } - } - -#endif - return 1; -} - -//------------------------------------------------------------------------------------------------- -Vec2 CFontTexture::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) -{ - return m_pGlyphCache.GetKerning(leftGlyph, rightGlyph); -} - -//------------------------------------------------------------------------------------------------- -float CFontTexture::GetAscenderToHeightRatio() -{ - return m_pGlyphCache.GetAscenderToHeightRatio(); -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::CreateSlotList(int iListSize) -{ - int y, x; - - for (int i = 0; i < iListSize; i++) - { - CTextureSlot* pTextureSlot = new CTextureSlot; - - if (!pTextureSlot) - { - return 0; - } - - pTextureSlot->iTextureSlot = i; - pTextureSlot->Reset(); - - y = i / m_iWidthCellCount; - x = i % m_iWidthCellCount; - - pTextureSlot->vTexCoord[0] = (float)(x * m_fTextureCellWidth) + (0.5f / (float)m_iWidth); - pTextureSlot->vTexCoord[1] = (float)(y * m_fTextureCellHeight) + (0.5f / (float)m_iHeight); - - m_pSlotList.push_back(pTextureSlot); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::ReleaseSlotList() -{ - CTextureSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - delete (*pItor); - - pItor = m_pSlotList.erase(pItor); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CFontTexture::UpdateSlot(int iSlot, uint16 wSlotUsage, uint32 cChar, float sizeRatio, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - CTextureSlot* pSlot = m_pSlotList[iSlot]; - - if (!pSlot) - { - return 0; - } - - CTextureSlotTableItor pItor = m_pSlotTable.find(GetTextureSlotKey(pSlot->cCurrentChar, pSlot->glyphSize)); - - if (pItor != m_pSlotTable.end()) - { - m_pSlotTable.erase(pItor); - } - m_pSlotTable.insert(AZStd::pair(GetTextureSlotKey(cChar, glyphSize), pSlot)); - pSlot->glyphSize = glyphSize; - pSlot->wSlotUsage = wSlotUsage; - pSlot->cCurrentChar = cChar; - - int iWidth = 0; - int iHeight = 0; - - // blit the char glyph into the texture - int x = pSlot->iTextureSlot % m_iWidthCellCount; - int y = pSlot->iTextureSlot / m_iWidthCellCount; - - CGlyphBitmap* pGlyphBitmap; - - if (glyphSize.x > 0 && glyphSize.y > 0) - { - m_pGlyphCache.SetGlyphBitmapSize(glyphSize.x, glyphSize.y, sizeRatio); - } - - if (!m_pGlyphCache.GetGlyph(&pGlyphBitmap, &pSlot->iHoriAdvance, &iWidth, &iHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, cChar, glyphSize, fontHintParams)) - { - return 0; - } - - pSlot->iCharWidth = iWidth; - pSlot->iCharHeight = iHeight; - - // Add a pixel along width and height to avoid artifacts being rendered - // from a previous glyph in this slot due to bilinear filtering. The source - // glyph bitmap buffer is presumed to be cleared prior to FreeType rendering - // to the bitmap. - const int blitWidth = AZ::GetMin(iWidth + 1, m_iCellWidth); - const int blitHeight = AZ::GetMin(iHeight + 1, m_iCellHeight); - - pGlyphBitmap->BlitTo8(m_pBuffer, 0, 0, - blitWidth, blitHeight, x * m_iCellWidth, y * m_iCellHeight, m_iWidth); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -void CFontTexture::CreateGradientSlot() -{ - CTextureSlot* pSlot = GetGradientSlot(); - assert(pSlot->cCurrentChar == (uint32)~0); // 0 needs to be unused spot - - pSlot->Reset(); - pSlot->iCharWidth = m_iCellWidth - 2; - pSlot->iCharHeight = m_iCellHeight - 2; - pSlot->SetNotReusable(); - - int x = pSlot->iTextureSlot % m_iWidthCellCount; - int y = pSlot->iTextureSlot / m_iWidthCellCount; - - assert(sizeof(*m_pBuffer) == sizeof(uint8)); - uint8* pBuffer = &m_pBuffer[x * m_iCellWidth + y * m_iCellHeight * m_iWidth]; - - for (uint32 dwY = 0; dwY < pSlot->iCharHeight; ++dwY) - { - for (uint32 dwX = 0; dwX < pSlot->iCharWidth; ++dwX) - { - pBuffer[dwX + dwY * m_iWidth] = dwY * 255 / (pSlot->iCharHeight - 1); - } - } -} - -//------------------------------------------------------------------------------------------------- -CTextureSlot* CFontTexture::GetGradientSlot() -{ - return m_pSlotList[0]; -} - -//------------------------------------------------------------------------------------------------- -CryFont::FontTexture::CTextureSlotKey CFontTexture::GetTextureSlotKey(uint32 cChar, const Vec2i& glyphSize) const -{ - const Vec2i clampedGlyphSize(ClampGlyphSize(glyphSize, m_iCellWidth, m_iCellHeight)); - return CryFont::FontTexture::CTextureSlotKey(clampedGlyphSize, cChar); -} - -Vec2i CFontTexture::ClampGlyphSize(const Vec2i& glyphSize, int cellWidth, int cellHeight) -{ - const Vec2i maxCellDimensions(cellWidth, cellHeight); - Vec2i clampedGlyphSize(glyphSize); - - const bool hasZeroDimension = glyphSize.x == 0 || glyphSize.y == 0; - const bool isDefaultSize = glyphSize == CCryFont::defaultGlyphSize; - const bool exceedsDimensions = glyphSize.x > cellWidth || glyphSize.y > cellHeight; - const bool useMaxCellDimension = hasZeroDimension || isDefaultSize || exceedsDimensions; - if (useMaxCellDimension) - { - clampedGlyphSize = maxCellDimensions; - } - - return clampedGlyphSize; -} - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/FontTexture.h b/Code/CryEngine/CryFont/FontTexture.h deleted file mode 100644 index 45d0403f47..0000000000 --- a/Code/CryEngine/CryFont/FontTexture.h +++ /dev/null @@ -1,301 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYFONT_FONTTEXTURE_H -#define CRYINCLUDE_CRYFONT_FONTTEXTURE_H -#pragma once - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "GlyphCache.h" -#include "GlyphBitmap.h" -#include "CryFont.h" -#include "FFont.h" - -typedef uint8 FONT_TEXTURE_TYPE; - -// the number of slots in the glyph cache -// each slot ocupies ((glyph_bitmap_width * glyph_bitmap_height) + 24) bytes -#define FONT_GLYPH_CACHE_SIZE (1) - -// the glyph spacing in font texels between characters in proportional font mode (more correct would be to take the value in the character) -#define FONT_GLYPH_PROP_SPACING (1) - -// the size of a rendered space, this value gets multiplied by the default characted width -#define FONT_SPACE_SIZE (0.5f) - -// don't draw this char (used to avoid drawing color codes) -#define FONT_NOT_DRAWABLE_CHAR (0xffff) - -// smoothing methods -#define FONT_SMOOTH_NONE 0 -#define FONT_SMOOTH_BLUR 1 -#define FONT_SMOOTH_SUPERSAMPLE 2 - -// smoothing amounts -#define FONT_SMOOTH_AMOUNT_NONE 0 -#define FONT_SMOOTH_AMOUNT_2X 1 -#define FONT_SMOOTH_AMOUNT_4X 2 - -//! Stores glyph meta-data read from the font (FreeType). -//! -//! \sa CCacheSlot -typedef struct CTextureSlot -{ - Vec2i glyphSize = CCryFont::defaultGlyphSize; //!< Size of the rendered glyph stored in the font texture - uint16 wSlotUsage; //!< For LRU strategy, 0xffff is never released - uint32 cCurrentChar; //!< ~0 if not used for characters - int iTextureSlot; - int iHoriAdvance; //!< Advance width. See FT_Glyph_Metrics::horiAdvance. - float vTexCoord[2]; //!< Character position in the texture (not yet half texel corrected) - uint8 iCharWidth; //!< Glyph width (in pixel) - uint8 iCharHeight; //!< Glyph height (in pixel) - AZ::s32 iCharOffsetX; //!< Glyph's left-side bearing (in pixels). See FT_GlyphSlotRec::bitmap_left. - AZ::s32 iCharOffsetY; //!< Glyph's top bearing (in pixels). See FT_GlyphSlotRec::bitmap_top. - - void Reset() - { - wSlotUsage = 0; - cCurrentChar = ~0; - iHoriAdvance = 0; - iCharWidth = 0; - iCharHeight = 0; - iCharOffsetX = 0; - iCharOffsetY = 0; - } - - void SetNotReusable() - { - wSlotUsage = 0xffff; - } - - void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} -} CTextureSlot; - - -typedef std::vector CTextureSlotList; -typedef std::vector::iterator CTextureSlotListItor; - -namespace CryFont -{ - namespace FontTexture - { - //! Height and width pair for glyph size mapping - typedef Vec2i CGlyphSizeType; - - //! Pair for mapping a height and width size to a UTF32 character/glyph - typedef AZStd::pair CTextureSlotKey; - - //! Hasher for texture slot table keys (glyphsize-char code pair) - //! - //! Instead of creating our own custom hash, the types are broken down to their - //! native types (ints) and passed to existing hashes that handle those types. - struct HashTextureSlotTableKey - { - typedef CTextureSlotKey ArgumentType; - typedef AZStd::size_t ResultType; - typedef AZStd::pair Int32Pair; - typedef AZStd::pair Int32PairU32Pair; - ResultType operator()(const ArgumentType& value) const - { - // Utiliize existing hash function for pairs of ints - AZStd::hash pairHash; - return pairHash(Int32PairU32Pair(Int32Pair(value.first.x, value.first.y), value.second)); - } - }; - } -} - -//! Maps size-speicifc UTF32 glyphs to their corresponding texture slots -typedef AZStd::unordered_map CTextureSlotTable; - -typedef CTextureSlotTable::iterator CTextureSlotTableItor; -typedef CTextureSlotTable::const_iterator CTextureSlotTableItorConst; - -#ifdef WIN64 -#undef GetCharWidth -#undef GetCharHeight -#endif - -//! Stores the glyphs of a font within a single texture. -//! -//! The texture resolution is configurable, as is the number of slots within -//! the texture. -//! -//! A texture slot contains a single glyph within the font and are uniform -//! size throughout the font texture (each slot occupies the same size -//! regardless of the size of a glyph being stored, so a '.' occupies the -//! same amount of space as a 'W', for example). -//! -//! Font glyph buffers are read from FreeType and copied into the texture. -//! -//! \sa CTextureSlot, CFontRenderer -class CFontTexture -{ -public: - CFontTexture(); - ~CFontTexture(); - - int CreateFromFile(const string& szFileName, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount = 16, int iHeightCharCount = 16); - - //! Default texture slot width/height is 16x8 slots, allowing for 128 glyphs to be stored in the font texture. This was - //! previously 16x16, allowing 256 glyphs to be stored. For reference, there are 95 printable ASCII characters, so by - //! reducing the number of slots, the height of the font texture can be halved (for some nice memory savings). We may - //! want to make this configurable in the font XML (especially for languages with a large number of printable chars). - int CreateFromMemory(unsigned char* pFileData, int iDataSize, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount, int iHeightCharCount, float sizeRatio); - - int Create(int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount = 16, int iHeightCharCount = 16, float sizeRatio = IFFontConstants::defaultSizeRatio); - int Release(); - - int SetEncoding(FT_Encoding pEncoding) { return m_pGlyphCache.SetEncoding(pEncoding); } - FT_Encoding GetEncoding() { return m_pGlyphCache.GetEncoding(); } - - int GetCellWidth() { return m_iCellWidth; } - int GetCellHeight() { return m_iCellHeight; } - - int GetWidth() { return m_iWidth; } - int GetHeight() { return m_iHeight; } - - int GetWidthCellCount() { return m_iWidthCellCount; } - int GetHeightCellCount() { return m_iHeightCellCount; } - - float GetTextureCellWidth() { return m_fTextureCellWidth; } - float GetTextureCellHeight() { return m_fTextureCellHeight; } - - FONT_TEXTURE_TYPE* GetBuffer() { return m_pBuffer; } - - uint32 GetSlotChar(int iSlot) const; - CTextureSlot* GetCharSlot(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - CTextureSlot* GetGradientSlot(); - - CTextureSlot* GetLRUSlot(); - CTextureSlot* GetMRUSlot(); - - //! Returns 1 if texture updated, returns 2 if texture not updated, returns 0 on error - //! \param szString A string of glyphs (UTF8) to added to the font texture (if they don't already exist in the font texture) - //! \param pUpdated is the number of slots updated - //! \param sizeRatio A sizing scale that gets applied to all glyphs sizes before they are stored in the font texture. - //! \param glyphSize The resolution to render the glyphs in szString at. - //! \param glyphFlags Controls hinting behavior for glyphs rendered to the font texture. - int PreCacheString(const char* szString, int* pUpdated = 0, float sizeRatio = IFFontConstants::defaultSizeRatio, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - // Arguments: - // pSlot - function does nothing if this pointer is 0 - void GetTextureCoord(CTextureSlot * pSlot, float texCoords[4], int& iCharSizeX, int& iCharSizeY, int& iCharOffsetX, int& iCharOffsetY, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - int GetCharacterWidth(uint32 cChar) const; - //! Gets the horizontal advance for the given glyph/char. - //! \param cChar The glyph (UTF32) to get the horizontal advance for. - //! \param glyphSize The rendered size of the glyph to get the advance for (the same glyph could be stored in the font texture at multiple sizes). - int GetHorizontalAdvance(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - // int GetCharHeightByChar(wchar_t cChar); - - // useful for special feature rendering interleaved with fonts (e.g. box behind the text) - void CreateGradientSlot(); - - int WriteToFile(const string& szFileName); - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(this, sizeof(*this)); - pSizer->AddObject(m_pGlyphCache); - pSizer->AddObject(m_pSlotList); - //pSizer->AddContainer(m_pSlotTable); - pSizer->AddObject(m_pBuffer, m_iWidth * m_iHeight * sizeof(FONT_TEXTURE_TYPE)); - } - - bool GetMonospaced() const { return m_pGlyphCache.GetMonospaced(); } - - Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph); - - float GetAscenderToHeightRatio(); - -public: // --------------------------------------------------------------- - - //! Clamps the given glyph size to the given max cell width and height dimensions. - static Vec2i ClampGlyphSize(const Vec2i& glyphSize, int cellWidth, int cellHeight); - -private: // --------------------------------------------------------------- - - int CreateSlotList(int iListSize); - int ReleaseSlotList(); - - //! Updates the given font texture slot with the given glyph (UTF8) with the given parameters. If the glyph doesn't - //! exist in the font texture at the given size, then the glyph will be rendered to the font texture with the given - //! parameters. - //! \param iSlot Index of the texture slot to update within the slot list. - //! \param wSlotUsage Used for LRU strategy to determine how many times a glyph is referenced for retention within the font texture (before eviction). - //! \param cChar UTF32 glyph to store within the slot. - //! \param sizeRatio A sizing scale that should be applied to the glyph before being stored within the font texture. - //! \param glyphSize The size of the glyph to be rendered at within the font texture. - //! \param glyphFlags Specifies hinting behavior that should be applied to the glyph when rendered to the font texture. - int UpdateSlot(int iSlot, uint16 wSlotUsage, uint32 cChar, float sizeRatio, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - - CryFont::FontTexture::CTextureSlotKey GetTextureSlotKey(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - - //! Calculates scaling info that should be applied when the rendered glyph size doesn't match the maximum glyph slot resolution. - //! - //! Glyphs can be re-rendered to glyph slots at smaller resolutions for pixel-perfect resolution (rather than applying a scale - //! to glyphs rendered at larger sizes). These scaling values allow clients of the font texture to use the glyphs without regard - //! to whether the glyphs have been re-rendered or not. - float GetRequestSizeWidthScale(const Vec2i& glyphSize) const - { - const int cellWidth = m_iCellWidth == 0 ? 1 : m_iCellWidth; - const float invCellWidth = 1.0f / cellWidth; - return glyphSize.x > 0 ? glyphSize.x * invCellWidth : 1.0f; - } - - //! Calculates scaling info that should be applied when the rendered glyph size doesn't match the maximum glyph slot resolution. - //! - //! Glyphs can be re-rendered to glyph slots at smaller resolutions for pixel-perfect resolution (rather than applying a scale - //! to glyphs rendered at larger sizes). These scaling values allow clients of the font texture to use the glyphs without regard - //! to whether the glyphs have been re-rendered or not. - float GetRequestSizeHeightScale(const Vec2i& glyphSize) const - { - const int cellHeight = m_iCellHeight == 0 ? 1 : m_iCellHeight; - const float invCellHeight = 1.0f / cellHeight; - return glyphSize.y > 0 ? glyphSize.y * invCellHeight : 1.0f; - } - - // -------------------------------- - - int m_iWidth; // whole texture cache width - int m_iHeight; // whole texture cache height - - float m_fInvWidth; - float m_fInvHeight; - - int m_iCellWidth; - int m_iCellHeight; - - float m_fTextureCellWidth; - float m_fTextureCellHeight; - - int m_iWidthCellCount; - int m_iHeightCellCount; - - int m_nTextureSlotCount; - - int m_iSmoothMethod; - int m_iSmoothAmount; - - CGlyphCache m_pGlyphCache; - CTextureSlotList m_pSlotList; - CTextureSlotTable m_pSlotTable; - - FONT_TEXTURE_TYPE* m_pBuffer; // [y*iWidth * x] x=0..iWidth-1, y=0..iHeight-1 - - uint16 m_wSlotUsage; -}; - -#endif // #if !defined(USE_NULLFONT_ALWAYS) - -#endif // CRYINCLUDE_CRYFONT_FONTTEXTURE_H diff --git a/Code/CryEngine/CryFont/GlyphBitmap.cpp b/Code/CryEngine/CryFont/GlyphBitmap.cpp deleted file mode 100644 index 8ae893c317..0000000000 --- a/Code/CryEngine/CryFont/GlyphBitmap.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose: -// - Hold a glyph bitmap and blit it to the main texture - -#include "CryFont_precompiled.h" -#include "GlyphBitmap.h" -#include - - -//------------------------------------------------------------------------------------------------- -CGlyphBitmap::CGlyphBitmap() - : m_iWidth(0) - , m_iHeight(0) - , m_pBuffer(0) -{ -} - -//------------------------------------------------------------------------------------------------- -CGlyphBitmap::~CGlyphBitmap() -{ - Release(); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Create(int iWidth, int iHeight) -{ - Release(); - - m_pBuffer = new unsigned char[iWidth * iHeight]; - - if (!m_pBuffer) - { - return 0; - } - - m_iWidth = iWidth; - m_iHeight = iHeight; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Release() -{ - if (m_pBuffer) - { - delete[] m_pBuffer; - } - m_pBuffer = 0; - m_iWidth = m_iHeight = 0; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Blur(int iIterations) -{ - int cSum; - int yOffset; - int yupOffset; - int ydownOffset; - - for (int i = 0; i < iIterations; i++) - { - for (int y = 0; y < m_iHeight; y++) - { - yOffset = y * m_iWidth; - - if (y - 1 >= 0) - { - yupOffset = (y - 1) * m_iWidth; - } - else - { - yupOffset = (y) * m_iWidth; - } - - if (y + 1 < m_iHeight) - { - ydownOffset = (y + 1) * m_iWidth; - } - else - { - ydownOffset = (y) * m_iWidth; - } - - for (int x = 0; x < m_iWidth; x++) - { - cSum = m_pBuffer[yupOffset + x] + m_pBuffer[ydownOffset + x]; - - if (x - 1 >= 0) - { - cSum += m_pBuffer[yOffset + x - 1]; - } - else - { - cSum += m_pBuffer[yOffset + x]; - } - - if (x + 1 < m_iWidth) - { - cSum += m_pBuffer[yOffset + x + 1]; - } - else - { - cSum += m_pBuffer[yOffset + x]; - } - - m_pBuffer[yOffset + x] = cSum >> 2; - } - } - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Scale(float fScaleX, float fScaleY) -{ - int iNewWidth = (int)(m_iWidth * fScaleX); - int iNewHeight = (int)(m_iHeight * fScaleY); - - unsigned char* pNewBuffer = new unsigned char[iNewWidth * iNewHeight]; - - if (!pNewBuffer) - { - return 0; - } - - float xFactor = m_iWidth / (float)iNewWidth; - float yFactor = m_iHeight / (float)iNewHeight; - - float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1; - int xCeil, yCeil, xFloor, yFloor, yNewOffset; - - unsigned char c0, c1, c2, c3; - - for (int y = 0; y < iNewHeight; ++y) - { - yFractioned = y * yFactor; - yFloor = (int)floor_tpl(yFractioned); - yCeil = yFloor + 1; - - if (yCeil >= m_iHeight) - { - yCeil = yFloor; - } - - yFraction = yFractioned - yFloor; - oneMinusY = 1.0f - yFraction; - - yNewOffset = y * iNewWidth; - - for (int x = 0; x < iNewWidth; ++x) - { - xFractioned = x * xFactor; - xFloor = (int)floor_tpl(xFractioned); - xCeil = xFloor + 1; - - if (xCeil >= m_iWidth) - { - xCeil = xFloor; - } - - xFraction = xFractioned - xFloor; - oneMinusX = 1.0f - xFraction; - - c0 = m_pBuffer[yFloor * m_iWidth + xFloor]; - c1 = m_pBuffer[yFloor * m_iWidth + xCeil]; - c2 = m_pBuffer[yCeil * m_iWidth + xFloor]; - c3 = m_pBuffer[yCeil * m_iWidth + xCeil]; - - fR0 = (oneMinusX * c0 + xFraction * c1); - fR1 = (oneMinusX * c2 + xFraction * c3); - - pNewBuffer[yNewOffset + x] = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1)); - } - } - - m_iWidth = iNewWidth; - m_iHeight = iNewHeight; - - delete[] m_pBuffer; - m_pBuffer = pNewBuffer; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::Clear() -{ - memset(m_pBuffer, 0, m_iWidth * m_iHeight); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth) -{ - int ySrcOffset, yDestOffset; - - for (int y = 0; y < iSrcHeight; y++) - { - ySrcOffset = (iSrcY + y) * m_iWidth; - yDestOffset = (iDestY + y) * iDestWidth; - - for (int x = 0; x < iSrcWidth; x++) - { - pBuffer[yDestOffset + iDestX + x] = m_pBuffer[ySrcOffset + iSrcX + x]; - } - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitTo32(unsigned int* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth) -{ - int ySrcOffset, yDestOffset; - char cColor; - - for (int y = 0; y < iSrcHeight; y++) - { - ySrcOffset = (iSrcY + y) * m_iWidth; - yDestOffset = (iDestY + y) * iDestWidth; - - for (int x = 0; x < iSrcWidth; x++) - { - cColor = m_pBuffer[ySrcOffset + iSrcX + x]; - - pBuffer[yDestOffset + iDestX + x] = (cColor << 24) | (255 << 16) | (255 << 8) | 255; - } - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitScaledTo8(unsigned char* pBuffer, [[maybe_unused]] int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, [[maybe_unused]] int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth) -{ - int iNewWidth = (int)iDestWidth; - int iNewHeight = (int)iDestHeight; - - unsigned char* pNewBuffer = pBuffer; - - float xFactor = iSrcWidth / (float)iNewWidth; - float yFactor = iSrcHeight / (float)iNewHeight; - - float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1; - int xCeil, yCeil, xFloor, yFloor, yNewOffset; - - unsigned char c0, c1, c2, c3; - - for (int y = 0; y < iNewHeight; ++y) - { - yFractioned = y * yFactor; - yFloor = (int)floor_tpl(yFractioned); - yCeil = yFloor + 1; - - yFraction = yFractioned - yFloor; - oneMinusY = 1.0f - yFraction; - - yNewOffset = y * iDestBufferWidth; - - yFloor += iSrcY; - yCeil += iSrcY; - - if (yCeil >= m_iHeight) - { - yCeil = yFloor; - } - - for (int x = 0; x < iNewWidth; ++x) - { - xFractioned = x * xFactor; - xFloor = (int)floor_tpl(xFractioned); - xCeil = xFloor + 1; - - xFraction = xFractioned - xFloor; - oneMinusX = 1.0f - xFraction; - - xFloor += iSrcY; - xCeil += iSrcY; - - if (xCeil >= m_iWidth) - { - xCeil = xFloor; - } - - c0 = m_pBuffer[yFloor * m_iWidth + xFloor]; - c1 = m_pBuffer[yFloor * m_iWidth + xCeil]; - c2 = m_pBuffer[yCeil * m_iWidth + xFloor]; - c3 = m_pBuffer[yCeil * m_iWidth + xCeil]; - - fR0 = (oneMinusX * c0 + xFraction * c1); - fR1 = (oneMinusX * c2 + xFraction * c3); - - pNewBuffer[yNewOffset + x + iDestX] = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1)); - } - } - - return 1; -} - - -#if defined(__GNUC__) -#if __GNUC__ >= 4 && __GNUC__MINOR__ < 7 -#pragma GCC diagnostic ignored "-Woverflow" -#endif -#endif -//------------------------------------------------------------------------------------------------- -int CGlyphBitmap::BlitScaledTo32(unsigned char* pBuffer, [[maybe_unused]] int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, [[maybe_unused]] int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth) -{ - int iNewWidth = (int)iDestWidth; - int iNewHeight = (int)iDestHeight; - - unsigned char* pNewBuffer = pBuffer; - - float xFactor = iSrcWidth / (float)iNewWidth; - float yFactor = iSrcHeight / (float)iNewHeight; - - float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1; - int xCeil, yCeil, xFloor, yFloor, yNewOffset; - - unsigned char c0, c1, c2, c3, cColor; - - for (int y = 0; y < iNewHeight; ++y) - { - yFractioned = y * yFactor; - yFloor = (int)floor_tpl(yFractioned); - yCeil = yFloor + 1; - - yFraction = yFractioned - yFloor; - oneMinusY = 1.0f - yFraction; - - yNewOffset = y * iDestBufferWidth; - - yFloor += iSrcY; - yCeil += iSrcY; - - if (yCeil >= m_iHeight) - { - yCeil = yFloor; - } - - for (int x = 0; x < iNewWidth; ++x) - { - xFractioned = x * xFactor; - xFloor = (int)floor_tpl(xFractioned); - xCeil = xFloor + 1; - - xFraction = xFractioned - xFloor; - oneMinusX = 1.0f - xFraction; - - xFloor += iSrcY; - xCeil += iSrcY; - - if (xCeil >= m_iWidth) - { - xCeil = xFloor; - } - - c0 = m_pBuffer[yFloor * m_iWidth + xFloor]; - c1 = m_pBuffer[yFloor * m_iWidth + xCeil]; - c2 = m_pBuffer[yCeil * m_iWidth + xFloor]; - c3 = m_pBuffer[yCeil * m_iWidth + xCeil]; - - fR0 = (oneMinusX * c0 + xFraction * c1); - fR1 = (oneMinusX * c2 + xFraction * c3); - - cColor = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1)); - - pNewBuffer[yNewOffset + x + iDestX] = 0xffffff | (cColor << 24); - } - } - - return 1; -} -#if defined(__GNUC__) -#if __GNUC__ >= 4 && __GNUC__MINOR__ < 7 -#pragma GCC diagnostic error "-Woverflow" -#endif -#endif -//------------------------------------------------------------------------------------------------- diff --git a/Code/CryEngine/CryFont/GlyphBitmap.h b/Code/CryEngine/CryFont/GlyphBitmap.h deleted file mode 100644 index 3d04a36cf7..0000000000 --- a/Code/CryEngine/CryFont/GlyphBitmap.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose : Hold a glyph bitmap and blit it to the main texture - -#ifndef CRYINCLUDE_CRYFONT_GLYPHBITMAP_H -#define CRYINCLUDE_CRYFONT_GLYPHBITMAP_H - -#pragma once - - -class CGlyphBitmap -{ -public: - CGlyphBitmap(); - ~CGlyphBitmap(); - - int Create(int iWidth, int iHeight); - int Release(); - - unsigned char* GetBuffer() { return m_pBuffer; }; - - int Blur(int iIterations); - int Scale(float fScaleX, float fScaleY); - - int Clear(); - - int BlitTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth); - int BlitTo32(unsigned int* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth); - - int BlitScaledTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth); - int BlitScaledTo32(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth); - - int GetWidth() { return m_iWidth; } - int GetHeight() { return m_iHeight; } - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_pBuffer, m_iWidth * m_iHeight); - } - -private: - - unsigned char* m_pBuffer; - int m_iWidth; - int m_iHeight; -}; - -#endif // CRYINCLUDE_CRYFONT_GLYPHBITMAP_H diff --git a/Code/CryEngine/CryFont/GlyphCache.cpp b/Code/CryEngine/CryFont/GlyphCache.cpp deleted file mode 100644 index 96949009df..0000000000 --- a/Code/CryEngine/CryFont/GlyphCache.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Purpose: -// - Manage and cache glyphs, retrieving them from the renderer as needed - -#include "CryFont_precompiled.h" - -#if !defined(USE_NULLFONT_ALWAYS) - -#include "GlyphCache.h" -#include "FontTexture.h" - - - -//------------------------------------------------------------------------------------------------- -CGlyphCache::CGlyphCache() - : m_dwUsage(1) - , m_iGlyphBitmapWidth(0) - , m_iGlyphBitmapHeight(0) - , m_pScaleBitmap(0) -{ - m_pCacheTable.clear(); - m_pSlotList.clear(); -} - -//------------------------------------------------------------------------------------------------- -CGlyphCache::~CGlyphCache() -{ -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::Create(int iCacheSize, int iGlyphBitmapWidth, int iGlyphBitmapHeight, int iSmoothMethod, int iSmoothAmount, float sizeRatio) -{ - m_iSmoothMethod = iSmoothMethod; - m_iSmoothAmount = iSmoothAmount; - - m_iGlyphBitmapWidth = iGlyphBitmapWidth; - m_iGlyphBitmapHeight = iGlyphBitmapHeight; - - - if (!CreateSlotList(iCacheSize)) - { - ReleaseSlotList(); - - return 0; - } - - int iScaledGlyphWidth = 0; - int iScaledGlyphHeight = 0; - - switch (m_iSmoothMethod) - { - case FONT_SMOOTH_SUPERSAMPLE: - { - switch (m_iSmoothAmount) - { - case FONT_SMOOTH_AMOUNT_2X: - iScaledGlyphWidth = m_iGlyphBitmapWidth << 1; - iScaledGlyphHeight = m_iGlyphBitmapHeight << 1; - break; - case FONT_SMOOTH_AMOUNT_4X: - iScaledGlyphWidth = m_iGlyphBitmapWidth << 2; - iScaledGlyphHeight = m_iGlyphBitmapHeight << 2; - break; - } - } - break; - } - - if (iScaledGlyphWidth) - { - m_pScaleBitmap = new CGlyphBitmap; - - if (!m_pScaleBitmap) - { - Release(); - - return 0; - } - - if (!m_pScaleBitmap->Create(iScaledGlyphWidth, iScaledGlyphHeight)) - { - Release(); - - return 0; - } - - m_pFontRenderer.SetGlyphBitmapSize(iScaledGlyphWidth, iScaledGlyphHeight, sizeRatio); - } - else - { - m_pFontRenderer.SetGlyphBitmapSize(m_iGlyphBitmapWidth, m_iGlyphBitmapHeight, sizeRatio); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::Release() -{ - ReleaseSlotList(); - - m_pCacheTable.clear(); - - if (m_pScaleBitmap) - { - m_pScaleBitmap->Release(); - - delete m_pScaleBitmap; - - m_pScaleBitmap = 0; - } - - m_iGlyphBitmapWidth = 0; - m_iGlyphBitmapHeight = 0; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::LoadFontFromFile(const string& szFileName) -{ - return m_pFontRenderer.LoadFromFile(szFileName); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::LoadFontFromMemory(unsigned char* pFileBuffer, int iDataSize) -{ - return m_pFontRenderer.LoadFromMemory(pFileBuffer, iDataSize); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::ReleaseFont() -{ - m_pFontRenderer.Release(); - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::GetGlyphBitmapSize(int* pWidth, int* pHeight) -{ - if (pWidth) - { - *pWidth = m_iGlyphBitmapWidth; - } - - if (pHeight) - { - *pHeight = m_iGlyphBitmapWidth; - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -void CGlyphCache::SetGlyphBitmapSize(int width, int height, float sizeRatio) -{ - m_pFontRenderer.SetGlyphBitmapSize(width, height, sizeRatio); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::PreCacheGlyph(uint32 cChar, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - if (pItor != m_pCacheTable.end()) - { - pItor->second->dwUsage = m_dwUsage; - - return 1; - } - - CCacheSlot* pSlot = GetLRUSlot(); - - if (!pSlot) - { - return 0; - } - - if (pSlot->dwUsage > 0) - { - UnCacheGlyph(pSlot->cCurrentChar, pSlot->glyphSize); - } - - if (m_pScaleBitmap) - { - int iOffsetMult = 1; - - switch (m_iSmoothAmount) - { - case FONT_SMOOTH_AMOUNT_2X: - iOffsetMult = 2; - break; - case FONT_SMOOTH_AMOUNT_4X: - iOffsetMult = 4; - break; - } - - m_pScaleBitmap->Clear(); - - if (!m_pFontRenderer.GetGlyph(m_pScaleBitmap, &pSlot->iHoriAdvance, &pSlot->iCharWidth, &pSlot->iCharHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, 0, 0, cChar, fontHintParams)) - { - return 0; - } - - pSlot->iCharWidth >>= iOffsetMult >> 1; - pSlot->iCharHeight >>= iOffsetMult >> 1; - - m_pScaleBitmap->BlitScaledTo8(pSlot->pGlyphBitmap.GetBuffer(), 0, 0, m_pScaleBitmap->GetWidth(), m_pScaleBitmap->GetHeight(), 0, 0, pSlot->pGlyphBitmap.GetWidth(), pSlot->pGlyphBitmap.GetHeight(), pSlot->pGlyphBitmap.GetWidth()); - } - else - { - if (!m_pFontRenderer.GetGlyph(&pSlot->pGlyphBitmap, &pSlot->iHoriAdvance, &pSlot->iCharWidth, &pSlot->iCharHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, 0, 0, cChar, fontHintParams)) - { - return 0; - } - } - - if (m_iSmoothMethod == FONT_SMOOTH_BLUR) - { - pSlot->pGlyphBitmap.Blur(m_iSmoothAmount); - } - - pSlot->dwUsage = m_dwUsage; - pSlot->cCurrentChar = cChar; - pSlot->glyphSize = glyphSize; - - m_pCacheTable.insert(AZStd::pair(GetCacheSlotKey(cChar, glyphSize), pSlot)); - - return 1; -} - -int CGlyphCache::UnCacheGlyph(uint32 cChar, const Vec2i& glyphSize) -{ - CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - if (pItor != m_pCacheTable.end()) - { - CCacheSlot* pSlot = pItor->second; - - pSlot->Reset(); - - m_pCacheTable.erase(pItor); - - return 1; - } - - return 0; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::GlyphCached(uint32 cChar, const Vec2i& glyphSize) -{ - return (m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)) != m_pCacheTable.end()); -} - -//------------------------------------------------------------------------------------------------- -CCacheSlot* CGlyphCache::GetLRUSlot() -{ - unsigned int dwMinUsage = 0xffffffff; - CCacheSlot* pLRUSlot = 0; - CCacheSlot* pSlot; - - CCacheSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->dwUsage == 0) - { - return pSlot; - } - else - { - if (pSlot->dwUsage < dwMinUsage) - { - pLRUSlot = pSlot; - dwMinUsage = pSlot->dwUsage; - } - } - - pItor++; - } - - return pLRUSlot; -} - -//------------------------------------------------------------------------------------------------- -CCacheSlot* CGlyphCache::GetMRUSlot() -{ - unsigned int dwMaxUsage = 0; - CCacheSlot* pMRUSlot = 0; - CCacheSlot* pSlot; - - CCacheSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - pSlot = *pItor; - - if (pSlot->dwUsage != 0) - { - if (pSlot->dwUsage > dwMaxUsage) - { - pMRUSlot = pSlot; - dwMaxUsage = pSlot->dwUsage; - } - } - - pItor++; - } - - return pMRUSlot; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::GetGlyph(CGlyphBitmap** pGlyph, int* piHoriAdvance, int* piWidth, int* piHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, uint32 cChar, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams) -{ - CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - if (pItor == m_pCacheTable.end()) - { - if (!PreCacheGlyph(cChar, glyphSize, fontHintParams)) - { - return 0; - } - } - - pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)); - - pItor->second->dwUsage = m_dwUsage++; - (*pGlyph) = &pItor->second->pGlyphBitmap; - - if (piHoriAdvance) - { - *piHoriAdvance = pItor->second->iHoriAdvance; - } - - if (piWidth) - { - *piWidth = pItor->second->iCharWidth; - } - - if (piHeight) - { - *piHeight = pItor->second->iCharHeight; - } - - iCharOffsetX = pItor->second->iCharOffsetX; - iCharOffsetY = pItor->second->iCharOffsetY; - - return 1; -} - -//------------------------------------------------------------------------------------------------- -Vec2 CGlyphCache::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph) -{ - return m_pFontRenderer.GetKerning(leftGlyph, rightGlyph); -} - -//------------------------------------------------------------------------------------------------- -float CGlyphCache::GetAscenderToHeightRatio() -{ - return m_pFontRenderer.GetAscenderToHeightRatio(); -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::CreateSlotList(int iListSize) -{ - for (int i = 0; i < iListSize; i++) - { - CCacheSlot* pCacheSlot = new CCacheSlot; - - if (!pCacheSlot) - { - return 0; - } - - if (!pCacheSlot->pGlyphBitmap.Create(m_iGlyphBitmapWidth, m_iGlyphBitmapHeight)) - { - delete pCacheSlot; - - return 0; - } - - pCacheSlot->Reset(); - - pCacheSlot->iCacheSlot = i; - - m_pSlotList.push_back(pCacheSlot); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -int CGlyphCache::ReleaseSlotList() -{ - CCacheSlotListItor pItor = m_pSlotList.begin(); - - while (pItor != m_pSlotList.end()) - { - (*pItor)->pGlyphBitmap.Release(); - - delete (*pItor); - - pItor = m_pSlotList.erase(pItor); - } - - return 1; -} - -//------------------------------------------------------------------------------------------------- -CryFont::GlyphCache::CCacheTableKey CGlyphCache::GetCacheSlotKey(uint32 cChar, const Vec2i& glyphSize) const -{ - const Vec2i clampedGlyphSize = CFontTexture::ClampGlyphSize(glyphSize, m_iGlyphBitmapWidth, m_iGlyphBitmapHeight); - return CryFont::GlyphCache::CCacheTableKey(clampedGlyphSize, cChar); -} - -#endif // #if !defined(USE_NULLFONT_ALWAYS) diff --git a/Code/CryEngine/CryFont/GlyphCache.h b/Code/CryEngine/CryFont/GlyphCache.h deleted file mode 100644 index c0cc1db555..0000000000 --- a/Code/CryEngine/CryFont/GlyphCache.h +++ /dev/null @@ -1,200 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. -// Purpose: -// - Manage and cache glyphs, retrieving them from the renderer as needed - -#ifndef CRYINCLUDE_CRYFONT_GLYPHCACHE_H -#define CRYINCLUDE_CRYFONT_GLYPHCACHE_H -#pragma once - -#if !defined(USE_NULLFONT_ALWAYS) - -#include -#include "GlyphBitmap.h" -#include "FontRenderer.h" -#include "CryFont.h" -#include - -//! Glyph cache slots store the bitmap buffer and glyph metadata from FreeType. -//! -//! This bitmap buffer is eventually copied to a CFontTexture texture buffer. -//! A glyph cache slot bitmap buffer only holds a single glyph, whereas the -//! CFontTexture stores multiple glyphs in a grid (row/col) format. -typedef struct CCacheSlot -{ - Vec2i glyphSize = CCryFont::defaultGlyphSize; //!< The render resolution of the glyph in the glyph bitmap - unsigned int dwUsage; - int iCacheSlot; - int iHoriAdvance; //!< Advance width. See FT_Glyph_Metrics::horiAdvance. - uint32 cCurrentChar; - - uint8 iCharWidth; //!< Glyph width (in pixel) - uint8 iCharHeight; //!< Glyph height (in pixel) - AZ::s32 iCharOffsetX; //!< Glyph's left-side bearing (in pixels). See FT_GlyphSlotRec::bitmap_left. - AZ::s32 iCharOffsetY; //!< Glyph's top bearing (in pixels). See FT_GlyphSlotRec::bitmap_top. - - CGlyphBitmap pGlyphBitmap; //!< Contains a buffer storing a copy of the glyph from FreeType - - void Reset() - { - dwUsage = 0; - cCurrentChar = ~0; - - iCharWidth = 0; - iCharHeight = 0; - iCharOffsetX = 0; - iCharOffsetY = 0; - - pGlyphBitmap.Clear(); - } - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(this, sizeof(*this)); - pSizer->AddObject(pGlyphBitmap); - } -} CCacheSlot; - -namespace CryFont -{ - namespace GlyphCache - { - //! Height and width pair for glyph size mapping - typedef Vec2i CCacheTableGlyphSizeType; - - //! Pair for mapping a height and width size to a UTF32 character/glyph - typedef AZStd::pair CCacheTableKey; - - //! Hasher for glyph cache table keys (glyphsize-char code pair) - //! - //! Instead of creating our own custom hash, the types are broken down to their - //! native types (ints) and passed to existing hashes that handle those types. - struct HashGlyphCacheTableKey - { - typedef CCacheTableKey ArgumentType; - typedef AZStd::size_t ResultType; - typedef AZStd::pair Int32Pair; - typedef AZStd::pair Int32PairU32Pair; - ResultType operator()(const ArgumentType& value) const - { - AZStd::hash pairHash; - return pairHash(Int32PairU32Pair(Int32Pair(value.first.x, value.first.y), value.second)); - } - }; - } -} - -//! Maps size-speicifc UTF32 glyphs to their corresponding cache slots -typedef AZStd::unordered_map CCacheTable; - -typedef std::vector CCacheSlotList; -typedef std::vector::iterator CCacheSlotListItor; - - -#ifdef WIN64 -#undef GetCharWidth -#undef GetCharHeight -#endif - -//! The glyph cache maps UTF32 codepoints to their corresponding FreeType data. -//! -//! This cache is used to associate font glyph info (read from FreeType) with -//! UTF32 codepoints. Ultimately the glyph info will be read into a font texture -//! (CFontTexture) to avoid future FreeType lookups. -//! -//! If a CFontTexture is missing a glyph that is currently stored in the glyph -//! cache, the cached data can be returned instead of having to be rendered from -//! FreeType again. -//! -//! \sa CFontTexture -class CGlyphCache -{ -public: - CGlyphCache(); - ~CGlyphCache(); - - int Create(int iCacheSize, int iGlyphBitmapWidth, int iGlyphBitmapHeight, int iSmoothMethod, int iSmoothAmount, float sizeRatio); - int Release(); - - int LoadFontFromFile(const string& szFileName); - int LoadFontFromMemory(unsigned char* pFileBuffer, int iDataSize); - int ReleaseFont(); - - int SetEncoding(FT_Encoding pEncoding) { return m_pFontRenderer.SetEncoding(pEncoding); }; - FT_Encoding GetEncoding() { return m_pFontRenderer.GetEncoding(); }; - - int GetGlyphBitmapSize(int* pWidth, int* pHeight); - void SetGlyphBitmapSize(int width, int height, float sizeRatio); - - int PreCacheGlyph(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - int UnCacheGlyph(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - int GlyphCached(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize); - - CCacheSlot* GetLRUSlot(); - CCacheSlot* GetMRUSlot(); - - //! Obtains glyph information for the given UTF32 codepoint. - //! This information is obtained from a CCacheSlot that corresponds to - //! the given codepoint. If the codepoint doesn't exist within the cache - //! table (m_pCacheTable), then the information is obtain from FreeType - //! directly via CFontRenderer. - //! - //! Ultimately the glyph bitmap is copied into a font texture - //! (CFontTexture). Once the glyph is copied into the font texture then - //! the font texture is referenced directly rather than relying on the - //! glyph cache or FreeType. - //! - //! \sa CFontRenderer::GetGlyph, CFontTexture::UpdateSlot - int GetGlyph(CGlyphBitmap** pGlyph, int* piHoriAdvance, int* piWidth, int* piHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams()); - - void GetMemoryUsage(ICrySizer* pSizer) const - { - pSizer->AddObject(m_pSlotList); - //pSizer->AddContainer(m_pCacheTable); - pSizer->AddObject(m_pScaleBitmap); - pSizer->AddObject(m_pFontRenderer); - } - - bool GetMonospaced() const { return m_pFontRenderer.GetMonospaced(); } - - Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph); - - float GetAscenderToHeightRatio(); - -private: - - //! Returns a key for the cache table where the given char is mapped at the given size. - CryFont::GlyphCache::CCacheTableKey GetCacheSlotKey(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const; - - int CreateSlotList(int iListSize); - int ReleaseSlotList(); - - CCacheSlotList m_pSlotList; - CCacheTable m_pCacheTable; - - int m_iGlyphBitmapWidth; - int m_iGlyphBitmapHeight; - - int m_iSmoothMethod; - int m_iSmoothAmount; - - CGlyphBitmap* m_pScaleBitmap; - - CFontRenderer m_pFontRenderer; - - unsigned int m_dwUsage; -}; - -#endif // #if !defined(USE_NULLFONT_ALWAYS) - -#endif // CRYINCLUDE_CRYFONT_GLYPHCACHE_H diff --git a/Code/CryEngine/CryFont/ICryFont.cpp b/Code/CryEngine/CryFont/ICryFont.cpp deleted file mode 100644 index dfbaf65335..0000000000 --- a/Code/CryEngine/CryFont/ICryFont.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Create the font interface. - - -#include "CryFont_precompiled.h" - -#include -#include -#include - -#include "CryFont.h" -#if defined(USE_NULLFONT) -#include "NullFont.h" -#endif - -////////////////////////////////////////////////////////////////////////// -struct CSystemEventListner_Font - : public ISystemEventListener -{ -public: - virtual void OnSystemEvent(ESystemEvent event, [[maybe_unused]] UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam) - { - switch (event) - { - case ESYSTEM_EVENT_LEVEL_POST_UNLOAD: - { - STLALLOCATOR_CLEANUP; - break; - } - } - } -}; -static CSystemEventListner_Font g_system_event_listener_font; - -/////////////////////////////////////////////// -extern "C" ICryFont * CreateCryFontInterface(ISystem * pSystem) -{ - ModuleInitISystem(pSystem, "CryFont"); - - if (gEnv->IsDedicated()) - { -#if defined(USE_NULLFONT) - return new CCryNullFont(); -#else - // The NULL font implementation must be present for all platforms - // supporting running as a pure dedicated server. - pSystem->GetILog()->LogError("Missing NULL font implementation for dedicated server"); - return NULL; -#endif - } - else - { -#if defined(USE_NULLFONT) && defined(USE_NULLFONT_ALWAYS) - return new CCryNullFont(); -#else - pSystem->GetISystemEventDispatcher()->RegisterListener(&g_system_event_listener_font); - return new CCryFont(pSystem); -#endif - } -} - -////////////////////////////////////////////////////////////////////////// -class CEngineModule_CryFont - : public IEngineModule -{ - CRYINTERFACE_SIMPLE(IEngineModule) - CRYGENERATE_SINGLETONCLASS(CEngineModule_CryFont, "EngineModule_CryFont", 0x6758643f43214957, 0x9b920d898d31f434) - - ////////////////////////////////////////////////////////////////////////// - virtual const char* GetName() const { - return "CryFont"; - }; - virtual const char* GetCategory() const { return "CryEngine"; }; - - ////////////////////////////////////////////////////////////////////////// - virtual bool Initialize(SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) - { - ISystem* pSystem = env.pSystem; - env.pCryFont = CreateCryFontInterface(pSystem); - return env.pCryFont != 0; - } -}; - -CRYREGISTER_SINGLETON_CLASS(CEngineModule_CryFont) - -CEngineModule_CryFont::CEngineModule_CryFont() -{ -}; - -CEngineModule_CryFont::~CEngineModule_CryFont() -{ -}; diff --git a/Code/CryEngine/CryFont/NullFont.cpp b/Code/CryEngine/CryFont/NullFont.cpp deleted file mode 100644 index bddca1bbed..0000000000 --- a/Code/CryEngine/CryFont/NullFont.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Dummy font implementation (dedicated server) - -#include "CryFont_precompiled.h" - -#if defined(USE_NULLFONT) - -#include "NullFont.h" - -CNullFont CCryNullFont::ms_nullFont; - -#endif // USE_NULLFONT diff --git a/Code/CryEngine/CryFont/NullFont.h b/Code/CryEngine/CryFont/NullFont.h deleted file mode 100644 index 94fceeb9b0..0000000000 --- a/Code/CryEngine/CryFont/NullFont.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Dummy font implementation (dedicated server) - - -#ifndef CRYINCLUDE_CRYFONT_NULLFONT_H -#define CRYINCLUDE_CRYFONT_NULLFONT_H -#pragma once - - -#if defined(USE_NULLFONT) - -#include - -class CNullFont - : public IFFont -{ -public: - CNullFont() {} - virtual ~CNullFont() {} - - virtual int32 AddRef() { return 0; }; - virtual int32 Release() { return 0; }; - - virtual bool Load([[maybe_unused]] const char* pFontFilePath, [[maybe_unused]] unsigned int width, [[maybe_unused]] unsigned int height, [[maybe_unused]] unsigned int widthNumSlots, [[maybe_unused]] unsigned int heightNumSlots, [[maybe_unused]] unsigned int flags, [[maybe_unused]] float sizeRatio) { return true; } - virtual bool Load([[maybe_unused]] const char* pXMLFile) { return true; } - virtual void Free() {} - - virtual void DrawString([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - virtual void DrawString([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - - virtual void DrawStringW([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - virtual void DrawStringW([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {} - - virtual Vec2 GetTextSize([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return Vec2(0.0f, 0.0f); } - virtual Vec2 GetTextSizeW([[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return Vec2(0.0f, 0.0f); } - - virtual size_t GetTextLength([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine) const { return 0; } - virtual size_t GetTextLengthW([[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine) const { return 0; } - - virtual void WrapText(string& result, [[maybe_unused]] float maxWidth, const char* pStr, [[maybe_unused]] const STextDrawContext& ctx) { result = pStr; } - virtual void WrapTextW(wstring& result, [[maybe_unused]] float maxWidth, const wchar_t* pStr, [[maybe_unused]] const STextDrawContext& ctx) { result = pStr; } - - virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - - virtual void GetGradientTextureCoord([[maybe_unused]] float& minU, [[maybe_unused]] float& minV, [[maybe_unused]] float& maxU, [[maybe_unused]] float& maxV) const {} - - virtual unsigned int GetEffectId([[maybe_unused]] const char* pEffectName) const { return 0; } - virtual unsigned int GetNumEffects() const { return 0; } - virtual const char* GetEffectName([[maybe_unused]] unsigned int effectId) const { return nullptr; } - virtual Vec2 GetMaxEffectOffset([[maybe_unused]] unsigned int effectId) const { return Vec2(); } - virtual bool DoesEffectHaveTransparency([[maybe_unused]] unsigned int effectId) const { return false; } - - virtual void AddCharsToFontTexture([[maybe_unused]] const char* pChars, [[maybe_unused]] int glyphSizeX, [[maybe_unused]] int glyphSizeY) override {} - virtual Vec2 GetKerning([[maybe_unused]] uint32_t leftGlyph, [[maybe_unused]] uint32_t rightGlyph, [[maybe_unused]] const STextDrawContext& ctx) const override { return Vec2(); } - virtual float GetAscender([[maybe_unused]] const STextDrawContext& ctx) const override { return 0.0f; } - virtual float GetBaseline([[maybe_unused]] const STextDrawContext& ctx) const override { return 0.0f; } - virtual float GetSizeRatio() const override { return IFFontConstants::defaultSizeRatio; } - virtual uint32 GetNumQuadsForText([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return 0; } - virtual uint32 WriteTextQuadsToBuffers([[maybe_unused]] SVF_P2F_C4B_T2F_F4B* verts, [[maybe_unused]] uint16* indices, [[maybe_unused]] uint32 maxQuads, [[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return 0; } - virtual int GetFontTextureId() { return -1; } - virtual uint32 GetFontTextureVersion() { return 0; } -}; - -class CCryNullFont - : public ICryFont -{ -public: - virtual void Release() {} - virtual IFFont* NewFont([[maybe_unused]] const char* pFontName) { return &ms_nullFont; } - virtual IFFont* GetFont([[maybe_unused]] const char* pFontName) const { return &ms_nullFont; } - virtual FontFamilyPtr LoadFontFamily([[maybe_unused]] const char* pFontFamilyName) override { CRY_ASSERT(false); return nullptr; } - virtual FontFamilyPtr GetFontFamily([[maybe_unused]] const char* pFontFamilyName) override { CRY_ASSERT(false); return nullptr; } - virtual void AddCharsToFontTextures(FontFamilyPtr pFontFamily, [[maybe_unused]] const char* pChars, [[maybe_unused]] int glyphSizeX, [[maybe_unused]] int glyphSizeY) override {}; - virtual void SetRendererProperties([[maybe_unused]] IRenderer* pRenderer) {} - virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {} - virtual string GetLoadedFontNames() const { return ""; } - virtual void OnLanguageChanged() override { } - virtual void ReloadAllFonts() override { } - -private: - static CNullFont ms_nullFont; -}; - -#endif // USE_NULLFONT - -#endif // CRYINCLUDE_CRYFONT_NULLFONT_H diff --git a/Code/CryEngine/CryFont/Platform/Linux/platform_linux.cmake b/Code/CryEngine/CryFont/Platform/Linux/platform_linux.cmake deleted file mode 100644 index bafe20e506..0000000000 --- a/Code/CryEngine/CryFont/Platform/Linux/platform_linux.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -# Platform specific cmake file for configuring target compiler/link properties -# based on the active platform -# NOTE: functions in cmake are global, therefore adding functions to this file -# is being avoided to prevent overriding functions declared in other targets platfrom -# specific cmake files diff --git a/Code/CryEngine/CryFont/cryfont_files.cmake b/Code/CryEngine/CryFont/cryfont_files.cmake deleted file mode 100644 index f46a5b5b44..0000000000 --- a/Code/CryEngine/CryFont/cryfont_files.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - CryFont.cpp - FFont.cpp - FFontXML.cpp - FontRenderer.cpp - FontTexture.cpp - GlyphBitmap.cpp - GlyphCache.cpp - ICryFont.cpp - NullFont.cpp - CryFont.h - FBitmap.h - FFont.h - FontRenderer.h - FontTexture.h - GlyphBitmap.h - GlyphCache.h - NullFont.h - resource.h - CryFont_precompiled.h - CryFont_precompiled.cpp -) diff --git a/Code/CryEngine/CryFont/resource.h b/Code/CryEngine/CryFont/resource.h deleted file mode 100644 index ed88839421..0000000000 --- a/Code/CryEngine/CryFont/resource.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#define VS_VERSION_INFO 1 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/Code/CryEngine/CrySystem/CMakeLists.txt b/Code/CryEngine/CrySystem/CMakeLists.txt index e7816cc1cd..1a5593e5d8 100644 --- a/Code/CryEngine/CrySystem/CMakeLists.txt +++ b/Code/CryEngine/CrySystem/CMakeLists.txt @@ -90,8 +90,6 @@ ly_add_target( AZ::AzCore Legacy::CryCommon Legacy::CryCommon.EngineSettings.Static - RUNTIME_DEPENDENCIES - Legacy::CryFont ) ################################################################################ diff --git a/Code/CryEngine/CrySystem/CPUDetect.cpp b/Code/CryEngine/CrySystem/CPUDetect.cpp index 9af68a1854..6d924a1514 100644 --- a/Code/CryEngine/CrySystem/CPUDetect.cpp +++ b/Code/CryEngine/CrySystem/CPUDetect.cpp @@ -52,11 +52,7 @@ # define cpuid(op, eax, ebx, ecx, edx) __asm__("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (op) : "cc"); #endif -#if defined(AZ_MONOLITHIC_BUILD) -extern int g_CpuFlags; -#else int g_CpuFlags; -#endif struct SAutoMaxPriority { diff --git a/Code/CryEngine/CrySystem/System.cpp b/Code/CryEngine/CrySystem/System.cpp index a48f63afdf..827a393103 100644 --- a/Code/CryEngine/CrySystem/System.cpp +++ b/Code/CryEngine/CrySystem/System.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include @@ -1162,31 +1161,6 @@ void CSystem::SleepIfInactive() { return; } - -#if defined(WIN32) - if (!AZ::Interface::Get()) - { - WIN_HWND hRendWnd = GetIRenderer()->GetHWND(); - if (!hRendWnd) - { - return; - } - - AZ_TRACE_METHOD(); - // Loop here waiting for window to be activated. - for (int nLoops = 0; nLoops < 5; nLoops++) - { - WIN_HWND hActiveWnd = ::GetActiveWindow(); - if (hActiveWnd == hRendWnd) - { - break; - } - - AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::PumpSystemEventLoopUntilEmpty); - Sleep(5); - } - } -#endif } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/CryEngine/CrySystem/System.h b/Code/CryEngine/CrySystem/System.h index 47fdb362e9..e4fcc82552 100644 --- a/Code/CryEngine/CrySystem/System.h +++ b/Code/CryEngine/CrySystem/System.h @@ -676,17 +676,11 @@ private: //! @name Initialization routines //@{ bool InitConsole(); - bool InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams); - - bool InitFont(const SSystemInitParams& initParams); bool InitFileSystem(); bool InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams); bool InitStreamEngine(); - bool Init3DEngine(const SSystemInitParams& initParams); bool InitAudioSystem(const SSystemInitParams& initParams); bool InitShine(const SSystemInitParams& initParams); - bool OpenRenderLibrary(int type, const SSystemInitParams& initParams); - bool OpenRenderLibrary(const char* t_rend, const SSystemInitParams& initParams); //@} @@ -738,9 +732,6 @@ private: bool GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize); #endif - //! \brief Initializes the given IFFont member variable with the given name (internal use only). - bool LoadFontInternal(IFFont*& font, const string& fontName); - public: void EnableFloatExceptions(int type); diff --git a/Code/CryEngine/CrySystem/SystemInit.cpp b/Code/CryEngine/CrySystem/SystemInit.cpp index fcbf0b8215..826810ef8a 100644 --- a/Code/CryEngine/CrySystem/SystemInit.cpp +++ b/Code/CryEngine/CrySystem/SystemInit.cpp @@ -43,8 +43,6 @@ #include #include -#include "CryFontBus.h" - #include #include @@ -70,7 +68,6 @@ #include #include #include -#include #include #include @@ -247,24 +244,6 @@ CUNIXConsole* pUnixConsole; #define LOCALIZATION_TRANSLATIONS_LIST_FILE_NAME "Libs/Localization/localization.xml" -#define LOAD_LEGACY_RENDERER_FOR_EDITOR false // If you set this to true you must also set 'ed_useAtomNativeViewport' to false (see /Code/Sandbox/Editor/ViewManager.cpp) -#define LOAD_LEGACY_RENDERER_FOR_LAUNCHER false - -////////////////////////////////////////////////////////////////////////// -// Where possible, these are defaults used to initialize cvars -// System.cfg can then be used to override them -// This includes the Game DLL, although it is loaded elsewhere - -#define DLL_FONT "CryFont" -#define DLL_3DENGINE "Cry3DEngine" -#define DLL_RENDERER_DX9 "CryRenderD3D9" -#define DLL_RENDERER_DX11 "CryRenderD3D11" -#define DLL_RENDERER_DX12 "CryRenderD3D12" -#define DLL_RENDERER_METAL "CryRenderMetal" -#define DLL_RENDERER_GL "CryRenderGL" -#define DLL_RENDERER_NULL "CryRenderNULL" -#define DLL_SHINE "LyShine" - ////////////////////////////////////////////////////////////////////////// #if defined(WIN32) || defined(LINUX) || defined(APPLE) # define DLL_MODULE_INIT_ISYSTEM "ModuleInitISystem" @@ -1079,58 +1058,6 @@ void CSystem::ShutdownModuleLibraries() #endif // !defined(AZ_MONOLITHIC_BUILD) } -////////////////////////////////////////////////////////////////////////// -bool CSystem::OpenRenderLibrary([[maybe_unused]] const char* t_rend, const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - -#if defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_6 -#include AZ_RESTRICTED_FILE(SystemInit_cpp) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - - if (gEnv->IsDedicated()) - { - return OpenRenderLibrary(R_NULL_RENDERER, initParams); - } - - if (AZ::Interface::Get()) - { - return OpenRenderLibrary(R_DX11_RENDERER, initParams); - } - else if (azstricmp(t_rend, "DX9") == 0) - { - return OpenRenderLibrary(R_DX9_RENDERER, initParams); - } - else if (azstricmp(t_rend, "DX11") == 0) - { - return OpenRenderLibrary(R_DX11_RENDERER, initParams); - } - else if (azstricmp(t_rend, "DX12") == 0) - { - return OpenRenderLibrary(R_DX12_RENDERER, initParams); - } - else if (azstricmp(t_rend, "GL") == 0) - { - return OpenRenderLibrary(R_GL_RENDERER, initParams); - } - else if (azstricmp(t_rend, "METAL") == 0) - { - return OpenRenderLibrary(R_METAL_RENDERER, initParams); - } - else if (azstricmp(t_rend, "NULL") == 0) - { - return OpenRenderLibrary(R_NULL_RENDERER, initParams); - } - - AZ_Assert(false, "Unknown renderer type: %s", t_rend); - return false; -#endif -} - ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// @@ -1220,126 +1147,6 @@ wstring GetErrorStringUnsupportedGPU(const char* gpuName, unsigned int gpuVendor } #endif -bool CSystem::OpenRenderLibrary(int type, const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION; -#if defined(WIN32) || defined(WIN64) - if (!gEnv->IsDedicated()) - { - unsigned int gpuVendorId = 0, gpuDeviceId = 0, totVidMem = 0; - char gpuName[256]; - Win32SysInspect::DXFeatureLevel featureLevel = Win32SysInspect::DXFL_Undefined; - Win32SysInspect::GetGPUInfo(gpuName, sizeof(gpuName), gpuVendorId, gpuDeviceId, totVidMem, featureLevel); - - if (m_env.IsEditor()) - { -#if defined(EXTERNAL_CRASH_REPORTING) - CrashHandler::CrashHandlerBase::AddAnnotation("dx.feature.level", Win32SysInspect::GetFeatureLevelAsString(featureLevel)); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.name", gpuName); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.vendorId", std::to_string(gpuVendorId)); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.deviceId", std::to_string(gpuDeviceId)); - CrashHandler::CrashHandlerBase::AddAnnotation("gpu.memory", std::to_string(totVidMem)); -#endif - } - else - { - if (featureLevel < Win32SysInspect::DXFL_11_0) - { - const char logMsgFmt[] ("Unsupported GPU configuration!\n- %s (vendor = 0x%.4x, device = 0x%.4x)\n- Dedicated video memory: %d MB\n- Feature level: %s\n"); - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, logMsgFmt, gpuName, gpuVendorId, gpuDeviceId, totVidMem >> 20, GetFeatureLevelAsString(featureLevel)); - -#if !defined(_RELEASE) - const bool allowPrompts = m_env.pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "noprompt") == 0; -#else - const bool allowPrompts = true; -#endif // !defined(_RELEASE) - if (allowPrompts) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Asking user if they wish to continue..."); - const int mbRes = MessageBoxW(0, GetErrorStringUnsupportedGPU(gpuName, gpuVendorId, gpuDeviceId).c_str(), L"Open 3D Engine", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_DEFAULT_DESKTOP_ONLY); - if (mbRes == IDCANCEL) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to cancel startup due to unsupported GPU."); - return false; - } - } - else - { -#if !defined(_RELEASE) - const bool obeyGPUCheck = m_env.pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "anygpu") == 0; -#else - const bool obeyGPUCheck = true; -#endif // !defined(_RELEASE) - if (obeyGPUCheck) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "No prompts allowed and unsupported GPU check active. Treating unsupported GPU as error and exiting."); - return false; - } - } - - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to continue despite unsupported GPU!"); - } - } - } -#endif -#if defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_7 -#include AZ_RESTRICTED_FILE(SystemInit_cpp) -#endif - - if (gEnv->IsDedicated()) - { - type = R_NULL_RENDERER; - } - const char* libname = ""; - if (AZ::Interface::Get()) - { - libname = DLL_RENDERER_NULL; - } - else if (type == R_DX9_RENDERER) - { - libname = DLL_RENDERER_DX9; - } - else if (type == R_DX11_RENDERER) - { - libname = DLL_RENDERER_DX11; - } - else if (type == R_DX12_RENDERER) - { - libname = DLL_RENDERER_DX12; - } - else if (type == R_NULL_RENDERER) - { - libname = DLL_RENDERER_NULL; - } - else if (type == R_GL_RENDERER) - { - libname = DLL_RENDERER_GL; - } - else if (type == R_METAL_RENDERER) - { - libname = DLL_RENDERER_METAL; - } - else - { - AZ_Assert(false, "Renderer did not initialize correctly; no valid renderer specified."); - return false; - } - - if (!InitializeEngineModule(libname, "EngineModule_CryRenderer", initParams)) - { - return false; - } - - if (!m_env.pRenderer) - { - AZ_Assert(false, "Renderer did not initialize correctly; it could not be found in the system environment."); - return false; - } - - return true; -} - ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// bool CSystem::InitConsole() @@ -1391,123 +1198,6 @@ ICVar* CSystem::attachVariable (const char* szVarName, int* pContainer, const ch return pVar; } -///////////////////////////////////////////////////////////////////////////////// -bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - - if (m_pUserCallback) - { - m_pUserCallback->OnInitProgress("Initializing Renderer..."); - } - - if (m_bEditor) - { - m_env.pConsole->GetCVar("r_Width"); - - // save current screen width/height/bpp, so they can be restored on shutdown - m_iWidth = m_env.pConsole->GetCVar("r_Width")->GetIVal(); - m_iHeight = m_env.pConsole->GetCVar("r_Height")->GetIVal(); - m_iColorBits = m_env.pConsole->GetCVar("r_ColorBits")->GetIVal(); - } - - if (!OpenRenderLibrary(m_rDriver->GetString(), initParams)) - { - return false; - } - -#if defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_ANDROID) - if (m_rWidthAndHeightAsFractionOfScreenSize->GetFlags() & VF_WASINCONFIG) - { - int displayWidth = 0; - int displayHeight = 0; - if (GetPrimaryPhysicalDisplayDimensions(displayWidth, displayHeight)) - { - // Ideally we would probably want to clamp this at the source, - // but I don't believe cvars support specifying a valid range. - float scaleFactor = 1.0f; - - if(IsTablet()) - { - scaleFactor = AZ::GetClamp(m_rTabletWidthAndHeightAsFractionOfScreenSize->GetFVal(), 0.1f, 1.0f); - } - else - { - scaleFactor = AZ::GetClamp(m_rWidthAndHeightAsFractionOfScreenSize->GetFVal(), 0.1f, 1.0f); - } - - displayWidth *= scaleFactor; - displayHeight *= scaleFactor; - - const int maxWidth = m_rMaxWidth->GetIVal(); - if (maxWidth > 0 && maxWidth < displayWidth) - { - const float widthScaleFactor = static_cast(maxWidth) / static_cast(displayWidth); - displayWidth *= widthScaleFactor; - displayHeight *= widthScaleFactor; - } - - const int maxHeight = m_rMaxHeight->GetIVal(); - if (maxHeight > 0 && maxHeight < displayHeight) - { - const float heightScaleFactor = static_cast(maxHeight) / static_cast(displayHeight); - displayWidth *= heightScaleFactor; - displayHeight *= heightScaleFactor; - } - - m_rWidth->Set(displayWidth); - m_rHeight->Set(displayHeight); - } - } -#endif // defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_ANDROID) - - if (m_env.pRenderer) - { - // This is crucial as textures suffix are hard coded to context and we need to initialize - // the texture semantics to look it up. - m_env.pRenderer->InitTexturesSemantics(); - -#ifdef WIN32 - SCustomRenderInitArgs args; - args.appStartedFromMediaCenter = strstr(initParams.szSystemCmdLine, "ReLaunchMediaCenter") != 0; - - m_hWnd = m_env.pRenderer->Init(0, 0, m_rWidth->GetIVal(), m_rHeight->GetIVal(), m_rColorBits->GetIVal(), m_rDepthBits->GetIVal(), m_rStencilBits->GetIVal(), m_rFullscreen->GetIVal() ? true : false, initParams.bEditor, hinst, hwnd, false, &args, initParams.bShaderCacheGen); - //Timur, Not very clean code, we need to push new hwnd value to the system init params, so other modules can used when initializing. - (const_cast(&initParams))->hWnd = m_hWnd; - - - bool retVal = (initParams.bShaderCacheGen || m_hWnd != 0); - AZ_Assert(retVal, "Renderer failed to initialize correctly."); - return retVal; -#else // WIN32 - WIN_HWND h = m_env.pRenderer->Init(0, 0, m_rWidth->GetIVal(), m_rHeight->GetIVal(), m_rColorBits->GetIVal(), m_rDepthBits->GetIVal(), m_rStencilBits->GetIVal(), m_rFullscreen->GetIVal() ? true : false, initParams.bEditor, hinst, hwnd, false, nullptr, initParams.bShaderCacheGen); - -#if (defined(LINUX) && !defined(AZ_PLATFORM_ANDROID)) - return true; -#define AZ_RESTRICTED_SECTION_IMPLEMENTED -#elif defined(AZ_RESTRICTED_PLATFORM) -#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_8 -#include AZ_RESTRICTED_FILE(SystemInit_cpp) -#endif -#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED) -#undef AZ_RESTRICTED_SECTION_IMPLEMENTED -#else - bool retVal = (initParams.bShaderCacheGen || h != 0); - if (retVal) - { - return true; - } - - AZ_Assert(false, "Renderer failed to initialize correctly."); - return false; -#endif -#endif - } - return true; -} - - - ///////////////////////////////////////////////////////////////////////////////// bool CSystem::InitFileSystem() { @@ -1662,68 +1352,6 @@ bool CSystem::InitStreamEngine() return true; } -///////////////////////////////////////////////////////////////////////////////// -bool CSystem::InitFont(const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - - bool fontInited = false; - AZ::CryFontCreationRequestBus::BroadcastResult(fontInited, &AZ::CryFontCreationRequests::CreateCryFont, m_env, initParams); - if (!fontInited && !InitializeEngineModule(DLL_FONT, "EngineModule_CryFont", initParams)) - { - return false; - } - - if (!m_env.pCryFont) - { - AZ_Assert(false, "Font System did not initialize correctly; it could not be found in the system environment"); - return false; - } - - if (gEnv->IsDedicated()) - { - return true; - } - - if (!LoadFontInternal(m_pIFont, "default")) - { - return false; - } - - if (!LoadFontInternal(m_pIFontUi, "default-ui")) - { - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CSystem::Init3DEngine(const SSystemInitParams& initParams) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - - if (!InitializeEngineModule(DLL_3DENGINE, "EngineModule_Cry3DEngine", initParams)) - { - return false; - } - - if (!m_env.p3DEngine) - { - AZ_Assert(false, "3D Engine did not initialize correctly; it could not be found in the system environment"); - return false; - } - - if (!m_env.p3DEngine->Init()) - { - return false; - } - m_pProcess = m_env.p3DEngine; - m_pProcess->SetFlags(PROC_3DENGINE); - - return true; -} - ////////////////////////////////////////////////////////////////////////// bool CSystem::InitAudioSystem(const SSystemInitParams& initParams) { @@ -2785,42 +2413,6 @@ AZ_POP_DISABLE_WARNING } InlineInitializationProcessing("CSystem::Init InitLocalizations"); - ////////////////////////////////////////////////////////////////////////// - // RENDERER - ////////////////////////////////////////////////////////////////////////// - const bool loadLegacyRenderer = gEnv->IsEditor() ? - LOAD_LEGACY_RENDERER_FOR_EDITOR : - LOAD_LEGACY_RENDERER_FOR_LAUNCHER; - if (loadLegacyRenderer && !startupParams.bSkipRenderer) - { - AZ_Assert(CryMemory::IsHeapValid(), "CryMemory must be valid before initializing renderer."); - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Renderer initialization"); - - if (!InitRenderer(m_hInst, m_hWnd, startupParams)) - { - return false; - } - AZ_Assert(CryMemory::IsHeapValid(), "CryMemory must be valid after initializing renderer."); - if (m_env.pRenderer) - { - bool bMultiGPUEnabled = false; - m_env.pRenderer->EF_Query(EFQ_MultiGPUEnabled, bMultiGPUEnabled); - if (bMultiGPUEnabled) - { - LoadConfiguration("mgpu.cfg"); - } - } - - InlineInitializationProcessing("CSystem::Init InitRenderer"); - - if (m_env.pCryFont) - { - m_env.pCryFont->SetRendererProperties(m_env.pRenderer); - } - - AZ_Assert(m_env.pRenderer || startupParams.bSkipRenderer, "The renderer did not initialize correctly."); - } - #if !defined(AZ_RELEASE_BUILD) && defined(AZ_PLATFORM_ANDROID) m_thermalInfoHandler = AZStd::make_unique(); #endif @@ -2869,21 +2461,6 @@ AZ_POP_DISABLE_WARNING m_env.pRenderer->SetViewport(0, 0, screenWidth, screenHeight); - // Skip splash screen rendering - if (!AZ::Interface::Get()) - { - // make sure it's rendered in full screen mode when triple buffering is enabled as well - for (size_t n = 0; n < 3; n++) - { - m_env.pRenderer->BeginFrame(); - m_env.pRenderer->SetCullMode(R_CULL_NONE); - m_env.pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST); - m_env.pRenderer->Draw2dImageStretchMode(true); - m_env.pRenderer->Draw2dImage(x * vx, y * vy, w * vx, h * vy, pTex->GetTextureID(), 0.0f, 1.0f, 1.0f, 0.0f); - m_env.pRenderer->Draw2dImageStretchMode(false); - m_env.pRenderer->EndFrame(); - } - } #if defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_MAC) // Pump system events in order to update the screen AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::PumpSystemEventLoopUntilEmpty); @@ -2928,24 +2505,10 @@ AZ_POP_DISABLE_WARNING } } - ////////////////////////////////////////////////////////////////////////// - // FONT - ////////////////////////////////////////////////////////////////////////// - if (!startupParams.bSkipFont) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Font initialization"); - if (!InitFont(startupParams)) - { - return false; - } - } - InlineInitializationProcessing("CSystem::Init InitFonts"); - - // The last update to the loading screen message was 'Initializing CryFont...' // Compiling the default system textures can be the lengthiest portion of // editor initialization, so it is useful to inform users that they are waiting on - // the necessary default textures to compile, and that they are not waiting on CryFont. + // the necessary default textures to compile. if (m_pUserCallback) { m_pUserCallback->OnInitProgress("First time asset processing - may take a minute..."); @@ -3040,28 +2603,6 @@ AZ_POP_DISABLE_WARNING return false; } - ////////////////////////////////////////////////////////////////////////// - // Init 3d engine - ////////////////////////////////////////////////////////////////////////// - if (loadLegacyRenderer && !startupParams.bSkipRenderer && !startupParams.bShaderCacheGen) - { - AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Initializing 3D Engine"); - INDENT_LOG_DURING_SCOPE(); - - if (!Init3DEngine(startupParams)) - { - return false; - } - - // try flush to keep renderer busy - if (m_env.pRenderer) - { - m_env.pRenderer->TryFlush(); - } - - InlineInitializationProcessing("CSystem::Init Init3DEngine"); - } - ////////////////////////////////////////////////////////////////////////// // SERVICE NETWORK ////////////////////////////////////////////////////////////////////////// @@ -4223,24 +3764,3 @@ void CSystem::SetAssertVisible(bool bAssertVisble) { m_bIsAsserting = bAssertVisble; } - -bool CSystem::LoadFontInternal(IFFont*& font, const string& fontName) -{ - font = m_env.pCryFont->NewFont(fontName); - if (!font) - { - AZ_Assert(false, "Could not instantiate the default font."); - return false; - } - - ////////////////////////////////////////////////////////////////////////// - string szFontPath = "Fonts/" + fontName + ".font"; - - if (!font->Load(szFontPath.c_str())) - { - AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "Could not load font: %s. Make sure the program is running from the correct working directory.", szFontPath.c_str()); - return false; - } - - return true; -} diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp index 4e7a19c197..2ff6143912 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetContainer.cpp @@ -239,8 +239,13 @@ namespace AZ return; } - CheckReady(); m_initComplete = true; + + // *After* setting initComplete to true, check to see if the assets are already ready. + // This check needs to wait until after setting initComplete because if they *are* ready, we want the final call to + // RemoveWaitingAsset to trigger the OnAssetContainerReady/Canceled event. If we call CheckReady() *before* setting + // initComplete, if all the assets are ready, the event will never get triggered. + CheckReady(); } bool AssetContainer::IsReady() const diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x3.h b/Code/Framework/AzCore/AzCore/Math/Matrix3x3.h index e1736e1444..973bb52df3 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x3.h +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x3.h @@ -142,27 +142,44 @@ namespace AZ void SetBasis(const Vector3& basisX, const Vector3& basisY, const Vector3& basisZ); //! @} - Matrix3x3 operator*(const Matrix3x3& rhs) const; - //! Calculates (this->GetTranspose() * rhs). Matrix3x3 TransposedMultiply(const Matrix3x3& rhs) const; //! Post-multiplies the matrix by a vector. Vector3 operator*(const Vector3& rhs) const; - Matrix3x3 operator+(const Matrix3x3& rhs) const; - Matrix3x3 operator-(const Matrix3x3& rhs) const; - - Matrix3x3 operator*(float multiplier) const; - Matrix3x3 operator/(float divisor) const; - - Matrix3x3 operator-() const; - - Matrix3x3& operator*=(const Matrix3x3& rhs); + //! Operator for matrix-matrix addition. + //! @{ + [[nodiscard]] Matrix3x3 operator+(const Matrix3x3& rhs) const; Matrix3x3& operator+=(const Matrix3x3& rhs); + //! @} + + //! Operator for matrix-matrix substraction. + //! @{ + [[nodiscard]] Matrix3x3 operator-(const Matrix3x3& rhs) const; Matrix3x3& operator-=(const Matrix3x3& rhs); + //! @} + + //! Operator for matrix-matrix multiplication. + //! @{ + [[nodiscard]] Matrix3x3 operator*(const Matrix3x3& rhs) const; + Matrix3x3& operator*=(const Matrix3x3& rhs); + //! @} + + //! Operator for multiplying all matrix's elements with a scalar + //! @{ + [[nodiscard]] Matrix3x3 operator*(float multiplier) const; Matrix3x3& operator*=(float multiplier); + //! @} + + //! Operator for dividing all matrix's elements with a scalar + //! @{ + [[nodiscard]] Matrix3x3 operator/(float divisor) const; Matrix3x3& operator/=(float divisor); + //! @} + + //! Operator for negating all matrix's elements + [[nodiscard]] Matrix3x3 operator-() const; bool operator==(const Matrix3x3& rhs) const; bool operator!=(const Matrix3x3& rhs) const; @@ -187,7 +204,10 @@ namespace AZ //! @} //! Gets the scale part of the transformation, i.e. the length of the scale components. - Vector3 RetrieveScale() const; + [[nodiscard]] Vector3 RetrieveScale() const; + + //! Gets the squared scale part of the transformation (the squared length of the basis vectors). + [[nodiscard]] Vector3 RetrieveScaleSq() const; //! Gets the scale part of the transformation as in RetrieveScale, and also removes this scaling from the matrix. Vector3 ExtractScale(); @@ -195,6 +215,9 @@ namespace AZ //! Quick multiplication by a scale matrix, equivalent to m*=Matrix3x3::CreateScale(scale). void MultiplyByScale(const Vector3& scale); + //! Returns a matrix with the reciprocal scale, keeping the same rotation and translation. + [[nodiscard]] Matrix3x3 GetReciprocalScaled() const; + //! Polar decomposition, M=U*H, U is orthogonal (unitary) and H is symmetric (hermitian). //! This function returns the orthogonal part only Matrix3x3 GetPolarDecomposition() const; @@ -241,7 +264,9 @@ namespace AZ //! Note that this is not the usual multiplication order for transformations. Vector3& operator*=(Vector3& lhs, const Matrix3x3& rhs); + //! Pre-multiplies the matrix by a scalar. Matrix3x3 operator*(float lhs, const Matrix3x3& rhs); -} + +} // namespace AZ #include diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x3.inl b/Code/Framework/AzCore/AzCore/Math/Matrix3x3.inl index ff92da1398..6b4dccf3c1 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x3.inl +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x3.inl @@ -392,14 +392,6 @@ namespace AZ } - AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(const Matrix3x3& rhs) const - { - Matrix3x3 result; - Simd::Vec3::Mat3x3Multiply(GetSimdValues(), rhs.GetSimdValues(), result.GetSimdValues()); - return result; - } - - AZ_MATH_INLINE Matrix3x3 Matrix3x3::TransposedMultiply(const Matrix3x3& rhs) const { Matrix3x3 result; @@ -416,51 +408,12 @@ namespace AZ AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator+(const Matrix3x3& rhs) const { - return Matrix3x3(Simd::Vec3::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()) - , Simd::Vec3::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()) - , Simd::Vec3::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())); - } - - - AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-(const Matrix3x3& rhs) const - { - return Matrix3x3(Simd::Vec3::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()) - , Simd::Vec3::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()) - , Simd::Vec3::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())); - } - - - AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(float multiplier) const - { - const Simd::Vec3::FloatType mulVec = Simd::Vec3::Splat(multiplier); - return Matrix3x3(Simd::Vec3::Mul(m_rows[0].GetSimdValue(), mulVec) - , Simd::Vec3::Mul(m_rows[1].GetSimdValue(), mulVec) - , Simd::Vec3::Mul(m_rows[2].GetSimdValue(), mulVec)); - } - - - AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator/(float divisor) const - { - const Simd::Vec3::FloatType divVec = Simd::Vec3::Splat(divisor); - return Matrix3x3(Simd::Vec3::Div(m_rows[0].GetSimdValue(), divVec) - , Simd::Vec3::Div(m_rows[1].GetSimdValue(), divVec) - , Simd::Vec3::Div(m_rows[2].GetSimdValue(), divVec)); - } - - - AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-() const - { - const Simd::Vec3::FloatType zeroVec = Simd::Vec3::ZeroFloat(); - return Matrix3x3(Simd::Vec3::Sub(zeroVec, m_rows[0].GetSimdValue()) - , Simd::Vec3::Sub(zeroVec, m_rows[1].GetSimdValue()) - , Simd::Vec3::Sub(zeroVec, m_rows[2].GetSimdValue())); - } - - - AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator*=(const Matrix3x3& rhs) - { - *this = *this * rhs; - return *this; + return Matrix3x3 + ( + Simd::Vec3::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()), + Simd::Vec3::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()), + Simd::Vec3::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()) + ); } @@ -471,6 +424,17 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-(const Matrix3x3& rhs) const + { + return Matrix3x3 + ( + Simd::Vec3::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()), + Simd::Vec3::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()), + Simd::Vec3::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()) + ); + } + + AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator-=(const Matrix3x3& rhs) { *this = *this - rhs; @@ -478,6 +442,33 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(const Matrix3x3& rhs) const + { + Matrix3x3 result; + Simd::Vec3::Mat3x3Multiply(GetSimdValues(), rhs.GetSimdValues(), result.GetSimdValues()); + return result; + } + + + AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator*=(const Matrix3x3& rhs) + { + *this = *this * rhs; + return *this; + } + + + AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(float multiplier) const + { + const Simd::Vec3::FloatType mulVec = Simd::Vec3::Splat(multiplier); + return Matrix3x3 + ( + Simd::Vec3::Mul(m_rows[0].GetSimdValue(), mulVec), + Simd::Vec3::Mul(m_rows[1].GetSimdValue(), mulVec), + Simd::Vec3::Mul(m_rows[2].GetSimdValue(), mulVec) + ); + } + + AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator*=(float multiplier) { *this = *this * multiplier; @@ -485,6 +476,18 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator/(float divisor) const + { + const Simd::Vec3::FloatType divVec = Simd::Vec3::Splat(divisor); + return Matrix3x3 + ( + Simd::Vec3::Div(m_rows[0].GetSimdValue(), divVec), + Simd::Vec3::Div(m_rows[1].GetSimdValue(), divVec), + Simd::Vec3::Div(m_rows[2].GetSimdValue(), divVec) + ); + } + + AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator/=(float divisor) { *this = *this / divisor; @@ -492,6 +495,18 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-() const + { + const Simd::Vec3::FloatType zeroVec = Simd::Vec3::ZeroFloat(); + return Matrix3x3 + ( + Simd::Vec3::Sub(zeroVec, m_rows[0].GetSimdValue()), + Simd::Vec3::Sub(zeroVec, m_rows[1].GetSimdValue()), + Simd::Vec3::Sub(zeroVec, m_rows[2].GetSimdValue()) + ); + } + + AZ_MATH_INLINE bool Matrix3x3::operator==(const Matrix3x3& rhs) const { return (Simd::Vec3::CmpAllEq(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()) @@ -552,6 +567,12 @@ namespace AZ } + AZ_MATH_INLINE Vector3 Matrix3x3::RetrieveScaleSq() const + { + return Vector3(GetBasisX().GetLengthSq(), GetBasisY().GetLengthSq(), GetBasisZ().GetLengthSq()); + } + + AZ_MATH_INLINE Vector3 Matrix3x3::ExtractScale() { const Vector3 x = GetBasisX(); @@ -584,6 +605,14 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x3 Matrix3x3::GetReciprocalScaled() const + { + Matrix3x3 result = *this; + result.MultiplyByScale(RetrieveScaleSq().GetReciprocal()); + return result; + } + + AZ_MATH_INLINE void Matrix3x3::GetPolarDecomposition(Matrix3x3* orthogonalOut, Matrix3x3* symmetricOut) const { *orthogonalOut = GetPolarDecomposition(); @@ -679,8 +708,6 @@ namespace AZ AZ_MATH_INLINE Matrix3x3 operator*(float lhs, const Matrix3x3& rhs) { - const Simd::Vec3::FloatType lhsVec = Simd::Vec3::Splat(lhs); - const Simd::Vec3::FloatType* rows = rhs.GetSimdValues(); - return Matrix3x3(Simd::Vec3::Mul(lhsVec, rows[0]), Simd::Vec3::Mul(lhsVec, rows[1]), Simd::Vec3::Mul(lhsVec, rows[2])); + return rhs * lhs; } -} +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h index 8773d4ea6a..a18f1e7565 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.h @@ -225,11 +225,38 @@ namespace AZ //! Sets the three basis vectors and the translation. void SetBasisAndTranslation(const Vector3& basisX, const Vector3& basisY, const Vector3& basisZ, const Vector3& translation); - //! Operator for matrix-matrix multiplication. - [[nodiscard]] Matrix3x4 operator*(const Matrix3x4& rhs) const; + //! Operator for matrix-matrix addition. + //! @{ + [[nodiscard]] Matrix3x4 operator+(const Matrix3x4& rhs) const; + Matrix3x4& operator+=(const Matrix3x4& rhs); + //! @} - //! Compound assignment operator for matrix-matrix multiplication. + //! Operator for matrix-matrix substraction. + //! @{ + [[nodiscard]] Matrix3x4 operator-(const Matrix3x4& rhs) const; + Matrix3x4& operator-=(const Matrix3x4& rhs); + //! @} + + //! Operator for matrix-matrix multiplication. + //! @{ + [[nodiscard]] Matrix3x4 operator*(const Matrix3x4& rhs) const; Matrix3x4& operator*=(const Matrix3x4& rhs); + //! @} + + //! Operator for multiplying all matrix's elements with a scalar + //! @{ + [[nodiscard]] Matrix3x4 operator*(float multiplier) const; + Matrix3x4& operator*=(float multiplier); + //! @} + + //! Operator for dividing all matrix's elements with a scalar + //! @{ + [[nodiscard]] Matrix3x4 operator/(float divisor) const; + Matrix3x4& operator/=(float divisor); + //! @} + + //! Operator for negating all matrix's elements + [[nodiscard]] Matrix3x4 operator-() const; //! Operator for transforming a Vector3. [[nodiscard]] Vector3 operator*(const Vector3& rhs) const; @@ -274,12 +301,18 @@ namespace AZ //! Gets the scale part of the transformation (the length of the basis vectors). [[nodiscard]] Vector3 RetrieveScale() const; + //! Gets the squared scale part of the transformation (the squared length of the basis vectors). + [[nodiscard]] Vector3 RetrieveScaleSq() const; + //! Gets the scale part of the transformation as in RetrieveScale, and also removes this scaling from the matrix. Vector3 ExtractScale(); //! Multiplies the basis vectors of the matrix by the elements of the scale specified. void MultiplyByScale(const Vector3& scale); + //! Returns a matrix with the reciprocal scale, keeping the same rotation and translation. + [[nodiscard]] Matrix3x4 GetReciprocalScaled() const; + //! Tests if the 3x3 part of the matrix is orthogonal. bool IsOrthogonal(float tolerance = Constants::Tolerance) const; @@ -335,6 +368,10 @@ namespace AZ Vector4 m_rows[RowCount]; }; + + //! Pre-multiplies the matrix by a scalar. + Matrix3x4 operator*(float lhs, const Matrix3x4& rhs); + } // namespace AZ #include diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl index bd310d293e..781dcf9b66 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl +++ b/Code/Framework/AzCore/AzCore/Math/Matrix3x4.inl @@ -472,6 +472,42 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator+(const Matrix3x4& rhs) const + { + return Matrix3x4 + ( + Simd::Vec4::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()), + Simd::Vec4::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()), + Simd::Vec4::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()) + ); + } + + + AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator+=(const Matrix3x4& rhs) + { + *this = *this + rhs; + return *this; + } + + + AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator-(const Matrix3x4& rhs) const + { + return Matrix3x4 + ( + Simd::Vec4::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()), + Simd::Vec4::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()), + Simd::Vec4::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()) + ); + } + + + AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator-=(const Matrix3x4& rhs) + { + *this = *this - rhs; + return *this; + } + + AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator*(const Matrix3x4& rhs) const { Matrix3x4 result; @@ -487,6 +523,56 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator*(float multiplier) const + { + const Simd::Vec4::FloatType mulVec = Simd::Vec4::Splat(multiplier); + return Matrix3x4 + ( + Simd::Vec4::Mul(m_rows[0].GetSimdValue(), mulVec), + Simd::Vec4::Mul(m_rows[1].GetSimdValue(), mulVec), + Simd::Vec4::Mul(m_rows[2].GetSimdValue(), mulVec) + ); + } + + + AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator*=(float multiplier) + { + *this = *this * multiplier; + return *this; + } + + + AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator/(float divisor) const + { + const Simd::Vec4::FloatType divVec = Simd::Vec4::Splat(divisor); + return Matrix3x4 + ( + Simd::Vec4::Div(m_rows[0].GetSimdValue(), divVec), + Simd::Vec4::Div(m_rows[1].GetSimdValue(), divVec), + Simd::Vec4::Div(m_rows[2].GetSimdValue(), divVec) + ); + } + + + AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator/=(float divisor) + { + *this = *this / divisor; + return *this; + } + + + AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator-() const + { + const Simd::Vec4::FloatType zeroVec = Simd::Vec4::ZeroFloat(); + return Matrix3x4 + ( + Simd::Vec4::Sub(zeroVec, m_rows[0].GetSimdValue()), + Simd::Vec4::Sub(zeroVec, m_rows[1].GetSimdValue()), + Simd::Vec4::Sub(zeroVec, m_rows[2].GetSimdValue()) + ); + } + + AZ_MATH_INLINE Vector3 Matrix3x4::operator*(const Vector3& rhs) const { return Vector3 @@ -583,6 +669,12 @@ namespace AZ } + AZ_MATH_INLINE Vector3 Matrix3x4::RetrieveScaleSq() const + { + return Vector3(GetColumn(0).GetLengthSq(), GetColumn(1).GetLengthSq(), GetColumn(2).GetLengthSq()); + } + + AZ_MATH_INLINE Vector3 Matrix3x4::ExtractScale() { const Vector3 scale = RetrieveScale(); @@ -600,6 +692,14 @@ namespace AZ } + AZ_MATH_INLINE Matrix3x4 Matrix3x4::GetReciprocalScaled() const + { + Matrix3x4 result = *this; + result.MultiplyByScale(RetrieveScaleSq().GetReciprocal()); + return result; + } + + AZ_MATH_INLINE void Matrix3x4::Orthogonalize() { *this = GetOrthogonalized(); @@ -660,4 +760,10 @@ namespace AZ { return reinterpret_cast(m_rows); } + + + AZ_MATH_INLINE Matrix3x4 operator*(float lhs, const Matrix3x4& rhs) + { + return rhs * lhs; + } } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix4x4.h b/Code/Framework/AzCore/AzCore/Math/Matrix4x4.h index 1612f8c962..a94b3c7ae2 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix4x4.h +++ b/Code/Framework/AzCore/AzCore/Math/Matrix4x4.h @@ -171,14 +171,38 @@ namespace AZ void SetTranslation(const Vector3& v); //! @} - Matrix4x4 operator+(const Matrix4x4& rhs) const; + //! Operator for matrix-matrix addition. + //! @{ + [[nodiscard]] Matrix4x4 operator+(const Matrix4x4& rhs) const; Matrix4x4& operator+=(const Matrix4x4& rhs); + //! @} - Matrix4x4 operator-(const Matrix4x4& rhs) const; + //! Operator for matrix-matrix substraction. + //! @{ + [[nodiscard]] Matrix4x4 operator-(const Matrix4x4& rhs) const; Matrix4x4& operator-=(const Matrix4x4& rhs); + //! @} - Matrix4x4 operator*(const Matrix4x4& rhs) const; + //! Operator for matrix-matrix multiplication. + //! @{ + [[nodiscard]] Matrix4x4 operator*(const Matrix4x4& rhs) const; Matrix4x4& operator*=(const Matrix4x4& rhs); + //! @} + + //! Operator for multiplying all matrix's elements with a scalar + //! @{ + [[nodiscard]] Matrix4x4 operator*(float multiplier) const; + Matrix4x4& operator*=(float multiplier); + //! @} + + //! Operator for dividing all matrix's elements with a scalar + //! @{ + [[nodiscard]] Matrix4x4 operator/(float divisor) const; + Matrix4x4& operator/=(float divisor); + //! @} + + //! Operator for negating all matrix's elements + [[nodiscard]] Matrix4x4 operator-() const; //! Post-multiplies the matrix by a vector. //! Assumes that the w-component of the Vector3 is 1.0. @@ -222,7 +246,10 @@ namespace AZ //! @} //! Gets the scale part of the transformation, i.e. the length of the scale components. - Vector3 RetrieveScale() const; + [[nodiscard]] Vector3 RetrieveScale() const; + + //! Gets the squared scale part of the transformation (the squared length of the basis vectors). + [[nodiscard]] Vector3 RetrieveScaleSq() const; //! Gets the scale part of the transformation as in RetrieveScale, and also removes this scaling from the matrix. Vector3 ExtractScale(); @@ -230,6 +257,9 @@ namespace AZ //! Quick multiplication by a scale matrix, equivalent to m*=Matrix4x4::CreateScale(scale). void MultiplyByScale(const Vector3& scale); + //! Returns a matrix with the reciprocal scale, keeping the same rotation and translation. + [[nodiscard]] Matrix4x4 GetReciprocalScaled() const; + bool IsClose(const Matrix4x4& rhs, float tolerance = Constants::Tolerance) const; bool operator==(const Matrix4x4& rhs) const; @@ -270,6 +300,10 @@ namespace AZ //! Pre-multiplies the matrix by a vector in-place. //! Note that this is not the usual multiplication order for transformations. Vector4& operator*=(Vector4& lhs, const Matrix4x4& rhs); -} + + //! Pre-multiplies the matrix by a scalar. + Matrix4x4 operator*(float lhs, const Matrix4x4& rhs); + +} // namespace AZ #include diff --git a/Code/Framework/AzCore/AzCore/Math/Matrix4x4.inl b/Code/Framework/AzCore/AzCore/Math/Matrix4x4.inl index 3c4572accd..e32ebe31af 100644 --- a/Code/Framework/AzCore/AzCore/Math/Matrix4x4.inl +++ b/Code/Framework/AzCore/AzCore/Math/Matrix4x4.inl @@ -480,20 +480,12 @@ namespace AZ AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator+(const Matrix4x4& rhs) const { return Matrix4x4 - ( Simd::Vec4::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()) - , Simd::Vec4::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()) - , Simd::Vec4::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()) - , Simd::Vec4::Add(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue())); - } - - - AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator-(const Matrix4x4& rhs) const - { - return Matrix4x4 - ( Simd::Vec4::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()) - , Simd::Vec4::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()) - , Simd::Vec4::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()) - , Simd::Vec4::Sub(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue())); + ( + Simd::Vec4::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()), + Simd::Vec4::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()), + Simd::Vec4::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()), + Simd::Vec4::Add(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue()) + ); } AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator+=(const Matrix4x4& rhs) @@ -502,6 +494,18 @@ namespace AZ return *this; } + + AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator-(const Matrix4x4& rhs) const + { + return Matrix4x4 + ( + Simd::Vec4::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()), + Simd::Vec4::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()), + Simd::Vec4::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()), + Simd::Vec4::Sub(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue()) + ); + } + AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator-=(const Matrix4x4& rhs) { *this = *this - rhs; @@ -523,6 +527,59 @@ namespace AZ } + AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator*(float multiplier) const + { + const Simd::Vec4::FloatType mulVec = Simd::Vec4::Splat(multiplier); + return Matrix4x4 + ( + Simd::Vec4::Mul(m_rows[0].GetSimdValue(), mulVec), + Simd::Vec4::Mul(m_rows[1].GetSimdValue(), mulVec), + Simd::Vec4::Mul(m_rows[2].GetSimdValue(), mulVec), + Simd::Vec4::Mul(m_rows[3].GetSimdValue(), mulVec) + ); + } + + + AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator*=(float multiplier) + { + *this = *this * multiplier; + return *this; + } + + + AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator/(float divisor) const + { + const Simd::Vec4::FloatType divVec = Simd::Vec4::Splat(divisor); + return Matrix4x4 + ( + Simd::Vec4::Div(m_rows[0].GetSimdValue(), divVec), + Simd::Vec4::Div(m_rows[1].GetSimdValue(), divVec), + Simd::Vec4::Div(m_rows[2].GetSimdValue(), divVec), + Simd::Vec4::Div(m_rows[3].GetSimdValue(), divVec) + ); + } + + + AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator/=(float divisor) + { + *this = *this / divisor; + return *this; + } + + + AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator-() const + { + const Simd::Vec4::FloatType zeroVec = Simd::Vec4::ZeroFloat(); + return Matrix4x4 + ( + Simd::Vec4::Sub(zeroVec, m_rows[0].GetSimdValue()), + Simd::Vec4::Sub(zeroVec, m_rows[1].GetSimdValue()), + Simd::Vec4::Sub(zeroVec, m_rows[2].GetSimdValue()), + Simd::Vec4::Sub(zeroVec, m_rows[3].GetSimdValue()) + ); + } + + AZ_MATH_INLINE Vector3 Matrix4x4::operator*(const Vector3& rhs) const { return Vector3(Simd::Vec4::Mat4x4TransformPoint3(GetSimdValues(), rhs.GetSimdValue())); @@ -595,6 +652,12 @@ namespace AZ } + AZ_MATH_INLINE Vector3 Matrix4x4::RetrieveScaleSq() const + { + return Vector3(GetBasisX().GetLengthSq(), GetBasisY().GetLengthSq(), GetBasisZ().GetLengthSq()); + } + + AZ_MATH_INLINE Vector3 Matrix4x4::ExtractScale() { Vector4 x = GetBasisX(); @@ -619,6 +682,14 @@ namespace AZ } + AZ_MATH_INLINE Matrix4x4 Matrix4x4::GetReciprocalScaled() const + { + Matrix4x4 result = *this; + result.MultiplyByScale(RetrieveScaleSq().GetReciprocal()); + return result; + } + + AZ_MATH_INLINE bool Matrix4x4::IsClose(const Matrix4x4& rhs, float tolerance) const { const Simd::Vec4::FloatType vecTolerance = Simd::Vec4::Splat(tolerance); @@ -702,4 +773,10 @@ namespace AZ lhs = lhs * rhs; return lhs; } -} + + + AZ_MATH_INLINE Matrix4x4 operator*(float lhs, const Matrix4x4& rhs) + { + return rhs * lhs; + } +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl index ab92604266..079c70c878 100644 --- a/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl +++ b/Code/Framework/AzCore/AzCore/RTTI/AzStdOnDemandReflection.inl @@ -816,7 +816,7 @@ namespace AZ template static void ReflectUnpackMethodFold(BehaviorContext::ClassBuilder& builder) { - AZStd::string methodName = AZStd::string::format("Get%ld", Index); + const AZStd::string methodName = AZStd::string::format("Get%zu", Index); builder->Method(methodName.data(), [](ContainerType& value) { return AZStd::get(value); }) ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Attribute(AZ::ScriptCanvasAttributes::TupleGetFunctionIndex, Index) diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp index f2e9bb866f..8d0da9e54a 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonDeserializer.cpp @@ -97,7 +97,8 @@ namespace AZ return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, AZStd::string::format("Failed to retrieve rtti information for %s.", classData->m_name)); } - AZ_Assert(classData->m_azRtti->GetTypeId() == typeId, "Type id mismatch during deserialization of a json file. (%s vs %s)"); + AZ_Assert(classData->m_azRtti->GetTypeId() == typeId, "Type id mismatch during deserialization of a json file. (%s vs %s)", + classData->m_azRtti->GetTypeId().ToString().c_str(), typeId.ToString().c_str()); void** objectPtr = reinterpret_cast(object); bool isNull = *objectPtr == nullptr; @@ -512,27 +513,24 @@ namespace AZ if (*object) { const AZ::Uuid& actualClassId = rtti.GetActualUuid(*object); - if (actualClassId != objectType) + const SerializeContext::ClassData* actualClassData = context.GetSerializeContext()->FindClassData(actualClassId); + if (!actualClassData) { - const SerializeContext::ClassData* actualClassData = context.GetSerializeContext()->FindClassData(actualClassId); - if (!actualClassData) - { - status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, - AZStd::string::format("Unable to find serialization information for type %s.", actualClassId.ToString().c_str())); - return ResolvePointerResult::FullyProcessed; - } + status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown, + AZStd::string::format("Unable to find serialization information for type %s.", actualClassId.ToString().c_str())); + return ResolvePointerResult::FullyProcessed; + } - if (actualClassData->m_factory) - { - actualClassData->m_factory->Destroy(*object); - *object = nullptr; - } - else - { - status = context.Report(Tasks::RetrieveInfo, Outcomes::Catastrophic, - "Unable to find the factory needed to clear out the default value."); - return ResolvePointerResult::FullyProcessed; - } + if (actualClassData->m_factory) + { + actualClassData->m_factory->Destroy(*object); + *object = nullptr; + } + else + { + status = context.Report(Tasks::RetrieveInfo, Outcomes::Catastrophic, + "Unable to find the factory needed to clear out the default value."); + return ResolvePointerResult::FullyProcessed; } } status = ResultCode(Tasks::ReadField, Outcomes::Success); diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h index 5746005832..cf73d8dc56 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/JsonSerialization.h @@ -38,6 +38,20 @@ namespace AZ }; //! Core class to handle serialization to and from json documents. + //! The Json Serialization works by taking a default constructed object and then apply the information found in the JSON document + //! on top of that object. This allows the Json Serialization to avoid storing default values and helps guarantee that the final + //! object is in a valid state even if non-fatal issues are encountered. + //! Note on containers: Containers such as vector or map are always considered to be empty even if there's entries in the provided + //! default object. During deserialization entries will be appended to any existing values. A flag is provided to automatically + //! clear containers during deserialization. + //! Note on maps: If the key for map containers such as unordered_map can be interpret as a string the Json Serialization will use + //! a JSON Object to store the data in instead of an array with key/value objects. + //! Note on pointers: The Json Serialization assumes that are always constructed, so a default JSON value of "{}" is interpret as + //! creating a new default instance even if the default value is a null pointer. A JSON Null needs to be explicitly stored in + //! the JSON Document in order to default or explicitly set a pointer to null. + //! Note on pointer memory: Objects created/destroyed by the Json Serialization for pointers require that the AZ_CLASS_ALLOCATOR is + //! declared and the object is created using aznew or memory is allocated using azmalloc. Without these the application may + //! crash if the Json Serialization tries to create or destroy an object pointed to by a pointer. class JsonSerialization final { public: diff --git a/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp b/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp index 0180e99592..9e707f8644 100644 --- a/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Serialization/Json/SmartPointerSerializer.cpp @@ -23,13 +23,6 @@ namespace AZ { namespace JSR = JsonSerializationResult; - if (IsExplicitDefault(inputValue)) - { - // Do nothing if the input is an explicit default. - return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed, - "Default value for smart pointer requested so no change was made."); - } - const SerializeContext::ClassData* containerClass = context.GetSerializeContext()->FindClassData(outputValueTypeId); if (!containerClass) { @@ -153,8 +146,7 @@ namespace AZ if (defaultValue) { - bool typesMatch = false; - auto defaultInputCallback = [&defaultValue, &inputPtrType, &typesMatch] + auto defaultInputCallback = [&defaultValue] (void* elementPtr, const Uuid&, const SerializeContext::ClassData*, const SerializeContext::ClassElement*) { defaultValue = elementPtr; @@ -164,11 +156,6 @@ namespace AZ } JSR::ResultCode result = ContinueStoring(outputValue, inputValue, defaultValue, inputPtrType, context, Flags::ResolvePointer); - if (result.GetOutcome() == JSR::Outcomes::DefaultsUsed) - { - outputValue = GetExplicitDefault(); - return context.Report(result, "Smart pointer used all defaults."); - } return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ? "Successfully processed smart pointer." : "A problem occurred while processing a smart pointer."); } diff --git a/Code/Framework/AzCore/Tests/Asset/AssetManagerStreamingTests.cpp b/Code/Framework/AzCore/Tests/Asset/AssetManagerStreamingTests.cpp index 807288ff82..c55a95cf2a 100644 --- a/Code/Framework/AzCore/Tests/Asset/AssetManagerStreamingTests.cpp +++ b/Code/Framework/AzCore/Tests/Asset/AssetManagerStreamingTests.cpp @@ -330,4 +330,163 @@ namespace UnitTest } } -} + // The AssetManagerStreamerImmediateCompletionTests class adjusts the asset loading to force it to complete immediately, + // while still within the callstack for GetAsset(). This can be used to test various conditions in which the load thread + // completes more rapidly than expected, and can expose subtle race conditions. + // There are a few key things that this class does to make this work: + // - The file I/O streamer is mocked + // - The asset stream data is mocked to a 0-byte length for the asset so that the stream load will bypass the I/O streamer and + // just immediately return completion. + // - The number of JobManager threads is set to 0, forcing jobs to execute synchronously inline when they are started. + // With these changes, GetAssetInternal() will queue the stream, which will immediately call the callback that creates LoadAssetJob, + // which immediately executes in-place to process the asset due to the synchronous JobManager. + // Note that if we just created the asset in a Ready state, most of the asset loading code is completely bypassed, and so we + // wouldn't be able to test for race conditions in the AssetContainer. + // + // This class also unregisters the catalog and asset handler before shutting down the asset manager. This is done to catch + // any outstanding asset references that exist due to loads not completing and cleaning up successfully. + struct AssetManagerStreamerImmediateCompletionTests : public BaseAssetManagerTest, + public AZ::Data::AssetCatalogRequestBus::Handler, + public AZ::Data::AssetHandler, + public AZ::Data::AssetCatalog + { + static inline const AZ::Uuid TestAssetId{"{E970B177-5F45-44EB-A2C4-9F29D9A0B2A2}"}; + static inline constexpr AZStd::string_view TestAssetPath = "test"; + + void SetUp() override + { + BaseAssetManagerTest::SetUp(); + AssetManager::Descriptor desc; + AssetManager::Create(desc); + + // Register the handler and catalog after creation, because we intend to destroy them before AssetManager destruction. + // The specific asset we load is irrelevant, so register EmptyAsset. + AZ::Data::AssetManager::Instance().RegisterHandler(this, AZ::AzTypeInfo::Uuid()); + AZ::Data::AssetManager::Instance().RegisterCatalog(this, AZ::AzTypeInfo::Uuid()); + + // Intercept messages for finding assets by name so that we can mock out the asset we're loading. + AZ::Data::AssetCatalogRequestBus::Handler::BusConnect(); + } + + void TearDown() override + { + // Unregister before destroying AssetManager. + // This will catch any assets that got stuck in a loading state without getting cleaned up. + AZ::Data::AssetManager::Instance().UnregisterCatalog(this); + AZ::Data::AssetManager::Instance().UnregisterHandler(this); + + AZ::Data::AssetCatalogRequestBus::Handler::BusDisconnect(); + + AssetManager::Destroy(); + BaseAssetManagerTest::TearDown(); + } + + size_t GetNumJobManagerThreads() const override + { + // Return 0 threads so that the Job Manager executes jobs synchronously inline. This lets us finish a load while still + // in the callstack that initiates the load. + return 0; + } + + // Create a mock streamer instead of a real one, since we don't really want to load an asset. + IO::IStreamer* CreateStreamer() override + { + m_mockStreamer = AZStd::make_unique(); + return &(m_mockStreamer->m_mockStreamer); + } + + void DestroyStreamer([[maybe_unused]] IO::IStreamer* streamer) override + { + m_mockStreamer = nullptr; + } + + // AssetHandler implementation + + // Minimalist mock to create a new EmptyAsset with the desired asset ID. + AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override + { + return new EmptyAsset(id); + } + + void DestroyAsset(AZ::Data::AssetPtr ptr) override + { + delete ptr; + } + + // The mocked-out Asset Catalog handles EmptyAsset types. + void GetHandledAssetTypes(AZStd::vector& assetTypes) override + { + assetTypes.push_back(AZ::AzTypeInfo::Uuid()); + } + + // This is a mocked-out load, so just immediately return completion without doing anything. + AZ::Data::AssetHandler::LoadResult LoadAssetData( + [[maybe_unused]] const AZ::Data::Asset& asset, + [[maybe_unused]] AZStd::shared_ptr stream, + [[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB) + { + return AZ::Data::AssetHandler::LoadResult::LoadComplete; + } + + // AssetCatalogRequestBus implementation + + // Minimalist mocks to provide our desired asset path or asset id + AZStd::string GetAssetPathById([[maybe_unused]] const AZ::Data::AssetId& id) override + { + return TestAssetPath; + } + AZ::Data::AssetId GetAssetIdByPath( + [[maybe_unused]] const char* path, [[maybe_unused]] const AZ::Data::AssetType& typeToRegister, + [[maybe_unused]] bool autoRegisterIfNotFound) override + { + return TestAssetId; + } + + // Return the mocked-out information for our test asset + AZ::Data::AssetInfo GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& id) override + { + AZ::Data::AssetInfo assetInfo; + assetInfo.m_assetId = TestAssetId; + assetInfo.m_assetType = AZ::AzTypeInfo::Uuid(); + assetInfo.m_relativePath = TestAssetPath; + return assetInfo; + } + + // AssetCatalog implementation + + // Set the mocked-out asset load to have a 0-byte length so that the load skips I/O and immediately returns success + AZ::Data::AssetStreamInfo GetStreamInfoForLoad( + [[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override + { + EXPECT_TRUE(type == AZ::AzTypeInfo::Uuid()); + AZ::Data::AssetStreamInfo info; + info.m_dataOffset = 0; + info.m_streamName = TestAssetPath; + info.m_dataLen = 0; + info.m_streamFlags = AZ::IO::OpenMode::ModeRead; + + return info; + } + + AZStd::unique_ptr m_mockStreamer; + }; + + // This test will verify that even if the asset loading stream/job returns immediately, all of the loading + // code works successfully. The test here is fairly simple - it just loads the asset and verifies that it + // loaded successfully. The bulk of the test is really in the setup class above, where the load is forced + // to complete immediately. Also, the true failure condition is caught in the setup class too, which is + // the presence of any assets at the point that the asset handler is unregistered. If they're present, then + // the immediate load wasn't truly successful, as it left around extra references to the asset that haven't + // been cleaned up. + TEST_F(AssetManagerStreamerImmediateCompletionTests, LoadAssetWithImmediateJobCompletion_WorksSuccessfully) + { + AZ::Data::AssetLoadParameters loadParams; + + auto testAsset = + AssetManager::Instance().GetAsset(TestAssetId, AZ::Data::AssetLoadBehavior::Default, loadParams); + + AZ::Data::AssetManager::Instance().DispatchEvents(); + EXPECT_TRUE(testAsset.IsReady()); + } + +} // namespace UnitTest diff --git a/Code/Framework/AzCore/Tests/Asset/TestAssetTypes.h b/Code/Framework/AzCore/Tests/Asset/TestAssetTypes.h index 83f3909676..d4267972ec 100644 --- a/Code/Framework/AzCore/Tests/Asset/TestAssetTypes.h +++ b/Code/Framework/AzCore/Tests/Asset/TestAssetTypes.h @@ -24,6 +24,13 @@ namespace UnitTest public: AZ_CLASS_ALLOCATOR(EmptyAsset, AZ::SystemAllocator, 0); AZ_RTTI(EmptyAsset, "{098E3F7F-13AC-414B-9B4E-49B5AD1BD7FE}", AZ::Data::AssetData); + + EmptyAsset( + const AZ::Data::AssetId& assetId = AZ::Data::AssetId(), + AZ::Data::AssetData::AssetStatus status = AZ::Data::AssetData::AssetStatus::NotLoaded) + : AZ::Data::AssetData(assetId, status) + { + } }; // EmptyAssetWithNoHandler: no data contained within, and no AssetHandler registered for this type diff --git a/Code/Framework/AzCore/Tests/Math/Matrix3x3Tests.cpp b/Code/Framework/AzCore/Tests/Math/Matrix3x3Tests.cpp index a849cfdaab..efa0ee531c 100644 --- a/Code/Framework/AzCore/Tests/Math/Matrix3x3Tests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Matrix3x3Tests.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace AZ; @@ -251,19 +252,19 @@ namespace UnitTest m2.SetRow(2, 13.0f, 14.0f, 15.0f); Matrix3x3 m3 = m1 * m2; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(66.0f, 72.0f, 78.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(156.0f, 171.0f, 186.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(246.0f, 270.0f, 294.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(66.0f, 72.0f, 78.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(156.0f, 171.0f, 186.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(246.0f, 270.0f, 294.0f))); Matrix3x3 m4 = m1; m4 *= m2; - AZ_TEST_ASSERT(m4.GetRow(0).IsClose(Vector3(66.0f, 72.0f, 78.0f))); - AZ_TEST_ASSERT(m4.GetRow(1).IsClose(Vector3(156.0f, 171.0f, 186.0f))); - AZ_TEST_ASSERT(m4.GetRow(2).IsClose(Vector3(246.0f, 270.0f, 294.0f))); + EXPECT_THAT(m4.GetRow(0), IsClose(Vector3(66.0f, 72.0f, 78.0f))); + EXPECT_THAT(m4.GetRow(1), IsClose(Vector3(156.0f, 171.0f, 186.0f))); + EXPECT_THAT(m4.GetRow(2), IsClose(Vector3(246.0f, 270.0f, 294.0f))); m3 = m1.TransposedMultiply(m2); - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(138.0f, 150.0f, 162.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(168.0f, 183.0f, 198.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(198.0f, 216.0f, 234.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(138.0f, 150.0f, 162.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(168.0f, 183.0f, 198.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(198.0f, 216.0f, 234.0f))); } TEST(MATH_Matrix3x3, TestVectorMultiplication) @@ -277,11 +278,11 @@ namespace UnitTest m2.SetRow(1, 10.0f, 11.0f, 12.0f); m2.SetRow(2, 13.0f, 14.0f, 15.0f); - AZ_TEST_ASSERT((m1 * Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(14.0f, 32.0f, 50.0f))); + EXPECT_THAT((m1 * Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(14.0f, 32.0f, 50.0f))); Vector3 v1(1.0f, 2.0f, 3.0f); - AZ_TEST_ASSERT((v1 * m1).IsClose(Vector3(30.0f, 36.0f, 42.0f))); + EXPECT_THAT((v1 * m1), IsClose(Vector3(30.0f, 36.0f, 42.0f))); v1 *= m1; - AZ_TEST_ASSERT(v1.IsClose(Vector3(30.0f, 36.0f, 42.0f))); + EXPECT_THAT(v1, IsClose(Vector3(30.0f, 36.0f, 42.0f))); } TEST(MATH_Matrix3x3, TestSum) @@ -296,15 +297,15 @@ namespace UnitTest m2.SetRow(2, 13.0f, 14.0f, 15.0f); Matrix3x3 m3 = m1 + m2; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(8.0f, 10.0f, 12.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(14.0f, 16.0f, 18.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(20.0f, 22.0f, 24.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(8.0f, 10.0f, 12.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(14.0f, 16.0f, 18.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(20.0f, 22.0f, 24.0f))); m3 = m1; m3 += m2; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(8.0f, 10.0f, 12.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(14.0f, 16.0f, 18.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(20.0f, 22.0f, 24.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(8.0f, 10.0f, 12.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(14.0f, 16.0f, 18.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(20.0f, 22.0f, 24.0f))); } TEST(MATH_Matrix3x3, TestDifference) @@ -319,14 +320,14 @@ namespace UnitTest m2.SetRow(2, 13.0f, 14.0f, 15.0f); Matrix3x3 m3 = m1 - m2; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(-6.0f, -6.0f, -6.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(-6.0f, -6.0f, -6.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(-6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(-6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(-6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(-6.0f, -6.0f, -6.0f))); m3 = m1; m3 -= m2; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(-6.0f, -6.0f, -6.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(-6.0f, -6.0f, -6.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(-6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(-6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(-6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(-6.0f, -6.0f, -6.0f))); } TEST(MATH_Matrix3x3, TestScalarMultiplication) @@ -341,18 +342,18 @@ namespace UnitTest m2.SetRow(2, 13.0f, 14.0f, 15.0f); Matrix3x3 m3 = m1 * 2.0f; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f))); m3 = m1; m3 *= 2.0f; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f))); m3 = 2.0f * m1; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f))); } TEST(MATH_Matrix3x3, TestScalarDivision) @@ -367,18 +368,32 @@ namespace UnitTest m2.SetRow(2, 13.0f, 14.0f, 15.0f); Matrix3x3 m3 = m1 / 0.5f; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f))); m3 = m1; m3 /= 0.5f; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f))); - m3 = -m1; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(-1.0f, -2.0f, -3.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(-4.0f, -5.0f, -6.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(-7.0f, -8.0f, -9.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f))); + } + + TEST(MATH_Matrix3x3, TestNegation) + { + Matrix3x3 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f); + m1.SetRow(1, 4.0f, 5.0f, 6.0f); + m1.SetRow(2, 7.0f, 8.0f, 9.0f); + EXPECT_THAT(-(-m1), IsClose(m1)); + EXPECT_THAT(-Matrix3x3::CreateZero(), IsClose(Matrix3x3::CreateZero())); + + Matrix3x3 m2 = -m1; + EXPECT_THAT(m2.GetRow(0), IsClose(Vector3(-1.0f, -2.0f, -3.0f))); + EXPECT_THAT(m2.GetRow(1), IsClose(Vector3(-4.0f, -5.0f, -6.0f))); + EXPECT_THAT(m2.GetRow(2), IsClose(Vector3(-7.0f, -8.0f, -9.0f))); + + Matrix3x3 m3 = m1 + (-m1); + EXPECT_THAT(m3, IsClose(Matrix3x3::CreateZero())); } TEST(MATH_Matrix3x3, TestTranspose) @@ -425,11 +440,33 @@ namespace UnitTest TEST(MATH_Matrix3x3, TestScaleAccess) { Matrix3x3 m1 = Matrix3x3::CreateRotationX(DegToRad(40.0f)) * Matrix3x3::CreateScale(Vector3(2.0f, 3.0f, 4.0f)); - AZ_TEST_ASSERT(m1.RetrieveScale().IsClose(Vector3(2.0f, 3.0f, 4.0f))); - AZ_TEST_ASSERT(m1.ExtractScale().IsClose(Vector3(2.0f, 3.0f, 4.0f))); - AZ_TEST_ASSERT(m1.RetrieveScale().IsClose(Vector3::CreateOne())); + EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f))); + EXPECT_THAT(m1.ExtractScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f))); + EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3::CreateOne())); m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f)); - AZ_TEST_ASSERT(m1.RetrieveScale().IsClose(Vector3(3.0f, 4.0f, 5.0f))); + EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(3.0f, 4.0f, 5.0f))); + } + + TEST(MATH_Matrix3x3, TestScaleSqAccess) + { + Matrix3x3 m1 = Matrix3x3::CreateRotationX(DegToRad(40.0f)) * Matrix3x3::CreateScale(Vector3(2.0f, 3.0f, 4.0f)); + EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(4.0f, 9.0f, 16.0f))); + m1.ExtractScale(); + EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3::CreateOne())); + m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f)); + EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(9.0f, 16.0f, 25.0f))); + } + + TEST(MATH_Matrix3x3, TestReciprocalScaled) + { + Matrix3x3 orthogonalMatrix = Matrix3x3::CreateRotationX(DegToRad(40.0f)); + EXPECT_THAT(orthogonalMatrix.GetReciprocalScaled(), IsClose(orthogonalMatrix)); + const AZ::Vector3 scale(2.8f, 0.7f, 1.3f); + AZ::Matrix3x3 scaledMatrix = orthogonalMatrix; + scaledMatrix.MultiplyByScale(scale); + AZ::Matrix3x3 reciprocalScaledMatrix = orthogonalMatrix; + reciprocalScaledMatrix.MultiplyByScale(scale.GetReciprocal()); + EXPECT_THAT(scaledMatrix.GetReciprocalScaled(), IsClose(reciprocalScaledMatrix)); } TEST(MATH_Matrix3x3, TestPolarDecomposition) diff --git a/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp b/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp index f61b633fc2..0bb64411e6 100644 --- a/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Matrix3x4Tests.cpp @@ -467,21 +467,136 @@ namespace UnitTest EXPECT_THAT(matrix.Multiply3x3(axisDirection), IsClose(forwardDirection)); } - TEST(MATH_Matrix3x4, MultiplyByMatrix3x4) + TEST(MATH_Matrix3x4, TestMatrixMultiplication) { - const AZ::Matrix3x4 matrix1 = AZ::Matrix3x4::CreateFromValue(1.2f); - const AZ::Matrix3x4 matrix2 = AZ::Matrix3x4::CreateDiagonal(AZ::Vector3(1.3f, 1.5f, 0.4f)); - const AZ::Matrix3x4 matrix3 = AZ::Matrix3x4::CreateFromQuaternionAndTranslation( - AZ::Quaternion(0.42f, 0.46f, -0.66f, 0.42f), AZ::Vector3(2.8f, -3.7f, 1.6f)); - const AZ::Matrix3x4 matrix4 = AZ::Matrix3x4::CreateRotationX(-0.7f) * AZ::Matrix3x4::CreateScale(AZ::Vector3(0.6f, 1.3f, 0.7f)); - AZ::Matrix3x4 matrix5 = matrix1; - matrix5 *= matrix4; - const AZ::Vector3 vector(1.9f, 2.3f, 0.2f); - EXPECT_TRUE((matrix1 * (matrix2 * matrix3)).IsClose((matrix1 * matrix2) * matrix3)); - EXPECT_THAT((matrix3 * matrix4) * vector, IsClose(matrix3 * (matrix4 * vector))); - EXPECT_TRUE((matrix2 * AZ::Matrix3x4::Identity()).IsClose(matrix2)); - EXPECT_TRUE((matrix3 * AZ::Matrix3x4::Identity()).IsClose(AZ::Matrix3x4::Identity() * matrix3)); - EXPECT_TRUE(matrix5.IsClose(matrix1 * matrix4)); + AZ::Matrix3x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + AZ::Matrix3x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + AZ::Matrix3x4 m3 = m1 * m2; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(74.0f, 80.0f, 86.0f, 96.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(206.0f, 224.0f, 242.0f, 268.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(338.0f, 368.0f, 398.0f, 440.0f))); + AZ::Matrix3x4 m4 = m1; + m4 *= m2; + EXPECT_THAT(m4.GetRow(0), IsClose(AZ::Vector4(74.0f, 80.0f, 86.0f, 96.0f))); + EXPECT_THAT(m4.GetRow(1), IsClose(AZ::Vector4(206.0f, 224.0f, 242.0f, 268.0f))); + EXPECT_THAT(m4.GetRow(2), IsClose(AZ::Vector4(338.0f, 368.0f, 398.0f, 440.0f))); + } + + TEST(MATH_Matrix3x4, TestSum) + { + AZ::Matrix3x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + AZ::Matrix3x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + + AZ::Matrix3x4 m3 = m1 + m2; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(8.0f, 10.0f, 12.0f, 14.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(16.0f, 18.0f, 20.0f, 22.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(24.0f, 26.0f, 28.0f, 30.0f))); + + m3 = m1; + m3 += m2; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(8.0f, 10.0f, 12.0f, 14.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(16.0f, 18.0f, 20.0f, 22.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(24.0f, 26.0f, 28.0f, 30.0f))); + } + + TEST(MATH_Matrix3x4, TestDifference) + { + AZ::Matrix3x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + AZ::Matrix3x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + + AZ::Matrix3x4 m3 = m1 - m2; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + m3 = m1; + m3 -= m2; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + } + + TEST(MATH_Matrix3x4, TestScalarMultiplication) + { + AZ::Matrix3x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + AZ::Matrix3x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + + AZ::Matrix3x4 m3 = m1 * 2.0f; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + m3 = m1; + m3 *= 2.0f; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + m3 = 2.0f * m1; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + } + + TEST(MATH_Matrix3x4, TestScalarDivision) + { + AZ::Matrix3x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + AZ::Matrix3x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + + AZ::Matrix3x4 m3 = m1 / 0.5f; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + m3 = m1; + m3 /= 0.5f; + EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + } + + TEST(MATH_Matrix3x4, TestNegation) + { + AZ::Matrix3x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + EXPECT_THAT(-(-m1), IsClose(m1)); + EXPECT_THAT(-AZ::Matrix3x4::CreateZero(), IsClose(AZ::Matrix3x4::CreateZero())); + + AZ::Matrix3x4 m2 = -m1; + EXPECT_THAT(m2.GetRow(0), IsClose(AZ::Vector4(-1.0f, -2.0f, -3.0f, -4.0f))); + EXPECT_THAT(m2.GetRow(1), IsClose(AZ::Vector4(-5.0f, -6.0f, -7.0f, -8.0f))); + EXPECT_THAT(m2.GetRow(2), IsClose(AZ::Vector4(-9.0f, -10.0f, -11.0f, -12.0f))); + + AZ::Matrix3x4 m3 = m1 + (-m1); + EXPECT_THAT(m3, IsClose(AZ::Matrix3x4::CreateZero())); } TEST(MATH_Matrix3x4, MultiplyByVector3) @@ -652,6 +767,34 @@ namespace UnitTest EXPECT_THAT(scaledMatrix.RetrieveScale(), IsClose(AZ::Vector3::CreateOne())); } + TEST_P(Matrix3x4ScaleFixture, ScaleSq) + { + const AZ::Matrix3x4 orthogonalMatrix = GetParam(); + EXPECT_THAT(orthogonalMatrix.RetrieveScaleSq(), IsClose(AZ::Vector3::CreateOne())); + AZ::Matrix3x4 unscaledMatrix = orthogonalMatrix; + unscaledMatrix.ExtractScale(); + EXPECT_THAT(unscaledMatrix.RetrieveScaleSq(), IsClose(AZ::Vector3::CreateOne())); + const AZ::Vector3 scale(2.8f, 0.7f, 1.3f); + AZ::Matrix3x4 scaledMatrix = orthogonalMatrix; + scaledMatrix.MultiplyByScale(scale); + EXPECT_THAT(scaledMatrix.RetrieveScaleSq(), IsClose(scale * scale)); + EXPECT_THAT(scaledMatrix.RetrieveScaleSq(), IsClose(scaledMatrix.RetrieveScale() * scaledMatrix.RetrieveScale())); + scaledMatrix.ExtractScale(); + EXPECT_THAT(scaledMatrix.RetrieveScaleSq(), IsClose(AZ::Vector3::CreateOne())); + } + + TEST_P(Matrix3x4ScaleFixture, GetReciprocalScaled) + { + const AZ::Matrix3x4 orthogonalMatrix = GetParam(); + EXPECT_THAT(orthogonalMatrix.GetReciprocalScaled(), IsClose(orthogonalMatrix)); + const AZ::Vector3 scale(2.8f, 0.7f, 1.3f); + AZ::Matrix3x4 scaledMatrix = orthogonalMatrix; + scaledMatrix.MultiplyByScale(scale); + AZ::Matrix3x4 reciprocalScaledMatrix = orthogonalMatrix; + reciprocalScaledMatrix.MultiplyByScale(scale.GetReciprocal()); + EXPECT_THAT(scaledMatrix.GetReciprocalScaled(), IsClose(reciprocalScaledMatrix)); + } + INSTANTIATE_TEST_CASE_P(MATH_Matrix3x4, Matrix3x4ScaleFixture, ::testing::ValuesIn(MathTestData::OrthogonalMatrix3x4s)); TEST(MATH_Matrix3x4, IsOrthogonal) diff --git a/Code/Framework/AzCore/Tests/Math/Matrix4x4Tests.cpp b/Code/Framework/AzCore/Tests/Math/Matrix4x4Tests.cpp index 851de490d0..a9baa3ddea 100644 --- a/Code/Framework/AzCore/Tests/Math/Matrix4x4Tests.cpp +++ b/Code/Framework/AzCore/Tests/Math/Matrix4x4Tests.cpp @@ -246,16 +246,16 @@ namespace UnitTest m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f); Matrix4x4 m3 = m1 * m2; - AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f))); - AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f))); - AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f))); - AZ_TEST_ASSERT(m3.GetRow(3).IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f))); + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f))); Matrix4x4 m4 = m1; m4 *= m2; - AZ_TEST_ASSERT(m4.GetRow(0).IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f))); - AZ_TEST_ASSERT(m4.GetRow(1).IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f))); - AZ_TEST_ASSERT(m4.GetRow(2).IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f))); - AZ_TEST_ASSERT(m4.GetRow(3).IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f))); + EXPECT_THAT(m4.GetRow(0), IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f))); + EXPECT_THAT(m4.GetRow(1), IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f))); + EXPECT_THAT(m4.GetRow(2), IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f))); + EXPECT_THAT(m4.GetRow(3), IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f))); } TEST(MATH_Matrix4x4, TestVectorMultiplication) @@ -265,18 +265,148 @@ namespace UnitTest m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f); - AZ_TEST_ASSERT((m1 * Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(18.0f, 46.0f, 74.0f))); - AZ_TEST_ASSERT((m1 * Vector4(1.0f, 2.0f, 3.0f, 4.0f)).IsClose(Vector4(30.0f, 70.0f, 110.0f, 150.0f))); - AZ_TEST_ASSERT(m1.TransposedMultiply3x3(Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(38.0f, 44.0f, 50.0f))); - AZ_TEST_ASSERT(m1.Multiply3x3(Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(14.0f, 38.0f, 62.0f))); + EXPECT_THAT((m1 * Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(18.0f, 46.0f, 74.0f))); + EXPECT_THAT((m1 * Vector4(1.0f, 2.0f, 3.0f, 4.0f)), IsClose(Vector4(30.0f, 70.0f, 110.0f, 150.0f))); + EXPECT_THAT(m1.TransposedMultiply3x3(Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(38.0f, 44.0f, 50.0f))); + EXPECT_THAT(m1.Multiply3x3(Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(14.0f, 38.0f, 62.0f))); Vector3 v1(1.0f, 2.0f, 3.0f); - AZ_TEST_ASSERT((v1 * m1).IsClose(Vector3(51.0f, 58.0f, 65.0f))); + EXPECT_THAT((v1 * m1), IsClose(Vector3(51.0f, 58.0f, 65.0f))); v1 *= m1; - AZ_TEST_ASSERT(v1.IsClose(Vector3(51.0f, 58.0f, 65.0f))); + EXPECT_THAT(v1, IsClose(Vector3(51.0f, 58.0f, 65.0f))); Vector4 v2(1.0f, 2.0f, 3.0f, 4.0f); - AZ_TEST_ASSERT((v2 * m1).IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f))); + EXPECT_THAT((v2 * m1), IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f))); v2 *= m1; - AZ_TEST_ASSERT(v2.IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f))); + EXPECT_THAT(v2, IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f))); + } + + TEST(MATH_Matrix4x4, TestSum) + { + Matrix4x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f); + Matrix4x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f); + + Matrix4x4 m3 = m1 + m2; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(8.0f, 10.0f, 12.0f, 14.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(16.0f, 18.0f, 20.0f, 22.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(24.0f, 26.0f, 28.0f, 30.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(32.0f, 34.0f, 36.0f, 38.0f))); + + m3 = m1; + m3 += m2; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(8.0f, 10.0f, 12.0f, 14.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(16.0f, 18.0f, 20.0f, 22.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(24.0f, 26.0f, 28.0f, 30.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(32.0f, 34.0f, 36.0f, 38.0f))); + } + + TEST(MATH_Matrix4x4, TestDifference) + { + Matrix4x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f); + Matrix4x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f); + + Matrix4x4 m3 = m1 - m2; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + m3 = m1; + m3 -= m2; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f))); + } + + TEST(MATH_Matrix4x4, TestScalarMultiplication) + { + Matrix4x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f); + Matrix4x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f); + + Matrix4x4 m3 = m1 * 2.0f; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f))); + m3 = m1; + m3 *= 2.0f; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f))); + m3 = 2.0f * m1; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f))); + } + + TEST(MATH_Matrix4x4, TestScalarDivision) + { + Matrix4x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f); + Matrix4x4 m2; + m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f); + m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f); + m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f); + m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f); + + Matrix4x4 m3 = m1 / 0.5f; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f))); + m3 = m1; + m3 /= 0.5f; + EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f))); + EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f))); + EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f))); + EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f))); + } + + TEST(MATH_Matrix4x4, TestNegation) + { + Matrix4x4 m1; + m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f); + m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f); + m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f); + m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f); + EXPECT_THAT(-(-m1), IsClose(m1)); + EXPECT_THAT(-Matrix4x4::CreateZero(), IsClose(Matrix4x4::CreateZero())); + + Matrix4x4 m2 = -m1; + EXPECT_THAT(m2.GetRow(0), IsClose(Vector4(-1.0f, -2.0f, -3.0f, -4.0f))); + EXPECT_THAT(m2.GetRow(1), IsClose(Vector4(-5.0f, -6.0f, -7.0f, -8.0f))); + EXPECT_THAT(m2.GetRow(2), IsClose(Vector4(-9.0f, -10.0f, -11.0f, -12.0f))); + EXPECT_THAT(m2.GetRow(3), IsClose(Vector4(-13.0f, -14.0f, -15.0f, -16.0f))); + + Matrix4x4 m3 = m1 + (-m1); + EXPECT_THAT(m3, IsClose(Matrix4x4::CreateZero())); } TEST(MATH_Matrix4x4, TestTranspose) @@ -368,4 +498,36 @@ namespace UnitTest m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f); AZ_TEST_ASSERT(m1.GetDiagonal() == Vector4(1.0f, 6.0f, 11.0f, 16.0f)); } + + TEST(MATH_Matrix4x4, TestScaleAccess) + { + Matrix4x4 m1 = Matrix4x4::CreateRotationX(DegToRad(40.0f)) * Matrix4x4::CreateScale(Vector3(2.0f, 3.0f, 4.0f)); + EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f))); + EXPECT_THAT(m1.ExtractScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f))); + EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3::CreateOne())); + m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f)); + EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(3.0f, 4.0f, 5.0f))); + } + + TEST(MATH_Matrix4x4, TestScaleSqAccess) + { + Matrix4x4 m1 = Matrix4x4::CreateRotationX(DegToRad(40.0f)) * Matrix4x4::CreateScale(Vector3(2.0f, 3.0f, 4.0f)); + EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(4.0f, 9.0f, 16.0f))); + m1.ExtractScale(); + EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3::CreateOne())); + m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f)); + EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(9.0f, 16.0f, 25.0f))); + } + + TEST(MATH_Matrix4x4, TestReciprocalScaled) + { + Matrix4x4 orthogonalMatrix = Matrix4x4::CreateRotationX(DegToRad(40.0f)); + EXPECT_THAT(orthogonalMatrix.GetReciprocalScaled(), IsClose(orthogonalMatrix)); + const AZ::Vector3 scale(2.8f, 0.7f, 1.3f); + AZ::Matrix4x4 scaledMatrix = orthogonalMatrix; + scaledMatrix.MultiplyByScale(scale); + AZ::Matrix4x4 reciprocalScaledMatrix = orthogonalMatrix; + reciprocalScaledMatrix.MultiplyByScale(scale.GetReciprocal()); + EXPECT_THAT(scaledMatrix.GetReciprocalScaled(), IsClose(reciprocalScaledMatrix)); + } } diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp index 417cb10c8c..08de21b54f 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/BaseJsonSerializerTests.cpp @@ -110,7 +110,7 @@ namespace JsonSerializationTests EXPECT_EQ(42, value); } - TEST_F(BaseJsonSerializerTests, ContinueLoading_PointerInstance_ValueLoadedCorrectly) + TEST_F(BaseJsonSerializerTests, ContinueLoading_ToPointerInstance_ValueLoadedCorrectly) { using namespace AZ::JsonSerializationResult; @@ -126,6 +126,51 @@ namespace JsonSerializationTests EXPECT_EQ(42, value); } + TEST_F(BaseJsonSerializerTests, ContinueLoading_ToNullPointer_ValueLoadedCorrectly) + { + using namespace AZ::JsonSerializationResult; + + rapidjson::Value json; + json.Set(42); + int* ptrValue = nullptr; + + ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, Flags::ResolvePointer); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + ASSERT_NE(nullptr, ptrValue); + EXPECT_EQ(42, *ptrValue); + + azfree(ptrValue, AZ::SystemAllocator, sizeof(int), alignof(int)); + } + + TEST_F(BaseJsonSerializerTests, ContinueLoading_DefaultToNullPointer_ValueLoadedCorrectly) + { + using namespace AZ::JsonSerializationResult; + + rapidjson::Value json(rapidjson::kObjectType); + int* ptrValue = nullptr; + + ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, Flags::ResolvePointer); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + ASSERT_NE(nullptr, ptrValue); + + azfree(ptrValue, AZ::SystemAllocator, sizeof(int), alignof(int)); + } + + TEST_F(BaseJsonSerializerTests, ContinueLoading_NullDeletesObject_ValueLoadedCorrectly) + { + using namespace AZ::JsonSerializationResult; + + rapidjson::Value json(rapidjson::kNullType); + int* ptrValue = reinterpret_cast(azmalloc(sizeof(int), alignof(int), AZ::SystemAllocator)); + + ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid(), json, *m_jsonDeserializationContext, Flags::ResolvePointer); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + ASSERT_EQ(nullptr, ptrValue); + } + // // ContinueStoring // @@ -156,6 +201,64 @@ namespace JsonSerializationTests Expect_DocStrEq("42"); } + TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToFullDefaultedInstance_ValueStoredCorrectly) + { + using namespace AZ::JsonSerializationResult; + + int value = 42; + int* ptrValue = &value; + int value2 = 42; + int* defaultPtrValue = &value2; + + ResultCode result = + ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + Expect_DocStrEq("{}"); + } + + TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptr_ValueStoredCorrectly) + { + using namespace AZ::JsonSerializationResult; + + int* ptrValue = nullptr; + + ResultCode result = ContinueStoring( + *m_jsonDocument, &ptrValue, nullptr, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + Expect_DocStrEq("null"); + } + + TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptrWithValueDefault_ValueStoredCorrectly) + { + using namespace AZ::JsonSerializationResult; + + int* ptrValue = nullptr; + int value2 = 42; + int* defaultPtrValue = &value2; + + ResultCode result = + ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + Expect_DocStrEq("null"); + } + + TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptrWithNullPtrDefault_NullPtrIsStored) + { + using namespace AZ::JsonSerializationResult; + + int* ptrValue = nullptr; + int* defaultPtrValue = nullptr; + + ResultCode result = + ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid(), *m_jsonSerializationContext, Flags::ResolvePointer); + + EXPECT_EQ(Processing::Completed, result.GetProcessing()); + Expect_DocStrEq("null"); + } + TEST_F(BaseJsonSerializerTests, ContinueStoring_ReplaceDefault_ValueStoredCorrectly) { using namespace AZ::JsonSerializationResult; diff --git a/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp b/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp index df340a2e61..2fc131aae2 100644 --- a/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/Serialization/Json/SmartPointerSerializerTests.cpp @@ -32,11 +32,6 @@ namespace JsonSerializationTests return AZStd::make_shared(); } - AZStd::shared_ptr CreateDefaultInstance() override - { - return AZStd::make_shared(); - } - void Reflect(AZStd::unique_ptr& context) override { context->RegisterGenericType(); @@ -51,6 +46,13 @@ namespace JsonSerializationTests using SmartPointer = T; using Base = SmartPointerBaseTestDescription; + AZStd::shared_ptr CreateDefaultInstance() override + { + auto result = AZStd::make_shared(); + *result = SmartPointer(aznew SimpleClass()); + return result; + } + AZStd::shared_ptr CreateFullySetInstance() override { auto result = AZStd::make_shared(); @@ -106,21 +108,6 @@ namespace JsonSerializationTests } }; - template class T> - class SmartPointerSimpleClassWithInstanceTestDescription : - public SmartPointerSimpleClassTestDescription - { - public: - using SmartPointer = typename SmartPointerSimpleClassTestDescription::SmartPointer; - - AZStd::shared_ptr CreateDefaultInstance() override - { - auto result = AZStd::make_shared(); - *result = SmartPointer(aznew SimpleClass()); - return result; - } - }; - template class T> class SmartPointerSimpleDerivedClassTestDescription : public SmartPointerBaseTestDescription> @@ -129,6 +116,13 @@ namespace JsonSerializationTests using SmartPointer = T; using Base = SmartPointerBaseTestDescription; + AZStd::shared_ptr CreateDefaultInstance() override + { + auto result = AZStd::make_shared(); + *result = SmartPointer(aznew BaseClass()); + return result; + } + AZStd::shared_ptr CreateFullySetInstance() override { auto* instance = aznew SimpleInheritence(); @@ -272,6 +266,13 @@ namespace JsonSerializationTests using SmartPointer = T; using Base = SmartPointerBaseTestDescription; + AZStd::shared_ptr CreateDefaultInstance() override + { + auto result = AZStd::make_shared(); + *result = SmartPointer(aznew BaseClass2()); + return result; + } + AZStd::shared_ptr CreateFullySetInstance() override { auto* instance = aznew MultipleInheritence(); @@ -424,9 +425,6 @@ namespace JsonSerializationTests SmartPointerSimpleClassTestDescription, SmartPointerSimpleClassTestDescription, SmartPointerSimpleClassTestDescription, - SmartPointerSimpleClassWithInstanceTestDescription, - SmartPointerSimpleClassWithInstanceTestDescription, - SmartPointerSimpleClassWithInstanceTestDescription, // Simple derived class, include single inheritance. SmartPointerSimpleDerivedClassTestDescription, SmartPointerSimpleDerivedClassTestDescription, @@ -551,6 +549,37 @@ namespace JsonSerializationTests EXPECT_EQ(nullptr, *instance); } + TEST_F(JsonSmartPointerSerializerTests, Load_DefaultInstanceToNullptr_ReturnsSuccess) + { + namespace JSR = AZ::JsonSerializationResult; + + SmartPointer instance; + AZStd::shared_ptr compare = m_description.CreateDefaultInstance(); + m_jsonDocument->SetObject(); + + JSR::ResultCode result = + m_serializer.Load(&instance, azrtti_typeid(), *m_jsonDocument, *m_jsonDeserializationContext); + + EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing()); + EXPECT_NE(nullptr, instance); + EXPECT_TRUE(m_description.AreEqual(instance, *compare)); + } + + TEST_F(JsonSmartPointerSerializerTests, Load_DefaultObjectDoesNotUpdateInstance_ReturnsSuccess) + { + namespace JSR = AZ::JsonSerializationResult; + + AZStd::shared_ptr instance = m_description.CreateFullySetInstance(); + AZStd::shared_ptr compare = m_description.CreateFullySetInstance(); + m_jsonDocument->SetObject(); + + JSR::ResultCode result = + m_serializer.Load(instance.get(), azrtti_typeid(), *m_jsonDocument, *m_jsonDeserializationContext); + + EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing()); + EXPECT_TRUE(m_description.AreEqual(*instance, *compare)); + } + TEST_F(JsonSmartPointerSerializerTests, Load_InstanceBeingReplacedWithDifferentType_ReturnsSuccess) { namespace JSR = AZ::JsonSerializationResult; @@ -720,13 +749,66 @@ namespace JsonSerializationTests namespace JSR = AZ::JsonSerializationResult; AZStd::shared_ptr instance = m_description.CreateFullySetInstance(); - SmartPointer nullPtr; - JSR::ResultCode result = m_serializer.Store(*m_jsonDocument, instance.get(), &nullPtr, + SmartPointer defaultInstance; + JSR::ResultCode result = m_serializer.Store( + *m_jsonDocument, instance.get(), &defaultInstance, azrtti_typeid(), *m_jsonSerializationContext); EXPECT_EQ(JSR::Outcomes::Success, result.GetOutcome()); } + TEST_F(JsonSmartPointerSerializerTests, Store_ValuePointerIsNullPtr_ReturnsSuccessAndStoresNull) + { + namespace JSR = AZ::JsonSerializationResult; + + SmartPointer instance; + AZStd::shared_ptr defaultInstance = m_description.CreateFullySetInstance(); + JSR::ResultCode result = m_serializer.Store( + *m_jsonDocument, &instance, defaultInstance.get(), azrtti_typeid(), *m_jsonSerializationContext); + + EXPECT_EQ(JSR::Outcomes::Success, result.GetOutcome()); + EXPECT_TRUE(m_jsonDocument->IsNull()); + } + + TEST_F(JsonSmartPointerSerializerTests, Store_ValueAndDefaultPointersAreNullPtr_ReturnsSuccessAndStoresNull) + { + namespace JSR = AZ::JsonSerializationResult; + + SmartPointer instance; + SmartPointer defaultInstance; + JSR::ResultCode result = + m_serializer.Store(*m_jsonDocument, &instance, &defaultInstance, azrtti_typeid(), *m_jsonSerializationContext); + + EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome()); + EXPECT_TRUE(m_jsonDocument->IsNull()); + } + + TEST_F(JsonSmartPointerSerializerTests, Store_ValueAndDefaultPointersAreBothDefault_ReturnsSuccess) + { + namespace JSR = AZ::JsonSerializationResult; + + AZStd::shared_ptr instance = m_description.CreateDefaultInstance(); + AZStd::shared_ptr defaultInstance = m_description.CreateDefaultInstance(); + JSR::ResultCode result = + m_serializer.Store(*m_jsonDocument, instance.get(), defaultInstance.get(), azrtti_typeid(), *m_jsonSerializationContext); + + EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome()); + Expect_ExplicitDefault(*m_jsonDocument); + } + + TEST_F(JsonSmartPointerSerializerTests, Store_ValueHasDefaultValuesAndDefaultHasNullPointer_ReturnsSuccess) + { + namespace JSR = AZ::JsonSerializationResult; + + AZStd::shared_ptr instance = m_description.CreateDefaultInstance(); + SmartPointer defaultInstance; + JSR::ResultCode result = m_serializer.Store( + *m_jsonDocument, instance.get(), &defaultInstance, azrtti_typeid(), *m_jsonSerializationContext); + + EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome()); + Expect_ExplicitDefault(*m_jsonDocument); + } + TEST_F(JsonSmartPointerSerializerTests, Store_DefaultPointerIsOtherClass_CompletesButDoesNotReturnDefaults) { namespace JSR = AZ::JsonSerializationResult; @@ -749,7 +831,7 @@ namespace JsonSerializationTests EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing()); } - TEST_F(JsonSmartPointerSerializerTests, Store_SaveAnClassThatIsNotReflected_ReturnsUnknown) + TEST_F(JsonSmartPointerSerializerTests, Store_ClassThatIsNotReflected_ReturnsUnknown) { namespace JSR = AZ::JsonSerializationResult; diff --git a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp index ea8fd75cfd..985bc4665d 100644 --- a/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/ProjectManager/ProjectManager.cpp @@ -137,7 +137,7 @@ namespace AzFramework::ProjectManager } AZ::IO::FixedMaxPath pythonPath = engineRootPath / "python"; pythonPath /= AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL; - auto cmdPath = AZ::IO::FixedMaxPathString::format("%s %s%s --executable_path=%s --parent_pid=%" PRId64, pythonPath.Native().c_str(), + auto cmdPath = AZ::IO::FixedMaxPathString::format("%s %s%s --executable_path=%s --parent_pid=%" PRIu32, pythonPath.Native().c_str(), debugOption.c_str(), (projectManagerPath / projectsScript).c_str(), executablePath.c_str(), AZ::Platform::GetCurrentProcessId()); AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; diff --git a/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl index b0c1a18b08..360ab93436 100644 --- a/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl +++ b/Code/Framework/AzFramework/AzFramework/Scene/Scene.inl @@ -51,7 +51,7 @@ namespace AzFramework } template - bool Scene::UnsetSubsystem(const T& system) + bool Scene::UnsetSubsystem([[maybe_unused]] const T& system) { const AZ::TypeId& targetType = azrtti_typeid(); const size_t systemKeysCount = m_systemKeys.size(); diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index ee49a95b23..e9dace3433 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -12,14 +12,150 @@ #include "CameraInput.h" +#include #include #include +#include #include #include namespace AzFramework { - void CameraSystem::HandleEvents(const InputEvent& event) + AZ_CVAR( + float, ed_cameraSystemDefaultPlaneHeight, 34.0f, nullptr, AZ::ConsoleFunctorFlags::Null, + "The default height of the ground plane to do intersection tests against when orbiting"); + AZ_CVAR(float, ed_cameraSystemBoostMultiplier, 3.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemTranslateSpeed, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemDefaultOrbitDistance, 60.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 100.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemRotateSpeed, 0.005f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + + AZ_CVAR( + AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR( + AZ::CVarFixedString, ed_cameraSystemTranslateBackwardKey, "keyboard_key_alphanumeric_S", nullptr, AZ::ConsoleFunctorFlags::Null, + ""); + AZ_CVAR( + AZ::CVarFixedString, ed_cameraSystemTranslateLeftKey, "keyboard_key_alphanumeric_A", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR( + AZ::CVarFixedString, ed_cameraSystemTranslateRightKey, "keyboard_key_alphanumeric_D", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemTranslateUpKey, "keyboard_key_alphanumeric_E", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR( + AZ::CVarFixedString, ed_cameraSystemTranslateDownKey, "keyboard_key_alphanumeric_Q", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR( + AZ::CVarFixedString, ed_cameraSystemTranslateBoostKey, "keyboard_key_modifier_shift_l", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitKey, "keyboard_key_modifier_alt_l", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + + AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemFreeLookButton, "mouse_button_right", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemFreePanButton, "mouse_button_middle", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitLookButton, "mouse_button_left", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitDollyButton, "mouse_button_right", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitPanButton, "mouse_button_middle", nullptr, AZ::ConsoleFunctorFlags::Null, ""); + + static InputChannelId CameraTranslateForwardId; + static InputChannelId CameraTranslateBackwardId; + static InputChannelId CameraTranslateLeftId; + static InputChannelId CameraTranslateRightId; + static InputChannelId CameraTranslateDownId; + static InputChannelId CameraTranslateUpId; + static InputChannelId CameraTranslateBoostId; + static InputChannelId CameraOrbitId; + + // externed elsewhere + InputChannelId CameraFreeLookButton; + InputChannelId CameraFreePanButton; + InputChannelId CameraOrbitLookButton; + InputChannelId CameraOrbitDollyButton; + InputChannelId CameraOrbitPanButton; + + void ReloadCameraKeyBindings() + { + const AZ::CVarFixedString& forward = ed_cameraSystemTranslateForwardKey; + CameraTranslateForwardId = InputChannelId(forward.c_str()); + const AZ::CVarFixedString& backward = ed_cameraSystemTranslateBackwardKey; + CameraTranslateBackwardId = InputChannelId(backward.c_str()); + const AZ::CVarFixedString& left = ed_cameraSystemTranslateLeftKey; + CameraTranslateLeftId = InputChannelId(left.c_str()); + const AZ::CVarFixedString& right = ed_cameraSystemTranslateRightKey; + CameraTranslateRightId = InputChannelId(right.c_str()); + const AZ::CVarFixedString& down = ed_cameraSystemTranslateDownKey; + CameraTranslateDownId = InputChannelId(down.c_str()); + const AZ::CVarFixedString& up = ed_cameraSystemTranslateUpKey; + CameraTranslateUpId = InputChannelId(up.c_str()); + const AZ::CVarFixedString& boost = ed_cameraSystemTranslateBoostKey; + CameraTranslateBoostId = InputChannelId(boost.c_str()); + const AZ::CVarFixedString& orbit = ed_cameraSystemOrbitKey; + CameraOrbitId = InputChannelId(orbit.c_str()); + const AZ::CVarFixedString& freeLook = ed_cameraSystemFreeLookButton; + CameraFreeLookButton = InputChannelId(freeLook.c_str()); + const AZ::CVarFixedString& freePan = ed_cameraSystemFreePanButton; + CameraFreePanButton = InputChannelId(freePan.c_str()); + const AZ::CVarFixedString& orbitLook = ed_cameraSystemOrbitLookButton; + CameraOrbitLookButton = InputChannelId(orbitLook.c_str()); + const AZ::CVarFixedString& orbitDolly = ed_cameraSystemOrbitDollyButton; + CameraOrbitDollyButton = InputChannelId(orbitDolly.c_str()); + const AZ::CVarFixedString& orbitPan = ed_cameraSystemOrbitPanButton; + CameraOrbitPanButton = InputChannelId(orbitPan.c_str()); + } + + static void ReloadCameraKeyBindingsConsole(const AZ::ConsoleCommandContainer&) + { + ReloadCameraKeyBindings(); + } + + AZ_CONSOLEFREEFUNC(ReloadCameraKeyBindingsConsole, AZ::ConsoleFunctorFlags::Null, "Reload keybindings for the modern camera system"); + + // Based on paper by David Eberly - https://www.geometrictools.com/Documentation/EulerAngles.pdf + AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation) + { + float x; + float y; + float z; + + // 2.4 Factor as RzRyRx + if (orientation.GetElement(2, 0) < 1.0f) + { + if (orientation.GetElement(2, 0) > -1.0f) + { + x = std::atan2(orientation.GetElement(2, 1), orientation.GetElement(2, 2)); + y = std::asin(-orientation.GetElement(2, 0)); + z = std::atan2(orientation.GetElement(1, 0), orientation.GetElement(0, 0)); + } + else + { + x = 0.0f; + y = AZ::Constants::Pi * 0.5f; + z = -std::atan2(-orientation.GetElement(2, 1), orientation.GetElement(1, 1)); + } + } + else + { + x = 0.0f; + y = -AZ::Constants::Pi * 0.5f; + z = std::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1)); + } + + return {x, y, z}; + } + + void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform) + { + const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(transform)); + + camera.m_lookAt = transform.GetTranslation(); + camera.m_pitch = eulerAngles.GetX(); + camera.m_yaw = eulerAngles.GetZ(); + } + + bool CameraSystem::HandleEvents(const InputEvent& event) { if (const auto& cursor_motion = AZStd::get_if(&event)) { @@ -30,10 +166,10 @@ namespace AzFramework m_scrollDelta = scroll->m_delta; } - m_cameras.HandleEvents(event); + return m_cameras.HandleEvents(event); } - Camera CameraSystem::StepCamera(const Camera& targetCamera, float deltaTime) + Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime) { const auto cursorDelta = m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value() ? m_currentCursorPosition.value() - m_lastCursorPosition.value() @@ -51,36 +187,41 @@ namespace AzFramework return nextCamera; } - void Cameras::AddCamera(AZStd::shared_ptr camera_input) + void Cameras::AddCamera(AZStd::shared_ptr cameraInput) { - m_idleCameraInputs.push_back(AZStd::move(camera_input)); + m_idleCameraInputs.push_back(AZStd::move(cameraInput)); } - void Cameras::HandleEvents(const InputEvent& event) + bool Cameras::HandleEvents(const InputEvent& event) { - for (auto& camera_input : m_activeCameraInputs) + bool handling = false; + for (auto& cameraInput : m_activeCameraInputs) { - camera_input->HandleEvents(event); + cameraInput->HandleEvents(event); + handling = !cameraInput->Idle() || handling; } - for (auto& camera_input : m_idleCameraInputs) + for (auto& cameraInput : m_idleCameraInputs) { - camera_input->HandleEvents(event); + cameraInput->HandleEvents(event); } + + return handling; } - Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, const float deltaTime) + Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime) { for (int i = 0; i < m_idleCameraInputs.size();) { - auto& camera_input = m_idleCameraInputs[i]; - const bool can_begin = camera_input->Beginning() && + auto& cameraInput = m_idleCameraInputs[i]; + const bool canBegin = cameraInput->Beginning() && std::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(), [](const auto& input) { return !input->Exclusive(); }) && - (!camera_input->Exclusive() || (camera_input->Exclusive() && m_activeCameraInputs.empty())); - if (can_begin) + (!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty())); + + if (canBegin) { - m_activeCameraInputs.push_back(camera_input); + m_activeCameraInputs.push_back(cameraInput); using AZStd::swap; swap(m_idleCameraInputs[i], m_idleCameraInputs[m_idleCameraInputs.size() - 1]); m_idleCameraInputs.pop_back(); @@ -93,25 +234,25 @@ namespace AzFramework // accumulate Camera nextCamera = targetCamera; - for (auto& camera_input : m_activeCameraInputs) + for (auto& cameraInput : m_activeCameraInputs) { - nextCamera = camera_input->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); + nextCamera = cameraInput->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); } for (int i = 0; i < m_activeCameraInputs.size();) { - auto& camera_input = m_activeCameraInputs[i]; - if (camera_input->Ending()) + auto& cameraInput = m_activeCameraInputs[i]; + if (cameraInput->Ending()) { - camera_input->ClearActivation(); - m_idleCameraInputs.push_back(camera_input); + cameraInput->ClearActivation(); + m_idleCameraInputs.push_back(cameraInput); using AZStd::swap; swap(m_activeCameraInputs[i], m_activeCameraInputs[m_activeCameraInputs.size() - 1]); m_activeCameraInputs.pop_back(); } else { - camera_input->ContinueActivation(); + cameraInput->ContinueActivation(); i++; } } @@ -134,7 +275,7 @@ namespace AzFramework { if (const auto& input = AZStd::get_if(&event)) { - if (input->m_channelId == m_channelId) + if (input->m_channelId == m_rotateChannelId) { if (input->m_state == InputChannel::State::Began) { @@ -154,14 +295,14 @@ namespace AzFramework { Camera nextCamera = targetCamera; - nextCamera.m_pitch += float(cursorDelta.m_y) * m_props.m_rotateSpeed; - nextCamera.m_yaw += float(cursorDelta.m_x) * m_props.m_rotateSpeed; + nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed; + nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed; - auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoOverPi, AZ::Constants::TwoOverPi); }; + const auto clampRotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; - nextCamera.m_yaw = clamp_rotation(nextCamera.m_yaw); + nextCamera.m_yaw = clampRotation(nextCamera.m_yaw); // clamp pitch to be +-90 degrees - nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::Pi * 0.5f, AZ::Constants::Pi * 0.5f); + nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi); return nextCamera; } @@ -170,7 +311,7 @@ namespace AzFramework { if (const auto& input = AZStd::get_if(&event)) { - if (input->m_channelId == InputDeviceMouse::Button::Middle) + if (input->m_channelId == m_panChannelId) { if (input->m_state == InputChannel::State::Began) { @@ -190,51 +331,50 @@ namespace AzFramework { Camera nextCamera = targetCamera; - const auto pan_axes = m_panAxesFn(nextCamera); + const auto panAxes = m_panAxesFn(nextCamera); - const auto delta_pan_x = float(cursorDelta.m_x) * pan_axes.m_horizontalAxis * m_props.m_panSpeed; - const auto delta_pan_y = float(cursorDelta.m_y) * pan_axes.m_verticalAxis * m_props.m_panSpeed; + const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed; + const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed; const auto inv = [](const bool invert) { constexpr float Dir[] = {1.0f, -1.0f}; return Dir[static_cast(invert)]; }; - nextCamera.m_lookAt += delta_pan_x * inv(m_props.m_panInvertX); - nextCamera.m_lookAt += delta_pan_y * -inv(m_props.m_panInvertY); + nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX); + nextCamera.m_lookAt += deltaPanY * -inv(ed_cameraSystemPanInvertY); return nextCamera; } TranslateCameraInput::TranslationType TranslateCameraInput::translationFromKey(InputChannelId channelId) { - // note: remove hard-coded InputDevice keys - if (channelId == InputDeviceKeyboard::Key::AlphanumericW) + if (channelId == CameraTranslateForwardId) { return TranslationType::Forward; } - if (channelId == InputDeviceKeyboard::Key::AlphanumericS) + if (channelId == CameraTranslateBackwardId) { return TranslationType::Backward; } - if (channelId == InputDeviceKeyboard::Key::AlphanumericA) + if (channelId == CameraTranslateLeftId) { return TranslationType::Left; } - if (channelId == InputDeviceKeyboard::Key::AlphanumericD) + if (channelId == CameraTranslateRightId) { return TranslationType::Right; } - if (channelId == InputDeviceKeyboard::Key::AlphanumericQ) + if (channelId == CameraTranslateDownId) { return TranslationType::Down; } - if (channelId == InputDeviceKeyboard::Key::AlphanumericE) + if (channelId == CameraTranslateUpId) { return TranslationType::Up; } @@ -259,19 +399,19 @@ namespace AzFramework BeginActivation(); } - if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL) + if (input->m_channelId == CameraTranslateBoostId) { m_boost = true; } } else if (input->m_state == InputChannel::State::Ended) { - m_translation ^= translationFromKey(input->m_channelId); + m_translation &= ~(translationFromKey(input->m_channelId)); if (m_translation == TranslationType::Nil) { EndActivation(); } - if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL) + if (input->m_channelId == CameraTranslateBoostId) { m_boost = false; } @@ -285,13 +425,13 @@ namespace AzFramework { Camera nextCamera = targetCamera; - const auto translation_basis = m_translationAxesFn(nextCamera); - const auto axisX = translation_basis.GetBasisX(); - const auto axisY = translation_basis.GetBasisY(); - const auto axisZ = translation_basis.GetBasisZ(); + const auto translationBasis = m_translationAxesFn(nextCamera); + const auto axisX = translationBasis.GetBasisX(); + const auto axisY = translationBasis.GetBasisY(); + const auto axisZ = translationBasis.GetBasisZ(); - const float speed = [boost = m_boost, props = m_props]() { - return props.m_translateSpeed * (boost ? props.m_boostMultiplier : 1.0f); + const float speed = [boost = m_boost]() { + return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f); }(); if ((m_translation & TranslationType::Forward) == TranslationType::Forward) @@ -342,12 +482,8 @@ namespace AzFramework { if (const auto* input = AZStd::get_if(&event)) { - if (input->m_channelId == InputDeviceKeyboard::Key::ModifierAltL) + if (input->m_channelId == CameraOrbitId) { - if (input->m_state == InputChannel::State::Updated) - { - goto end; - } if (input->m_state == InputChannel::State::Began) { BeginActivation(); @@ -358,7 +494,7 @@ namespace AzFramework } } } - end: + if (Active()) { m_orbitCameras.HandleEvents(event); @@ -366,29 +502,29 @@ namespace AzFramework } Camera OrbitCameraInput::StepCamera( - const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, float deltaTime) + const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime) { Camera nextCamera = targetCamera; if (Beginning()) { float hit_distance = 0.0f; - if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateZero()) - .CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY() * m_props.m_maxOrbitDistance, hit_distance)) + if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_cameraSystemDefaultPlaneHeight)) + .CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance)) { + hit_distance = AZStd::min(hit_distance, ed_cameraSystemMaxOrbitDistance); nextCamera.m_lookDist = -hit_distance; nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * hit_distance; } else { - nextCamera.m_lookDist = -m_props.m_defaultOrbitDistance; - nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * m_props.m_defaultOrbitDistance; + nextCamera.m_lookDist = -ed_cameraSystemMaxOrbitDistance; + nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * ed_cameraSystemMaxOrbitDistance; } } if (Active()) { - // todo: need to return nested cameras to idle state when ending nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); } @@ -413,10 +549,10 @@ namespace AzFramework Camera OrbitDollyScrollCameraInput::StepCamera( const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta, - [[maybe_unused]] float deltaTime) + [[maybe_unused]] const float deltaTime) { Camera nextCamera = targetCamera; - nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * m_props.m_dollySpeed, 0.0f); + nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * ed_cameraSystemOrbitDollyScrollSpeed, 0.0f); EndActivation(); return nextCamera; } @@ -425,7 +561,7 @@ namespace AzFramework { if (const auto& input = AZStd::get_if(&event)) { - if (input->m_channelId == InputDeviceMouse::Button::Right) + if (input->m_channelId == m_dollyChannelId) { if (input->m_state == InputChannel::State::Began) { @@ -444,7 +580,7 @@ namespace AzFramework [[maybe_unused]] const float deltaTime) { Camera nextCamera = targetCamera; - nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + float(cursorDelta.m_y) * m_props.m_dollySpeed, 0.0f); + nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + float(cursorDelta.m_y) * ed_cameraSystemOrbitDollyCursorSpeed, 0.0f); return nextCamera; } @@ -457,7 +593,7 @@ namespace AzFramework } Camera ScrollTranslationCameraInput::StepCamera( - const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, float scrollDelta, + const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta, [[maybe_unused]] const float deltaTime) { Camera nextCamera = targetCamera; @@ -465,38 +601,39 @@ namespace AzFramework const auto translation_basis = LookTranslation(nextCamera); const auto axisY = translation_basis.GetBasisY(); - nextCamera.m_lookAt += axisY * scrollDelta * m_props.m_translateSpeed; + nextCamera.m_lookAt += axisY * scrollDelta * ed_cameraSystemScrollTranslateSpeed; EndActivation(); return nextCamera; } - Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const SmoothProps& props, const float deltaTime) + Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime) { const auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; // keep yaw in 0 - 360 range - float target_yaw = clamp_rotation(targetCamera.m_yaw); - const float current_yaw = clamp_rotation(currentCamera.m_yaw); + float targetYaw = clamp_rotation(targetCamera.m_yaw); + const float currentYaw = clamp_rotation(currentCamera.m_yaw); - auto sign = [](const float value) { return static_cast((0.0f < value) - (value < 0.0f)); }; + // return the sign of the float input (-1, 0, 1) + const auto sign = [](const float value) { return aznumeric_cast((0.0f < value) - (value < 0.0f)); }; // ensure smooth transition when moving across 0 - 360 boundary - const float yaw_delta = target_yaw - current_yaw; - if (std::abs(yaw_delta) >= AZ::Constants::Pi) + const float yawDelta = targetYaw - currentYaw; + if (std::abs(yawDelta) >= AZ::Constants::Pi) { - target_yaw -= AZ::Constants::TwoPi * sign(yaw_delta); + targetYaw -= AZ::Constants::TwoPi * sign(yawDelta); } Camera camera; - // note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent + // note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent // article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php - const float lookRate = std::exp2(props.m_lookSmoothness); + const float lookRate = std::exp2(ed_cameraSystemLookSmoothness); const float lookT = std::exp2(-lookRate * deltaTime); camera.m_pitch = AZ::Lerp(targetCamera.m_pitch, currentCamera.m_pitch, lookT); - camera.m_yaw = AZ::Lerp(target_yaw, current_yaw, lookT); - const float moveRate = std::exp2(props.m_moveSmoothness); + camera.m_yaw = AZ::Lerp(targetYaw, currentYaw, lookT); + const float moveRate = std::exp2(ed_cameraSystemTranslateSmoothness); const float moveT = std::exp2(-moveRate * deltaTime); camera.m_lookDist = AZ::Lerp(targetCamera.m_lookDist, currentCamera.m_lookDist, moveT); camera.m_lookAt = targetCamera.m_lookAt.Lerp(currentCamera.m_lookAt, moveT); @@ -508,20 +645,24 @@ namespace AzFramework const auto& inputChannelId = inputChannel.GetInputChannelId(); const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId(); - if (inputChannelId == InputDeviceMouse::SystemCursorPosition) + const bool wasMouseButton = + AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) { + return button == inputChannelId; + }); + + if (inputChannelId == InputDeviceMouse::Movement::X || inputChannelId == InputDeviceMouse::Movement::Y) { - AZ::Vector2 systemCursorPositionNormalized = AZ::Vector2::CreateZero(); - InputSystemCursorRequestBus::EventResult( - systemCursorPositionNormalized, inputDeviceId, &InputSystemCursorRequestBus::Events::GetSystemCursorPositionNormalized); + const auto* position = inputChannel.GetCustomData(); + AZ_Assert(position, "Expected PositionData2D but found nullptr"); return CursorMotionEvent{ScreenPoint( - systemCursorPositionNormalized.GetX() * windowSize.m_width, systemCursorPositionNormalized.GetY() * windowSize.m_height)}; + position->m_normalizedPosition.GetX() * windowSize.m_width, position->m_normalizedPosition.GetY() * windowSize.m_height)}; } else if (inputChannelId == InputDeviceMouse::Movement::Z) { return ScrollEvent{inputChannel.GetValue()}; } - else if (InputDeviceMouse::IsMouseDevice(inputDeviceId) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) + else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) { return DiscreteInputEvent{inputChannelId, inputChannel.GetState()}; } diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 736e2404d9..6ccd7c43eb 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -17,13 +17,16 @@ #include #include #include -#include -#include #include +#include namespace AzFramework { - struct WindowSize; + //! Update camera key bindings that can be overridden with AZ console vars (invoke from console to update) + void ReloadCameraKeyBindings(); + + //! Return Euler angles (pitch, roll, yaw) for the incoming orientation. + AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation); struct Camera { @@ -51,8 +54,8 @@ namespace AzFramework inline AZ::Transform Camera::Transform() const { - return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationX(m_pitch) * - AZ::Transform::CreateRotationZ(m_yaw) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(m_lookDist)); + return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationZ(m_yaw) * + AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(m_lookDist)); } inline AZ::Matrix3x3 Camera::Rotation() const @@ -65,6 +68,8 @@ namespace AzFramework return Transform().GetTranslation(); } + void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform); + struct CursorMotionEvent { ScreenPoint m_position; @@ -159,19 +164,13 @@ namespace AzFramework Activation m_activation = Activation::Idle; }; - struct SmoothProps - { - float m_lookSmoothness = 5.0f; - float m_moveSmoothness = 5.0f; - }; - - Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const SmoothProps& props, float deltaTime); + Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, float deltaTime); class Cameras { public: void AddCamera(AZStd::shared_ptr cameraInput); - void HandleEvents(const InputEvent& event); + bool HandleEvents(const InputEvent& event); Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime); void Reset(); @@ -183,7 +182,7 @@ namespace AzFramework class CameraSystem { public: - void HandleEvents(const InputEvent& event); + bool HandleEvents(const InputEvent& event); Camera StepCamera(const Camera& targetCamera, float deltaTime); Cameras m_cameras; @@ -197,19 +196,16 @@ namespace AzFramework class RotateCameraInput : public CameraInput { public: - explicit RotateCameraInput(const InputChannelId channelId) - : m_channelId(channelId) + explicit RotateCameraInput(const InputChannelId rotateChannelId) + : m_rotateChannelId(rotateChannelId) { } + void HandleEvents(const InputEvent& event) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; - InputChannelId m_channelId; - - struct Props - { - float m_rotateSpeed = 0.005f; - } m_props; + private: + InputChannelId m_rotateChannelId; }; struct PanAxes @@ -242,22 +238,17 @@ namespace AzFramework class PanCameraInput : public CameraInput { public: - explicit PanCameraInput(PanAxesFn panAxesFn) + PanCameraInput(const InputChannelId panChannelId, PanAxesFn panAxesFn) : m_panAxesFn(AZStd::move(panAxesFn)) + , m_panChannelId(panChannelId) { } void HandleEvents(const InputEvent& event) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; - struct Props - { - float m_panSpeed = 0.01f; - bool m_panInvertX = true; - bool m_panInvertY = true; - } m_props; - private: PanAxesFn m_panAxesFn; + InputChannelId m_panChannelId; }; using TranslationAxesFn = AZStd::function; @@ -298,17 +289,11 @@ namespace AzFramework Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; void ResetImpl() override; - struct Props - { - float m_translateSpeed = 10.0f; - float m_boostMultiplier = 3.0f; - } m_props; - private: enum class TranslationType { // clang-format off - Nil = 0, + Nil = 0, Forward = 1 << 0, Backward = 1 << 1, Left = 1 << 2, @@ -354,6 +339,11 @@ namespace AzFramework return lhs; } + friend TranslationType operator~(const TranslationType lhs) + { + return static_cast(~static_cast>(lhs)); + } + static TranslationType translationFromKey(InputChannelId channelId); TranslationType m_translation = TranslationType::Nil; @@ -366,23 +356,19 @@ namespace AzFramework public: void HandleEvents(const InputEvent& event) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; - - struct Props - { - float m_dollySpeed = 0.2f; - } m_props; }; class OrbitDollyCursorMoveCameraInput : public CameraInput { public: + explicit OrbitDollyCursorMoveCameraInput(const InputChannelId dollyChannelId) + : m_dollyChannelId(dollyChannelId) {} + void HandleEvents(const InputEvent& event) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; - struct Props - { - float m_dollySpeed = 0.1f; - } m_props; + private: + InputChannelId m_dollyChannelId; }; class ScrollTranslationCameraInput : public CameraInput @@ -390,11 +376,6 @@ namespace AzFramework public: void HandleEvents(const InputEvent& event) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; - - struct Props - { - float m_translateSpeed = 0.2f; - } m_props; }; class OrbitCameraInput : public CameraInput @@ -408,13 +389,10 @@ namespace AzFramework } Cameras m_orbitCameras; - - struct Props - { - float m_defaultOrbitDistance = 15.0f; - float m_maxOrbitDistance = 100.0f; - } m_props; }; + struct WindowSize; + + //! Map from a generic InputChannel event to a camera specific InputEvent. InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize); } // namespace AzFramework diff --git a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake index b126a192ac..88f68d8bab 100644 --- a/Code/Framework/AzFramework/AzFramework/azframework_files.cmake +++ b/Code/Framework/AzFramework/AzFramework/azframework_files.cmake @@ -14,7 +14,6 @@ set(FILES AzFrameworkModule.h AzFrameworkModule.cpp API/ApplicationAPI.h - API/AtomActiveInterface.h Application/Application.cpp Application/Application.h Archive/Archive.cpp diff --git a/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/HandleDpiAwareness_Windows.cpp b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/HandleDpiAwareness_Windows.cpp index 9ffe06f7e3..b834995bd9 100644 --- a/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/HandleDpiAwareness_Windows.cpp +++ b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/HandleDpiAwareness_Windows.cpp @@ -16,7 +16,6 @@ #include #include -#include #include namespace AzQtComponents diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorPythonConsoleBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorPythonConsoleBus.h index 4f5a349518..de4ff396b2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorPythonConsoleBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/EditorPythonConsoleBus.h @@ -13,6 +13,12 @@ #include #include +#include + +namespace AZ +{ + struct BehaviorParameter; +} namespace AzToolsFramework { @@ -40,6 +46,8 @@ namespace AzToolsFramework }; using GlobalFunctionCollection = AZStd::vector; virtual void GetGlobalFunctionList(GlobalFunctionCollection& globalFunctionCollection) const = 0; + + virtual AZStd::string FetchPythonTypeName(const AZ::BehaviorParameter& param) = 0; }; //! Interface to signal the phases for the Python virtual machine diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp index 78681f3b4b..71bac86c0a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Thumbnails/FolderThumbnail.cpp @@ -10,8 +10,8 @@ * */ +#include #include -#include #include #include #include @@ -50,8 +50,8 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // FolderThumbnail ////////////////////////////////////////////////////////////////////////// - static constexpr const char* FolderIconPath = "Icons/AssetBrowser/Folder_16.svg"; - static constexpr const char* GemIconPath = "Icons/AssetBrowser/GemFolder_16.svg"; + static constexpr const char* FolderIconPath = "Assets/Editor/Icons/AssetBrowser/Folder_16.svg"; + static constexpr const char* GemIconPath = "Assets/Editor/Icons/AssetBrowser/GemFolder_16.svg"; FolderThumbnail::FolderThumbnail(SharedThumbnailKey key) : Thumbnail(key) @@ -62,13 +62,8 @@ namespace AzToolsFramework auto folderKey = azrtti_cast(m_key.data()); AZ_Assert(folderKey, "Incorrect key type, excpected FolderThumbnailKey"); - const char* engineRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot); - AZ_Assert(engineRoot, "Engine Root not initialized"); const char* folderIcon = folderKey->IsGem() ? GemIconPath : FolderIconPath; - AZStd::string absoluteIconPath; - AZ::StringFunc::Path::Join(engineRoot, folderIcon, absoluteIconPath); - + auto absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / folderIcon; m_pixmap.load(absoluteIconPath.c_str()); m_state = m_pixmap.isNull() ? State::Failed : State::Ready; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp index 61e144d338..95319d2e6b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBundle/AssetBundleComponent.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -250,7 +250,7 @@ namespace AzToolsFramework AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); AZ_Assert(fileIO != nullptr, "AZ::IO::FileIOBase must be ready for use.\n"); - AZStd::string bundleFilePath = assetBundleSettings.m_bundleFilePath; + AZ::IO::Path bundleFilePath = AZ::IO::Path(AZStd::string_view{ AZ::Utils::GetEnginePath() }) / assetBundleSettings.m_bundleFilePath; AzFramework::PlatformId platformId = static_cast(AzFramework::PlatformHelper::GetPlatformIndexFromName(assetBundleSettings.m_platform.c_str())); @@ -259,22 +259,13 @@ namespace AzToolsFramework return false; } - const char* appRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot); - - if (AzFramework::StringFunc::Path::IsRelative(bundleFilePath.c_str())) - { - AzFramework::StringFunc::Path::ConstructFull(appRoot, bundleFilePath.c_str(), bundleFilePath, true); - } - AZ::u64 maxSizeInBytes = static_cast(assetBundleSettings.m_maxBundleSizeInMB * NumOfBytesInMB); AZ::u64 assetCatalogFileSizeBuffer = static_cast(AssetCatalogFileSizeBufferPercentage * assetBundleSettings.m_maxBundleSizeInMB * NumOfBytesInMB) / 100; AZ::u64 bundleSize = 0; AZ::u64 totalFileSize = 0; int bundleIndex = 0; - AZStd::string bundleFullPath = bundleFilePath; - AZStd::string tempBundleFilePath = bundleFullPath + "_temp"; + AZStd::string tempBundleFilePath = bundleFilePath.Native() + "_temp"; AZStd::vector dependentBundleNames; AZStd::vector levelDirs; @@ -301,7 +292,7 @@ namespace AzToolsFramework if (fileIO->Exists(bundleFilePath.c_str())) { // This will delete both the parent bundle as well as all the dependent bundles mentioned in the manifest file of the parent bundle. - if (!DeleteBundleFiles(bundleFilePath)) + if (!DeleteBundleFiles(bundleFilePath.Native())) { return false; } @@ -390,7 +381,7 @@ namespace AzToolsFramework // we need to find a bundle which does not exist on disk; bundleIndex++; numOfTries--; - dependentBundleFileName = CreateAssetBundleFileName(bundleFilePath, bundleIndex); + dependentBundleFileName = CreateAssetBundleFileName(bundleFilePath.Native(), bundleIndex); AzFramework::StringFunc::Path::ReplaceFullName(tempBundleFilePath, (dependentBundleFileName + tempBundleFileSuffix).c_str()); } while (numOfTries && fileIO->Exists(tempBundleFilePath.c_str())); @@ -463,15 +454,7 @@ namespace AzToolsFramework AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZStd::string assetFileInfoListPath = assetBundleSettings.m_assetFileInfoListPath; - - const char* appRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot); - - if (AzFramework::StringFunc::Path::IsRelative(assetFileInfoListPath.c_str())) - { - AzFramework::StringFunc::Path::ConstructFull(appRoot, assetFileInfoListPath.c_str(), assetFileInfoListPath, true); - } + AZ::IO::Path assetFileInfoListPath = AZ::IO::Path{ AZStd::string_view{AZ::Utils::GetEnginePath()} } / assetBundleSettings.m_assetFileInfoListPath; if (!fileIO->Exists(assetFileInfoListPath.c_str())) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp index e7037c8936..373787e7dd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp @@ -53,7 +53,6 @@ #include #include #include -#include #include namespace AzToolsFramework @@ -93,7 +92,6 @@ namespace AzToolsFramework AzToolsFramework::SliceDependencyBrowserComponent::CreateDescriptor(), AzToolsFramework::Thumbnailer::ThumbnailerComponent::CreateDescriptor(), AzToolsFramework::AssetBrowser::AssetBrowserComponent::CreateDescriptor(), - AzToolsFramework::MaterialBrowser::MaterialBrowserComponent::CreateDescriptor(), AzToolsFramework::EditorInteractionSystemComponent::CreateDescriptor(), AzToolsFramework::Components::EditorComponentAPIComponent::CreateDescriptor(), AzToolsFramework::Components::EditorLevelComponentAPIComponent::CreateDescriptor(), diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserBus.h deleted file mode 100644 index b0d625b6e4..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserBus.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include - -namespace AZ -{ - namespace Data - { - struct AssetId; - } -} - -namespace AzToolsFramework -{ - namespace MaterialBrowser - { - class MaterialBrowserRequests - : public AZ::EBusTraits - { - public: - - // Only a single handler is allowed - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - - virtual bool HasRecord(const AZ::Data::AssetId& assetId) = 0; - virtual bool IsMultiMaterial(const AZ::Data::AssetId& assetId) = 0; - }; - - using MaterialBrowserRequestBus = AZ::EBus; - } // namespace MaterialBrowser -} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.cpp deleted file mode 100644 index f64d4af23d..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include - -#include -#include -#include -#include -#include -#include - -#include -AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: 'QBrush::d': class 'QScopedPointer' needs to have dll-interface to be used by clients of class 'QBrush' -#include -AZ_POP_DISABLE_WARNING - -namespace AzToolsFramework -{ - namespace MaterialBrowser - { - MaterialBrowserComponent::MaterialBrowserComponent() - { - } - - void MaterialBrowserComponent::Activate() - { - using namespace Thumbnailer; - using namespace AssetBrowser; - const char* contextName = "MaterialBrowser"; - ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterContext, contextName); - ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(FolderThumbnailCache), contextName); - ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(SourceThumbnailCache), contextName); - ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(MaterialThumbnailCache), contextName); - ThumbnailerRequestsBus::Broadcast(&ThumbnailerRequests::RegisterThumbnailProvider, MAKE_TCACHE(SourceControlThumbnailCache), contextName); - } - - void MaterialBrowserComponent::Deactivate() - { - } - - void MaterialBrowserComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serialize = azrtti_cast(context); - if (serialize) - { - serialize->Class(); - } - } - - void MaterialBrowserComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("ThumbnailerService", 0x65422b97)); - } - } // namespace MaterialBrowser -} // namespace AzToolsFramework - diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.h deleted file mode 100644 index 93a48cf22c..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialBrowserComponent.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include - -namespace AzToolsFramework -{ - namespace MaterialBrowser - { - //! MaterialBrowserComponent allows initialization of MaterialBrowser systems, such as thumbnails - class MaterialBrowserComponent - : public AZ::Component - { - public: - AZ_COMPONENT(MaterialBrowserComponent, "{121F3F3B-2412-490D-9E3E-C205C677F476}") - - MaterialBrowserComponent(); - virtual ~MaterialBrowserComponent() = default; - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component - ////////////////////////////////////////////////////////////////////////// - void Activate() override; - void Deactivate() override; - static void Reflect(AZ::ReflectContext* context); - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); - }; - } // namespace MaterialBrowser -} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialThumbnail.cpp deleted file mode 100644 index e04df8937c..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialThumbnail.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include - -#include - -namespace AzToolsFramework -{ - namespace MaterialBrowser - { - static constexpr const char* SimpleMaterialIconPath = ":/MaterialBrowser/images/material_04.png"; - static constexpr const char* MultiMaterialIconPath = ":/MaterialBrowser/images/material_06.png"; - - ////////////////////////////////////////////////////////////////////////// - // MaterialThumbnail - ////////////////////////////////////////////////////////////////////////// - MaterialThumbnail::MaterialThumbnail(Thumbnailer::SharedThumbnailKey key) - : Thumbnail(key) - { - auto productKey = azrtti_cast(m_key.data()); - AZ_Assert(productKey, "Incorrect key type, excpected ProductThumbnailKey"); - - bool multiMat = false; - MaterialBrowserRequestBus::BroadcastResult(multiMat, &MaterialBrowserRequests::IsMultiMaterial, productKey->GetAssetId()); - - QString iconPath = multiMat ? MultiMaterialIconPath : SimpleMaterialIconPath; - m_pixmap.load(iconPath); - m_state = m_pixmap.isNull() ? State::Failed : State::Ready; - } - - ////////////////////////////////////////////////////////////////////////// - // MaterialThumbnailCache - ////////////////////////////////////////////////////////////////////////// - MaterialThumbnailCache::MaterialThumbnailCache() - : ThumbnailCache() {} - - MaterialThumbnailCache::~MaterialThumbnailCache() = default; - - int MaterialThumbnailCache::GetPriority() const - { - return 1; - } - - const char* MaterialThumbnailCache::GetProviderName() const - { - return ProviderName; - } - - bool MaterialThumbnailCache::IsSupportedThumbnail(Thumbnailer::SharedThumbnailKey key) const - { - return azrtti_istypeof(key.data()); - } - - } // namespace MaterialBrowser -} // namespace AzToolsFramework - -#include "MaterialBrowser/moc_MaterialThumbnail.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialThumbnail.h b/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialThumbnail.h deleted file mode 100644 index 60a2bb11e5..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/MaterialBrowser/MaterialThumbnail.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include -#include -#endif - -namespace AzToolsFramework -{ - namespace MaterialBrowser - { - //! Material Browser uses only 2 thumbnails: simple and multimaterial - class MaterialThumbnail - : public Thumbnailer::Thumbnail - { - Q_OBJECT - public: - MaterialThumbnail(Thumbnailer::SharedThumbnailKey key); - }; - - namespace - { - class MaterialKeyHash - { - public: - size_t operator()(const Thumbnailer::SharedThumbnailKey& /*val*/) const - { - return 0; // there is only 2 thumbnails in this cache - } - }; - - class MaterialKeyEqual - { - public: - bool operator()(const Thumbnailer::SharedThumbnailKey& val1, const Thumbnailer::SharedThumbnailKey& val2) const - { - auto productThumbnailKey1 = azrtti_cast(val1.data()); - auto productThumbnailKey2 = azrtti_cast(val2.data()); - if (!productThumbnailKey1 || !productThumbnailKey2) - { - return false; - } - - // check whether keys point to single or multimaterial asset type - bool multiMat1 = false; - bool multiMat2 = false; - MaterialBrowserRequestBus::BroadcastResult(multiMat1, &MaterialBrowserRequests::IsMultiMaterial, productThumbnailKey1->GetAssetId()); - MaterialBrowserRequestBus::BroadcastResult(multiMat2, &MaterialBrowserRequests::IsMultiMaterial, productThumbnailKey2->GetAssetId()); - return multiMat1 == multiMat2; - } - }; - } - - //! MaterialBrowserEntry thumbnails - class MaterialThumbnailCache - : public Thumbnailer::ThumbnailCache - { - public: - MaterialThumbnailCache(); - ~MaterialThumbnailCache() override; - - int GetPriority() const override; - const char* GetProviderName() const override; - - static constexpr const char* ProviderName = "CryMaterial Thumbnails"; - - protected: - bool IsSupportedThumbnail(Thumbnailer::SharedThumbnailKey key) const override; - }; - } // namespace MaterialBrowser -} // namespace AzToolsFramework - - diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 1e9cc35230..475510c52f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -96,9 +96,7 @@ namespace AzToolsFramework // target templates of the other instances. for (auto& nestedInstance : instances) { - PrefabUndoHelpers::RemoveLink( - nestedInstance->GetTemplateId(), commonRootEntityOwningInstance->get().GetTemplateId(), - nestedInstance->GetInstanceAlias(), nestedInstance->GetLinkId(), undoBatch.GetUndoBatch()); + RemoveLink(nestedInstance, commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch()); } PrefabUndoHelpers::UpdatePrefabInstance( @@ -238,14 +236,9 @@ namespace AzToolsFramework // Retrieve the owning instance of the common root entity, which will be our new instance's parent instance. commonRootEntityOwningInstance = GetOwnerInstanceByEntityId(commonRootEntityId); - if (!commonRootEntityOwningInstance) - { - AZ_Assert( - false, - "Failed to create prefab : Couldn't get a valid owning instance for the common root entity of the enities provided"); - return AZ::Failure(AZStd::string( - "Failed to create prefab : Couldn't get a valid owning instance for the common root entity of the enities provided")); - } + AZ_Assert( + commonRootEntityOwningInstance.has_value(), + "Failed to create prefab : Couldn't get a valid owning instance for the common root entity of the enities provided"); return AZ::Success(); } @@ -287,6 +280,34 @@ namespace AzToolsFramework m_prefabUndoCache.Store(containerEntityId, AZStd::move(containerEntityDomAfter)); } + void PrefabPublicHandler::RemoveLink( + AZStd::unique_ptr& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch) + { + LinkReference nestedInstanceLink = m_prefabSystemComponentInterface->FindLink(sourceInstance->GetLinkId()); + AZ_Assert( + nestedInstanceLink.has_value(), + "A valid link was not found for one of the instances provided as input for the CreatePrefab operation."); + + PrefabDomReference nestedInstanceLinkDom = nestedInstanceLink->get().GetLinkDom(); + AZ_Assert( + nestedInstanceLinkDom.has_value(), + "A valid DOM was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); + + PrefabDomValueReference nestedInstanceLinkPatches = + PrefabDomUtils::FindPrefabDomValue(nestedInstanceLinkDom->get(), PrefabDomUtils::PatchesName); + AZ_Assert( + nestedInstanceLinkPatches.has_value(), + "A valid DOM for patches was not found for the link corresponding to one of the instances provided as input for the " + "CreatePrefab operation."); + + PrefabDom patchesCopyForUndoSupport; + patchesCopyForUndoSupport.CopyFrom(nestedInstanceLinkPatches->get(), patchesCopyForUndoSupport.GetAllocator()); + PrefabUndoHelpers::RemoveLink( + sourceInstance->GetTemplateId(), targetTemplateId, sourceInstance->GetInstanceAlias(), sourceInstance->GetLinkId(), + patchesCopyForUndoSupport, undoBatch); + } + PrefabOperationResult PrefabPublicHandler::SavePrefab(AZ::IO::Path filePath) { auto templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(filePath.c_str()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index e83513dbff..5ade666a40 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -82,6 +82,16 @@ namespace AzToolsFramework const EntityList& topLevelEntities, Instance& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch, AZ::EntityId commonRootEntityId); + /** + * Removes the link between template of the sourceInstance and the template corresponding to targetTemplateId. + * + * \param sourceInstance The instance corresponding to the source template of the link to be removed. + * \param targetTemplateId The id of the target template of the link to be removed. + * \param undoBatch The undo batch to set as parent for this remove link action. + */ + void RemoveLink( + AZStd::unique_ptr& sourceInstance, TemplateId targetTemplateId, UndoSystem::URSequencePoint* undoBatch); + /** * Given a list of entityIds, finds the prefab instance that owns the common root entity of the entityIds. * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 3f660bb73b..4413586e77 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -663,8 +663,9 @@ namespace AzToolsFramework newLink.SetSourceTemplateId(linkSourceId); newLink.SetInstanceName(instanceAlias.c_str()); newLink.GetLinkDom().SetObject(); - newLink.GetLinkDom().AddMember(rapidjson::StringRef(PrefabDomUtils::SourceName), - rapidjson::StringRef(sourceTemplate.GetFilePath().c_str()), newLink.GetLinkDom().GetAllocator()); + newLink.GetLinkDom().AddMember( + rapidjson::StringRef(PrefabDomUtils::SourceName), rapidjson::StringRef(sourceTemplate.GetFilePath().c_str()), + newLink.GetLinkDom().GetAllocator()); if (linkPatch && linkPatch->get().IsArray() && !(linkPatch->get().Empty())) { @@ -770,8 +771,8 @@ namespace AzToolsFramework return false; } - Template& sourceTemplate = sourceTemplateReference->get(); #if defined(AZ_ENABLE_TRACING) + Template& sourceTemplate = sourceTemplateReference->get(); Template& targetTemplate = targetTemplateReference->get(); #endif diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp index ea3fa5d84d..ad0cdc166a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.cpp @@ -113,7 +113,7 @@ namespace AzToolsFramework , m_sourceId(InvalidTemplateId) , m_instanceAlias("") , m_linkId(InvalidLinkId) - , m_linkDom(PrefabDom()) + , m_linkPatches(PrefabDom()) , m_linkStatus(LinkStatus::LINKSTATUS) { m_prefabSystemComponentInterface = AZ::Interface::Get(); @@ -124,7 +124,7 @@ namespace AzToolsFramework const TemplateId& targetId, const TemplateId& sourceId, const InstanceAlias& instanceAlias, - PrefabDomReference linkDom, + PrefabDomReference linkPatches, const LinkId linkId) { m_targetId = targetId; @@ -132,9 +132,9 @@ namespace AzToolsFramework m_instanceAlias = instanceAlias; m_linkId = linkId; - if (linkDom.has_value()) + if (linkPatches.has_value()) { - m_linkDom = AZStd::move(linkDom->get()); + m_linkPatches = AZStd::move(linkPatches->get()); } //if linkId is invalid, set as ADD @@ -193,7 +193,7 @@ namespace AzToolsFramework void PrefabUndoInstanceLink::AddLink() { - m_linkId = m_prefabSystemComponentInterface->CreateLink(m_targetId, m_sourceId, m_instanceAlias, m_linkDom, m_linkId); + m_linkId = m_prefabSystemComponentInterface->CreateLink(m_targetId, m_sourceId, m_instanceAlias, m_linkPatches, m_linkId); } void PrefabUndoInstanceLink::RemoveLink() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.h index 0d15d707d2..49bae4eda0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndo.h @@ -101,7 +101,7 @@ namespace AzToolsFramework const TemplateId& targetId, const TemplateId& sourceId, const InstanceAlias& instanceAlias, - PrefabDomReference linkDom = PrefabDomReference(), + PrefabDomReference linkPatches = PrefabDomReference(), const LinkId linkId = InvalidLinkId); void Undo() override; @@ -120,7 +120,7 @@ namespace AzToolsFramework InstanceAlias m_instanceAlias; LinkId m_linkId; - PrefabDom m_linkDom; //data for delete/update + PrefabDom m_linkPatches; //data for delete/update LinkStatus m_linkStatus; PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.cpp index 2062e8b12c..24eb71e055 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.cpp @@ -46,13 +46,11 @@ namespace AzToolsFramework } void RemoveLink( - TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias, - LinkId linkId, UndoSystem::URSequencePoint* undoBatch) + TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias, LinkId linkId, + PrefabDomReference linkPatches, UndoSystem::URSequencePoint* undoBatch) { auto linkRemoveUndo = aznew PrefabUndoInstanceLink("Remove Link"); - PrefabDom emptyLinkDom; - linkRemoveUndo->Capture( - targetTemplateId, sourceTemplateId, instanceAlias, emptyLinkDom, linkId); + linkRemoveUndo->Capture(targetTemplateId, sourceTemplateId, instanceAlias, linkPatches, linkId); linkRemoveUndo->SetParent(undoBatch); linkRemoveUndo->Redo(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.h index 74532b87a2..6429df3b04 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabUndoHelpers.h @@ -25,8 +25,8 @@ namespace AzToolsFramework TemplateId sourceTemplateId, TemplateId targetTemplateId, PrefabDomReference patch, const InstanceAlias& instanceAlias, UndoSystem::URSequencePoint* undoBatch); void RemoveLink( - TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias, - LinkId linkId, UndoSystem::URSequencePoint* undoBatch); + TemplateId sourceTemplateId, TemplateId targetTemplateId, const InstanceAlias& instanceAlias, LinkId linkId, + PrefabDomReference linkPatches, UndoSystem::URSequencePoint* undoBatch); } } // namespace Prefab } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp index fb9d156b20..c29a9e4c6b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/LoadingThumbnail.cpp @@ -10,7 +10,7 @@ * */ -#include +#include #include #include @@ -23,18 +23,14 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // LoadingThumbnail ////////////////////////////////////////////////////////////////////////// - static const char* LoadingIconPath = "Icons/AssetBrowser/in_progress.gif"; + static constexpr const char* LoadingIconPath = "Assets/Editor/Icons/AssetBrowser/in_progress.gif"; LoadingThumbnail::LoadingThumbnail() : Thumbnail(MAKE_TKEY(ThumbnailKey)) , m_angle(0) { - const char* engineRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot); - AZ_Assert(engineRoot, "Engine Root not initialized"); - AZStd::string iconPath; - AZ::StringFunc::Path::Join(engineRoot, LoadingIconPath, iconPath); - m_loadingMovie.setFileName(iconPath.c_str()); + auto absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / LoadingIconPath; + m_loadingMovie.setFileName(absoluteIconPath.c_str()); m_loadingMovie.setCacheMode(QMovie::CacheMode::CacheAll); m_loadingMovie.setScaledSize(QSize(LoadingThumbnailSize, LoadingThumbnailSize)); m_loadingMovie.start(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp index 270a5b113f..39af7d9293 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/MissingThumbnail.cpp @@ -10,18 +10,21 @@ * */ +#include +#include #include namespace AzToolsFramework { namespace Thumbnailer { - static const char* MISSING_ICON_PATH = "Icons/AssetBrowser/Default_16.svg"; + static constexpr const char* MissingIconPath = "Assets/Editor/Icons/AssetBrowser/Default_16.svg"; MissingThumbnail::MissingThumbnail() : Thumbnail(MAKE_TKEY(ThumbnailKey)) { - m_pixmap.load(MISSING_ICON_PATH); + auto absoluteIconPath = AZ::IO::FixedMaxPath(AZ::Utils::GetEnginePath()) / MissingIconPath; + m_pixmap.load(absoluteIconPath.c_str()); m_state = m_pixmap.isNull() ? State::Failed : State::Ready; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 4cf121c517..a7fcf2e711 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -70,11 +70,6 @@ set(FILES AssetCatalog/PlatformAddressedAssetCatalog.cpp AssetCatalog/PlatformAddressedAssetCatalogManager.h AssetCatalog/PlatformAddressedAssetCatalogManager.cpp - MaterialBrowser/MaterialBrowserBus.h - MaterialBrowser/MaterialBrowserComponent.cpp - MaterialBrowser/MaterialBrowserComponent.h - MaterialBrowser/MaterialThumbnail.cpp - MaterialBrowser/MaterialThumbnail.h Thumbnails/ThumbnailerComponent.cpp Thumbnails/ThumbnailerComponent.h Thumbnails/LoadingThumbnail.cpp diff --git a/Code/LauncherUnified/StaticModules.in b/Code/LauncherUnified/StaticModules.in index 629973bdf4..03b22b076a 100644 --- a/Code/LauncherUnified/StaticModules.in +++ b/Code/LauncherUnified/StaticModules.in @@ -20,15 +20,6 @@ #include -#define DECLARE_CRYREGISTER_SINGLETON_CLASS(implclassname) \ - void* Get##implclassname##Factory(); - -DECLARE_CRYREGISTER_SINGLETON_CLASS(CEngineModule_Cry3DEngine) -DECLARE_CRYREGISTER_SINGLETON_CLASS(CEngineModule_CryFont) -DECLARE_CRYREGISTER_SINGLETON_CLASS(CEngineModule_CryRenderer) - -#undef DECLARE_CRYREGISTER_SINGLETON_CLASS - namespace AZ { class Module; @@ -39,14 +30,6 @@ ${extern_module_declarations} extern "C" void CreateStaticModules(AZStd::vector& modulesOut) { ${module_invocations} - // Call methods to avoid symbol striping -#define NON_STRIPPING_CALL(Module) \ - AZ_UNUSED(Get##Module##Factory()) - - NON_STRIPPING_CALL(CEngineModule_Cry3DEngine); - NON_STRIPPING_CALL(CEngineModule_CryFont); - NON_STRIPPING_CALL(CEngineModule_CryRenderer); -#undef NON_STRIPPING_CALL } #endif // AZ_MONOLITHIC_BUILD diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 08ddd538fc..28429729e1 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -66,7 +66,6 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC set(game_build_dependencies ${game_gem_dependencies} Legacy::CrySystem - Legacy::CryFont ) if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) @@ -95,7 +94,6 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC set(server_build_dependencies ${game_gem_dependencies} Legacy::CrySystem - Legacy::CryFont ) endif() @@ -103,7 +101,6 @@ foreach(project_name project_path IN ZIP_LISTS LY_PROJECTS_TARGET_NAME LY_PROJEC set(game_runtime_dependencies Legacy::CrySystem - Legacy::CryFont ) endif() diff --git a/Code/Sandbox/Editor/Controls/PreviewModelCtrl.cpp b/Code/Sandbox/Editor/Controls/PreviewModelCtrl.cpp index 5746e9db2f..9b07f59e6a 100644 --- a/Code/Sandbox/Editor/Controls/PreviewModelCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/PreviewModelCtrl.cpp @@ -365,10 +365,6 @@ bool CPreviewModelCtrl::Render() } _smart_ptr pMaterial; - if (m_pCurrentMaterial) - { - pMaterial = m_pCurrentMaterial->GetMatInfo(); - } if (m_bPrecacheMaterial) { @@ -430,11 +426,6 @@ bool CPreviewModelCtrl::Render() m_pRenderer->EF_ADDDlight(&m_lights[i], passInfo); } - if (m_pCurrentMaterial) - { - m_pCurrentMaterial->DisableHighlightForFrame(); - } - if (m_bShowObject) { RenderObject(pMaterial, passInfo); @@ -778,32 +769,6 @@ void CPreviewModelCtrl::SetRotation(bool bEnable) m_bRotate = bEnable; } -void CPreviewModelCtrl::SetMaterial(CMaterial* pMaterial) -{ - if (pMaterial) - { - if ((pMaterial->GetFlags() & MTL_FLAG_NOPREVIEW)) - { - m_pCurrentMaterial = 0; - if (isVisible()) - { - update(); - } - return; - } - } - m_pCurrentMaterial = pMaterial; - if (isVisible()) - { - update(); - } -} - -CMaterial* CPreviewModelCtrl::GetMaterial() -{ - return m_pCurrentMaterial; -} - void CPreviewModelCtrl::OnEditorNotifyEvent(EEditorNotifyEvent event) { switch (event) diff --git a/Code/Sandbox/Editor/Controls/PreviewModelCtrl.h b/Code/Sandbox/Editor/Controls/PreviewModelCtrl.h index 73839612af..6388be9fd5 100644 --- a/Code/Sandbox/Editor/Controls/PreviewModelCtrl.h +++ b/Code/Sandbox/Editor/Controls/PreviewModelCtrl.h @@ -22,8 +22,6 @@ #include -#include - #endif struct IRenderNode; @@ -71,9 +69,6 @@ public: int heightForWidth(int w) const override; bool hasHeightForWidth() const override; - void SetMaterial(CMaterial* pMaterial); - CMaterial* GetMaterial(); - void GetImageOffscreen(CImageEx& image, const QSize& customSize = QSize(0, 0)); void GetCameraTM(Matrix34& cameraTM); @@ -192,7 +187,6 @@ protected: float m_tileY; float m_tileSizeX; float m_tileSizeY; - _smart_ptr m_pCurrentMaterial; CameraChangeCallback m_cameraChangeCallback; void* m_pCameraChangeUserData; diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp index b777bb6930..f0367ffdc1 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyCtrl.cpp @@ -29,14 +29,12 @@ void RegisterReflectedVarHandlers() EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AnimationPropertyWidgetHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ShaderPropertyHandler()); - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew MaterialPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ReverbPresetPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LightAnimationPropertyHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew UserPopupWidgetHandler()); - EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LensFlareHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew ColorCurveHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FloatCurveHandler()); EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew MotionPropertyWidgetHandler()); diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp index 3d17e77bb0..75344b2172 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.cpp @@ -27,7 +27,6 @@ // Editor #include "ShadersDialog.h" -#include "Material/MaterialManager.h" #include "SelectLightAnimationDialog.h" #include "SelectSequenceDialog.h" #include "SelectEAXPresetDlg.h" @@ -88,25 +87,6 @@ void ShaderPropertyEditor::onEditClicked() } } -void MaterialPropertyEditor::onEditClicked() -{ -} - -void MaterialPropertyEditor::onButton2Clicked() -{ - // Open material browser dialog. - IDataBaseItem *pItem = GetIEditor()->GetMaterialManager()->GetSelectedItem(); - if (pItem) - { - QString value = pItem->GetName(); - value.replace('\\', '/'); - if (value.length() >= MAX_PATH) - value = value.left(MAX_PATH); - SetValue(value); - } - else - SetValue(QString()); -} void ReverbPresetPropertyEditor::onEditClicked() { diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h index d5ec0045c4..cdbb18ae12 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyGenericCtrl.h @@ -109,16 +109,6 @@ public: void onEditClicked() override; }; -class MaterialPropertyEditor - : public GenericPopupPropertyEditor -{ -public: - MaterialPropertyEditor(QWidget* pParent = nullptr) - : GenericPopupPropertyEditor(pParent, true){} - void onEditClicked() override; - void onButton2Clicked() override; -}; - class ReverbPresetPropertyEditor : public GenericPopupPropertyEditor { @@ -179,7 +169,6 @@ public: #define CONST_AZ_CRC(name, value) AZ::u32(value) using ShaderPropertyHandler = GenericPopupWidgetHandler; -using MaterialPropertyHandler = GenericPopupWidgetHandler; using ReverbPresetPropertyHandler = GenericPopupWidgetHandler; using MissionObjPropertyHandler = GenericPopupWidgetHandler; using SequencePropertyHandler = GenericPopupWidgetHandler; diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp index bce244e06b..89bb66b08a 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.cpp @@ -25,7 +25,6 @@ // Editor #include "GenericSelectItemDialog.h" #include "QtViewPaneManager.h" -#include "LensFlareEditor/LensFlareEditor.h" UserPropertyEditor::UserPropertyEditor(QWidget *pParent /*= nullptr*/) @@ -147,79 +146,6 @@ bool UserPopupWidgetHandler::ReadValuesIntoGUI(size_t index, UserPropertyEditor* #include -LensFlarePropertyWidget::LensFlarePropertyWidget(QWidget *pParent /*= nullptr*/) - :QWidget(pParent) -{ - m_valueEdit = new QLineEdit; - - QToolButton *mainButton = new QToolButton; - mainButton->setText("D"); - connect(mainButton, &QToolButton::clicked, this, &LensFlarePropertyWidget::OnEditClicked); - connect(m_valueEdit, &QLineEdit::editingFinished, m_valueEdit, [this] () {emit ValueChanged(m_valueEdit->text());}); - - QHBoxLayout *mainLayout = new QHBoxLayout(this); - mainLayout->addWidget(m_valueEdit, 1); - mainLayout->addWidget(mainButton); - mainLayout->setContentsMargins(1, 1, 1, 1); -} - -void LensFlarePropertyWidget::SetValue(const QString &value) -{ - m_valueEdit->setText(value); -} - -QString LensFlarePropertyWidget::GetValue() const -{ - return m_valueEdit->text(); -} - -void LensFlarePropertyWidget::OnEditClicked() -{ - const QtViewPane *lensFlarePane = GetIEditor()->OpenView(CLensFlareEditor::s_pLensFlareEditorClassName); - if (!lensFlarePane) - return; - - CLensFlareEditor *editor = FindViewPane(QtUtil::ToQString(CLensFlareEditor::s_pLensFlareEditorClassName)); - if (editor) - QTimer::singleShot(0, editor, SLOT(OnUpdateTreeCtrl())); -} - -QWidget* LensFlareHandler::CreateGUI(QWidget *pParent) -{ - LensFlarePropertyWidget* newCtrl = aznew LensFlarePropertyWidget(pParent); - connect(newCtrl, &LensFlarePropertyWidget::ValueChanged, newCtrl, [newCtrl]() - { - EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl); - }); - - return newCtrl; -} - -void LensFlareHandler::ConsumeAttribute(LensFlarePropertyWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) -{ - Q_UNUSED(GUI); Q_UNUSED(attrib); Q_UNUSED(attrValue); Q_UNUSED(debugName); -} - -void LensFlareHandler::WriteGUIValuesIntoProperty(size_t index, LensFlarePropertyWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) -{ - Q_UNUSED(index); - Q_UNUSED(node); - CReflectedVarGenericProperty val = instance; - val.m_value = GUI->GetValue().toUtf8().data(); - instance = static_cast(val); -} - -bool LensFlareHandler::ReadValuesIntoGUI(size_t index, LensFlarePropertyWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) -{ - Q_UNUSED(index); - Q_UNUSED(node); - CReflectedVarGenericProperty val = instance; - GUI->SetValue(val.m_value.c_str()); - return false; -} - - - QWidget* FloatCurveHandler::CreateGUI(QWidget *pParent) { CSplineCtrl *cSpline = new CSplineCtrl(pParent); diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h index 00fb8e5f98..7ddbf6a338 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyMiscCtrl.h @@ -70,39 +70,6 @@ public: }; - -class LensFlarePropertyWidget : public QWidget -{ - Q_OBJECT -public: - AZ_CLASS_ALLOCATOR(LensFlarePropertyWidget, AZ::SystemAllocator, 0); - LensFlarePropertyWidget(QWidget *pParent = nullptr); - - void SetValue(const QString &value); - QString GetValue() const; - - void OnEditClicked(); - -signals: - void ValueChanged(const QString &value); - -private: - QLineEdit *m_valueEdit; -}; - -class LensFlareHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarGenericProperty, LensFlarePropertyWidget> -{ -public: - AZ_CLASS_ALLOCATOR(LensFlareHandler, AZ::SystemAllocator, 0); - bool IsDefaultHandler() const override { return false; } - QWidget* CreateGUI(QWidget *pParent) override; - - AZ::u32 GetHandlerName(void) const override { return AZ_CRC("ePropertyFlare", 0x5ce803df); } - void ConsumeAttribute(LensFlarePropertyWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override; - void WriteGUIValuesIntoProperty(size_t index, LensFlarePropertyWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override; - bool ReadValuesIntoGUI(size_t index, LensFlarePropertyWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override; -}; - class FloatCurveHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarSpline, CSplineCtrl> { public: diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp index a66a73eaa4..e698b86341 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp @@ -111,14 +111,12 @@ private: { case ePropertyTexture: case ePropertyModel: - case ePropertyMaterial: newPath.replace("\\\\", "/"); } switch (m_propertyType) { case ePropertyTexture: case ePropertyModel: - case ePropertyMaterial: case ePropertyFile: if (newPath.size() > MAX_PATH) { diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp index 92610021b9..a188ee117b 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.cpp @@ -361,16 +361,6 @@ void ReflectedPropertyControl::CreateItems(XmlNodeRef node, CVarBlockPtr& outBlo textureVar->Set(textureName); } } - else if (!azstricmp(type, "material")) - { - CSmartVariable materialVar; - AddVariable(group, materialVar, child->getTag(), humanReadableName.toUtf8().data(), strDescription.toUtf8().data(), func, pUserData, IVariable::DT_MATERIAL); - const char* materialName; - if (child->getAttr("value", &materialName)) - { - materialVar->Set(materialName); - } - } else if (!azstricmp(type, "color")) { CSmartVariable colorVar; diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp index b759b46ceb..13584d9b82 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedPropertyItem.cpp @@ -269,7 +269,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) m_reflectedVarAdapter = new ReflectedVarUserAdapter; break; case ePropertyShader: - case ePropertyMaterial: case ePropertyEquip: case ePropertyReverbPreset: case ePropertyGameToken: @@ -279,7 +278,6 @@ void ReflectedPropertyItem::SetVariable(IVariable *var) case ePropertyLocalString: case ePropertyLightAnimation: case ePropertyParticleName: - case ePropertyFlare: m_reflectedVarAdapter = new ReflectedVarGenericPropertyAdapter(desc.m_type); break; case ePropertyTexture: @@ -577,7 +575,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo case ePropertyTexture: case ePropertyModel: - case ePropertyMaterial: value.replace('\\', '/'); break; } @@ -587,7 +584,6 @@ void ReflectedPropertyItem::SetValue(const QString& sValue, bool bRecordUndo, bo { case ePropertyTexture: case ePropertyModel: - case ePropertyMaterial: case ePropertyFile: if (value.length() >= MAX_PATH) { diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp index e0f7f29524..12165d2be8 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVar.cpp @@ -286,8 +286,6 @@ AZ::u32 CReflectedVarGenericProperty::handler() { case ePropertyShader: return AZ_CRC("ePropertyShader", 0xc40932f1); - case ePropertyMaterial: - return AZ_CRC("ePropertyMaterial", 0xf324dffa); case ePropertyEquip: return AZ_CRC("ePropertyEquip", 0x66ffd290); case ePropertyReverbPreset: @@ -308,8 +306,6 @@ AZ::u32 CReflectedVarGenericProperty::handler() return AZ_CRC("ePropertyLightAnimation", 0x277097da); case ePropertyParticleName: return AZ_CRC("ePropertyParticleName", 0xf44c7133); - case ePropertyFlare: - return AZ_CRC("ePropertyFlare", 0x5ce803df); default: AZ_Assert(false, "No property handlers defined for the property type"); return AZ_CRC("Default", 0xe35e00df); diff --git a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp index 84a7f8c26f..b2fc07073f 100644 --- a/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp +++ b/Code/Sandbox/Editor/Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp @@ -455,8 +455,6 @@ void ReflectedVarGenericPropertyAdapter::SyncReflectedVarToIVar(IVariable *pVari { QString value; pVariable->Get(value); - if (m_reflectedVar->m_propertyType == ePropertyMaterial) - value.replace('\\', '/'); m_reflectedVar->m_value = value.toUtf8().data(); } diff --git a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp index 3f396894ff..869fa2fe25 100644 --- a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp @@ -23,7 +23,6 @@ #include "Objects/SelectionGroup.h" #include "ViewManager.h" -#include #include // Qt diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index e118104687..abffd1f995 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -102,7 +102,6 @@ AZ_POP_DISABLE_WARNING #include "ModelViewport.h" #include "FileTypeUtils.h" #include "PluginManager.h" -#include "Material/MaterialManager.h" #include "IEditorImpl.h" #include "StartupLogoDialog.h" @@ -157,9 +156,6 @@ AZ_POP_DISABLE_WARNING #include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h" -// LmbrCentral -#include - // AWSNativeSDK #include #include @@ -459,9 +455,6 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_CHANGEMOVESPEED_INCREASE, OnChangemovespeedIncrease) ON_COMMAND(ID_CHANGEMOVESPEED_DECREASE, OnChangemovespeedDecrease) ON_COMMAND(ID_CHANGEMOVESPEED_CHANGESTEP, OnChangemovespeedChangestep) - ON_COMMAND(ID_MATERIAL_ASSIGNCURRENT, OnMaterialAssigncurrent) - ON_COMMAND(ID_MATERIAL_RESETTODEFAULT, OnMaterialResettodefault) - ON_COMMAND(ID_MATERIAL_GETMATERIAL, OnMaterialGetmaterial) ON_COMMAND(ID_FILE_SAVELEVELRESOURCES, OnFileSavelevelresources) ON_COMMAND(ID_CLEAR_REGISTRY, OnClearRegistryData) ON_COMMAND(ID_VALIDATELEVEL, OnValidatelevel) @@ -4180,25 +4173,6 @@ void CCryEditApp::OnSwitchcameraNext() } } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnMaterialAssigncurrent() -{ - CUndo undo("Assign Material To Selection"); - GetIEditor()->GetMaterialManager()->Command_AssignToSelection(); -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnMaterialResettodefault() -{ - GetIEditor()->GetMaterialManager()->Command_ResetSelection(); -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnMaterialGetmaterial() -{ - GetIEditor()->GetMaterialManager()->Command_SelectFromObject(); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnOpenAssetBrowserView() { diff --git a/Code/Sandbox/Editor/CryEdit.h b/Code/Sandbox/Editor/CryEdit.h index 8c0c4bd59b..bce7f0c90d 100644 --- a/Code/Sandbox/Editor/CryEdit.h +++ b/Code/Sandbox/Editor/CryEdit.h @@ -417,9 +417,6 @@ private: void OnChangemovespeedIncrease(); void OnChangemovespeedDecrease(); void OnChangemovespeedChangestep(); - void OnMaterialAssigncurrent(); - void OnMaterialResettodefault(); - void OnMaterialGetmaterial(); void OnFileSavelevelresources(); void OnClearRegistryData(); void OnValidatelevel(); diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 8819c8b382..2138c5c79e 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -27,7 +27,6 @@ // AzFramework #include #include -#include // AzToolsFramework #include @@ -51,8 +50,6 @@ #include "CryEdit.h" #include "ActionManager.h" #include "Include/IObjectManager.h" -#include "Material/MaterialManager.h" -#include "LensFlareEditor/LensFlareManager.h" #include "ErrorReportDialog.h" #include "SurfaceTypeValidator.h" #include "ShaderCache.h" @@ -65,6 +62,9 @@ #include "StatObjBus.h" // LmbrCentral +#include +#include +#include #include // for LmbrCentral::EditorLightComponentRequestBus @@ -358,10 +358,6 @@ void CCryEditDoc::Save(TDocMultiArchive& arrXmlAr) SerializeFogSettings((*arrXmlAr[DMAS_GENERAL])); // Serialize Missions ////////////////////////////////////////////////// SerializeMissions(arrXmlAr, currentMissionName, false); - //! Serialize material manager. - GetIEditor()->GetMaterialManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); - //! Serialize LensFlare manager. - GetIEditor()->GetLensFlareManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); SerializeShaderCache((*arrXmlAr[DMAS_GENERAL_NAMED_DATA])); SerializeNameSelection((*arrXmlAr[DMAS_GENERAL])); @@ -516,22 +512,6 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename) ////////////////////////////////////////////////////////////////////////// (*arrXmlAr[DMAS_GENERAL]).root->getAttr("WaterColor", m_waterColor); - ////////////////////////////////////////////////////////////////////////// - // Load materials. - ////////////////////////////////////////////////////////////////////////// - { - CAutoLogTime logtime("Load MaterialManager"); - GetIEditor()->GetMaterialManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); - } - - ////////////////////////////////////////////////////////////////////////// - // Load LensFlares. - ////////////////////////////////////////////////////////////////////////// - { - CAutoLogTime logtime("Load Flares"); - GetIEditor()->GetLensFlareManager()->Serialize((*arrXmlAr[DMAS_GENERAL]).root, (*arrXmlAr[DMAS_GENERAL]).bLoading); - } - ////////////////////////////////////////////////////////////////////////// // Load View Settings ////////////////////////////////////////////////////////////////////////// @@ -669,6 +649,7 @@ void CCryEditDoc::SerializeViewSettings(CXmlArchive& xmlAr) CViewport* pVP = GetIEditor()->GetViewManager()->GetView(i); + if (pVP) { Matrix34 tm = Matrix34::CreateRotationXYZ(va); @@ -2426,44 +2407,9 @@ void CCryEditDoc::InitEmptyLevel(int /*resolution*/, int /*unitSize*/, bool /*bU GetIEditor()->SetStatusText("Ready"); } -void CCryEditDoc::CreateDefaultLevelAssets(int resolution, int unitSize) +void CCryEditDoc::CreateDefaultLevelAssets([[maybe_unused]] int resolution, [[maybe_unused]] int unitSize) { - if (AZ::Interface::Get()) - { - AzToolsFramework::EditorLevelNotificationBus::Broadcast(&AzToolsFramework::EditorLevelNotificationBus::Events::OnNewLevelCreated); - } - else - { - bool isPrefabSystemEnabled = false; - AzFramework::ApplicationRequests::Bus::BroadcastResult( - isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); - - if (!isPrefabSystemEnabled) - { - AZ::Data::AssetCatalogRequestBus::BroadcastResult( - m_envProbeSliceAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, m_envProbeSliceRelativePath, - azrtti_typeid(), false); - - if (m_envProbeSliceAssetId.IsValid()) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().FindOrCreateAsset( - m_envProbeSliceAssetId, AZ::Data::AssetLoadBehavior::Default); - if (asset) - { - m_terrainSize = resolution * unitSize; - const float halfTerrainSize = m_terrainSize / 2.0f; - - AZ::Transform worldTransform = AZ::Transform::CreateIdentity(); - worldTransform = AZ::Transform::CreateTranslation(AZ::Vector3(halfTerrainSize, halfTerrainSize, m_envProbeHeight / 2)); - - AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect(); - GetIEditor()->SuspendUndo(); - AzToolsFramework::SliceEditorEntityOwnershipServiceRequestBus::Broadcast( - &AzToolsFramework::SliceEditorEntityOwnershipServiceRequests::InstantiateEditorSlice, asset, worldTransform); - } - } - } - } + AzToolsFramework::EditorLevelNotificationBus::Broadcast(&AzToolsFramework::EditorLevelNotificationBus::Events::OnNewLevelCreated); } void CCryEditDoc::OnEnvironmentPropertyChanged(IVariable* pVar) diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.cpp b/Code/Sandbox/Editor/DatabaseFrameWnd.cpp deleted file mode 100644 index 89843c8247..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.cpp +++ /dev/null @@ -1,1491 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "DatabaseFrameWnd.h" - -// Qt -#include -#include -#include -#include - -// AzToolsFramework -#include - -// Editor -#include "BaseLibraryManager.h" -#include "BaseLibraryItem.h" -#include "StringDlg.h" -#include "QtViewPaneManager.h" -#include "Undo/Undo.h" - -#include "ui_DatabaseFrameWnd.h" - - -class CUndoSelectLibraryUndo - : public IUndoObject -{ -public: - CUndoSelectLibraryUndo(const QString& libraryName, const QString& wndClssName) - { - m_LibraryName = libraryName; - m_WndClassName = wndClssName; - } - ~CUndoSelectLibraryUndo(){} - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return "Select database library."; }; - void Undo(bool bUndo) - { - SelectLibrary(bUndo); - } - void Redo() - { - SelectLibrary(true); - } - -private: - - void SelectLibrary(bool bUndo) - { - CDatabaseFrameWnd* pDatabaseEditor = FindViewPane(m_WndClassName); - if (!pDatabaseEditor) - { - return; - } - - QString libraryNameForUndo(m_LibraryName); - if (bUndo) - { - m_LibraryName = pDatabaseEditor->GetSelectedLibraryName(); - } - pDatabaseEditor->SelectLibrary(libraryNameForUndo); - } - - QString m_LibraryName; - QString m_WndClassName; -}; - -static const int LIBRARY_CB_WIDTH(150); - -CDatabaseFrameWnd::CDatabaseFrameWnd(CBaseLibraryManager* pItemManager, QWidget* pParent) - : AzQtComponents::DockMainWindow(pParent) - , m_pItemManager(pItemManager) - , ui(new Ui::DatabaseFrameWnd) - , m_initialized(false) - , m_pLibraryItemTreeModel(nullptr) -{ - ui->setupUi(this); - m_sortRecursionType = SORT_RECURSION_FULL; - m_pLibrary = NULL; - m_bLibsLoaded = false; - m_pCurrentItem = NULL; - - GetIEditor()->RegisterNotifyListener(this); - GetIEditor()->GetUndoManager()->AddListener(this); - - m_pLibraryListComboBox = new QComboBox; - m_pLibraryListComboBox->setFixedSize(LIBRARY_CB_WIDTH, 16); - ui->m_toolBar->insertWidget(ui->m_toolBar->actions()[4], m_pLibraryListComboBox); - connect(m_pLibraryListComboBox, static_cast(&QComboBox::currentIndexChanged), this, &CDatabaseFrameWnd::OnChangedLibrary); - - m_pLibraryListModel = new LibraryListModel(m_pItemManager, this); - m_pLibraryListComboBox->setModel(m_pLibraryListModel); - - connect(ui->actionDBAddLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnAddLibrary); - connect(ui->actionDBDelLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnRemoveLibrary); - connect(ui->actionDBRemove, &QAction::triggered, this, &CDatabaseFrameWnd::OnRemoveItem); - connect(ui->actionDBSave, &QAction::triggered, this, &CDatabaseFrameWnd::OnSave); - connect(ui->actionDBLoadLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnLoadLibrary); - connect(ui->actionDBReload, &QAction::triggered, this, &CDatabaseFrameWnd::OnReloadLib); - connect(ui->actionDBReloadLib, &QAction::triggered, this, &CDatabaseFrameWnd::OnReloadLib); - connect(ui->actionDBCopy, &QAction::triggered, this, &CDatabaseFrameWnd::OnCopy); - connect(ui->actionDBPaste, &QAction::triggered, this, &CDatabaseFrameWnd::OnPaste); - connect(ui->actionDBClone, &QAction::triggered, this, &CDatabaseFrameWnd::OnClone); - connect(ui->actionUndo, &QAction::triggered, this, &CDatabaseFrameWnd::OnUndo); - connect(ui->actionRedo, &QAction::triggered, this, &CDatabaseFrameWnd::OnRedo); -} - -CDatabaseFrameWnd::~CDatabaseFrameWnd() -{ - // Block Signals to prevent changes in the m_pLibraryListComboBox - // from triggering OnChangedLibrary on teardown. - m_pLibraryListComboBox->blockSignals(true); - - m_pLibraryListModel->clear(); - - GetIEditor()->UnregisterNotifyListener(this); - GetIEditor()->GetUndoManager()->RemoveListener(this); -} - -void CDatabaseFrameWnd::InitTreeCtrl() -{ - QTreeView* treeView = GetTreeCtrl(); - - connect(treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &CDatabaseFrameWnd::OnSelChangedItemTree); - treeView->installEventFilter(this); -} - -void CDatabaseFrameWnd::ReloadLibs() -{ - if (!m_pItemManager) - { - return; - } - - SelectItem(0); - - m_pLibraryListModel->Reload(); - - if (m_pLibraryListComboBox) - { - SelectLibrary(m_pLibraryListComboBox->itemData(0, Qt::UserRole).value()); - } - - m_bLibsLoaded = true; -} - -void CDatabaseFrameWnd::ReloadItems() -{ - SelectItem(0); - m_selectedGroup = ""; - m_pCurrentItem = 0; - m_cpoSelectedLibraryItems.clear(); - if (m_pItemManager) - { - m_pItemManager->SetSelectedItem(0); - } - ReleasePreviewControl(); - - if (m_pLibrary && m_pLibraryItemTreeModel) - { - m_pLibraryItemTreeModel->Reload(m_pLibrary); - GetTreeCtrl()->expandAll(); - } -} - -void CDatabaseFrameWnd::SelectLibrary(const QString& library, bool bForceSelect) -{ - QWaitCursor wait; - if (GetSelectedLibraryName() != library || bForceSelect) - { - if (CUndo::IsRecording()) - { - CUndo::Record(new CUndoSelectLibraryUndo(GetSelectedLibraryName(), GetClassName())); - } - - SelectItem(0); - m_pLibrary = FindLibrary(library); - ReloadItems(); - } - if (m_pLibraryListComboBox) - { - m_pLibraryListComboBox->setCurrentIndex(GetComboBoxIndex(m_pLibrary)); - } -} - -void CDatabaseFrameWnd::SelectLibrary(CBaseLibrary* pItem, bool bForceSelect) -{ - QWaitCursor wait; - if (m_pLibrary != pItem || bForceSelect) - { - if (CUndo::IsRecording() && m_pLibrary) - { - CUndo::Record(new CUndoSelectLibraryUndo(GetSelectedLibraryName(), GetClassName())); - } - - SelectItem(0); - m_pLibrary = pItem; - ReloadItems(); - } - if (m_pLibraryListComboBox) - { - m_pLibraryListComboBox->setCurrentIndex(GetComboBoxIndex(pItem)); - } -} - -void CDatabaseFrameWnd::SelectItem(CBaseLibraryItem* item, bool bForceReload) -{ - if (item == m_pCurrentItem && !bForceReload) - { - return; - } - - QModelIndex index = m_pLibraryItemTreeModel->index(item); - if (index.isValid()) - { - GetTreeCtrl()->expand(index.parent()); - GetTreeCtrl()->setCurrentIndex(index); - } - else - { - GetTreeCtrl()->selectionModel()->clearCurrentIndex(); - } -} - -CBaseLibrary* CDatabaseFrameWnd::FindLibrary(const QString& libraryName) -{ - return (CBaseLibrary*)m_pItemManager->FindLibrary(libraryName); -} - -int CDatabaseFrameWnd::GetComboBoxIndex(CBaseLibrary* pLibrary) -{ - return m_pLibraryListComboBox->findData(QVariant::fromValue(pLibrary)); -} - -CBaseLibrary* CDatabaseFrameWnd::NewLibrary(const QString& libraryName) -{ - return (CBaseLibrary*)m_pItemManager->AddLibrary(libraryName, false); -} - -void CDatabaseFrameWnd::DeleteLibrary(CBaseLibrary* pLibrary) -{ - m_pItemManager->DeleteLibrary(pLibrary->GetName()); -} - -void CDatabaseFrameWnd::DeleteItem(CBaseLibraryItem* pItem) -{ - m_pItemManager->DeleteItem(pItem); -} - -void CDatabaseFrameWnd::OnAddLibrary() -{ - StringDlg dlg(tr("New Library Name"), this); - CUndo undo(tr("Add Database Library").toUtf8()); - if (dlg.exec() == QDialog::Accepted) - { - if (!dlg.GetString().isEmpty()) - { - SelectItem(0); - // Make new library. - QString library = dlg.GetString(); - NewLibrary(library); - ReloadLibs(); - SelectLibrary(library); - GetIEditor()->SetModifiedFlag(); - } - } -} - -void CDatabaseFrameWnd::OnRemoveLibrary() -{ - QString library = GetSelectedLibraryName(); - if (library.isEmpty()) - { - return; - } - if (m_pLibrary->IsModified()) - { - QString ask = tr("Save changes to the library %1?").arg(library); - if (QMessageBox::question(this, tr("Editor"), ask) == QMessageBox::Yes) - { - OnSave(); - } - } - QString ask = tr("When removing library All items contained in this library will be deleted.\r\nAre you sure you want to remove libarary %1?\r\n(Note: Library file will not be deleted from the disk)").arg(library); - if (QMessageBox::question(this, tr("Editor"), ask) == QMessageBox::Yes) - { - SelectItem(0); - DeleteLibrary(m_pLibrary); - m_pLibrary = 0; - ReleasePreviewControl(); - ReloadLibs(); - GetIEditor()->SetModifiedFlag(); - } -} - -void CDatabaseFrameWnd::OnAddItem() -{ -} - -void CDatabaseFrameWnd::OnRemoveItem() -{ - // When we have no set of selected items, it may be the case that we are - // dealing with old fashioned selection. If such is the case, let's deal - // with it using the old code system, which should be deprecated. - if (m_cpoSelectedLibraryItems.empty()) - { - if (m_pCurrentItem) - { - // Remove prototype from prototype manager and library. - QString str = tr("Delete %1?").arg(m_pCurrentItem->GetName()); - if (QMessageBox::question(this, tr("Delete Confirmation"), str) == QMessageBox::Yes) - { - CUndo undo(tr("Remove library item").toUtf8()); - TSmartPtr pCurrent = m_pCurrentItem; - DeleteItem(pCurrent); - m_pLibraryItemTreeModel->Remove(m_pCurrentItem); - GetIEditor()->SetModifiedFlag(); - SelectItem(0); - } - } - } - else // This is to be used when deleting multiple items... - { - QString strMessageString = tr("Delete the following items:\n"); - int nItemCount(0); - std::set::iterator itCurrentIterator; - std::set::iterator itEnd; - - itEnd = m_cpoSelectedLibraryItems.end(); - itCurrentIterator = m_cpoSelectedLibraryItems.begin(); - // For now, we have a maximum limit of 7 items per messagebox... - for (nItemCount = 0; nItemCount < 7; ++nItemCount, itCurrentIterator++) - { - if (itCurrentIterator == itEnd) - { - // As there were less than 7 items selected, we got to put them all - // into the formated string for the messagebox. - break; - } - strMessageString += QStringLiteral("%1\n").arg((*itCurrentIterator)->GetName()); - } - if (itCurrentIterator != itEnd) - { - strMessageString += QStringLiteral("..."); - } - - if (QMessageBox::question(this, tr("Delete Confirmation"), strMessageString) == QMessageBox::Yes) - { - for (itCurrentIterator = m_cpoSelectedLibraryItems.begin(); itCurrentIterator != itEnd; itCurrentIterator++) - { - CBaseLibraryItem* pCurrent = *itCurrentIterator; - DeleteItem(pCurrent); - m_pLibraryItemTreeModel->Remove(pCurrent); - } - m_cpoSelectedLibraryItems.clear(); - GetIEditor()->SetModifiedFlag(); - SelectItem(0); - } - } -} - -void CDatabaseFrameWnd::OnRenameItem() -{ - if (m_pCurrentItem) - { - StringGroupDlg dlg; - dlg.SetGroup(m_pCurrentItem->GetGroupName()); - dlg.SetString(m_pCurrentItem->GetShortName()); - if (dlg.exec() == QDialog::Accepted) - { - static bool warn = true; - if (warn) - { - warn = false; - QMessageBox::warning(this, tr("Warning"), tr("Levels referencing this archetype will need to be exported.")); - } - - CUndo undo(tr("Rename library item").toUtf8()); - TSmartPtr curItem = m_pCurrentItem; - SetItemName(curItem, dlg.GetGroup(), dlg.GetString()); - ReloadItems(); - SelectItem(curItem, true); - curItem->SetModified(); - //m_pCurrentItem->Update(); - } - GetIEditor()->SetModifiedFlag(); - } -} - -void CDatabaseFrameWnd::OnChangedLibrary() -{ - CBaseLibrary* pBaseLibrary = NULL; - if (m_pLibraryListComboBox) - { - pBaseLibrary = m_pLibraryListComboBox->currentData(Qt::UserRole).value(); - } - - if (pBaseLibrary && pBaseLibrary != m_pLibrary) - { - CUndo undo("Change database library"); - SelectLibrary(pBaseLibrary); - } -} - -void CDatabaseFrameWnd::OnExportLibrary() -{ - if (!m_pLibrary) - { - return; - } - - QString filename; - if (CFileUtil::SelectSaveFile("Library XML Files (*.xml)", "xml", (Path::GetEditingGameDataFolder() + "/Materials").c_str(), filename)) - { - XmlNodeRef libNode = XmlHelpers::CreateXmlNode("MaterialLibrary"); - m_pLibrary->Serialize(libNode, false); - XmlHelpers::SaveXmlNode(GetIEditor()->GetFileUtil(), libNode, filename.toStdString().c_str()); - } -} - -void CDatabaseFrameWnd::OnSave() -{ - if (m_bLibsLoaded) - { - m_pLibrary->SetModified(true); - m_pItemManager->SaveAllLibs(); - m_pLibrary->SetModified(false); - } -} - -void CDatabaseFrameWnd::OnReloadLib() -{ - if (!m_pLibrary) - { - return; - } - - QString libname = m_pLibrary->GetName(); - QString file = m_pLibrary->GetFilename(); - - //If the file we want to reload does not exist (and isn't the level library), we can't reload it - //Just display a warning to the user and stop the reload process - if (!CFileUtil::Exists(file, false) && !m_pLibrary->IsLevelLibrary()) - { - QString str = tr("Layer %1 does not exist on disk yet. Have you ever saved it?\nReloading layer is not possible!"). - arg(libname); - if (QMessageBox::information(this, tr("Editor"), str)) - { - return; - } - } - - if (m_pLibrary->IsModified()) - { - QString str = tr("Layer %1 was modified.\nReloading layer will discard all modifications to this library!"). - arg(libname); - if (QMessageBox::question(this, tr("Editor"), str) != QMessageBox::Yes) - { - return; - } - } - - //Don't try to delete/load level library from disk. - //It's managed by the level and there doesn't seem to be a way to "reload" it - if (!m_pLibrary->IsLevelLibrary()) - { - m_pItemManager->DeleteLibrary(libname); - m_pItemManager->LoadLibrary(file, true); - } - - ReloadLibs(); - SelectLibrary(libname); -} - -void CDatabaseFrameWnd::OnLoadLibrary() -{ - assert(m_pItemManager); - CUndo undo(tr("Load Database Library").toUtf8()); - LoadLibrary(); -} - -void CDatabaseFrameWnd::LoadLibrary() -{ - AssetSelectionModel selection = GetAssetSelectionModel(); - - AzToolsFramework::EditorRequests::Bus::Broadcast( - &AzToolsFramework::EditorRequests::BrowseForAssets, - selection); - if (selection.IsValid()) - { - GetIEditor()->SuspendUndo(); - IDataBaseLibrary* matLib = m_pItemManager->LoadLibrary(Path::FullPathToGamePath( - selection.GetResult()->GetFullPath().c_str()).c_str()); - GetIEditor()->ResumeUndo(); - ReloadLibs(); - if (matLib) - { - SelectLibrary((CBaseLibrary*)matLib); - } - } -} - -bool CDatabaseFrameWnd::SetItemName(CBaseLibraryItem* item, const QString& groupName, const QString& itemName) -{ - assert(item); - // Make prototype name. - QString name; - if (!groupName.isEmpty()) - { - name = groupName + "."; - } - name += itemName; - QString fullName = name; - if (item->GetLibrary()) - { - fullName = item->GetLibrary()->GetName() + "." + name; - } - IDataBaseItem* pOtherItem = m_pItemManager->FindItemByName(fullName); - if (pOtherItem && pOtherItem != item) - { - // Ensure uniqness of name. - Warning("Duplicate Item Name %s", name.toUtf8().data()); - return false; - } - else - { - item->SetName(name); - } - return true; -} - -void CDatabaseFrameWnd::OnSelChangedItemTree(const QModelIndex& index) -{ - CBaseLibraryItem* item = index.data(Qt::UserRole).value(); - - if (item) - { - if (item->GetLibrary() != m_pLibrary && item->GetLibrary()) - { - SelectLibrary((CBaseLibrary*)item->GetLibrary()); - } - } - - m_pCurrentItem = item; - - if (item) - { - m_selectedGroup = item->GetGroupName(); - } - else - { - m_selectedGroup = ""; - } - - m_pItemManager->SetSelectedItem(item); -} - -bool CDatabaseFrameWnd::eventFilter(QObject* watched, QEvent* event) -{ - if (event->type() != QEvent::KeyPress || watched != GetTreeCtrl()) - { - return QMainWindow::eventFilter(watched, event); - } - - QKeyEvent* keyEvent = static_cast(event); - - bool bCtrl = keyEvent->modifiers() == Qt::ControlModifier; - - if (keyEvent->matches(QKeySequence::Copy)) - { - OnCopy(); // Ctrl+C - } - else if (keyEvent->matches(QKeySequence::Paste)) - { - OnPaste(); // Ctrl+V - } - else if (keyEvent->matches(QKeySequence::Cut)) - { - OnCut(); // Ctrl+X - } - else if (bCtrl && keyEvent->key() == Qt::Key_D) - { - OnClone(); // Ctrl+D - } - else if (keyEvent->matches(QKeySequence::Delete)) - { - OnRemoveItem(); - } - else if (keyEvent->key() == Qt::Key_F2) - { - OnRenameItem(); - } - else if (keyEvent->key() == Qt::Key_Insert) - { - OnAddItem(); - } - else - { - return QMainWindow::eventFilter(watched, event); - } - - return true; -} - -void CDatabaseFrameWnd::OnUndo() -{ - GetIEditor()->Undo(); -} - -void CDatabaseFrameWnd::OnRedo() -{ - GetIEditor()->Redo(); -} - -void CDatabaseFrameWnd::OnCut() -{ - if (m_pCurrentItem) - { - OnCopy(); - OnRemoveItem(); - } -} - -void CDatabaseFrameWnd::OnClone() -{ - OnCopy(); - OnPaste(); -} - -void CDatabaseFrameWnd::DoesItemExist(const QString& itemName, bool& bOutExist) const -{ - for (int i = 0, iItemCount(m_pLibrary->GetItemCount()); i < iItemCount; ++i) - { - IDataBaseItem* pItem = m_pLibrary->GetItem(i); - if (pItem == NULL) - { - continue; - } - if (pItem->GetName() == itemName) - { - bOutExist = true; - return; - } - } - bOutExist = false; -} - -QString CDatabaseFrameWnd::MakeValidName(const QString& candidateName, AZStd::function FuncForCheck) const -{ - bool bCheck = false; - FuncForCheck(candidateName, bCheck); - if (!bCheck) - { - return candidateName; - } - - int nCounter = 0; - const int nEnoughBigNumber = 1000000; - do - { - QString counterBuffer; - counterBuffer = QString::number(nCounter); - QString newName = candidateName + counterBuffer; - FuncForCheck(newName, bCheck); - if (!bCheck) - { - return newName; - } - } while (nCounter++ < nEnoughBigNumber); - - assert(0 && "CDatabaseFrameWnd::MakeValidName()"); - return candidateName; -} - -void CDatabaseFrameWnd::DoesGroupExist(const QString& groupName, bool& bOutExist) const -{ - bOutExist = m_pLibraryItemTreeModel->DoesGroupExist(groupName); -} - -QString CDatabaseFrameWnd::GetSelectedLibraryName() const -{ - return m_pLibrary ? m_pLibrary->GetName() : ""; -} - -void CDatabaseFrameWnd::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnBeginNewScene: - m_bLibsLoaded = false; - // Clear all prototypes and libraries. - SelectItem(0); - if (m_pLibraryListComboBox) - { - m_pLibraryListComboBox->clear(); - } - m_pLibrary = nullptr; - break; - - case eNotify_OnEndSceneOpen: - m_bLibsLoaded = false; - ReloadLibs(); - break; - - case eNotify_OnCloseScene: - { - m_bLibsLoaded = false; - CUndo undo(tr("Close Database Library").toUtf8()); - GetTreeCtrl()->selectionModel()->clear(); - GetTreeCtrl()->clearSelection(); - m_pLibraryItemTreeModel->Clear(); - m_pCurrentItem = nullptr; - m_cpoSelectedLibraryItems.clear(); - } - break; - - case eNotify_OnDataBaseUpdate: - if (m_pLibrary && m_pLibrary->IsModified()) - { - ReloadItems(); - } - break; - } -} - -void CDatabaseFrameWnd::SignalNumUndoRedo(const unsigned int& numUndo, const unsigned int& numRedo) -{ - ui->actionUndo->setEnabled(numUndo > 0); - ui->actionRedo->setEnabled(numRedo > 0); -} - -void CDatabaseFrameWnd::showEvent(QShowEvent* event) -{ - if (!m_initialized) - { - OnInitDialog(); - m_initialized = true; - } - - QMainWindow::showEvent(event); -} - -LibraryListModel::LibraryListModel(CBaseLibraryManager* itemManager, QObject* pParent) - : QAbstractListModel(pParent) - , m_pItemManager(itemManager) -{ -} - -int LibraryListModel::rowCount(const QModelIndex& parent) const -{ - return parent.isValid() ? 0 : m_pItemManager->GetLibraryCount(); -} - -QVariant LibraryListModel::data(const QModelIndex& index, int role) const -{ - const int row = index.row(); - - if (row < 0 || row >= m_pItemManager->GetLibraryCount()) - { - return {}; - } - - auto library = static_cast(m_pItemManager->GetLibrary(row)); - - switch (role) - { - case Qt::DisplayRole: - { - QString name = library->GetName(); - if (library->IsModified()) - { - name += "*"; - } - return name; - } - - case Qt::UserRole: - return QVariant::fromValue(library); - } - - return {}; -} - -void LibraryListModel::Reload() -{ - beginResetModel(); - - const int count = m_pItemManager->GetLibraryCount(); - - for (int i = 0; i < count; i++) - { - CBaseLibrary* pLibrary = static_cast(m_pItemManager->GetLibrary(i)); - connect(pLibrary, &CBaseLibrary::Modified, this, &LibraryListModel::LibraryModified); - } - - endResetModel(); -} - -void LibraryListModel::clear() -{ - beginResetModel(); - endResetModel(); -} - -void LibraryListModel::LibraryModified(bool) -{ - CBaseLibrary* library = qobject_cast(sender()); - - const int count = m_pItemManager->GetLibraryCount(); - - for (int i = 0; i < count; i++) - { - CBaseLibrary* pLibrary = static_cast(m_pItemManager->GetLibrary(i)); - if (pLibrary == library) - { - emit dataChanged(index(i, 0), index(i, 0)); - } - } -} - -LibraryItemTreeModel::LibraryItemTreeModel(CDatabaseFrameWnd* pParent) - : QAbstractItemModel(pParent) - , m_dialog(pParent) -{ -} - -Qt::ItemFlags LibraryItemTreeModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return Qt::ItemFlags(); - } - - Qt::ItemFlags flags = QAbstractItemModel::flags(index); - - flags |= Qt::ItemIsEditable; - - if (!index.internalPointer()) - { - flags |= Qt::ItemIsDropEnabled; - } - else - { - flags |= Qt::ItemIsDragEnabled; - } - - return flags; -} - -int LibraryItemTreeModel::columnCount(const QModelIndex&) const -{ - return 1; -} - -int LibraryItemTreeModel::rowCount(const QModelIndex& parent) const -{ - if (!parent.isValid()) - { - return m_groups.size(); - } - else - { - if (!parent.internalPointer() && parent.row() >= 0 && parent.row() < m_groups.size()) - { - auto entry = std::begin(m_groups); - std::advance(entry, parent.row()); - return entry->second->second.size(); - } - } - - return 0; -} - -QModelIndex LibraryItemTreeModel::parent(const QModelIndex& index) const -{ - if (index.isValid() && index.internalPointer()) - { - auto group = static_cast(index.internalPointer()); - auto entry = m_groups.find(group->first); - return createIndex(std::distance(std::begin(m_groups), entry), 0, nullptr); - } - - return {}; -} - -QModelIndex LibraryItemTreeModel::index(int row, int column, const QModelIndex& parent) const -{ - if (column > 0) - { - return {}; - } - - if (!parent.isValid()) - { - if (row >= 0 && row < m_groups.size()) - { - return createIndex(row, 0, nullptr); - } - } - else - { - if (!parent.internalPointer() && parent.row() >= 0 && parent.row() < m_groups.size()) - { - auto entry = std::begin(m_groups); - std::advance(entry, parent.row()); - - if (row >= 0 && row < entry->second->second.size()) - { - return createIndex(row, 0, const_cast(entry->second.get())); - } - } - } - - return {}; -} - -QVariant LibraryItemTreeModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - { - return {}; - } - - if (!index.internalPointer()) - { - switch (role) - { - case Qt::DisplayRole: - { - auto entry = std::begin(m_groups); - std::advance(entry, index.row()); - return entry->first; - } - case Qt::UserRole: - return QVariant::fromValue(nullptr); - } - } - else - { - auto group = static_cast(index.internalPointer()); - auto item = group->second[index.row()]; - - switch (role) - { - case Qt::DisplayRole: - return item->GetShortName(); - case Qt::UserRole: - return QVariant::fromValue(item); - } - } - - return {}; -} - -void LibraryItemTreeModel::RenameItem(CBaseLibraryItem* item, const QString& fullName) -{ - QString prevFullName = item->GetFullName(); - item->SetName(fullName); - item->SetModified(); - emit itemRenamed(item, prevFullName); -} - -bool LibraryItemTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (!index.isValid() || role != Qt::EditRole) - { - return false; - } - - QString text = value.toString(); - - if (text.isEmpty()) - { - return false; - } - - if (text.contains(QLatin1Char('.'))) - { - QMessageBox::warning(AzToolsFramework::GetActiveWindow(), tr("Warning"), tr("The name must not contain \".\"")); - return false; - } - - if (!index.internalPointer()) - { - // rename group - - auto sourceEntry = std::begin(m_groups); - std::advance(sourceEntry, index.row()); - - if (text == sourceEntry->first) - { - return false; - } - - if (m_groups.find(text) != std::end(m_groups)) - { - QMessageBox::warning(AzToolsFramework::GetActiveWindow(), tr("Warning"), tr("The identical name exists.")); - return false; - } - - int sourceRow = index.row(); - int targetRow = std::distance(std::begin(m_groups), m_groups.lower_bound(text)); - - if (targetRow < sourceRow || targetRow > sourceRow + 1) - { - beginMoveRows({}, sourceRow, sourceRow, {}, targetRow); - } - - auto targetEntry = m_groups.insert({ text, sourceEntry->second }).first; - targetEntry->second->first = text; - m_groups.erase(sourceEntry); - - if (targetRow < sourceRow || targetRow > sourceRow + 1) - { - endMoveRows(); - } - else - { - emit dataChanged(index, index); - } - - CUndo undo(tr("Rename FlareGroupItem").toUtf8()); - - auto group = targetEntry->second.get(); - - for (int row = 0; row < group->second.size(); row++) - { - auto item = group->second[row]; - QString name = QString("%1.%2").arg(text).arg(item->GetShortName()); - RenameItem(item, name); - } - } - else - { - // rename single item - - auto group = static_cast(index.internalPointer()); - auto& items = group->second; - - auto item = items[index.row()]; - - if (text == item->GetShortName()) - { - return false; - } - - QString name = QString("%1.%2").arg(item->GetGroupName(), text); - - if (std::find_if(std::begin(items), std::end(items), - [&](const CBaseLibraryItem* item) - { - return item->GetName() == name; - }) != std::end(items)) - { - QMessageBox::warning(AzToolsFramework::GetActiveWindow(), tr("Warning"), tr("The identical name exists.")); - return false; - } - - CUndo undo(tr("Rename FlareGroupItem").toUtf8()); - RenameItem(item, name); - - emit dataChanged(index, index); - } - - return true; -} - -QModelIndex LibraryItemTreeModel::index(CBaseLibraryItem* item) const -{ - if (!item) - { - return {}; - } - - auto entry = m_groups.find(item->GetGroupName()); - if (entry == std::end(m_groups)) - { - return {}; - } - - auto& items = entry->second->second; - - auto it = std::find(std::begin(items), std::end(items), item); - if (it == std::end(items)) - { - return {}; - } - - return createIndex(std::distance(std::begin(items), it), 0, const_cast(entry->second.get())); -} - -bool LibraryItemTreeModel::removeRows(int row, int count, const QModelIndex& parent) -{ - if (!parent.isValid()) - { - beginRemoveRows({}, row, row + count - 1); - - auto first = std::begin(m_groups); - std::advance(first, row); - - auto last = std::begin(m_groups); - std::advance(last, row + count); - - m_groups.erase(first, last); - - endRemoveRows(); - } - else - { - beginRemoveRows(parent, row, row + count - 1); - - auto entry = std::begin(m_groups); - std::advance(entry, parent.row()); - - auto& items = entry->second->second; - items.erase(std::begin(items) + row, std::begin(items) + row + count); - - endRemoveRows(); - - if (items.empty()) - { - beginRemoveRows({}, parent.row(), parent.row()); - m_groups.erase(entry); - endRemoveRows(); - } - } - - return true; -} - -static bool LibraryItemLess(const CBaseLibraryItem* left, const CBaseLibraryItem* right) -{ - QString leftName = left->GetName(); - QString rightName = right->GetName(); - return leftName.compare(rightName) < 0; -} - -void LibraryItemTreeModel::Clear() -{ - beginResetModel(); - - m_groups.clear(); - - endResetModel(); -} - -void LibraryItemTreeModel::Reload(CBaseLibrary* pLibrary) -{ - beginResetModel(); - - m_groups.clear(); - - for (int i = 0; i < pLibrary->GetItemCount(); i++) - { - auto item = static_cast(pLibrary->GetItem(i)); - - QString itemName = item->GetName(); - QString groupName = item->GetGroupName(); - - auto entry = m_groups.find(groupName); - - if (entry == std::end(m_groups)) - { - entry = m_groups.insert({ groupName, std::make_shared(groupName, std::vector()) }).first; - } - - auto& items = entry->second->second; - items.insert(std::upper_bound(std::begin(items), std::end(items), item, LibraryItemLess), item); - } - - endResetModel(); -} - -QString LibraryItemTreeModel::GetFullName(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return QString(); - } - - if (!index.internalPointer()) - { - auto entry = std::begin(m_groups); - std::advance(entry, index.row()); - return entry->first; - } - else - { - auto group = static_cast(index.internalPointer()); - auto item = group->second[index.row()]; - return item->GetName(); - } -} - -void LibraryItemTreeModel::Add(CBaseLibraryItem* item) -{ - QString groupName = item->GetGroupName(); - - auto entry = m_groups.find(groupName); - if (entry == std::end(m_groups)) - { - int row = std::distance(std::begin(m_groups), m_groups.lower_bound(groupName)); - - emit beginInsertRows({}, row, row); - entry = m_groups.insert({ groupName, std::make_shared(groupName, std::vector()) }).first; - emit endInsertRows(); - } - - QModelIndex parentIndex = createIndex(std::distance(std::begin(m_groups), entry), 0, nullptr); - auto& items = entry->second->second; - - if (std::find(std::begin(items), std::end(items), item) == std::end(items)) - { - auto it = std::upper_bound(std::begin(items), std::end(items), item, LibraryItemLess); - int row = std::distance(std::begin(items), it); - - emit beginInsertRows(parentIndex, row, row); - items.insert(it, item); - emit endInsertRows(); - } -} - -std::vector LibraryItemTreeModel::ChildItems(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return {}; - } - - if (!index.internalPointer()) - { - auto entry = std::begin(m_groups); - std::advance(entry, index.row()); - return entry->second->second; - } - else - { - auto group = static_cast(index.internalPointer()); - return { - group->second[index.row()] - }; - } -} - -bool LibraryItemTreeModel::Remove(CBaseLibraryItem* pItem) -{ - QModelIndex itemIndex = index(pItem); - if (!itemIndex.isValid()) - { - return false; - } - return removeRow(itemIndex.row(), itemIndex.parent()); -} - -void LibraryItemTreeModel::Rename(CBaseLibraryItem* item, const QString& groupName, const QString& shortName) -{ - if (groupName != item->GetGroupName()) - { - auto entry = m_groups.find(groupName); - - if (entry == std::end(m_groups)) - { - int row = std::distance(std::begin(m_groups), m_groups.lower_bound(groupName)); - - emit beginInsertRows({}, row, row); - entry = m_groups.insert({ groupName, std::make_shared(groupName, std::vector()) }).first; - emit endInsertRows(); - } - - MoveItem(item, createIndex(std::distance(std::begin(m_groups), entry), 0, nullptr)); - } - - QString name = QString("%1.%2").arg(groupName).arg(shortName); - RenameItem(item, name); - - QModelIndex itemIndex = index(item); - emit dataChanged(itemIndex, itemIndex); -} - -QModelIndex LibraryItemTreeModel::FindLibraryItemByFullName(const QString& fullName) const -{ - for (auto& entry : m_groups) - { - auto& group = *entry.second; - auto& items = group.second; - - auto it = std::find_if(std::begin(items), std::end(items), - [&](CBaseLibraryItem* item) - { - return item->GetName() == fullName; - }); - - if (it != std::end(items)) - { - return createIndex(std::distance(std::begin(items), it), 0, &group); - } - } - - return {}; -} - -bool LibraryItemTreeModel::DoesGroupExist([[maybe_unused]] const QString& groupName) const -{ -#if 0 - auto it = std::find_if( - std::begin(m_root->m_children), - std::end(m_root->m_children), - [&](const TreeNode* node) - { - return node->m_text.compare(groupName, Qt::CaseInsensitive) == 0; - }); - - return it != std::end(m_root->m_children); -#else - return false; -#endif -} - -QStringList LibraryItemTreeModel::mimeTypes() const -{ - QStringList mimeTypes; - mimeTypes << QStringLiteral("application/x-o3de-libraryitems"); - return mimeTypes; -} - -QString LibraryItemTreeModel::MakeValidName(const Group& group, const QString& baseName) const -{ - auto& items = group.second; - - QString name = baseName; - - int counter = 0; - - while (std::find_if(std::begin(items), std::end(items), - [&](CBaseLibraryItem* item) - { - return item->GetShortName() == name; - }) != std::end(items)) - { - name = QString("%1%2").arg(baseName).arg(counter); - ++counter; - } - - return name; -} - -bool LibraryItemTreeModel::MoveItem(CBaseLibraryItem* item, const QModelIndex& targetParent) -{ - if (!targetParent.isValid() || targetParent.internalPointer()) - { - return false; - } - - auto sourceEntry = m_groups.find(item->GetGroupName()); - - auto targetEntry = std::begin(m_groups); - std::advance(targetEntry, targetParent.row()); - - if (sourceEntry == targetEntry) - { - return false; - } - - auto& sourceItems = sourceEntry->second->second; - auto sourceIt = std::find(std::begin(sourceItems), std::end(sourceItems), item); - int sourceRow = std::distance(std::begin(sourceItems), sourceIt); - - auto& targetItems = targetEntry->second->second; - auto targetIt = std::upper_bound( - std::begin(targetItems), - std::end(targetItems), - item, - [](CBaseLibraryItem* left, CBaseLibraryItem* right) - { - QString leftShortName = left->GetShortName(); - QString rightShortName = right->GetShortName(); - return leftShortName.compare(rightShortName) < 0; - }); - int targetRow = std::distance(std::begin(targetItems), targetIt); - - QModelIndex sourceParent = createIndex(std::distance(std::begin(m_groups), sourceEntry), 0, nullptr); - - beginMoveRows(sourceParent, sourceRow, sourceRow, targetParent, targetRow); - targetItems.insert(targetIt, item); - sourceItems.erase(sourceIt); - endMoveRows(); - - if (sourceItems.empty()) - { - removeRow(sourceParent.row(), {}); - } - - return true; -} - -bool LibraryItemTreeModel::dropMimeData(const QMimeData* data, [[maybe_unused]] Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, const QModelIndex& index) -{ - if (data->hasFormat("application/x-o3de-libraryitems")) - { - QByteArray array = data->data("application/x-o3de-libraryitems"); - - QModelIndex targetParent = index; - - if (!targetParent.isValid()) - { - return false; - } - - if (targetParent.internalPointer()) - { - targetParent = parent(targetParent); - } - - int count = array.size() / sizeof(CBaseLibraryItem*); - auto items = reinterpret_cast(array.data()); - - auto entry = std::begin(m_groups); - std::advance(entry, targetParent.row()); - - CUndo undo(tr("Copy/Cut & Paste for Lens Flare").toUtf8()); - - for (int i = 0; i < count; i++) - { - auto item = items[i]; - - QString shortName = MakeValidName(*entry->second, item->GetShortName()); - - if (MoveItem(item, targetParent)) - { - RenameItem(item, QString("%1.%2").arg(entry->first).arg(shortName)); - } - } - - return true; - } - - return false; -} - -QMimeData* LibraryItemTreeModel::mimeData(const QModelIndexList& indexes) const -{ - QByteArray array; - - for (auto& index : indexes) - { - auto item = static_cast(index.data(Qt::UserRole).value()); - - if (item) - { - array.append(reinterpret_cast(&item), sizeof(CBaseLibraryItem*)); - } - } - - if (array.isEmpty()) - { - return nullptr; - } - - QMimeData* data = new QMimeData; - data->setData(QStringLiteral("application/x-o3de-libraryitems"), array); - return data; -} - -Qt::DropActions LibraryItemTreeModel::supportedDragActions() const -{ - return Qt::MoveAction; -} - -Qt::DropActions LibraryItemTreeModel::supportedDropActions() const -{ - return Qt::MoveAction; -} - -#include diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.h b/Code/Sandbox/Editor/DatabaseFrameWnd.h deleted file mode 100644 index 71ef50191c..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.h +++ /dev/null @@ -1,250 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once -//////////////////////////////////////////////////////////////////////////// -// Crytek Engine Source File. -// Copyright (C), Crytek Studios, 2011. -// ------------------------------------------------------------------------- -// File name: DatabaseFrameWnd.h -// Created: 10/Dec/2012 by Jaesik. -//////////////////////////////////////////////////////////////////////////// -#ifndef CRYINCLUDE_EDITOR_DATABASEFRAMEWND_H -#define CRYINCLUDE_EDITOR_DATABASEFRAMEWND_H - -#if !defined(Q_MOC_RUN) -#include -#include -#include "Undo/IUndoManagerListener.h" -#include "BaseLibrary.h" - -#include -#include -#include -#include -#endif - -class QComboBox; -class QTreeView; -class QMimeData; - -class CBaseLibraryItem; -class CBaseLibraryManager; - -class LibraryListModel; -class LibraryItemTreeModel; - -namespace Ui { - class DatabaseFrameWnd; -} - -class CDatabaseFrameWnd - : public AzQtComponents::DockMainWindow - , public IEditorNotifyListener - , public IUndoManagerListener -{ - Q_OBJECT -public: - CDatabaseFrameWnd(CBaseLibraryManager* pItemManager, QWidget* pParent = nullptr); - virtual ~CDatabaseFrameWnd(); - - enum SortRecursionType - { - SORT_RECURSION_NONE = 1, - SORT_RECURSION_ITEM = 2, - SORT_RECURSION_FULL = 9999 - }; - - virtual void ReloadLibs(); - virtual void ReloadItems(); - virtual void SelectLibrary(const QString& library, bool bForceSelect = false); - virtual void SelectLibrary(CBaseLibrary* pItem, bool bForceSelect = false); - virtual void SelectItem(CBaseLibraryItem* item, bool bForceReload = false); - - virtual CBaseLibrary* FindLibrary(const QString& libraryName); - virtual CBaseLibrary* NewLibrary(const QString& libraryName); - virtual void DeleteLibrary(CBaseLibrary* pLibrary); - virtual void DeleteItem(CBaseLibraryItem* pItem); - - virtual void ReleasePreviewControl(){} - - virtual bool SetItemName(CBaseLibraryItem* item, const QString& groupName, const QString& itemName); - - void DoesItemExist(const QString& itemName, bool& bOutExist) const; - void DoesGroupExist(const QString& groupName, bool& bOutExist) const; - - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) override; - - void SignalNumUndoRedo(const unsigned int& numUndo, const unsigned int& numRedo) override; - - QString GetSelectedLibraryName() const; - - virtual const char* GetClassName() = 0; - -protected: - int GetComboBoxIndex(CBaseLibrary* pLibrary); - - virtual void OnInitDialog() = 0; - - void showEvent(QShowEvent* event) override; - - void OnUndo(); - void OnRedo(); - - virtual void OnAddLibrary(); - virtual void OnRemoveLibrary(); - virtual void OnAddItem(); - virtual void OnRemoveItem(); - virtual void OnRenameItem(); - virtual void OnChangedLibrary(); - virtual void OnExportLibrary(); - virtual void OnSave(); - virtual void OnReloadLib(); - virtual void OnLoadLibrary(); - - void OnSelChangedItemTree(const QModelIndex& index); - bool eventFilter(QObject* watched, QEvent* event); - - virtual void OnCopy() = 0; - virtual void OnPaste() = 0; - virtual void OnCut(); - virtual void OnClone(); - - void InitTreeCtrl(); - - virtual AssetSelectionModel GetAssetSelectionModel() const = 0; - - void LoadLibrary(); - - QString MakeValidName(const QString& candidateName, AZStd::function cb) const; - - virtual QTreeView* GetTreeCtrl() = 0; - virtual const QTreeView* GetTreeCtrl() const = 0; - -private: - LibraryListModel* m_pLibraryListModel; - QComboBox* m_pLibraryListComboBox; - - bool m_bLibsLoaded; - -protected: - LibraryItemTreeModel* m_pLibraryItemTreeModel; - - //! Selected library. - _smart_ptr m_pLibrary; - - //! Last selected Item. (kept here for compatibility reasons) - // See comments on m_cpoSelectedLibraryItems for more details. - _smart_ptr m_pCurrentItem; - - // A set containing all the currently selected items - // (it's disabled for MOST, but not ALL cases). - // This should be the new standard way of storing selections as - // opposed to the former mean, it allows us to store multiple selections. - // The migration to this new style should be done according to the needs - // for multiple selection. - std::set m_cpoSelectedLibraryItems; - - //! Pointer to item manager. - CBaseLibraryManager* m_pItemManager; - SortRecursionType m_sortRecursionType; - QString m_selectedGroup; - - QScopedPointer ui; - - bool m_initialized; -}; - -class LibraryListModel - : public QAbstractListModel -{ - Q_OBJECT - -public: - LibraryListModel(CBaseLibraryManager* itemManager, QObject* pParent = nullptr); - - int rowCount(const QModelIndex& parent = {}) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - - void Reload(); - - void clear(); - -private: - void LibraryModified(bool bModified); - - CBaseLibraryManager* m_pItemManager; -}; - -class LibraryItemTreeModel - : public QAbstractItemModel -{ - Q_OBJECT - - using Group = std::pair >; - -public: - LibraryItemTreeModel(CDatabaseFrameWnd* pParent); - - QModelIndex parent(const QModelIndex& index) const override; - QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override; - QModelIndex index(CBaseLibraryItem* pItem) const; - - int rowCount(const QModelIndex& parent) const override; - int columnCount(const QModelIndex& parent) const override; - - Qt::ItemFlags flags(const QModelIndex& index) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - - bool removeRows(int row, int count, const QModelIndex& parent = {}) override; - - QStringList mimeTypes() const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - QMimeData* mimeData(const QModelIndexList& indexes) const override; - - Qt::DropActions supportedDragActions() const override; - Qt::DropActions supportedDropActions() const override; - - void Clear(); - - void Reload(CBaseLibrary* library); - - void Add(CBaseLibraryItem* item); - bool Remove(CBaseLibraryItem* item); - - void Rename(CBaseLibraryItem* item, const QString& groupName, const QString& shortName); - - std::vector ChildItems(const QModelIndex& index) const; - - QString GetFullName(const QModelIndex& index) const; - - QModelIndex FindLibraryItemByFullName(const QString& fullName) const; - bool DoesGroupExist(const QString& groupName) const; - -signals: - void itemRenamed(CBaseLibraryItem* item, const QString& prevFullName); - -protected: - void RenameItem(CBaseLibraryItem* item, const QString& fullName); - QString MakeValidName(const Group& group, const QString& baseName) const; - bool MoveItem(CBaseLibraryItem* item, const QModelIndex& parent); - - CDatabaseFrameWnd* m_dialog; - - std::map > m_groups; -}; - -Q_DECLARE_METATYPE(CBaseLibrary*) - -#endif // CRYINCLUDE_EDITOR_DATABASEFRAMEWND_H diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.qrc b/Code/Sandbox/Editor/DatabaseFrameWnd.qrc deleted file mode 100644 index 37d97f5c9f..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.qrc +++ /dev/null @@ -1,35 +0,0 @@ - - - res/db_library_bar_00.png - res/db_library_bar_01.png - res/db_library_bar_02.png - res/db_library_bar_03.png - res/db_library_bar_04.png - res/db_library_bar_05.png - res/db_standart_00.png - res/db_standart_01.png - res/db_standart_02.png - res/db_standart_03.png - res/db_library_item_bar_00.png - res/db_library_item_bar_01.png - res/db_library_item_bar_02.png - res/db_library_item_bar_03.png - res/db_library_item_bar_04.png - res/db_library_item_bar_05.png - res/db_library_open.svg - res/db_library_save.svg - res/db_library_add.svg - res/db_library_delete.svg - res/db_library_refresh.svg - res/db_library_undo.svg - res/db_library_redo.svg - res/db_library_copy.svg - res/db_library_paste.svg - res/db_library_additem.svg - res/db_library_cloneitem.svg - res/db_library_removeitem.svg - res/db_library_assignitem.svg - res/db_library_getproperties.svg - res/db_library_reload.svg - - diff --git a/Code/Sandbox/Editor/DatabaseFrameWnd.ui b/Code/Sandbox/Editor/DatabaseFrameWnd.ui deleted file mode 100644 index 655de74a6e..0000000000 --- a/Code/Sandbox/Editor/DatabaseFrameWnd.ui +++ /dev/null @@ -1,279 +0,0 @@ - - - DatabaseFrameWnd - - - - 0 - 0 - 633 - 42 - - - - - Lens Flare Toolbar - - - - 32 - 32 - - - - false - - - TopToolBarArea - - - false - - - - - - - - - - StandartToolBar - - - - 32 - 32 - - - - false - - - TopToolBarArea - - - false - - - - - - - - - - ItemToolBar - - - - 32 - 32 - - - - false - - - TopToolBarArea - - - false - - - - - - - - - - - - - :/DatabaseFrameWnd/db_library_open.svg:/DatabaseFrameWnd/db_library_open.svg - - - Load Library - - - Load Library - - - - - - :/DatabaseFrameWnd/db_library_save.svg:/DatabaseFrameWnd/db_library_save.svg - - - Save Modified Libraries - - - Save Modified Libraries - - - - - - :/DatabaseFrameWnd/db_library_add.svg:/DatabaseFrameWnd/db_library_add.svg - - - Add Library - - - Add Library - - - - - - :/DatabaseFrameWnd/db_library_delete.svg:/DatabaseFrameWnd/db_library_delete.svg - - - Remove Library - - - Remove Library - - - - - - :/DatabaseFrameWnd/db_library_refresh.svg:/DatabaseFrameWnd/db_library_refresh.svg - - - Reload Library - - - Reload Library - - - - - false - - - - :/DatabaseFrameWnd/db_library_undo.svg:/DatabaseFrameWnd/db_library_undo.svg - - - Undo last operation - - - Undo - - - - - false - - - - :/DatabaseFrameWnd/db_library_redo.svg:/DatabaseFrameWnd/db_library_redo.svg - - - Redo last undo operation - - - Redo - - - - - - :/DatabaseFrameWnd/db_library_copy.svg:/DatabaseFrameWnd/db_library_copy.svg - - - Copy Item - - - Copy Item - - - - - - :/DatabaseFrameWnd/db_library_paste.svg:/DatabaseFrameWnd/db_library_paste.svg - - - Paste Item - - - Paste Item - - - - - - :/DatabaseFrameWnd/db_library_additem.svg:/DatabaseFrameWnd/db_library_additem.svg - - - Add New Item - - - Add New Item - - - - - - :/DatabaseFrameWnd/db_library_cloneitem.svg:/DatabaseFrameWnd/db_library_cloneitem.svg - - - Clone Library Item - - - Clone Library Item - - - - - - :/DatabaseFrameWnd/db_library_removeitem.svg:/DatabaseFrameWnd/db_library_removeitem.svg - - - Remove Item - - - Remove Item - - - - - - :/DatabaseFrameWnd/db_library_assignitem.svg:/DatabaseFrameWnd/db_library_assignitem.svg - - - Assign Item to Selected Objects - - - Assign Item to Selected Objects - - - - - - :/DatabaseFrameWnd/db_library_getproperties.svg:/DatabaseFrameWnd/db_library_getproperties.svg - - - Get Properties From Selection - - - Get Properties From Selection - - - - - - :/DatabaseFrameWnd/db_library_reload.svg:/DatabaseFrameWnd/db_library_reload.svg - - - Reload Item - - - Reload Item - - - - - - diff --git a/Code/Sandbox/Editor/DisplaySettings.cpp b/Code/Sandbox/Editor/DisplaySettings.cpp index bd4372ae70..75e5c54ae9 100644 --- a/Code/Sandbox/Editor/DisplaySettings.cpp +++ b/Code/Sandbox/Editor/DisplaySettings.cpp @@ -22,7 +22,6 @@ // Editor #include "Settings.h" -#include "Material/MaterialManager.h" @@ -112,30 +111,6 @@ void CDisplaySettings::SetDebugFlags(int flags) //SetCVarInt( "sys_enable_budgetmonitoring",(m_debugFlags&DBG_BUDGET_MONITORING) ? 4:0 ); //SetCVarInt( "Profile",(m_debugFlags&DBG_FRAMEPROFILE) ? 1:0 ); - - if (CMaterialManager* pMaterialManager = GetIEditor()->GetMaterialManager()) - { - int mask = pMaterialManager->GetHighlightMask(); - if (m_debugFlags & DBG_HIGHLIGHT_BREAKABLE) - { - mask |= eHighlight_Breakable; - } - else - { - mask &= ~eHighlight_Breakable; - } - - if (m_debugFlags & DBG_HIGHLIGHT_MISSING_SURFACE_TYPE) - { - mask |= eHighlight_NoSurfaceType; - } - else - { - mask &= ~eHighlight_NoSurfaceType; - } - - pMaterialManager->SetHighlightMask(mask); - } } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/EditorToolsApplication.cpp b/Code/Sandbox/Editor/EditorToolsApplication.cpp index 97caaf612a..2e3d70795a 100644 --- a/Code/Sandbox/Editor/EditorToolsApplication.cpp +++ b/Code/Sandbox/Editor/EditorToolsApplication.cpp @@ -21,14 +21,12 @@ #include #include #include -#include // Editor #include "MainWindow.h" #include "CryEdit.h" #include "DisplaySettingsPythonFuncs.h" #include "GameEngine.h" -#include "Material/MaterialPythonFuncs.h" #include "PythonEditorFuncs.h" #include "TrackView/TrackViewPythonFuncs.h" #include "Include/IObjectManager.h" @@ -65,7 +63,6 @@ namespace EditorInternal RegisterComponentDescriptor(AzToolsFramework::DisplaySettingsPythonFuncsHandler::CreateDescriptor()); RegisterComponentDescriptor(AzToolsFramework::MainWindowEditorFuncsHandler::CreateDescriptor()); RegisterComponentDescriptor(AzToolsFramework::ObjectManagerFuncsHandler::CreateDescriptor()); - RegisterComponentDescriptor(AzToolsFramework::MaterialPythonFuncsHandler::CreateDescriptor()); RegisterComponentDescriptor(AzToolsFramework::PythonEditorComponent::CreateDescriptor()); RegisterComponentDescriptor(AzToolsFramework::PythonEditorFuncsHandler::CreateDescriptor()); RegisterComponentDescriptor(AzToolsFramework::DisplaySettingsComponent::CreateDescriptor()); @@ -81,7 +78,6 @@ namespace EditorInternal components.emplace_back(azrtti_typeid()); components.emplace_back(azrtti_typeid()); - components.emplace_back(azrtti_typeid()); // Add new Bus-based Python Bindings components.emplace_back(azrtti_typeid()); diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 9165809c7f..a127203071 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -40,7 +40,6 @@ # include #endif // defined(AZ_PLATFORM_WINDOWS) #include // for AzFramework::InputDeviceMouse -#include #include // AzQtComponents @@ -1234,6 +1233,7 @@ void EditorViewportWidget::SetViewportId(int id) if (ed_useNewCameraSystem) { + AzFramework::ReloadCameraKeyBindings(); m_renderViewport->GetControllerList()->Add(AZStd::make_shared()); } else @@ -1626,8 +1626,8 @@ void EditorViewportWidget::keyPressEvent(QKeyEvent* event) QCoreApplication::sendEvent(GetIEditor()->GetEditorMainWindow(), event); } - // NOTE: we keep track of keypresses and releases explicitly because the OS/Qt will insert a slight delay between sending - // keyevents when the key is held down. This is standard, but makes responding to key events for game style input silly + // NOTE: we keep track of key presses and releases explicitly because the OS/Qt will insert a slight delay between sending + // key events when the key is held down. This is standard, but makes responding to key events for game style input silly // because we want the movement to be butter smooth. if (!event->isAutoRepeat()) { diff --git a/Code/Sandbox/Editor/ErrorReport.h b/Code/Sandbox/Editor/ErrorReport.h index f78410be62..b13f8ae120 100644 --- a/Code/Sandbox/Editor/ErrorReport.h +++ b/Code/Sandbox/Editor/ErrorReport.h @@ -19,7 +19,6 @@ #pragma once // forward declarations. -class CMaterial; class CParticleItem; #include "BaseLibraryItem.h" diff --git a/Code/Sandbox/Editor/Export/ExportManager.cpp b/Code/Sandbox/Editor/Export/ExportManager.cpp index b41872595a..638977b191 100644 --- a/Code/Sandbox/Editor/Export/ExportManager.cpp +++ b/Code/Sandbox/Editor/Export/ExportManager.cpp @@ -23,7 +23,6 @@ // Editor #include "Geometry/EdGeometry.h" -#include "Material/Material.h" #include "ViewManager.h" #include "OBJExporter.h" #include "OCMExporter.h" @@ -79,47 +78,6 @@ Export::CMesh::CMesh() } -void Export::CMesh::SetMaterial(CMaterial* pMtl, CBaseObject* pBaseObj) -{ - if (!pMtl) - { - cry_strcpy(material.name, pBaseObj->GetName().toUtf8().data()); - return; - } - - cry_strcpy(material.name, pMtl->GetFullName().toUtf8().data()); - - _smart_ptr matInfo = pMtl->GetMatInfo(); - IRenderShaderResources* pRes = matInfo->GetShaderItem().m_pShaderResources; - if (!pRes) - { - return; - } - - ColorF difColor = pRes->GetColorValue(EFTT_DIFFUSE); - material.diffuse.r = difColor.r; - material.diffuse.g = difColor.g; - material.diffuse.b = difColor.b; - material.diffuse.a = difColor.a; - - ColorF specColor = pRes->GetColorValue(EFTT_SPECULAR); - material.specular.r = specColor.r; - material.specular.g = specColor.g; - material.specular.b = specColor.b; - material.specular.a = specColor.a; - - material.opacity = pRes->GetStrengthValue(EFTT_OPACITY); - material.smoothness = pRes->GetStrengthValue(EFTT_SMOOTHNESS); - - SetTexture(material.mapDiffuse, pRes, EFTT_DIFFUSE); - SetTexture(material.mapSpecular, pRes, EFTT_SPECULAR); - SetTexture(material.mapOpacity, pRes, EFTT_OPACITY); - SetTexture(material.mapNormals, pRes, EFTT_NORMALS); - SetTexture(material.mapDecal, pRes, EFTT_DECAL_OVERLAY); - SetTexture(material.mapDisplacement, pRes, EFTT_HEIGHT); -} - - ////////////////////////////////////////////////////////// // CObject Export::CObject::CObject(const char* pName) @@ -416,18 +374,6 @@ void CExportManager::AddMesh(Export::CObject* pObj, const IIndexedMesh* pIndMesh pObj->m_texCoords.push_back(tc); } - CMaterial* pMtl = 0; - - if (m_pBaseObj) - { - pMtl = m_pBaseObj->GetRenderMaterial(); - } - - if (pMtl) - { - pObj->SetMaterialName(pMtl->GetFullName().toUtf8().data()); - } - if (pIndMesh->GetSubSetCount() && !(pIndMesh->GetSubSetCount() == 1 && pIndMesh->GetSubSet(0).nNumIndices == 0)) { for (int i = 0; i < pIndMesh->GetSubSetCount(); ++i) @@ -447,23 +393,6 @@ void CExportManager::AddMesh(Export::CObject* pObj, const IIndexedMesh* pIndMesh pMesh->m_faces.push_back(face); } - if (pMtl) - { - if (pMtl->IsMultiSubMaterial()) - { - CMaterial* pSubMtl = 0; - if (sms.nMatID < pMtl->GetSubMaterialCount()) - { - pSubMtl = pMtl->GetSubMaterial(sms.nMatID); - } - pMesh->SetMaterial(pSubMtl, m_pBaseObj); - } - else - { - pMesh->SetMaterial(pMtl, m_pBaseObj); - } - } - pObj->m_meshes.push_back(pMesh); } } @@ -497,10 +426,6 @@ void CExportManager::AddMesh(Export::CObject* pObj, const IIndexedMesh* pIndMesh } } - if (m_pBaseObj && pMtl) - { - pMesh->SetMaterial(pMtl, m_pBaseObj); - } pObj->m_meshes.push_back(pMesh); } } diff --git a/Code/Sandbox/Editor/Export/ExportManager.h b/Code/Sandbox/Editor/Export/ExportManager.h index 8904ef08ed..a27e54b085 100644 --- a/Code/Sandbox/Editor/Export/ExportManager.h +++ b/Code/Sandbox/Editor/Export/ExportManager.h @@ -43,8 +43,6 @@ namespace Export virtual int GetFaceCount() const { return m_faces.size(); } virtual const Face* GetFaceBuffer() const { return m_faces.size() ? &m_faces[0] : 0; } - void SetMaterial(CMaterial* pMtl, CBaseObject* pBaseObj); - private: std::vector m_faces; diff --git a/Code/Sandbox/Editor/GameExporter.cpp b/Code/Sandbox/Editor/GameExporter.cpp index 8a93dbedce..64e1fc6514 100644 --- a/Code/Sandbox/Editor/GameExporter.cpp +++ b/Code/Sandbox/Editor/GameExporter.cpp @@ -27,16 +27,11 @@ #include "Mission.h" #include "ShaderCache.h" #include "UsedResources.h" -#include "Material/MaterialManager.h" -#include "Material/MaterialLibrary.h" #include "WaitProgress.h" #include "Util/CryMemFile.h" #include "Objects/ObjectManager.h" #include "Objects/EntityObject.h" -#include "LensFlareEditor/LensFlareManager.h" -#include "LensFlareEditor/LensFlareLibrary.h" -#include "LensFlareEditor/LensFlareItem.h" #include @@ -210,7 +205,6 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE ExportLevelInfo(sLevelPath); - ExportLevelLensFlares(sLevelPath); ExportLevelResourceList(sLevelPath); ExportLevelUsedResourceList(sLevelPath); ExportLevelShaderCache(sLevelPath); @@ -340,11 +334,6 @@ void CGameExporter::ExportLevelData(const QString& path, bool bExportMission) ExportMapInfo(root); - ////////////////////////////////////////////////////////////////////////// - // Export materials. - ExportMaterials(root, path); - ////////////////////////////////////////////////////////////////////////// - CCryEditDoc* pDocument = pEditor->GetDocument(); CMission* pCurrentMission = 0; @@ -512,109 +501,6 @@ void CGameExporter::ExportMapInfo(XmlNodeRef& node) xmlAr.root = node; } -////////////////////////////////////////////////////////////////////////// -void CGameExporter::ExportMaterials(XmlNodeRef& levelDataNode, const QString& path) -{ - ////////////////////////////////////////////////////////////////////////// - // Export materials manager. - CMaterialManager* pManager = GetIEditor()->GetMaterialManager(); - pManager->Export(levelDataNode); - - QString filename = Path::Make(path, MATERIAL_LEVEL_LIBRARY_FILE); - - bool bHaveItems = true; - - int numMtls = 0; - - XmlNodeRef nodeMaterials = XmlHelpers::CreateXmlNode("MaterialsLibrary"); - // Export Materials local level library. - for (int i = 0; i < pManager->GetLibraryCount(); i++) - { - XmlNodeRef nodeLib = nodeMaterials->newChild("Library"); - CMaterialLibrary* pLib = (CMaterialLibrary*)pManager->GetLibrary(i); - if (pLib->GetItemCount() > 0) - { - bHaveItems = false; - // Export this library. - numMtls += pManager->ExportLib(pLib, nodeLib); - } - } - if (!bHaveItems) - { - XmlString xmlData = nodeMaterials->getXML(); - - CCryMemFile file; - file.Write(xmlData.c_str(), xmlData.length()); - m_levelPak.m_pakFile.UpdateFile(filename.toUtf8().data(), file); - } - else - { - m_levelPak.m_pakFile.RemoveFile(filename.toUtf8().data()); - } - m_numExportedMaterials = numMtls; -} - -////////////////////////////////////////////////////////////////////////// -void CGameExporter::ExportLevelLensFlares(const QString& path) -{ - GetIEditor()->SetStatusText(QObject::tr("Exporting Lens Flares...")); - std::vector objects; - GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, objects); - std::set flareNameSet; - for (int i = 0, iObjectSize(objects.size()); i < iObjectSize; ++i) - { - CEntityObject* pEntity = (CEntityObject*)objects[i]; - if (!pEntity->IsLight()) - { - continue; - } - QString flareName = pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName); - if (flareName.isEmpty() || flareName == "@root") - { - continue; - } - flareNameSet.insert(flareName); - } - - XmlNodeRef pRootNode = GetIEditor()->GetSystem()->CreateXmlNode("LensFlareList"); - pRootNode->setAttr("Version", FLARE_EXPORT_FILE_VERSION); - - CLensFlareManager* pLensManager = GetIEditor()->GetLensFlareManager(); - - if (CLensFlareLibrary* pLevelLib = (CLensFlareLibrary*)pLensManager->GetLevelLibrary()) - { - for (int i = 0; i < pLevelLib->GetItemCount(); i++) - { - CLensFlareItem* pItem = (CLensFlareItem*)pLevelLib->GetItem(i); - - if (flareNameSet.find(pItem->GetFullName()) == flareNameSet.end()) - { - continue; - } - - CBaseLibraryItem::SerializeContext ctx(pItem->CreateXmlData(), false); - pRootNode->addChild(ctx.node); - pItem->Serialize(ctx); - flareNameSet.erase(pItem->GetFullName()); - } - } - - std::set::iterator iFlareNameSet = flareNameSet.begin(); - for (; iFlareNameSet != flareNameSet.end(); ++iFlareNameSet) - { - QString flareName = *iFlareNameSet; - XmlNodeRef pFlareNode = GetIEditor()->GetSystem()->CreateXmlNode("LensFlare"); - pFlareNode->setAttr("name", flareName.toUtf8().data()); - pRootNode->addChild(pFlareNode); - } - - CCryMemFile lensFlareNames; - lensFlareNames.Write(pRootNode->getXMLData()->GetString(), pRootNode->getXMLData()->GetStringLength()); - - QString exportPathName = path + FLARE_EXPORT_FILE; - m_levelPak.m_pakFile.UpdateFile(exportPathName.toUtf8().data(), lensFlareNames); -} - ////////////////////////////////////////////////////////////////////////// void CGameExporter::ExportLevelResourceList(const QString& path) { diff --git a/Code/Sandbox/Editor/GameExporter.h b/Code/Sandbox/Editor/GameExporter.h index 87e24ef844..a428046f0a 100644 --- a/Code/Sandbox/Editor/GameExporter.h +++ b/Code/Sandbox/Editor/GameExporter.h @@ -95,11 +95,9 @@ private: void ExportOcclusionMesh(const char* pszGamePath); void ExportMapInfo(XmlNodeRef& node); - void ExportLevelLensFlares(const QString& path); void ExportLevelResourceList(const QString& path); void ExportLevelUsedResourceList(const QString& path); void ExportLevelShaderCache(const QString& path); - void ExportMaterials(XmlNodeRef& levelDataNode, const QString& path); void ExportGameData(const QString& path); void ExportFileList(const QString& path, const QString& levelName); diff --git a/Code/Sandbox/Editor/GameResourcesExporter.cpp b/Code/Sandbox/Editor/GameResourcesExporter.cpp index 564396d090..8a6c547dca 100644 --- a/Code/Sandbox/Editor/GameResourcesExporter.cpp +++ b/Code/Sandbox/Editor/GameResourcesExporter.cpp @@ -21,7 +21,6 @@ // Editor #include "UsedResources.h" #include "GameEngine.h" -#include "Material/MaterialManager.h" #include "Include/IObjectManager.h" #include "WaitProgress.h" @@ -51,7 +50,7 @@ void CGameResourcesExporter::ChooseDirectory() void CGameResourcesExporter::GatherAllLoadedResources() { m_files.clear(); - m_files.reserve(100000); // count from GetResourceList, GetFilesFromObjects, GetFilesFromMaterials ... is unknown + m_files.reserve(100000); // count from GetResourceList, GetFilesFromObjects ... is unknown auto pResList = gEnv->pCryPak->GetResourceList(AZ::IO::IArchive::RFOM_Level); { @@ -62,7 +61,6 @@ void CGameResourcesExporter::GatherAllLoadedResources() } GetFilesFromObjects(); - GetFilesFromMaterials(); } ////////////////////////////////////////////////////////////////////////// @@ -158,12 +156,3 @@ void CGameResourcesExporter::GetFilesFromObjects() Append(m_files, rs.files); } - -////////////////////////////////////////////////////////////////////////// -void CGameResourcesExporter::GetFilesFromMaterials() -{ - CUsedResources rs; - GetIEditor()->GetMaterialManager()->GatherUsedResources(rs); - Append(m_files, rs.files); -} - diff --git a/Code/Sandbox/Editor/GameResourcesExporter.h b/Code/Sandbox/Editor/GameResourcesExporter.h index b408cbb42f..8236458cb3 100644 --- a/Code/Sandbox/Editor/GameResourcesExporter.h +++ b/Code/Sandbox/Editor/GameResourcesExporter.h @@ -44,7 +44,6 @@ private: void GetFilesFromObjects(); void GetFilesFromVarBlock(CVarBlock* pVB); void GetFilesFromVariable(IVariable* pVar); - void GetFilesFromMaterials(); }; #endif // CRYINCLUDE_EDITOR_GAMERESOURCESEXPORTER_H diff --git a/Code/Sandbox/Editor/IEditor.h b/Code/Sandbox/Editor/IEditor.h index e1f41b9f41..c03b99e128 100644 --- a/Code/Sandbox/Editor/IEditor.h +++ b/Code/Sandbox/Editor/IEditor.h @@ -46,11 +46,8 @@ class CGameEngine; struct IIconManager; class CToolBoxManager; class CClassFactory; -class CMaterialManager; class CMusicManager; -class CMaterail; struct IEditorParticleManager; -class CLensFlareManager; class CEAXPresetManager; class CErrorReport; class CBaseLibraryItem; @@ -545,8 +542,6 @@ struct IEditor virtual CSettingsManager* GetSettingsManager() = 0; //! Get DB manager that own items of specified type. virtual IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType) = 0; - //! Get Manager of Materials. - virtual CMaterialManager* GetMaterialManager() = 0; virtual IBaseLibraryManager* GetMaterialManagerLibrary() = 0; // Vladimir@conffx virtual IEditorMaterialManager* GetIEditorMaterialManager() = 0; // Vladimir@Conffx //! Returns IconManager. @@ -555,8 +550,6 @@ struct IEditor virtual IEditorPanelUtils* GetEditorPanelUtils() = 0; //! Get Music Manager. virtual CMusicManager* GetMusicManager() = 0; - //! Get Lens Flare Manager. - virtual CLensFlareManager* GetLensFlareManager() = 0; virtual float GetTerrainElevation(float x, float y) = 0; virtual Editor::EditorQtApplication* GetEditorQtApplication() = 0; virtual const QColor& GetColorByName(const QString& name) = 0; diff --git a/Code/Sandbox/Editor/IEditorImpl.cpp b/Code/Sandbox/Editor/IEditorImpl.cpp index a81aff86a9..61d24db90c 100644 --- a/Code/Sandbox/Editor/IEditorImpl.cpp +++ b/Code/Sandbox/Editor/IEditorImpl.cpp @@ -53,14 +53,12 @@ AZ_POP_DISABLE_WARNING #include "KeyboardCustomizationSettings.h" #include "Export/ExportManager.h" #include "LevelIndependentFileMan.h" -#include "Material/MaterialManager.h" #include "TrackView/TrackViewSequenceManager.h" #include "AnimationContext.h" #include "GameEngine.h" #include "ToolBox.h" #include "MainWindow.h" #include "Alembic/AlembicCompiler.h" -#include "LensFlareEditor/LensFlareManager.h" #include "UIEnumsDatabase.h" #include "Util/Ruler.h" #include "RenderHelpers/AxisHelper.h" @@ -168,9 +166,7 @@ CEditorImpl::CEditorImpl() , m_pAnimationContext(nullptr) , m_pSequenceManager(nullptr) , m_pToolBoxManager(nullptr) - , m_pMaterialManager(nullptr) , m_pMusicManager(nullptr) - , m_pLensFlareManager(nullptr) , m_pErrorReport(nullptr) , m_pLasLoadedLevelErrorReport(nullptr) , m_pErrorsDlg(nullptr) @@ -224,13 +220,11 @@ CEditorImpl::CEditorImpl() m_pIconManager = new CIconManager; m_pUndoManager = new CUndoManager; m_pToolBoxManager = new CToolBoxManager; - m_pMaterialManager = new CMaterialManager(regCtx); m_pAlembicCompiler = new CAlembicCompiler(); m_pSequenceManager = new CTrackViewSequenceManager; m_pAnimationContext = new CAnimationContext; m_pImageUtil = new CImageUtil_impl(); - m_pLensFlareManager = new CLensFlareManager; m_pResourceSelectorHost.reset(CreateResourceSelectorHost()); m_pRuler = new CRuler; m_selectedRegion.min = Vec3(0, 0, 0); @@ -345,7 +339,6 @@ CEditorImpl::~CEditorImpl() m_bExiting = true; // Can't save level after this point (while Crash) SAFE_RELEASE(m_pSourceControl); - SAFE_DELETE(m_pMaterialManager) SAFE_DELETE(m_pAlembicCompiler) SAFE_DELETE(m_pIconManager) SAFE_DELETE(m_pViewManager) @@ -415,7 +408,6 @@ void CEditorImpl::SetGameEngine(CGameEngine* ge) m_pObjectManager->LoadClassTemplates("Editor"); m_pObjectManager->RegisterCVars(); - m_pMaterialManager->Set3DEngine(); m_pAnimationContext->Init(); } @@ -1003,13 +995,8 @@ void CEditorImpl::CloseView(const GUID& classId) } } -IDataBaseManager* CEditorImpl::GetDBItemManager(EDataBaseItemType itemType) +IDataBaseManager* CEditorImpl::GetDBItemManager([[maybe_unused]] EDataBaseItemType itemType) { - switch (itemType) - { - case EDB_TYPE_MATERIAL: - return m_pMaterialManager; - } return 0; } @@ -1775,13 +1762,13 @@ SEditorSettings* CEditorImpl::GetEditorSettings() // Vladimir@Conffx IBaseLibraryManager* CEditorImpl::GetMaterialManagerLibrary() { - return m_pMaterialManager; + return nullptr; } // Vladimir@Conffx IEditorMaterialManager* CEditorImpl::GetIEditorMaterialManager() { - return m_pMaterialManager; + return nullptr; } IImageUtil* CEditorImpl::GetImageUtil() diff --git a/Code/Sandbox/Editor/IEditorImpl.h b/Code/Sandbox/Editor/IEditorImpl.h index 908136297b..d17a94807f 100644 --- a/Code/Sandbox/Editor/IEditorImpl.h +++ b/Code/Sandbox/Editor/IEditorImpl.h @@ -42,7 +42,6 @@ class CUndoManager; class CGameEngine; class CExportManager; class CErrorsDlg; -class CLensFlareManager; class CIconManager; class CBackgroundTaskManager; class CTrackViewSequenceManager; @@ -181,9 +180,7 @@ public: bool IsSelectionLocked(); IDataBaseManager* GetDBItemManager(EDataBaseItemType itemType); - CMaterialManager* GetMaterialManager() { return m_pMaterialManager; } CMusicManager* GetMusicManager() { return m_pMusicManager; }; - CLensFlareManager* GetLensFlareManager() { return m_pLensFlareManager; }; IBackgroundTaskManager* GetBackgroundTaskManager() override; IBackgroundScheduleManager* GetBackgroundScheduleManager() override; @@ -381,10 +378,8 @@ protected: CAnimationContext* m_pAnimationContext; CTrackViewSequenceManager* m_pSequenceManager; CToolBoxManager* m_pToolBoxManager; - CMaterialManager* m_pMaterialManager; CAlembicCompiler* m_pAlembicCompiler; CMusicManager* m_pMusicManager; - CLensFlareManager* m_pLensFlareManager; CErrorReport* m_pErrorReport; //! Contains the error reports for the last loaded level. CErrorReport* m_pLasLoadedLevelErrorReport; diff --git a/Code/Sandbox/Editor/IconManager.cpp b/Code/Sandbox/Editor/IconManager.cpp index 09c2d41035..828a7cdfcc 100644 --- a/Code/Sandbox/Editor/IconManager.cpp +++ b/Code/Sandbox/Editor/IconManager.cpp @@ -15,7 +15,6 @@ #include "IconManager.h" -#include #include // AzToolsFramework @@ -115,71 +114,6 @@ int CIconManager::GetIconTexture(const char* iconName) return 0; } - if (AZ::Interface::Get()) - { - ITexture* texture = GetIEditor()->GetRenderer() ? GetIEditor()->GetRenderer()->EF_LoadTexture(iconName) : nullptr; - if (texture) - { - id = texture->GetTextureID(); - m_textures[iconName] = id; - } - } - else - { - QString ext = Path::GetExt(iconName); - QString actualName = iconName; - - char iconPath[AZ_MAX_PATH_LEN] = { 0 }; - gEnv->pFileIO->ResolvePath(actualName.toUtf8().data(), iconPath, AZ_MAX_PATH_LEN); - - // if we can't find it at the resolved path, try the devroot if necessary: - if (!gEnv->pFileIO->Exists(iconPath)) - { - if (iconName[0] != '@') // it has no specified alias - { - if (QString::compare(ext, "dds", Qt::CaseInsensitive) != 0) // if its a DDS, it comes out of processed files in @assets@, and assets is assumed by default (legacy renderer) - { - // check for a source file - AZStd::string iconFullPath; - bool pathFound = false; - using AssetSysReqBus = AzToolsFramework::AssetSystemRequestBus; - AssetSysReqBus::BroadcastResult(pathFound, &AssetSysReqBus::Events::GetFullSourcePathFromRelativeProductPath, iconName, iconFullPath); - - if (pathFound) - { - azstrncpy(iconPath, AZ_MAX_PATH_LEN, iconFullPath.c_str(), iconFullPath.length() + 1); - } - } - } - } - - CImageEx image; - // Load icon. - if (CImageUtil::LoadImage(iconPath, image)) - { - IRenderer* pRenderer(GetIEditor()->GetRenderer()); - if (pRenderer->GetRenderType() != eRT_DX11) - { - image.SwapRedAndBlue(); - } - - if (QString::compare(ext, "bmp", Qt::CaseInsensitive) == 0 || QString::compare(ext, "jpg", Qt::CaseInsensitive) == 0) - { - int sz = image.GetWidth() * image.GetHeight(); - uint8* buf = (uint8*)image.GetData(); - for (int i = 0; i < sz; i++) - { - uint32 alpha = max(max(buf[i * 4], buf[i * 4 + 1]), buf[i * 4 + 2]); - alpha *= 2; - buf[i * 4 + 3] = (alpha > 255) ? 255 : alpha; - } - } - - id = pRenderer->DownLoadToVideoMemory((unsigned char*)image.GetData(), image.GetWidth(), image.GetHeight(), eTF_R8G8B8A8, eTF_R8G8B8A8, 0, 0, 0); - m_textures[iconName] = id; - } - } - return id; } diff --git a/Code/Sandbox/Editor/Include/IErrorReport.h b/Code/Sandbox/Editor/Include/IErrorReport.h index 8afe269324..f25a1163a3 100644 --- a/Code/Sandbox/Editor/Include/IErrorReport.h +++ b/Code/Sandbox/Editor/Include/IErrorReport.h @@ -21,7 +21,6 @@ #include // forward declarations. -class CMaterial; class CParticleItem; class CBaseObject; class CBaseLibraryItem; diff --git a/Code/Sandbox/Editor/LayoutWnd.cpp b/Code/Sandbox/Editor/LayoutWnd.cpp index 34a96bca53..54389f30c1 100644 --- a/Code/Sandbox/Editor/LayoutWnd.cpp +++ b/Code/Sandbox/Editor/LayoutWnd.cpp @@ -24,7 +24,6 @@ #include #include -#include #include // for AzQtComponents::Style // Editor diff --git a/Code/Sandbox/Editor/LensFlareEditor/ILensFlareListener.h b/Code/Sandbox/Editor/LensFlareEditor/ILensFlareListener.h deleted file mode 100644 index 913faf2bb3..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/ILensFlareListener.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_ILENSFLARELISTENER_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_ILENSFLARELISTENER_H -#pragma once - -class CLensFlareItem; -class CLensFlareElement; - -class ILensFlareChangeItemListener -{ -public: - virtual void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) = 0; - virtual void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem) = 0; -}; - -class ILensFlareChangeElementListener -{ -public: - virtual void OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement) = 0; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_ILENSFLARELISTENER_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp deleted file mode 100644 index d30db3f5f3..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareAtomicList.h" - -// Qt -#include -#include - -// Editor -#include "LensFlareUtil.h" -#include "Util/Image.h" -#include "Util/ImageUtil.h" - - -struct QLensFlareAtomicListModel::Item -{ - QString text; - QSize size; - QPixmap pixmap; - EFlareType flareType; -}; - -CLensFlareAtomicList::CLensFlareAtomicList(QWidget* parent) - : CImageListCtrl(parent) - , m_model(new QLensFlareAtomicListModel(this)) -{ - setDragEnabled(true); - setDragDropMode(DragOnly); - setModel(m_model.data()); -} - -CLensFlareAtomicList::~CLensFlareAtomicList() -{ -} - -QModelIndex QLensFlareAtomicListModel::InsertItem(const FlareInfo& flareInfo) -{ - Item* pPreviewItem = new Item; - - if (flareInfo.imagename) - { - CImageEx* pImage = new CImageEx(); - if (CImageUtil::LoadImage(flareInfo.imagename, *pImage)) - { - pImage->SwapRedAndBlue(); - pPreviewItem->size = QSize(pImage->GetWidth(), pImage->GetHeight()); - QImage img(reinterpret_cast(pImage->GetData()), pImage->GetWidth(), pImage->GetHeight(), QImage::Format_RGB32); - pPreviewItem->pixmap = QPixmap::fromImage(img.copy()); - } - - delete pImage; - } - - if (pPreviewItem->pixmap.isNull()) - { - pPreviewItem->pixmap = QPixmap(":/water.png"); - pPreviewItem->size = QSize(64, 64); - } - - pPreviewItem->text = flareInfo.name; - pPreviewItem->flareType = flareInfo.type; - - const int row = m_items.count(); - beginInsertRows(QModelIndex(), row, row); - m_items.append(pPreviewItem); - endInsertRows(); - - return index(row, 0); -} - -void QLensFlareAtomicListModel::Populate() -{ - Clear(); - const FlareInfoArray::Props array = FlareInfoArray::Get(); - for (size_t i = 0; i < array.size; ++i) - { - const FlareInfo& flareInfo(array.p[i]); - if (LensFlareUtil::IsElement(flareInfo.type)) - { - InsertItem(flareInfo); - } - } -} - -void CLensFlareAtomicList::FillAtomicItems() -{ - if (m_model) - { - m_model->Populate(); - } -} - -void CLensFlareAtomicList::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; - } - - const QSize& borderSize = BorderSize(); - int x = borderSize.width(); - int y = borderSize.height(); - - QSize itemSize = ItemSize(); - const int nTextHeight = fontMetrics().height(); - const int xMax = nPageHorz - borderSize.width(); - int itemHeightMax = 0; - - for (int row = 0; row < rowCount; ++row) - { - QModelIndex index = m_model->index(row, 0); - itemSize = index.data(Qt::SizeHintRole).toSize(); - - if ((x + itemSize.width()) > xMax) - { - y += itemHeightMax + borderSize.height() + nTextHeight; - x = borderSize.width(); - itemHeightMax = 0; - } - - if (itemSize.height() > itemHeightMax) - { - itemHeightMax = itemSize.height(); - } - - SetItemGeometry(index, QRect(QPoint(x, y), itemSize)); - - x += itemSize.width() + borderSize.width(); - } - - verticalScrollBar()->setPageStep(viewport()->height()); - verticalScrollBar()->setRange(0, (y + itemHeightMax - viewport()->height())); -} - -QLensFlareAtomicListModel::QLensFlareAtomicListModel(QObject* parent) - : QAbstractListModel(parent) -{ -} - -QLensFlareAtomicListModel::~QLensFlareAtomicListModel() -{ -} - -void QLensFlareAtomicListModel::Clear() -{ - qDeleteAll(m_items); - m_items.clear(); -} - -int QLensFlareAtomicListModel::rowCount(const QModelIndex& parent) const -{ - if (parent.isValid()) - { - return 0; - } - - return m_items.count(); -} - -QVariant QLensFlareAtomicListModel::data(const QModelIndex& index, int role) const -{ - Item* item; - if (!index.isValid()) - { - return QVariant(); - } - else - { - item = ItemFromIndex(index); - if (!item) - { - return QVariant(); - } - } - - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return item->text; - - case Qt::SizeHintRole: - return item->size; - - case Qt::DecorationRole: - return item->pixmap; - - case Qt::UserRole: - return item->flareType; - } - - return QVariant(); -} - -bool QLensFlareAtomicListModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - Item* item; - if (index.isValid()) - { - return false; - } - else - { - item = ItemFromIndex(index); - if (!item) - { - return false; - } - } - - switch (role) - { - case Qt::EditRole: - item->text = value.toString(); - break; - - case Qt::DecorationRole: - item->pixmap = value.value(); - break; - - case Qt::SizeHintRole: - item->size = value.toSize(); - break; - - default: - return false; - } - - emit dataChanged(index, index, QVector() << role); - return false; -} - -Qt::ItemFlags QLensFlareAtomicListModel::flags(const QModelIndex& index) const -{ - return QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled; -} - -EFlareType QLensFlareAtomicListModel::FlareTypeFromIndex(QModelIndex index) const -{ - Item* item; - if (!index.isValid()) - { - return eFT_Max; - } - else - { - item = ItemFromIndex(index); - if (!item) - { - return eFT_Max; - } - } - - return item->flareType; -} - -QLensFlareAtomicListModel::Item* QLensFlareAtomicListModel::ItemFromIndex(QModelIndex index) const -{ - if (!index.isValid()) - { - return nullptr; - } - - return m_items.at(index.row()); -} - -QStringList QLensFlareAtomicListModel::mimeTypes() const -{ - return { - QStringLiteral("application/x-o3de-flaretypes") - }; -} - -QMimeData* QLensFlareAtomicListModel::mimeData(const QModelIndexList& indexes) const -{ - QMimeData* data = new QMimeData(); - - QByteArray encoded; - QDataStream stream(&encoded, QIODevice::WriteOnly); - - for (const QModelIndex& index : indexes) - { - stream << static_cast(FlareTypeFromIndex(index)); - } - - data->setData(QStringLiteral("application/x-o3de-flaretypes"), encoded); - - return data; -} - -bool QLensFlareAtomicListModel::dropMimeData([[maybe_unused]] const QMimeData* data, [[maybe_unused]] Qt::DropAction action, [[maybe_unused]] int row, [[maybe_unused]] int column, [[maybe_unused]] const QModelIndex& parent) -{ - return false; -} - -Qt::DropActions QLensFlareAtomicListModel::supportedDragActions() const -{ - return Qt::CopyAction; -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.h deleted file mode 100644 index 5748ff07f7..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareAtomicList.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREATOMICLIST_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREATOMICLIST_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "Controls/ImageListCtrl.h" -#endif - -#if !defined(Q_MOC_RUN) -#include -#include -#endif - -class CLensFlareEditor; -class QLensFlareAtomicListModel; - -class CLensFlareAtomicList - : public CImageListCtrl -{ - Q_OBJECT -public: - CLensFlareAtomicList(QWidget* parent = nullptr); - virtual ~CLensFlareAtomicList(); - - void FillAtomicItems(); - -protected: - void updateGeometries() override; - -private: - QScopedPointer m_model; -}; - -class QLensFlareAtomicListModel - : public QAbstractListModel -{ - struct Item; - Q_OBJECT -public: - QLensFlareAtomicListModel(QObject* parent = nullptr); - ~QLensFlareAtomicListModel(); - - void Clear(); - void Populate(); - - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - Qt::ItemFlags flags(const QModelIndex& index) const override; - - QStringList mimeTypes() const override; - QMimeData* mimeData(const QModelIndexList& indexes) const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - Qt::DropActions supportedDragActions() const override; - - EFlareType FlareTypeFromIndex(QModelIndex index) const; - -protected: - QModelIndex InsertItem(const FlareInfo& flareInfo); - Item* ItemFromIndex(QModelIndex index) const; - -private: - QVector m_items; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREATOMICLIST_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp deleted file mode 100644 index 763b5bf19b..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareEditor.h" - -// Qt -#include -#include - -// AzToolsFramework -#include -#include - -// AzQtComponents -#include -#include -#include - -// LmbrCentral -#include // for LmbrCentral::LensFlareAsset - -// Editor -#include "Clipboard.h" -#include "StringDlg.h" -#include "Settings.h" -#include "Include/IObjectManager.h" -#include "LensFlareView.h" -#include "LensFlareAtomicList.h" -#include "LensFlareElementTree.h" -#include "LensFlareManager.h" -#include "LensFlareItem.h" -#include "LensFlareLibrary.h" -#include "LensFlareUndo.h" -#include "LensFlareLightEntityTree.h" -#include "Controls/ReflectedPropertyControl/ReflectedPropertyCtrl.h" -#include "ui_DatabaseFrameWnd.h" -#include "LyViewPaneNames.h" - - - - -CLensFlareEditor* CLensFlareEditor::s_pLensFlareEditor = NULL; -const char* CLensFlareEditor::s_pLensFlareEditorClassName = LyViewPane::LensFlareEditor; - -#define DISABLE_REFERENCETREE - -CLensFlareEditor::CLensFlareEditor(QWidget* pParent) - : CDatabaseFrameWnd(GetIEditor()->GetLensFlareManager(), pParent) - , m_pLensFlareView(NULL) - , m_pLensFlareAtomicList(NULL) - , m_pLensFlareElementTree(NULL) - , m_pWndProps(NULL) - , m_pLensFlareLightEntityTree(NULL) - , m_pLensFlareReferenceTree(NULL) - , m_LensFlareItemTree(NULL) -{ - assert(!s_pLensFlareEditor); - s_pLensFlareEditor = this; - - m_pLensFlareView = new CLensFlareView(this); - m_pLensFlareAtomicList = new CLensFlareAtomicList(this); - m_pLensFlareElementTree = new CLensFlareElementTree(this); - m_pWndProps = new ReflectedPropertyControl(this); - m_pWndProps->Setup(); - m_pLensFlareLightEntityTree = new CLensFlareLightEntityTree(this); -#ifndef DISABLE_REFERENCETREE - m_pLensFlareReferenceTree = new CLensFlareReferenceTree; -#endif - m_LensFlareItemTree = new CLensFlareItemTree(this); - - m_pLibraryItemTreeModel = new LensFlareItemTreeModel(this); - m_LensFlareItemTree->setModel(m_pLibraryItemTreeModel); - - setCentralWidget(m_pLensFlareView); - - setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); - setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - m_advancedDockManager = new AzQtComponents::FancyDocking(this, "lensFlareEditor"); - - addDockWidget(Qt::LeftDockWidgetArea, m_LensFlareItemTree, tr("Lens Flare Tree"), false); - addDockWidget(Qt::LeftDockWidgetArea, m_pLensFlareElementTree, tr("Element Tree"), false); - - addDockWidget(Qt::BottomDockWidgetArea, m_pLensFlareAtomicList, tr("Basic Set"), false); -#ifndef DISABLE_REFERENCETREE - addDockWidget(Qt::TopDockWidgetArea, m_pLensFlareReferenceTree, tr("Reference Tree"), false); -#endif - - addDockWidget(Qt::RightDockWidgetArea, m_pWndProps, tr("Properties"), false); - addDockWidget(Qt::RightDockWidgetArea, m_pLensFlareLightEntityTree, tr("Light Entities"), false); - - m_pLensFlareElementTree->RegisterListener(this); - m_pLensFlareElementTree->RegisterListener(m_pLensFlareView); - - m_pWndProps->ExpandAll(); - m_pWndProps->SetUpdateCallback(AZStd::bind(&CLensFlareEditor::OnUpdateProperties, this, AZStd::placeholders::_1)); - m_pWndProps->SetCallbackOnNonModified(false); - - connect(ui->actionDBAdd, &QAction::triggered, this, &CLensFlareEditor::OnAddItem); - connect(ui->actionDBAssignToSelection, &QAction::triggered, this, &CLensFlareEditor::OnAssignFlareToLightEntities); - connect(ui->actionDBGetFromSelection, &QAction::triggered, this, &CLensFlareEditor::OnGetFlareFromSelection); - - connect(m_pLibraryItemTreeModel, &LibraryItemTreeModel::itemRenamed, this, &CLensFlareEditor::OnItemTreeDataRenamed); - - AzQtComponents::StyleManager::setStyleSheet(this, "style:LensFlareEditor.qss"); -} - -CLensFlareEditor::~CLensFlareEditor() -{ - if (m_pLensFlareElementTree) - { - m_pLensFlareElementTree->UnregisterListener(this); - m_pLensFlareElementTree->UnregisterListener(m_pLensFlareView); - } - - ReleaseWindowsToBePutIntoPanels(); - s_pLensFlareEditor = NULL; -} - -QMenu* CLensFlareEditor::createPopupMenu() -{ - return QMainWindow::createPopupMenu(); -} - -void CLensFlareEditor::OnInitDialog() -{ - InitTreeCtrl(); - - connect(m_LensFlareItemTree->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CLensFlareEditor::OnTvnItemSelChanged); - connect(m_LensFlareItemTree, &QWidget::customContextMenuRequested, this, &CLensFlareEditor::OnNotifyTreeRClick); - - m_pLensFlareAtomicList->FillAtomicItems(); - - ReloadLibs(); -} - -void CLensFlareEditor::addDockWidget(Qt::DockWidgetArea area, QWidget* widget, const QString& title, bool closable) -{ - QDockWidget* w = new AzQtComponents::StyledDockWidget(title); - w->setObjectName(widget->metaObject()->className()); - widget->setParent(w); - w->setWidget(widget); - if (!closable) - { - w->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); - } - QMainWindow::addDockWidget(area, w); -} - -void CLensFlareEditor::ReleaseWindowsToBePutIntoPanels() -{ - SAFE_DELETE(m_pWndProps); - SAFE_DELETE(m_pLensFlareAtomicList); - SAFE_DELETE(m_pLensFlareView); - SAFE_DELETE(m_pLensFlareElementTree); - SAFE_DELETE(m_pLensFlareLightEntityTree); -#ifndef DISABLE_REFERENCETREE - SAFE_DELETE(m_pLensFlareReferenceTree); -#endif -} - -const GUID& CLensFlareEditor::GetClassID() -{ - // {7e7a40e0-f0b8-4918-b94f-8cdd6c55f30b} - static const GUID guid = { - 0x7e7a40e0, 0xf0b8, 0x4918, { 0xb9, 0x4f, 0x8c, 0xdd, 0x6c, 0x55, 0xf3, 0x0b } - }; - return guid; -} - -void CLensFlareEditor::RegisterViewClass() -{ - AzToolsFramework::ViewPaneOptions options; - AzToolsFramework::RegisterViewPane(s_pLensFlareEditorClassName, LyViewPane::CategoryOther, options); - GetIEditor()->GetSettingsManager()->AddToolName("LensFlareEditor", "Lens Flare"); -} - -CLensFlareItem* CLensFlareEditor::GetSelectedLensFlareItem() const -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return nullptr; - } - return static_cast(selected.first().data(Qt::UserRole).value()); -} - -void CLensFlareEditor::ResetElementTreeControl() -{ - m_pLensFlareElementTree->InvalidateLensFlareItem(); -} - -void CLensFlareEditor::SelectItem(CBaseLibraryItem* item, bool bForceReload) -{ - if (item != m_pCurrentItem || bForceReload) - { - //Ensure that the property window is emptied out whenever the selected library changes - m_pWndProps->RemoveAllItems(); - } - - CDatabaseFrameWnd::SelectItem(item, bForceReload); -} - -void CLensFlareEditor::OnTvnItemSelChanged(const QItemSelection& selected, const QItemSelection& deselected) -{ - QModelIndex hItem; - - QModelIndexList selectedIndexes = selected.indexes(); - if (!selectedIndexes.isEmpty()) - { - hItem = selectedIndexes.first(); - } - - QModelIndex hPrevItem; - - QModelIndexList deselectedIndexes = deselected.indexes(); - if (!deselectedIndexes.isEmpty()) - { - hPrevItem = deselectedIndexes.first(); - } - - SelectLensFlareItem(hItem, hPrevItem); - UpdateLensFlareItem(GetSelectedLensFlareItem()); -} - -void CLensFlareEditor::SelectLensFlareItem(const QModelIndex& hItem, const QModelIndex& hPrevItem) -{ - if (hPrevItem.isValid() && CUndo::IsRecording()) - { - QString fullItemName = m_pLibraryItemTreeModel->GetFullName(hPrevItem); - if (!fullItemName.isEmpty()) - { - CUndo::Record(new CUndoLensFlareItemSelectionChange(fullItemName)); - } - } - m_pWndProps->RemoveAllItems(); - if (!hItem.isValid()) - { - return; - } - CLensFlareItem* pSelectedLensFlareItem = static_cast(hItem.data(Qt::UserRole).value()); - SelectItem(pSelectedLensFlareItem); -} - -void CLensFlareEditor::SelectLensFlareItem(const QModelIndex& hItem) -{ - QModelIndex hPrevItem; - - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (!selected.isEmpty()) - { - hPrevItem = selected.first(); - } - - SelectLensFlareItem(hItem, hPrevItem); -} - -void CLensFlareEditor::SelectLensFlareItem(const QString& fullItemName) -{ - QModelIndex hNewItem = m_pLibraryItemTreeModel->FindLibraryItemByFullName(fullItemName); - if (!hNewItem.isValid()) - { - return; - } - - SelectLensFlareItem(hNewItem); -} - -void CLensFlareEditor::RemovePropertyItems() -{ - m_pWndProps->RemoveAllItems(); -} - -bool CLensFlareEditor::IsExistTreeItem(const QString& name, bool bExclusiveSelectedItem) -{ - CBaseLibraryItem* pSelectedItem = GetSelectedLensFlareItem(); - - for (int i = 0; i < m_pLibrary->GetItemCount(); i++) - { - CBaseLibraryItem* pItem = static_cast(m_pLibrary->GetItem(i)); - - if (!bExclusiveSelectedItem || pItem != pSelectedItem) - { - if (pItem->GetName() == name) - { - return true; - } - } - } - - return false; -} - -void CLensFlareEditor::RenameLensFlareItem(CLensFlareItem* pLensFlareItem, const QString& newGroupName, const QString& newShortName) -{ - if (pLensFlareItem == NULL || newShortName.isEmpty() || newGroupName.isEmpty()) - { - return; - } - - m_pLibraryItemTreeModel->Rename(pLensFlareItem, newGroupName, newShortName); -} - -IOpticsElementBasePtr CLensFlareEditor::FindOptics(const QString& itemPath, const QString& opticsPath) -{ - CLensFlareItem* pItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(itemPath); - if (pItem == NULL) - { - return NULL; - } - - IOpticsElementBasePtr pOptics = pItem->GetOptics(); - if (pOptics == NULL) - { - return NULL; - } - - return LensFlareUtil::FindOptics(pOptics, opticsPath); -} - -void CLensFlareEditor::UpdateLensOpticsNames(const QString& oldFullName, const QString& newFullName) -{ - std::vector pEntityObjects; - GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, pEntityObjects); - for (int i = 0, iObjectSize(pEntityObjects.size()); i < iObjectSize; ++i) - { - CEntityObject* pEntity = (CEntityObject*)pEntityObjects[i]; - if (pEntity == NULL) - { - continue; - } - if (pEntity->CheckFlags(OBJFLAG_DELETED)) - { - continue; - } - if (!pEntity->IsLight()) - { - continue; - } - if (oldFullName == pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName)) - { - pEntity->SetOpticsName(newFullName); - } - } -} - -void CLensFlareEditor::OnCopy() -{ - UpdateClipboard(FLARECLIPBOARDTYPE_COPY); -} - -void CLensFlareEditor::OnPaste() -{ - if (!m_pLibrary) - { - return; - } - - CClipboard clipboard(this); - if (clipboard.IsEmpty()) - { - return; - } - - XmlNodeRef clipboardXML = clipboard.Get(); - if (clipboardXML == NULL) - { - return; - } - - Paste(clipboardXML); -} - -void CLensFlareEditor::Paste(XmlNodeRef node) -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - Paste(selected.first(), node); -} - -void CLensFlareEditor::Paste(const QModelIndex& hSelectedTreeItem, XmlNodeRef node) -{ - if (!m_pLibrary || node == NULL) - { - return; - } - - QString type; - node->getAttr("Type", type); - - QString sourceGroupName; - node->getAttr("GroupName", sourceGroupName); - - if (m_pLibrary == NULL) - { - return; - } - - bool bShouldCreateNewGroup(false); - if (!sourceGroupName.isEmpty()) - { - unsigned int nAnswer = CryMessageBox("Do you want to create a new group(YES) or add to the selected group(NO)?", "Question", MB_YESNOCANCEL); - if (nAnswer == IDCANCEL) - { - return; - } - bShouldCreateNewGroup = nAnswer == IDYES; - } - - QString targetGroupName; - - if (bShouldCreateNewGroup) - { - using namespace AZStd::placeholders; - targetGroupName = MakeValidName("NewGroup", AZStd::bind(&CDatabaseFrameWnd::DoesGroupExist, this, _1, _2)); - } - else - { - QModelIndex hTargetItem; - if (!m_pLibraryItemTreeModel->hasChildren(hSelectedTreeItem)) - { - hTargetItem = m_pLibraryItemTreeModel->parent(hSelectedTreeItem); - } - else - { - hTargetItem = hSelectedTreeItem; - } - - if (!hTargetItem.isValid()) - { - return; - } - - targetGroupName = m_pLibraryItemTreeModel->GetFullName(hTargetItem); - } - - CUndo undo(tr("Copy/Cut & Paste for Lens Flare").toUtf8()); - CLensFlareItem* pNewItem = NULL; - - for (int i = 0, iChildCount(node->getChildCount()); i < iChildCount; ++i) - { - LensFlareUtil::SClipboardData clipboardData; - clipboardData.FillThisFromXmlNode(node->getChild(i)); - - _smart_ptr pSourceItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(clipboardData.m_LensFlareFullPath); - if (pSourceItem == NULL) - { - continue; - } - - IOpticsElementBasePtr pSourceOptics = FindOptics(clipboardData.m_LensFlareFullPath, clipboardData.m_LensOpticsPath); - if (pSourceOptics == NULL) - { - continue; - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (clipboardData.m_From == LENSFLARE_ELEMENT_TREE) - { - LensFlareUtil::RemoveOptics(pSourceOptics); - } - else - { - DeleteItem(pSourceItem); - } - } - - QString sourceName; - if (clipboardData.m_From == LENSFLARE_ELEMENT_TREE) - { - sourceName = LensFlareUtil::GetShortName(pSourceOptics->GetName().c_str()); - } - else - { - sourceName = pSourceItem->GetShortName(); - } - - QString candidateName = targetGroupName + QString(".") + sourceName; - QString validName = MakeValidName(candidateName, - AZStd::bind(&CDatabaseFrameWnd::DoesItemExist, this, AZStd::placeholders::_1, AZStd::placeholders::_2)); - QString validShortName = LensFlareUtil::GetShortName(validName); - pNewItem = AddNewLensFlareItem(targetGroupName, validShortName); - assert(pNewItem); - if (pNewItem == NULL) - { - continue; - } - - if (LensFlareUtil::IsGroup(pSourceOptics->GetType())) - { - LensFlareUtil::CopyOptics(pSourceOptics, pNewItem->GetOptics(), true); - } - else - { - IOpticsElementBasePtr pNewOptics = LensFlareUtil::CreateOptics(pSourceOptics); - if (pNewOptics) - { - pNewItem->GetOptics()->AddElement(pNewOptics); - } - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (clipboardData.m_From == LENSFLARE_ITEM_TREE) - { - UpdateLensOpticsNames(pSourceItem->GetFullName(), pNewItem->GetFullName()); - } - if (pSourceItem != GetSelectedLensFlareItem()) - { - pSourceItem->UpdateLights(); - } - } - - LensFlareUtil::UpdateOpticsName(pNewItem->GetOptics()); - LensFlareUtil::ChangeOpticsRootName(pNewItem->GetOptics(), validShortName); - - ReloadItems(); - SelectLensFlareItem(m_pLibraryItemTreeModel->index(pNewItem), {}); - } -} - -void CLensFlareEditor::OnCut() -{ - UpdateClipboard(FLARECLIPBOARDTYPE_CUT); -} - -XmlNodeRef CLensFlareEditor::CreateXML(const char* type) const -{ - std::vector clipboardDataList; - QString groupName; - if (!GetClipboardDataList(clipboardDataList, groupName)) - { - return NULL; - } - return LensFlareUtil::CreateXMLFromClipboardData(type, groupName, false, clipboardDataList); -} - -void CLensFlareEditor::UpdateClipboard(const char* type) const -{ - std::vector clipboardDataList; - QString groupName; - if (!GetClipboardDataList(clipboardDataList, groupName)) - { - return; - } - LensFlareUtil::UpdateClipboard(type, groupName, false, clipboardDataList); -} - -bool CLensFlareEditor::GetClipboardDataList(std::vector& outList, QString& outGroupName) const -{ - CLensFlareLibrary* pLibrary = GetCurrentLibrary(); - if (pLibrary == NULL) - { - return false; - } - - std::vector clipboardDataList; - - CLensFlareItem* pLensFlareItem = GetSelectedLensFlareItem(); - if (pLensFlareItem) - { - clipboardDataList.push_back(LensFlareUtil::SClipboardData(LENSFLARE_ITEM_TREE, pLensFlareItem->GetFullName(), pLensFlareItem->GetShortName())); - } - else if (GetSelectedItemStatus() == eSIS_Group) - { - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return false; - } - outGroupName = selected.first().data(Qt::DisplayRole).toString(); - for (CBaseLibraryItem* pItem : m_pLibraryItemTreeModel->ChildItems(selected.first())) - { - pLensFlareItem = static_cast(pItem); - clipboardDataList.push_back(LensFlareUtil::SClipboardData(LENSFLARE_ITEM_TREE, pLensFlareItem->GetFullName(), pLensFlareItem->GetShortName())); - } - } - else - { - return false; - } - - outList = clipboardDataList; - - return true; -} - -void CLensFlareEditor::OnAddItem() -{ - if (!m_pLibrary) - { - return; - } - - StringGroupDlg dlg(tr("New Flare Name"), this); - dlg.SetGroup(m_selectedGroup); - - if (dlg.exec() != QDialog::Accepted || dlg.GetString().isEmpty()) - { - return; - } - - QString fullName = m_pItemManager->MakeFullItemName(m_pLibrary, dlg.GetGroup(), dlg.GetString()); - if (m_pItemManager->FindItemByName(fullName)) - { - Warning("Item with name %s already exist", fullName.toUtf8().data()); - return; - } - - CUndo undo(tr("Add flare library item").toUtf8()); - - CLensFlareItem* pNewLensFlare = AddNewLensFlareItem(dlg.GetGroup(), dlg.GetString()); - if (pNewLensFlare) - { - m_pLibraryItemTreeModel->Add(pNewLensFlare); - SelectItem(pNewLensFlare); - } -} - -CLensFlareItem* CLensFlareEditor::AddNewLensFlareItem(const QString& groupName, const QString& shortName) -{ - CLensFlareItem* pNewFlare = (CLensFlareItem*)m_pItemManager->CreateItem(m_pLibrary); - if (pNewFlare == NULL) - { - return NULL; - } - if (!SetItemName(pNewFlare, groupName, shortName)) - { - m_pItemManager->DeleteItem(pNewFlare); - return NULL; - } - pNewFlare->GetOptics()->SetName(pNewFlare->GetShortName().toUtf8().data()); - return pNewFlare; -} - -QModelIndex CLensFlareEditor::GetTreeLensFlareItem(CLensFlareItem* pItem) const -{ - return m_pLibraryItemTreeModel->index(pItem); -} - -void CLensFlareEditor::OnCopyNameToClipboard() -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - QString itemName = m_pLibraryItemTreeModel->GetFullName(selected.first()); - CClipboard clipboard(this); - clipboard.PutString(itemName); -} - -void CLensFlareEditor::OnAssignFlareToLightEntities() -{ - CLensFlareItem* pLensFlareItem = GetSelectedLensFlareItem(); - if (pLensFlareItem == NULL) - { - return; - } - std::vector entityList; - LensFlareUtil::GetSelectedLightEntities(entityList); - - for (int i = 0, iEntityCount(entityList.size()); i < iEntityCount; ++i) - { - entityList[i]->ApplyOptics(pLensFlareItem->GetFullName(), pLensFlareItem->GetOptics()); - } - - m_pLensFlareLightEntityTree->OnLensFlareChangeItem(pLensFlareItem); -} - -void CLensFlareEditor::OnSelectAssignedObjects() -{ - std::vector lightEntities; - LensFlareUtil::GetLightEntityObjects(lightEntities); - - CLensFlareItem* pLensFlareItem = GetSelectedLensFlareItem(); - if (pLensFlareItem == NULL) - { - return; - } - - int iLightSize(lightEntities.size()); - std::vector assignedObjects; - assignedObjects.reserve(iLightSize); - - for (int i = 0; i < iLightSize; ++i) - { - CEntityObject* pLightEntity = lightEntities[i]; - if (pLightEntity == NULL) - { - continue; - } - - IOpticsElementBasePtr pTargetOptics = pLightEntity->GetOpticsElement(); - if (pTargetOptics == NULL) - { - continue; - } - - if (QString::compare(pLensFlareItem->GetFullName(), pTargetOptics->GetName().c_str(), Qt::CaseInsensitive)) - { - continue; - } - - assignedObjects.push_back(pLightEntity); - } - - if (assignedObjects.empty()) - { - return; - } - - GetIEditor()->ClearSelection(); - for (int i = 0, iAssignedObjectsSize(assignedObjects.size()); i < iAssignedObjectsSize; ++i) - { - GetIEditor()->SelectObject(assignedObjects[i]); - } -} - -void CLensFlareEditor::OnGetFlareFromSelection() -{ - CEntityObject* pEntity = LensFlareUtil::GetSelectedLightEntity(); - if (pEntity == NULL) - { - QMessageBox::warning(this, tr("Warning"), tr("Please select a light entity first.")); - return; - } - if (m_pLibrary == NULL) - { - return; - } - - QString fullFlareName = pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName); - int nDotPosition = fullFlareName.indexOf("."); - if (nDotPosition == -1) - { - return; - } - - QString libraryName = fullFlareName.left(nDotPosition); - if (m_pLibrary->GetName() != libraryName) - { - GetIEditor()->GetLensFlareManager()->LoadItemByName(fullFlareName); - SelectLibrary(libraryName); - } - - SelectItemByName(fullFlareName); -} - -void CLensFlareEditor::OnUpdateTreeCtrl() -{ - OnGetFlareFromSelection(); -} - -void CLensFlareEditor::OnNotifyTreeRClick() -{ - CLensFlareItem* pLensFlareItem = 0; - - QModelIndex hItem = LensFlareUtil::GetTreeItemByHitTest(*GetTreeCtrl()); - if (hItem.isValid()) - { - pLensFlareItem = static_cast(hItem.data(Qt::UserRole).value()); - } - - SelectItem(pLensFlareItem); - - bool bGrayedFlag = false; - if (!pLensFlareItem) - { - bGrayedFlag = true; - } - - CClipboard clipboard(this); - bool bPasteFlags = true; - if (clipboard.IsEmpty()) - { - bPasteFlags = false; - } - - bool bCopyPasteCloneFlag = true; - if (GetSelectedItemStatus() != eSIS_Flare && GetSelectedItemStatus() != eSIS_Group) - { - bCopyPasteCloneFlag = false; - } - - QMenu menu; - - QAction* actionDBCut = menu.addAction(tr("Cut")); - actionDBCut->setEnabled(bCopyPasteCloneFlag); - connect(actionDBCut, &QAction::triggered, this, &CLensFlareEditor::OnCut); - - QAction* actionDBCopy = menu.addAction(tr("Copy")); - actionDBCopy->setEnabled(bCopyPasteCloneFlag); - connect(actionDBCopy, &QAction::triggered, this, &CLensFlareEditor::OnCopy); - - QAction* actionDBPaste = menu.addAction(tr("Paste")); - actionDBPaste->setEnabled(bPasteFlags); - connect(actionDBPaste, &QAction::triggered, this, &CLensFlareEditor::OnPaste); - - QAction* actionDBClone = menu.addAction(tr("Clone")); - actionDBClone->setEnabled(bCopyPasteCloneFlag); - connect(actionDBClone, &QAction::triggered, this, &CLensFlareEditor::OnClone); - - menu.addSeparator(); - - QAction* actionDBRename = menu.addAction(tr("Rename\tF2")); - connect(actionDBRename, &QAction::triggered, this, &CLensFlareEditor::OnRenameItem); - - QAction* actionDBRemove = menu.addAction(tr("Delete\tDel")); - connect(actionDBRemove, &QAction::triggered, this, &CLensFlareEditor::OnRemoveItem); - - menu.addSeparator(); - - QAction* actionDBAssignToSelection = menu.addAction(tr("Assign to Selected Objects")); - actionDBAssignToSelection->setEnabled(!bGrayedFlag); - connect(actionDBAssignToSelection, &QAction::triggered, this, &CLensFlareEditor::OnAssignFlareToLightEntities); - - QAction* actionDBSelectAssignedObjects = menu.addAction(tr("Select Assigned Objects")); - actionDBSelectAssignedObjects->setEnabled(!bGrayedFlag); - connect(actionDBSelectAssignedObjects, &QAction::triggered, this, &CLensFlareEditor::OnSelectAssignedObjects); - - QAction* actionDBCopyNameToClipboard = menu.addAction(tr("Copy Name to ClipBoard")); - connect(actionDBCopyNameToClipboard, &QAction::triggered, this, &CLensFlareEditor::OnCopyNameToClipboard); - - menu.exec(QCursor::pos()); -} - -bool CLensFlareEditor::SelectItemByName(const QString& itemName) -{ - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(itemName); - if (pLensFlareItem == NULL) - { - return false; - } - - GetIEditor()->GetLensFlareManager()->SetSelectedItem(pLensFlareItem); - - SelectLensFlareItem(m_pLibraryItemTreeModel->index(pLensFlareItem)); - - return true; -} - - -void CLensFlareEditor::StartEditItem(const QModelIndex& hItem) -{ - if (!hItem.isValid()) - { - return; - } - GetTreeCtrl()->edit(hItem); -} - -bool CLensFlareEditor::GetFullLensFlareItemName(const QModelIndex& hItem, QString& outFullName) const -{ - if (!hItem.isValid()) - { - return false; - } - - outFullName = m_pLibraryItemTreeModel->GetFullName(hItem); - - return true; -} - -CLensFlareEditor::ESelectedItemStatus CLensFlareEditor::GetSelectedItemStatus() const -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return eSIS_Unselected; - } - if (m_pLibraryItemTreeModel->hasChildren(selected.first())) - { - return eSIS_Group; - } - return eSIS_Flare; -} - -void CLensFlareEditor::SelectItemInLensFlareElementTreeByName(const QString& name) -{ - m_pLensFlareElementTree->SelectTreeItemByName(name); -} - -bool CLensFlareEditor::GetSelectedLensFlareName(QString& outName) const -{ - const CLensFlareElement* pElement = m_pLensFlareElementTree->GetCurrentLensFlareElement(); - if (pElement == NULL) - { - return false; - } - return pElement->GetName(outName); -} - -void CLensFlareEditor::ReloadItems() -{ - CDatabaseFrameWnd::ReloadItems(); - ResetElementTreeControl(); -} - -void CLensFlareEditor::OnRemoveItem() -{ - CLensFlareItem* pSelectedLensFlareItem = GetSelectedLensFlareItem(); - CUndo undo(tr("Remove Flare Group Item").toUtf8()); - - if (pSelectedLensFlareItem == NULL) - { - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex hLensFlareItem = selected.first(); - - QString fullLensFlareItemName = m_pLibraryItemTreeModel->GetFullName(hLensFlareItem); - - if (!fullLensFlareItemName.isEmpty()) - { - QString deleteMsgStr = tr("Delete %1?").arg(fullLensFlareItemName); - if (QMessageBox::question(this, tr("Confirmation"), deleteMsgStr) == QMessageBox::Yes) - { - CLensFlareLibrary* pLensFlareLibrary = GetCurrentLibrary(); - if (pLensFlareLibrary) - { - std::vector< _smart_ptr > deletedItems; - for (int i = 0, iItemCount(pLensFlareLibrary->GetItemCount()); i < iItemCount; ++i) - { - CLensFlareItem* pItem = (CLensFlareItem*)pLensFlareLibrary->GetItem(i); - if (pItem == NULL) - { - continue; - } - if (pItem->GetName().indexOf(fullLensFlareItemName) == -1) - { - continue; - } - QModelIndex hFlareItem = m_pLibraryItemTreeModel->index(pItem); - if (hFlareItem.isValid()) - { - UpdateLensOpticsNames(pItem->GetFullName(), ""); - deletedItems.push_back(pItem); - } - } - for (int i = 0, iDeleteItemSize(deletedItems.size()); i < iDeleteItemSize; ++i) - { - m_pLensFlareLightEntityTree->OnLensFlareDeleteItem(deletedItems[i]); - DeleteItem(deletedItems[i]); - } - - m_pLibraryItemTreeModel->removeRow(hLensFlareItem.row(), hLensFlareItem.parent()); - } - GetIEditor()->SetModifiedFlag(); - } - } - } - else - { - QString deleteMsgStr = tr("Delete %1?").arg(pSelectedLensFlareItem->GetName()); - // Remove prototype from prototype manager and library. - if (QMessageBox::question(this, tr("Confirmation"), deleteMsgStr) == QMessageBox::Yes) - { - m_pLensFlareLightEntityTree->OnLensFlareDeleteItem(pSelectedLensFlareItem); - - DeleteItem(pSelectedLensFlareItem); - - UpdateLensOpticsNames(pSelectedLensFlareItem->GetFullName(), ""); - - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (!selected.isEmpty()) - { - QModelIndex hLensFlareItem = selected.first(); - m_pLibraryItemTreeModel->removeRow(hLensFlareItem.row(), hLensFlareItem.parent()); - } - - m_pCurrentItem = NULL; - - GetIEditor()->SetModifiedFlag(); - SelectItem(0); - } - } -} - -void CLensFlareEditor::OnAddLibrary() -{ - StringDlg dlg(tr("Library Name"), this); - - dlg.SetCheckCallback([this](QString library) -> bool - { - QString path = m_pItemManager->MakeFilename(library); - if (CFileUtil::FileExists(path)) - { - QMessageBox::warning(this, tr("Library exists"), tr("Library '%1' already exists.").arg(library)); - return false; - } - return true; - }); - - if (dlg.exec() == QDialog::Accepted) - { - if (!dlg.GetString().isEmpty()) - { - SelectItem(0); - // Make new library. - QString library = dlg.GetString(); - NewLibrary(library); - ReloadLibs(); - SelectLibrary(library); - GetIEditor()->SetModifiedFlag(); - } - } -} - -void CLensFlareEditor::OnRenameItem() -{ - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - StartEditItem(selected.first()); -} - -void CLensFlareEditor::OnReloadLib() -{ - CDatabaseFrameWnd::OnReloadLib(); - CLensFlareLibrary* pLibrary = GetCurrentLibrary(); - if (pLibrary == NULL) - { - return; - } - for (int i = 0, iItemCount(pLibrary->GetItemCount()); i < iItemCount; ++i) - { - CLensFlareItem* pItem = (CLensFlareItem*)pLibrary->GetItem(i); - if (pItem == NULL) - { - continue; - } - pItem->UpdateLights(NULL); - } -} - -void CLensFlareEditor::RegisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener) -{ - for (int i = 0, iSize(m_LensFlareChangeItemListenerList.size()); i < iSize; ++i) - { - if (m_LensFlareChangeItemListenerList[i] == pListener) - { - return; - } - } - m_LensFlareChangeItemListenerList.push_back(pListener); -} - -void CLensFlareEditor::UnregisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener) -{ - auto iter = m_LensFlareChangeItemListenerList.begin(); - for (; iter != m_LensFlareChangeItemListenerList.end(); ++iter) - { - if (*iter == pListener) - { - m_LensFlareChangeItemListenerList.erase(iter); - return; - } - } -} - -void CLensFlareEditor::OnItemTreeDataRenamed(CBaseLibraryItem* pItem, const QString& prevFullName) -{ - CLensFlareItem* pLensFlareItem = static_cast(pItem); - - UpdateLensOpticsNames(prevFullName, pLensFlareItem->GetFullName()); - LensFlareUtil::ChangeOpticsRootName(pLensFlareItem->GetOptics(), pLensFlareItem->GetShortName()); - - if (pLensFlareItem == GetSelectedLensFlareItem()) - { - UpdateLensFlareItem(pLensFlareItem); - } - - GetIEditor()->GetLensFlareManager()->Modified(); -} - -void CLensFlareEditor::UpdateLensFlareItem(CLensFlareItem* pLensFlareItem) -{ - for (int i = 0, iSize(m_LensFlareChangeItemListenerList.size()); i < iSize; ++i) - { - m_LensFlareChangeItemListenerList[i]->OnLensFlareChangeItem(pLensFlareItem); - } -} - -void CLensFlareEditor::OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement) -{ - ReflectedPropertyControl* pPropertyCtrl = m_pWndProps; - pPropertyCtrl->RemoveAllItems(); - - if (pLensFlareElement == NULL) - { - return; - } - - // Update properties in a property panel - if (pLensFlareElement && pLensFlareElement->GetProperties()) - { - pPropertyCtrl->AddVarBlock(pLensFlareElement->GetProperties()); - pPropertyCtrl->ExpandAllChildren(pPropertyCtrl->GetRootItem(), false); - pPropertyCtrl->setEnabled(true); - } -} - -void CLensFlareEditor::AddNewItemByAtomicOptics(const QModelIndex& hSelectedItem, EFlareType flareType) -{ - if (!LensFlareUtil::IsValidFlare(flareType)) - { - return; - } - - QString groupName; - QModelIndex hParentItem = hSelectedItem.parent(); - if (hParentItem.isValid()) - { - groupName = hParentItem.data(Qt::DisplayRole).toString(); - } - else - { - groupName = hSelectedItem.data(Qt::DisplayRole).toString(); - } - - FlareInfoArray::Props flareProps = FlareInfoArray::Get(); - QString itemName = MakeValidName(groupName + QString(".") + flareProps.p[flareType].name, - AZStd::bind(&CDatabaseFrameWnd::DoesItemExist, this, AZStd::placeholders::_1, AZStd::placeholders::_2)); - CLensFlareItem* pNewItem = AddNewLensFlareItem(groupName, LensFlareUtil::GetShortName(itemName)); - - if (pNewItem) - { - pNewItem->GetOptics()->AddElement(gEnv->pOpticsManager->Create(flareType)); - ReloadItems(); - SelectLensFlareItem(GetTreeLensFlareItem(pNewItem), {}); - } -} - -void CLensFlareEditor::OnUpdateProperties([[maybe_unused]] IVariable* var) -{ - GetIEditor()->GetLensFlareManager()->Modified(); -} - -AssetSelectionModel CLensFlareEditor::GetAssetSelectionModel() const -{ - return AssetSelectionModel::AssetTypeSelection(AZ::AzTypeInfo::Uuid()); -} - -LensFlareItemTreeModel::LensFlareItemTreeModel(CDatabaseFrameWnd* pParent) - : LibraryItemTreeModel(pParent) -{ -} - -QStringList LensFlareItemTreeModel::mimeTypes() const -{ - QStringList mimeTypes = LibraryItemTreeModel::mimeTypes(); - mimeTypes << QStringLiteral("application/x-o3de-flaretypes"); - return mimeTypes; -} - -bool LensFlareItemTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) -{ - if (LibraryItemTreeModel::dropMimeData(data, action, row, column, parent)) - { - return true; - } - - if (data->hasFormat(QStringLiteral("application/x-o3de-flaretypes"))) - { - QByteArray encoded = data->data(QStringLiteral("application/x-o3de-flaretypes")); - QDataStream stream(&encoded, QIODevice::ReadOnly); - - while (!stream.atEnd()) - { - int flareType; - stream >> flareType; - static_cast(m_dialog)->AddNewItemByAtomicOptics(parent, static_cast(flareType)); - } - - return true; - } - - return false; -} - -Qt::ItemFlags LensFlareItemTreeModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return Qt::ItemFlags(); - } - - return LibraryItemTreeModel::flags(index) | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; -} - -Qt::DropActions LensFlareItemTreeModel::supportedDragActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -Qt::DropActions LensFlareItemTreeModel::supportedDropActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.h deleted file mode 100644 index d5753fa332..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareEditor.h +++ /dev/null @@ -1,233 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREEDITOR_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREEDITOR_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "DatabaseFrameWnd.h" -#include "LensFlareUtil.h" -#include "ILensFlareListener.h" -#include "LensFlareItemTree.h" -#include "UserMessageDefines.h" -#endif - -#include - -namespace AzQtComponents -{ - class FancyDocking; -} - -class CLensFlareView; -class CLensFlareElementTree; -class CLensFlareAtomicList; -class CLensFlareElementPropertyView; -class CLensFlareItem; -class CLensFlareLibrary; -class ReflectedPropertyControl; -class CLensFlareLightEntityTree; -class CLensFlareReferenceTree; - -class CLensFlareEditor - : public CDatabaseFrameWnd - , public ILensFlareChangeElementListener -{ - Q_OBJECT - -public: - static const GUID& GetClassID(); - static void RegisterViewClass(); - - CLensFlareEditor(QWidget* pParent = nullptr); - ~CLensFlareEditor(); - - QMenu* createPopupMenu() override; - - // CDatabaseFrameWnd overrides... - virtual void SelectItem(CBaseLibraryItem* item, bool bForceReload = false) override; - - CLensFlareItem* GetSelectedLensFlareItem() const; - bool GetSelectedLensFlareName(QString& outName) const; - void UpdateLensFlareItem(CLensFlareItem* pLensFlareItem); - void ResetElementTreeControl(); - - CLensFlareLibrary* GetCurrentLibrary() const - { - if (m_pLibrary == NULL) - { - return NULL; - } - return (CLensFlareLibrary*)&(*m_pLibrary); - } - - bool IsExistTreeItem(const QString& name, bool bExclusiveSelectedItem = false); - void RenameLensFlareItem(CLensFlareItem* pLensFlareItem, const QString& newGroupName, const QString& newShortName); - - IOpticsElementBasePtr FindOptics(const QString& itemPath, const QString& opticsPath); - - CLensFlareElementTree* GetLensFlareElementTree() - { - return m_pLensFlareElementTree; - } - - CLensFlareView* GetLensFlareView() const - { - return m_pLensFlareView; - } - - CLensFlareItemTree* GetLensFlareItemTree() - { - return m_LensFlareItemTree; - } - - void RemovePropertyItems(); - - ReflectedPropertyControl* GetPropertyCtrl() - { - return m_pWndProps; - } - - void UpdateLensOpticsNames(const QString& oldFullName, const QString& newFullName); - void SelectItemInLensFlareElementTreeByName(const QString& name); - void ReloadItems(); - - void RegisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener); - void UnregisterLensFlareItemChangeListener(ILensFlareChangeItemListener* pListener); - - bool SelectItemByName(const QString& itemName); - - static CLensFlareEditor* GetLensFlareEditor() - { - return s_pLensFlareEditor; - } - - bool GetFullSelectedFlareItemName(QString& outFullName) const - { - QModelIndexList selected = GetTreeCtrl()->selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return false; - } - return GetFullLensFlareItemName(selected.first(), outFullName); - } - - void SelectLensFlareItem(const QString& fullItemName); - - const char* GetClassName() - { - return s_pLensFlareEditorClassName; - } - - void Paste(XmlNodeRef node); - void Paste(const QModelIndex& index, XmlNodeRef node); - XmlNodeRef CreateXML(const char* type) const; - - static const char* s_pLensFlareEditorClassName; - - QTreeView* GetTreeCtrl() override - { - return m_LensFlareItemTree; - } - - const QTreeView* GetTreeCtrl() const override - { - return m_LensFlareItemTree; - } - - void AddNewItemByAtomicOptics(const QModelIndex& hSelectedItem, EFlareType flareType); - -public slots: - void OnUpdateTreeCtrl(); - -protected: - static CLensFlareEditor* s_pLensFlareEditor; - - void OnInitDialog() override; - - void OnCopy(); - void OnPaste(); - void OnCut(); - - void UpdateClipboard(const char* type) const; - bool GetClipboardDataList(std::vector& outList, QString& outGroupName) const; - void OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement); - - void OnAddLibrary(); - void OnAssignFlareToLightEntities(); - void OnSelectAssignedObjects(); - void OnGetFlareFromSelection(); - void OnRenameItem(); - void OnAddItem(); - void OnRemoveItem(); - void OnCopyNameToClipboard(); - void OnNotifyTreeRClick(); - - void OnTvnItemSelChanged(const QItemSelection& selected, const QItemSelection& deselected); - void OnReloadLib(); - void ReleaseWindowsToBePutIntoPanels(); - void SelectLensFlareItem(const QModelIndex& hItem); - void SelectLensFlareItem(const QModelIndex& hItem, const QModelIndex& hPrevItem); - - void StartEditItem(const QModelIndex& hItem); - bool GetFullLensFlareItemName(const QModelIndex& hItem, QString& outFullName) const; - AssetSelectionModel GetAssetSelectionModel() const override; - - CLensFlareItem* AddNewLensFlareItem(const QString& groupName, const QString& shortName); - QModelIndex GetTreeLensFlareItem(CLensFlareItem* pItem) const; - - void OnItemTreeDataRenamed(CBaseLibraryItem* pItem, const QString& prevFullName); - - enum ESelectedItemStatus - { - eSIS_Unselected, - eSIS_Group, - eSIS_Flare - }; - ESelectedItemStatus GetSelectedItemStatus() const; - - void addDockWidget(Qt::DockWidgetArea area, QWidget* widget, const QString& title, bool closable = true); - void OnUpdateProperties(IVariable* var); - -private: - - CLensFlareView* m_pLensFlareView; - CLensFlareAtomicList* m_pLensFlareAtomicList; - CLensFlareElementTree* m_pLensFlareElementTree; - ReflectedPropertyControl* m_pWndProps; - CLensFlareLightEntityTree* m_pLensFlareLightEntityTree; - CLensFlareReferenceTree* m_pLensFlareReferenceTree; - CLensFlareItemTree* m_LensFlareItemTree; - - std::vector m_LensFlareChangeItemListenerList; - AzQtComponents::FancyDocking* m_advancedDockManager = nullptr; -}; - -class LensFlareItemTreeModel - : public LibraryItemTreeModel -{ - Q_OBJECT - -public: - LensFlareItemTreeModel(CDatabaseFrameWnd* pParent); - - Qt::ItemFlags flags(const QModelIndex& index) const override; - - QStringList mimeTypes() const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - Qt::DropActions supportedDragActions() const override; - Qt::DropActions supportedDropActions() const override; -}; - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREEDITOR_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.cpp deleted file mode 100644 index a51c788a8b..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareElement.h" - -// Editor -#include "LensFlareElementTree.h" -#include "LensFlareUtil.h" -#include "LensFlareItem.h" -#include "LensFlareEditor.h" -#include "LensFlareView.h" -#include "LensFlareLibrary.h" - - -CLensFlareElement::CLensFlareElement() - : m_vars(NULL) - , m_pOpticsElement(NULL) - , m_pParent(NULL) -{ -} - -CLensFlareElement::~CLensFlareElement() -{ -} - -void CLensFlareElement::OnInternalVariableChange(IVariable* pVar) -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return; - } - - IFuncVariable* pFuncVar = LensFlareUtil::GetFuncVariable(pOptics, pVar->GetUserData().toInt()); - if (pFuncVar == NULL) - { - return; - } - - switch (pVar->GetType()) - { - case IVariable::INT: - { - int var(0); - pVar->Get(var); - if (pFuncVar->paramType == e_COLOR) - { - ColorF color(pFuncVar->GetColorF()); - color.a = (float)var / 255.0f; - pFuncVar->InvokeSetter((void*)&color); - } - else if (pFuncVar->paramType == e_INT) - { - if (LensFlareUtil::HaveParameterLowBoundary(pFuncVar->name.c_str())) - { - LensFlareUtil::BoundaryProcess(var); - } - pFuncVar->InvokeSetter((void*)&var); - if (pFuncVar->GetInt() != var) - { - pVar->Set(pFuncVar->GetInt()); - } - } - } - break; - case IVariable::BOOL: - { - if (pFuncVar->paramType == e_BOOL) - { - bool var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::FLOAT: - { - if (pFuncVar->paramType == e_FLOAT) - { - float var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::VECTOR2: - { - if (pFuncVar->paramType == e_VEC2) - { - Vec2 var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::VECTOR: - { - Vec3 var; - pVar->Get(var); - if (pFuncVar->paramType == e_COLOR) - { - ColorF color(pFuncVar->GetColorF()); - color.r = var.x; - color.g = var.y; - color.b = var.z; - pFuncVar->InvokeSetter((void*)&color); - } - else if (pFuncVar->paramType == e_VEC3) - { - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::VECTOR4: - { - if (pFuncVar->paramType == e_VEC4) - { - Vec4 var; - pVar->Get(var); - pFuncVar->InvokeSetter((void*)&var); - } - } - break; - case IVariable::STRING: - { - QString var; - pVar->Get(var); - if (pFuncVar->paramType == e_TEXTURE2D || pFuncVar->paramType == e_TEXTURE3D || pFuncVar->paramType == e_TEXTURE_CUBE) - { - var = var.trimmed(); - ITexture* pTexture = NULL; - if (!var.isEmpty()) - { - pTexture = GetIEditor()->GetRenderer()->EF_LoadTexture(var.toUtf8().data()); - } - pFuncVar->InvokeSetter((void*)pTexture); - if (pTexture) - { - pTexture->Release(); - } - } - } - break; - } - - UpdateLights(); -} - -bool CLensFlareElement::IsEnable() -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return false; - } - return pOptics->IsEnabled(); -} - -void CLensFlareElement::SetEnable(bool bEnable) -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return; - } - pOptics->SetEnabled(bEnable); - UpdateLights(); -} - -EFlareType CLensFlareElement::GetOpticsType() -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return eFT__Base__; - } - return pOptics->GetType(); -} - -bool CLensFlareElement::GetShortName(QString& outName) const -{ - QString fullName; - if (!GetName(fullName)) - { - return false; - } - int nPos = fullName.lastIndexOf('.'); - if (nPos == -1) - { - outName = fullName; - return true; - } - outName = fullName.right(fullName.length() - nPos - 1); - return true; -} - -void CLensFlareElement::UpdateLights() -{ - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return; - } - if (GetLensFlareTree()) - { - if (GetLensFlareTree()->GetLensFlareItem()) - { - GetLensFlareTree()->GetLensFlareItem()->UpdateLights(pOptics); - } - } -} - -void CLensFlareElement::UpdateProperty(IOpticsElementBasePtr pOptics) -{ - std::vector funcs; - - if (CLensFlareElementTree* lensFlareTree = GetLensFlareTree(); lensFlareTree) - { - auto callbackItr = m_callbackCache.find(lensFlareTree); - if (callbackItr == m_callbackCache.end()) - { - IVariable::OnSetCallback callback = - AZStd::bind(&CLensFlareElementTree::OnInternalVariableChange, lensFlareTree, AZStd::placeholders::_1); - - auto result = m_callbackCache.insert(AZStd::make_pair(lensFlareTree, callback)); - callbackItr = result.first; - } - - funcs.push_back(&(callbackItr->second)); - } - - if (CLensFlareView* lensFlareView = GetLensFlareView(); lensFlareView) - { - auto callbackItr = m_callbackCache.find(lensFlareView); - if (callbackItr == m_callbackCache.end()) - { - IVariable::OnSetCallback callback = - AZStd::bind(&CLensFlareView::OnInternalVariableChange, lensFlareView, AZStd::placeholders::_1); - - auto result = m_callbackCache.insert(AZStd::make_pair(lensFlareView, callback)); - callbackItr = result.first; - } - - funcs.push_back(&(callbackItr->second)); - } - - if (CLensFlareLibrary* lensFlareLibrary = GetLensFlareLibrary(); lensFlareLibrary) - { - auto callbackItr = m_callbackCache.find(lensFlareLibrary); - if (callbackItr == m_callbackCache.end()) - { - IVariable::OnSetCallback callback = - AZStd::bind(&CLensFlareLibrary::OnInternalVariableChange, lensFlareLibrary, AZStd::placeholders::_1); - - auto result = m_callbackCache.insert(AZStd::make_pair(lensFlareLibrary, callback)); - callbackItr = result.first; - } - - funcs.push_back(&(callbackItr->second)); - } - - LensFlareUtil::SetVariablesTemplateFromOptics(pOptics, m_vars, funcs); -} - -CLensFlareElementTree* CLensFlareElement::GetLensFlareTree() const -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return NULL; - } - return pEditor->GetLensFlareElementTree(); -} - -CLensFlareView* CLensFlareElement::GetLensFlareView() const -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return NULL; - } - return pEditor->GetLensFlareView(); -} - -CLensFlareLibrary* CLensFlareElement::GetLensFlareLibrary() const -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return NULL; - } - return pEditor->GetCurrentLibrary(); -} - -CLensFlareElement* CLensFlareElement::GetParent() const -{ - return m_pParent; -} - -void CLensFlareElement::SetParent(CLensFlareElement* pParent) -{ - m_pParent = pParent; -} - -int CLensFlareElement::GetChildCount() const -{ - return m_children.size(); -} - -CLensFlareElement* CLensFlareElement::GetChildAt(int nPos) const -{ - if (nPos < 0 || nPos >= m_children.size()) - { - return nullptr; - } - return m_children[nPos]; -} - -void CLensFlareElement::AddChild(CLensFlareElement* pElement) -{ - pElement->SetParent(this); - m_children.push_back(pElement); -} - -void CLensFlareElement::InsertChild(int nPos, CLensFlareElement* pElement) -{ - pElement->SetParent(this); - m_children.insert(std::begin(m_children) + nPos, pElement); -} - -void CLensFlareElement::RemoveChild(int nPos) -{ - m_children.erase(std::begin(m_children) + nPos); -} - -void CLensFlareElement::SwapChildren(int nPos1, int nPos2) -{ - std::swap(m_children[nPos1], m_children[nPos2]); -} - -void CLensFlareElement::RemoveAllChildren() -{ - m_children.clear(); -} - -int CLensFlareElement::GetChildIndex(const CLensFlareElement* pElement) const -{ - auto it = std::find_if( - std::begin(m_children), - std::end(m_children), - [=](const LensFlareElementPtr& pChild) - { - return pChild.get() == pElement; - }); - - if (it != std::end(m_children)) - { - return std::distance(std::begin(m_children), it); - } - else - { - return -1; - } -} - -int CLensFlareElement::GetRow() const -{ - return m_pParent ? m_pParent->GetChildIndex(this) : 0; -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.h deleted file mode 100644 index 9860fa597e..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElement.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENT_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENT_H -#pragma once - -#include "IFlares.h" - -#include "Util/Variable.h" - -class CLensFlareElementTree; -class CLensFlareView; -class CLensFlareLibrary; - -class CLensFlareElement - : public CRefCountBase -{ -public: - - typedef _smart_ptr LensFlareElementPtr; - typedef std::vector LensFlareElementList; - - CLensFlareElement(); - virtual ~CLensFlareElement(); - - CVarBlock* GetProperties() const - { - return m_vars; - } - - void OnInternalVariableChange(IVariable* pVar); - - bool IsEnable(); - void SetEnable(bool bEnable); - EFlareType GetOpticsType(); - - bool GetName(QString& outName) const - { - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - return false; - } - outName = pOptics->GetName(); - return true; - } - - bool GetShortName(QString& outName) const; - IOpticsElementBasePtr GetOpticsElement() const - { - return m_pOpticsElement; - } - void SetOpticsElement(IOpticsElementBasePtr pOptics) - { - m_pOpticsElement = pOptics; - UpdateProperty(m_pOpticsElement); - } - - CLensFlareElement* GetParent() const; - void SetParent(CLensFlareElement* pParent); - - int GetChildCount() const; - CLensFlareElement* GetChildAt(int nPos) const; - - void AddChild(CLensFlareElement* pElement); - void InsertChild(int nPos, CLensFlareElement* pElement); - - void RemoveChild(int nPos); - void RemoveAllChildren(); - - void SwapChildren(int nPos1, int nPos2); - - int GetChildIndex(const CLensFlareElement* pChild) const; - int GetRow() const; - -private: - - void UpdateLights(); - void UpdateProperty(IOpticsElementBasePtr pOptics); - - CLensFlareElementTree* GetLensFlareTree() const; - CLensFlareView* GetLensFlareView() const; - CLensFlareLibrary* GetLensFlareLibrary() const; - -private: - - IOpticsElementBasePtr m_pOpticsElement; - CVarBlockPtr m_vars; - - CLensFlareElement* m_pParent; - LensFlareElementList m_children; - - AZStd::map m_callbackCache; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENT_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp deleted file mode 100644 index be687a5469..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.cpp +++ /dev/null @@ -1,1393 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareElementTree.h" - -// Qt -#include -#include -#include - -// Editor -#include "Clipboard.h" -#include "LensFlareItem.h" -#include "LensFlareManager.h" -#include "LensFlareUndo.h" -#include "LensFlareEditor.h" -#include "LensFlareLibrary.h" - - -template -static CLensFlareElement* FindLensFlareElement(CLensFlareElement* pRoot, Predicate pred) -{ - if (pred(pRoot)) - { - return pRoot; - } - - for (int i = 0, childCount = pRoot->GetChildCount(); i < childCount; i++) - { - if (CLensFlareElement* pElement = FindLensFlareElement(pRoot->GetChildAt(i), pred)) - { - return pElement; - } - } - - return nullptr; -} - -CLensFlareElementTree::CLensFlareElementTree(QWidget* pParent) - : QTreeView(pParent) - , m_model(new LensFlareElementTreeModel(this)) -{ - setHeaderHidden(true); - setContextMenuPolicy(Qt::CustomContextMenu); - setDragEnabled(true); - setAcceptDrops(true); - setDropIndicatorShown(true); - setDragDropMode(DragDrop); - - setModel(m_model.data()); - - connect(this, &QWidget::customContextMenuRequested, this, &CLensFlareElementTree::OnNotifyTreeRClick); - connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &CLensFlareElementTree::OnTvnSelchangedTree); - connect(model(), &QAbstractItemModel::dataChanged, this, &CLensFlareElementTree::OnDataChanged); - connect(model(), &QAbstractItemModel::rowsInserted, this, &CLensFlareElementTree::OnRowsInserted); - connect(model(), &QAbstractItemModel::rowsRemoved, this, &CLensFlareElementTree::OnRowsRemoved); - connect(model(), &QAbstractItemModel::modelReset, this, &QTreeView::expandAll); -} - -void CLensFlareElementTree::OnInternalVariableChange(IVariable* pVar) -{ - CLensFlareElement::LensFlareElementPtr pCurrentElement = GetCurrentLensFlareElement(); - if (pCurrentElement == NULL) - { - return; - } - pCurrentElement->OnInternalVariableChange(pVar); -} - -CLensFlareElement* CLensFlareElementTree::GetCurrentLensFlareElement() const -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return nullptr; - } - return selected.first().data(Qt::UserRole).value(); -} - -void CLensFlareElementTree::OnNotifyTreeRClick() -{ - CLensFlareElement* pElement = GetCurrentLensFlareElement(); - - // Copy, Cut and Clone can't be done about a Root item so those menus should be disable when the selected item is a root item. - bool bGrayed = false; - if (!pElement || pElement->GetOpticsType() == eFT_Root) - { - bGrayed = true; - } - - QMenu menu; - - QAction* actionDBFlareAddGroup = menu.addAction(tr("Add Group")); - connect(actionDBFlareAddGroup, &QAction::triggered, this, &CLensFlareElementTree::OnAddGroup); - - menu.addSeparator(); - - QAction* actionDBFlareCopy = menu.addAction(tr("Copy")); - connect(actionDBFlareCopy, &QAction::triggered, this, &CLensFlareElementTree::OnCopy); - - QAction* actionDBFlareCut = menu.addAction(tr("Cut")); - actionDBFlareCut->setEnabled(!bGrayed); - connect(actionDBFlareCut, &QAction::triggered, this, &CLensFlareElementTree::OnCut); - - QAction* actionDBFlarePaste = menu.addAction(tr("Paste")); - connect(actionDBFlarePaste, &QAction::triggered, this, &CLensFlareElementTree::OnPaste); - - QAction* actionDBFlareClone = menu.addAction(tr("Clone")); - connect(actionDBFlareClone, &QAction::triggered, this, &CLensFlareElementTree::OnClone); - - menu.addSeparator(); - - QAction* actionDBFlareRename = menu.addAction(tr("Rename\tF2")); - connect(actionDBFlareRename, &QAction::triggered, this, &CLensFlareElementTree::OnRenameItem); - - QAction* actionDBFlareRemove = menu.addAction(tr("Delete\tDel")); - connect(actionDBFlareRemove, &QAction::triggered, this, &CLensFlareElementTree::OnRemoveItem); - - QAction* actionDBFlareRemoveAll = menu.addAction(tr("Delete All")); - connect(actionDBFlareRemoveAll, &QAction::triggered, this, &CLensFlareElementTree::OnRemoveAll); - - menu.addSeparator(); - - QAction* actionDBFlareItemUp = menu.addAction(tr("Up")); - connect(actionDBFlareItemUp, &QAction::triggered, this, &CLensFlareElementTree::OnItemUp); - - QAction* actionDBFlareItemDown = menu.addAction(tr("Down")); - connect(actionDBFlareItemDown, &QAction::triggered, this, &CLensFlareElementTree::OnItemDown); - - menu.exec(QCursor::pos()); -} - -void CLensFlareElementTree::OnTvnSelchangedTree([[maybe_unused]] const QItemSelection& selected, const QItemSelection& deselected) -{ - QModelIndexList deselectedIndices = deselected.indexes(); - if (!deselectedIndices.isEmpty()) - { - CLensFlareElement* pPrevLensFlareElement = deselectedIndices.first().data(Qt::UserRole).value(); - ElementChanged(pPrevLensFlareElement); - } - - CallChangeListeners(); -} - -void CLensFlareElementTree::ElementChanged(CLensFlareElement* pPrevLensFlareElement) -{ - if (!pPrevLensFlareElement) - { - return; - } - QString itemName; - if (pPrevLensFlareElement->GetName(itemName)) - { - if (CUndo::IsRecording()) - { - CUndo::Record(new CUndoLensFlareElementSelection(m_model->GetLensFlareItem(), itemName)); - } - } -} - -void CLensFlareElementTree::OnDataChanged([[maybe_unused]] const QModelIndex& index) -{ - CallChangeListeners(); -} - -void CLensFlareElementTree::OnRowsInserted(const QModelIndex& parent, int first, [[maybe_unused]] int last) -{ - if (parent.isValid()) - { - expand(parent); - SelectItem(parent.model()->index(first, 0, parent)); - CallChangeListeners(); - } -} - -void CLensFlareElementTree::OnRowsRemoved(const QModelIndex& parent, int first, [[maybe_unused]] int last) -{ - if (parent.isValid()) - { - SelectItem(parent.model()->index(first, 0, parent)); - CallChangeListeners(); - } -} - -void CLensFlareElementTree::keyPressEvent(QKeyEvent* event) -{ - if (event->key() == Qt::Key_F2) - { - OnRenameItem(); - event->accept(); - return; - } - else if (event->matches(QKeySequence::Delete)) - { - OnRemoveItem(); - event->accept(); - return; - } - - QTreeView::keyPressEvent(event); -} - -XmlNodeRef CLensFlareElementTree::CreateXML(const char* type) const -{ - std::vector clipboardData; - if (GetClipboardList(type, clipboardData)) - { - return LensFlareUtil::CreateXMLFromClipboardData(type, "", false, clipboardData); - } - return NULL; -} - -void CLensFlareElementTree::UpdateClipboard(const char* type, bool bPasteAtSameLevel) -{ - std::vector clipboardData; - if (GetClipboardList(type, clipboardData)) - { - LensFlareUtil::UpdateClipboard(type, "", bPasteAtSameLevel, clipboardData); - } -} - -bool CLensFlareElementTree::GetClipboardList([[maybe_unused]] const char* type, std::vector& outList) const -{ - CLensFlareElement::LensFlareElementPtr pElement = GetCurrentLensFlareElement(); - if (pElement == NULL) - { - return false; - } - QString name; - if (!pElement->GetName(name)) - { - return false; - } - - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return false; - } - - CLensFlareItem* pLensFlareItem = pEditor->GetSelectedLensFlareItem(); - if (pLensFlareItem == NULL) - { - return false; - } - - outList.push_back(LensFlareUtil::SClipboardData(LENSFLARE_ELEMENT_TREE, pLensFlareItem->GetFullName(), name)); - - return true; -} - -void CLensFlareElementTree::OnAddGroup() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - CUndo undo(tr("Add library item").toUtf8()); - m_model->AddElement(selected.first(), 0, eFT_Group); - GetIEditor()->GetLensFlareManager()->Modified(); -} - -void CLensFlareElementTree::OnCopy() -{ - UpdateClipboard(FLARECLIPBOARDTYPE_COPY, false); -} - -void CLensFlareElementTree::OnCut() -{ - Cut(false); -} - -void CLensFlareElementTree::Cut(bool bPasteAtSameLevel) -{ - UpdateClipboard(FLARECLIPBOARDTYPE_CUT, bPasteAtSameLevel); -} - -CLensFlareItem* CLensFlareElementTree::GetLensFlareItem() const -{ - return m_model->GetLensFlareItem(); -} - -void CLensFlareElementTree::OnPaste() -{ - CClipboard clipboard(this); - if (clipboard.IsEmpty()) - { - return; - } - - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - XmlNodeRef xmlNode = clipboard.Get(); - if (xmlNode == NULL) - { - return; - } - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - m_model->Paste(selected.first(), xmlNode); -} - -void CLensFlareElementTree::OnClone() -{ - OnCopy(); - OnPaste(); -} - -void CLensFlareElementTree::OnRenameItem() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - edit(selected.first()); -} - -void CLensFlareElementTree::OnRemoveItem() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex index = selected.first(); - - // A root item must not be removed. - if (!index.parent().isValid()) - { - return; - } - - CLensFlareElement::LensFlareElementPtr pCurrentElement = m_model->GetLensFlareElement(index); - if (pCurrentElement == NULL) - { - return; - } - - QString name; - pCurrentElement->GetName(name); - - QString str = tr("Delete %1?").arg(name); - if (QMessageBox::question(this, tr("Delete Confirmation"), str) == QMessageBox::Yes) - { - CUndo undo(tr("Remove an optics element").toUtf8()); - m_model->removeRow(index.row(), index.parent()); - } -} - -void CLensFlareElementTree::OnRemoveAll() -{ - CUndo undo(tr("Remove All in FlareTreeCtrl").toUtf8()); - - if (QMessageBox::question(this, tr("Delete Confirmation"), tr("Do you want delete all?")) == QMessageBox::Yes) - { - m_model->RemoveAllElements(); - GetIEditor()->GetLensFlareManager()->Modified(); - } -} - -void CLensFlareElementTree::OnItemUp() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex index = selected.first(); - int row = index.row(); - if (row == 0) - { - return; - } - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - - CLensFlareElement* pElement = index.data(Qt::UserRole).value(); - m_model->MoveElement(pElement, row - 1, index.parent()); -} - -void CLensFlareElementTree::OnItemDown() -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - QModelIndex index = selected.first(); - int row = index.row(); - if (row == m_model->rowCount(index.parent()) - 1) - { - return; - } - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - - CLensFlareElement* pElement = index.data(Qt::UserRole).value(); - m_model->MoveElement(pElement, row + 2, index.parent()); -} - -void CLensFlareElementTree::SelectItem(const QModelIndex& index) -{ - if (index.isValid()) - { - expand(index.parent()); - selectionModel()->select(index, QItemSelectionModel::ClearAndSelect); - } - else - { - selectionModel()->clear(); - } -} - -void CLensFlareElementTree::SelectTreeItemByName(const QString& name) -{ - SelectItem(m_model->GetTreeItemByName(name)); -} - -void CLensFlareElementTree::CallChangeListeners() -{ - CLensFlareElement* pElement = GetCurrentLensFlareElement(); - for (int i = 0, iSize(m_LensFlaresElementListeners.size()); i < iSize; ++i) - { - m_LensFlaresElementListeners[i]->OnLensFlareChangeElement(pElement); - } -} - -void CLensFlareElementTree::mousePressEvent(QMouseEvent* event) -{ - if (event->button() == Qt::LeftButton) - { - CUndo undo(tr("Changed Lens flares element").toUtf8()); - QTreeView::mousePressEvent(event); - } - else - { - QTreeView::mousePressEvent(event); - } -} - -void CLensFlareElementTree::InvalidateLensFlareItem() -{ - m_model->InvalidateLensFlareItem(); -} - -LensFlareElementTreeModel::LensFlareElementTreeModel(QObject* pParent) - : QAbstractItemModel(pParent) - , m_pRootElement(new CLensFlareElement) -{ - CLensFlareEditor::GetLensFlareEditor()->RegisterLensFlareItemChangeListener(this); -} - -LensFlareElementTreeModel::~LensFlareElementTreeModel() -{ - CLensFlareEditor::GetLensFlareEditor()->UnregisterLensFlareItemChangeListener(this); -} - -int LensFlareElementTreeModel::columnCount(const QModelIndex&) const -{ - return 1; -} - -QVariant LensFlareElementTreeModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - { - return {}; - } - - auto pElement = static_cast(index.internalPointer()); - - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - { - QString shortName; - pElement->GetShortName(shortName); - return shortName; - } - - case Qt::CheckStateRole: - return pElement->IsEnable() ? Qt::Checked : Qt::Unchecked; - - case Qt::UserRole: - return QVariant::fromValue(pElement); - } - - return {}; -} - -void LensFlareElementTreeModel::EnableElement(CLensFlareElement* pLensFlareElement, bool bEnable) -{ - StoreUndo(); - pLensFlareElement->SetEnable(bEnable); -} - -void LensFlareElementTreeModel::RenameElement(CLensFlareElement* pLensFlareElement, const QString& newName) -{ - StoreUndo(); - IOpticsElementBasePtr pOptics = pLensFlareElement->GetOpticsElement(); - if (pOptics) - { - pOptics->SetName(newName.toUtf8().data()); - LensFlareUtil::UpdateOpticsName(pOptics); - } -} - -QModelIndex LensFlareElementTreeModel::GetRootItem() const -{ - if (m_pRootElement->GetChildCount() == 0) - { - return {}; - } - - auto pRootElement = m_pRootElement->GetChildAt(0); - assert(pRootElement->GetOpticsType() == eFT_Root); - - return createIndex(0, 0, pRootElement); -} - -bool LensFlareElementTreeModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (!index.isValid()) - { - return false; - } - - auto pElement = static_cast(index.internalPointer()); - - switch (role) - { - case Qt::CheckStateRole: - { - CUndo undo(tr("Update an enable checkbox for tree ctrl.").toUtf8()); - EnableElement(pElement, value.toInt() == Qt::Checked); - emit dataChanged(index, index); - return true; - } - - case Qt::EditRole: - { - QString text = value.toString(); - - CUndo undo(tr("Rename library item").toUtf8()); - - if (IsExistElement(text)) - { - QMessageBox::warning(0, tr("Warning"), tr("The identical name exists in a database")); - return false; - } - else if (text.contains(QLatin1Char('.'))) - { - QMessageBox::warning(0, tr("Warning"), tr("The name must not contain \".\"")); - return false; - } - else - { - CLensFlareElement* pLensFlareElement = GetLensFlareElement(index); - - QString prevName; - if (pLensFlareElement && pLensFlareElement->GetName(prevName)) - { - QString parentName(prevName); - int offset = parentName.lastIndexOf('.'); - if (offset == -1) - { - parentName = ""; - } - else - { - parentName.remove(offset + 1, parentName.length() - offset); - } - - if (index == GetRootItem()) - { - CLensFlareEditor* pLensFlareEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pLensFlareEditor) - { - CLensFlareItem* pLensFlareItem = pLensFlareEditor->GetSelectedLensFlareItem(); - if (pLensFlareItem) - { - QString candidateName = LensFlareUtil::ReplaceLastName(pLensFlareItem->GetName(), text); - if (pLensFlareEditor->IsExistTreeItem(candidateName, true)) - { - QMessageBox::warning(0, tr("Warning"), tr("The identical name exists in a database")); - return false; - } - pLensFlareEditor->RenameLensFlareItem(pLensFlareItem, pLensFlareItem->GetGroupName(), text); - } - } - else - { - QMessageBox::warning(0, tr("Warning"), tr("Renaming is not possible.")); - return false; - } - } - - RenameElement(pLensFlareElement, parentName + text); - emit dataChanged(index, index); - - GetIEditor()->GetLensFlareManager()->Modified(); - } - - return true; - } - } - } - - return false; -} - -Qt::ItemFlags LensFlareElementTreeModel::flags(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return Qt::ItemFlags(); - } - - auto pElement = index.data(Qt::UserRole).value(); - - Qt::ItemFlags flags = QAbstractItemModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled; - - if (pElement->GetOpticsType() != eFT_Root) - { - flags |= Qt::ItemIsDragEnabled; - } - - return flags; -} - -QModelIndex LensFlareElementTreeModel::index(int row, int column, const QModelIndex& parent) const -{ - if (!hasIndex(row, column, parent)) - { - return {}; - } - - auto parentNode = GetLensFlareElement(parent); - auto childNode = parentNode->GetChildAt(row); - - if (childNode) - { - return createIndex(row, column, childNode); - } - else - { - return {}; - } -} - -QModelIndex LensFlareElementTreeModel::parent(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return {}; - } - - auto childNode = static_cast(index.internalPointer()); - auto parentNode = childNode->GetParent(); - - if (parentNode == m_pRootElement.get()) - { - return {}; - } - - return createIndex(parentNode->GetRow(), 0, parentNode); -} - -int LensFlareElementTreeModel::rowCount(const QModelIndex& parent) const -{ - if (parent.column() > 0) - { - return 0; - } - return GetLensFlareElement(parent)->GetChildCount(); -} - -bool LensFlareElementTreeModel::removeRows(int row, int count, const QModelIndex& parent) -{ - if (!parent.isValid()) - { - return false; - } - - auto pParent = static_cast(parent.internalPointer()); - - beginRemoveRows(parent, row, row + count - 1); - - for (int i = 0; i < count; i++) - { - CLensFlareElement* pChild = pParent->GetChildAt(row); - - IOpticsElementBasePtr pOptics = pChild->GetOpticsElement(); - if (pOptics) - { - LensFlareUtil::RemoveOptics(pOptics); - } - - pParent->RemoveChild(row); - } - - endRemoveRows(); - - GetIEditor()->GetLensFlareManager()->Modified(); // XXX - - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } - - return true; -} - -QStringList LensFlareElementTreeModel::mimeTypes() const -{ - QStringList types; - types << QStringLiteral("application/x-o3de-flareelements"); - types << QStringLiteral("application/x-o3de-flaretypes"); - return types; -} - -QMimeData* LensFlareElementTreeModel::mimeData(const QModelIndexList& indexes) const -{ - QMimeData* data = new QMimeData(); - - QByteArray array; - - for (auto& index : indexes) - { - auto pElement = static_cast(index.data(Qt::UserRole).value()); - array.append(reinterpret_cast(&pElement), sizeof(CLensFlareElement*)); - } - - data->setData(QStringLiteral("application/x-o3de-flareelements"), array); - - return data; -} - -void LensFlareElementTreeModel::RemoveAllElements() -{ - QModelIndex index = GetRootItem(); - if (!index.isValid()) - { - return; - } - - auto pElement = index.data(Qt::UserRole).value(); - - beginResetModel(); - - pElement->RemoveAllChildren(); - pElement->GetOpticsElement()->RemoveAll(); - - endResetModel(); - - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } -} - -bool LensFlareElementTreeModel::AddElement(const QModelIndex& parentIndex, int row, EFlareType flareType) -{ - if (!parentIndex.isValid()) - { - return false; - } - - auto pElement = GetLensFlareElement(parentIndex); - - int nIndex; - - if (LensFlareUtil::IsGroup(pElement->GetOpticsType())) - { - if (row != -1) - { - nIndex = row; - } - else - { - nIndex = pElement->GetChildCount(); - } - } - else - { - CLensFlareElement* pParentElement = GetLensFlareElement(parentIndex.parent()); - if (!pParentElement) - { - return false; - } - - if (!LensFlareUtil::IsGroup(pParentElement->GetOpticsType())) - { - return false; - } - - nIndex = LensFlareUtil::FindOpticsIndexUnderParentOptics(pElement->GetOpticsElement(), pParentElement->GetOpticsElement()); - if (nIndex == -1) - { - return false; - } - - pElement = pParentElement; - } - - CLensFlareElement::LensFlareElementPtr pNewElement = InsertAtomicElement(nIndex, flareType, pElement); - if (!pNewElement) - { - return false; - } - - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } - - return true; -} - -CLensFlareElement::LensFlareElementPtr LensFlareElementTreeModel::InsertAtomicElement(int nIndex, EFlareType flareType, CLensFlareElement* pParentElement) -{ - IOpticsElementBasePtr pParent = pParentElement->GetOpticsElement(); - if (pParent == NULL) - { - return NULL; - } - - IOpticsElementBasePtr pNewOptics = gEnv->pOpticsManager->Create(flareType); - if (pNewOptics == NULL) - { - return NULL; - } - - if (nIndex < 0) - { - return NULL; - } - - CLensFlareElement::LensFlareElementPtr pElement = AddElement(pNewOptics, pParentElement); - if (pElement == NULL) - { - return NULL; - } - - pParent->InsertElement(nIndex, pNewOptics); - - emit beginInsertRows(createIndex(pParentElement->GetRow(), 0, pParentElement), nIndex, nIndex); - pParentElement->InsertChild(nIndex, pElement); - emit endInsertRows(); - - return pElement; -} - -void LensFlareElementTreeModel::MakeValidElementName(const QString& seedName, QString& outValidName) const -{ - if (!IsExistElement(seedName)) - { - outValidName = seedName; - return; - } - - int counter = 0; - do - { - QString numberString; - numberString = QString::number(counter); - QString candidateName = seedName + numberString; - if (!IsExistElement(candidateName)) - { - outValidName = candidateName; - return; - } - } while (++counter < 100000); // prevent from infinite loop -} - -bool LensFlareElementTreeModel::IsExistElement(const QString& name) const -{ - const auto predicate = [&](CLensFlareElement* pElement) - { - QString flareName; - return pElement->GetName(flareName) && !QString::compare(flareName, name, Qt::CaseInsensitive); - }; - auto pElement = ::FindLensFlareElement(m_pRootElement.get(), predicate); - return pElement != nullptr; -} - -CLensFlareElement::LensFlareElementPtr LensFlareElementTreeModel::AddElement(IOpticsElementBasePtr pOptics, CLensFlareElement* pParentElement) -{ - if (pOptics == NULL) - { - return NULL; - } - - IOpticsElementBasePtr pParent = pParentElement->GetOpticsElement(); - - CLensFlareElement* pLensFlareElement = NULL; - - if (pParent == NULL) - { - if (pOptics->GetType() != eFT_Root) - { - assert(0 && "CFlareManager::AddItem() - pOptics must be a root optics if the parent doesn't exist."); - return NULL; - } - } - else - { - if (!LensFlareUtil::IsGroup(pParent->GetType())) - { - return NULL; - } - - QString fullElementName; - if (!pParentElement->GetName(fullElementName)) - { - return NULL; - } - if (!fullElementName.isEmpty()) - { - fullElementName += "."; - } - fullElementName += LensFlareUtil::GetShortName(pOptics->GetName().c_str()).toLower(); - - QString validName; - MakeValidElementName(fullElementName, validName); - pOptics->SetName(validName.toUtf8().data()); - } - - pLensFlareElement = CreateElement(pOptics); - - if (LensFlareUtil::IsGroup(pOptics->GetType())) - { - for (int i = 0, iElementCount(pOptics->GetElementCount()); i < iElementCount; ++i) - { - CLensFlareElement::LensFlareElementPtr pChild = AddElement(pOptics->GetElementAt(i), pLensFlareElement); - pLensFlareElement->AddChild(pChild); - } - } - - GetIEditor()->GetLensFlareManager()->Modified(); - if (m_pLensFlareItem) - { - m_pLensFlareItem->UpdateLights(); - } - - return pLensFlareElement; -} - -bool LensFlareElementTreeModel::MoveElement(CLensFlareElement* pElement, int row, const QModelIndex& index) -{ - if (!index.isValid()) - { - return false; - } - - QModelIndex sourceParentIndex = parent(createIndex(0, 0, pElement)); - if (!sourceParentIndex.isValid()) - { - return false; - } - - QModelIndex targetParentIndex = index; - CLensFlareElement* pTargetParent = targetParentIndex.data(Qt::UserRole).value(); - - QString fullElementName; - if (!pTargetParent->GetName(fullElementName)) - { - return false; - } - if (!fullElementName.isEmpty()) - { - fullElementName += "."; - } - fullElementName += LensFlareUtil::GetShortName(pElement->GetOpticsElement()->GetName().c_str()).toLower(); - - QString validName; - MakeValidElementName(fullElementName, validName); - - int targetRow; - - if (!LensFlareUtil::IsGroup(pTargetParent->GetOpticsElement()->GetType())) - { - targetParentIndex = targetParentIndex.parent(); - pTargetParent = targetParentIndex.data(Qt::UserRole).value(); - targetRow = index.row(); - } - else - { - if (row != -1) - { - targetRow = row; - } - else - { - targetRow = pTargetParent->GetChildCount(); - } - } - - CLensFlareElement* pSourceParent = pElement->GetParent(); - int sourceRow = pElement->GetRow(); - - if (!beginMoveRows(sourceParentIndex, sourceRow, sourceRow, targetParentIndex, targetRow)) - { - return false; - } - - StoreUndo(); - - // insert before removing to increase reference count - - pTargetParent->InsertChild(targetRow, pElement); - pTargetParent->GetOpticsElement()->InsertElement(targetRow, pElement->GetOpticsElement()); - - if (pTargetParent == pSourceParent && targetRow < sourceRow) - { - ++sourceRow; - } - - pSourceParent->RemoveChild(sourceRow); - pSourceParent->GetOpticsElement()->Remove(sourceRow); - - pElement->GetOpticsElement()->SetName(validName.toUtf8().data()); - LensFlareUtil::UpdateOpticsName(pElement->GetOpticsElement()); - - endMoveRows(); - - return true; -} - -bool LensFlareElementTreeModel::dropMimeData(const QMimeData* data, [[maybe_unused]] Qt::DropAction action, int row, [[maybe_unused]] int column, const QModelIndex& parent) -{ - if (data->hasFormat(QStringLiteral("application/x-o3de-flaretypes"))) - { - // drop from atomic list - - QByteArray encoded = data->data(QStringLiteral("application/x-o3de-flaretypes")); - QDataStream stream(&encoded, QIODevice::ReadOnly); - - while (!stream.atEnd()) - { - int flareType; - stream >> flareType; - - CUndo undo(tr("Add Atomic Lens Flare Item").toUtf8()); - AddElement(parent, row, static_cast(flareType)); - } - - return true; - } - else if (data->hasFormat(QStringLiteral("application/x-o3de-flareelements"))) - { - QByteArray array = data->data("application/x-o3de-flareelements"); - - int count = array.size() / sizeof(CLensFlareElement*); - auto ppElements = reinterpret_cast(array.data()); - - CUndo undo(tr("Copy/Cut & Paste library item").toUtf8()); - - for (int i = 0; i < count; i++) - { - MoveElement(ppElements[i], row, parent); - } - - return true; - } - else - { - return false; - } -} - -CLensFlareElement* LensFlareElementTreeModel::FindLensFlareElement(IOpticsElementBasePtr pOptics) const -{ - return ::FindLensFlareElement(m_pRootElement.get(), [&](CLensFlareElement* pElement) - { - return pElement->GetOpticsElement() == pOptics; - }); -} - -Qt::DropActions LensFlareElementTreeModel::supportedDragActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -Qt::DropActions LensFlareElementTreeModel::supportedDropActions() const -{ - return Qt::CopyAction | Qt::MoveAction; -} - -void LensFlareElementTreeModel::UpdateLensFlareItem(CLensFlareItem* pLensFlareItem) -{ - m_pLensFlareItem = pLensFlareItem; - - m_pRootElement.reset(new CLensFlareElement); - - if (pLensFlareItem != NULL) - { - auto pChild = UpdateLensFlareElementsRecusively(m_pLensFlareItem->GetOptics()); - if (pChild) - { - m_pRootElement->AddChild(pChild); - } - } -} - -CLensFlareElement* LensFlareElementTreeModel::UpdateLensFlareElementsRecusively(IOpticsElementBasePtr pOptics) -{ - auto pElement = new CLensFlareElement; - pElement->SetOpticsElement(pOptics); - - for (int i = 0, iCount(pOptics->GetElementCount()); i < iCount; i++) - { - auto pChild = UpdateLensFlareElementsRecusively(pOptics->GetElementAt(i)); - if (pElement) - { - pElement->AddChild(pChild); - } - } - - return pElement; -} - -CLensFlareElement* LensFlareElementTreeModel::CreateElement(IOpticsElementBasePtr pOptics) -{ - StoreUndo(); - CLensFlareElement* pElement = new CLensFlareElement; - pElement->SetOpticsElement(pOptics); - return pElement; -} - -void LensFlareElementTreeModel::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - beginResetModel(); - UpdateLensFlareItem(pLensFlareItem); - endResetModel(); -} - -void LensFlareElementTreeModel::OnLensFlareDeleteItem([[maybe_unused]] CLensFlareItem* pLensFlareItem) -{ -} - -CLensFlareElement* LensFlareElementTreeModel::GetLensFlareElement(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return m_pRootElement.get(); - } - else - { - return static_cast(index.internalPointer()); - } -} - -void LensFlareElementTreeModel::Paste(const QModelIndex& hItem, XmlNodeRef xmlNode) -{ - if (!hItem.isValid()) - { - return; - } - - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - - QString type; - xmlNode->getAttr("Type", type); - - bool bPasteAtSameLevel = false; - xmlNode->getAttr("PasteAtSameLevel", bPasteAtSameLevel); - - QModelIndex hParentItem; - - IOpticsElementBasePtr pSelectedOptics = GetOpticsElementByTreeItem(hItem); - if (pSelectedOptics == NULL) - { - return; - } - - if (!LensFlareUtil::IsGroup(pSelectedOptics->GetType())) - { - hParentItem = hItem.parent(); - } - else - { - if (bPasteAtSameLevel) - { - hParentItem = hItem.parent(); - } - else - { - hParentItem = hItem; - } - } - - IOpticsElementBasePtr pParentOptics = GetOpticsElementByTreeItem(hParentItem); - if (pParentOptics == NULL) - { - return; - } - - for (int i = 0, iChildCount(xmlNode->getChildCount()); i < iChildCount; ++i) - { - LensFlareUtil::SClipboardData clipboardData; - clipboardData.FillThisFromXmlNode(xmlNode->getChild(i)); - - if (clipboardData.m_LensFlareFullPath == m_pLensFlareItem->GetFullName() && clipboardData.m_From == LENSFLARE_ITEM_TREE) - { - QString msg; - msg = tr("[%1] lens item can be pasted into the same item").arg(clipboardData.m_LensFlareFullPath); - CryMessageBox(msg.toUtf8().data(), "Warning", MB_OK); - continue; - } - - IOpticsElementBasePtr pSourceOptics = pEditor->FindOptics(clipboardData.m_LensFlareFullPath, clipboardData.m_LensOpticsPath); - if (pSourceOptics == NULL) - { - continue; - } - - CLensFlareItem* pSourceLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(clipboardData.m_LensFlareFullPath); - if (pSourceLensFlareItem == NULL) - { - continue; - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (m_pLensFlareItem->GetFullName() == clipboardData.m_LensFlareFullPath && LensFlareUtil::FindOptics(pSourceOptics, pSelectedOptics->GetName().c_str())) - { - QMessageBox::warning(0, tr("Warning"), tr("You can't paste this item here.")); - return; - } - } - - // if the copied optics type is root, the type should be converted to group type. - bool bForceConvertType = false; - if (pSourceOptics->GetType() == eFT_Root) - { - bForceConvertType = true; - } - - IOpticsElementBasePtr pNewOptics = LensFlareUtil::CreateOptics(pSourceOptics, bForceConvertType); - if (pNewOptics == NULL) - { - return; - } - - if (type == FLARECLIPBOARDTYPE_CUT) - { - if (pSourceLensFlareItem == m_pLensFlareItem) - { - QModelIndex hSourceItem = GetTreeItemByOpticsElement(pSourceOptics); - if (hSourceItem.isValid()) - { - removeRow(hSourceItem.row(), hSourceItem.parent()); - } - } - else if (clipboardData.m_From == LENSFLARE_ITEM_TREE) - { - CLensFlareLibrary* pLibrary = pEditor->GetCurrentLibrary(); - if (pLibrary) - { - QString lensFlareFullName = m_pLensFlareItem ? m_pLensFlareItem->GetFullName() : ""; - pLibrary->RemoveItem(pSourceLensFlareItem); - pEditor->ReloadItems(); - pSourceLensFlareItem->UpdateLights(); - pEditor->UpdateLensOpticsNames(pSourceLensFlareItem->GetFullName(), ""); - if (!lensFlareFullName.isEmpty()) - { - pEditor->SelectItemByName(lensFlareFullName); - } - } - - LensFlareUtil::RemoveOptics(pSourceOptics); - } - } - - CLensFlareElement* pParentElement = FindLensFlareElement(pParentOptics); - - // The children optics items were already added in a creation phase so we don't need to update the optics object. - CLensFlareElement::LensFlareElementPtr pNewElement = AddElement(pNewOptics, pParentElement); - assert(pNewElement); - if (!pNewElement) - { - return; - } - - int nInsertedPos; - if (hParentItem == hItem) - { - nInsertedPos = 0; - } - else - { - nInsertedPos = LensFlareUtil::FindOpticsIndexUnderParentOptics(pSelectedOptics, pParentOptics); - if (nInsertedPos > pParentOptics->GetElementCount() || nInsertedPos == -1) - { - nInsertedPos = pParentOptics->GetElementCount(); - } - } - - pParentOptics->InsertElement(nInsertedPos, pNewOptics); - LensFlareUtil::UpdateOpticsName(pNewOptics); - - emit beginInsertRows(createIndex(pParentElement->GetRow(), 0, pParentElement), nInsertedPos, nInsertedPos); - pParentElement->InsertChild(nInsertedPos, pNewElement); - emit endInsertRows(); - - // pSelectedLensFlareItem->UpdateLights(); - } -} - -IOpticsElementBasePtr LensFlareElementTreeModel::GetOpticsElementByTreeItem(const QModelIndex& index) const -{ - if (!index.isValid()) - { - return nullptr; - } - return GetLensFlareElement(index)->GetOpticsElement(); -} - -QModelIndex LensFlareElementTreeModel::GetTreeItemByName(const QString& name) const -{ - auto pElement = ::FindLensFlareElement(m_pRootElement.get(), [&](CLensFlareElement* pElement) - { - QString flareName; - return pElement->GetName(flareName) && flareName == name; - }); - - if (!pElement) - { - return {}; - } - - return createIndex(pElement->GetRow(), 0, pElement); -} - -QModelIndex LensFlareElementTreeModel::GetTreeItemByOpticsElement(const IOpticsElementBasePtr pOptics) const -{ - auto pElement = FindLensFlareElement(pOptics); - if (!pElement) - { - return {}; - } - return createIndex(pElement->GetRow(), 0, pElement); -} - -void LensFlareElementTreeModel::InvalidateLensFlareItem() -{ - OnLensFlareChangeItem(nullptr); -} - -void LensFlareElementTreeModel::StoreUndo(const QString& undoDescription) -{ - if (CUndo::IsRecording()) - { - if (undoDescription.isEmpty()) - { - CUndo::Record(new CUndoLensFlareItem(GetLensFlareItem())); - } - else - { - CUndo::Record(new CUndoLensFlareItem(GetLensFlareItem(), undoDescription)); - } - } -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.h deleted file mode 100644 index d2b0051032..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareElementTree.h +++ /dev/null @@ -1,197 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENTTREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENTTREE_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "LensFlareElement.h" -#include "LensFlareUtil.h" -#include "ILensFlareListener.h" - -#include -#include -#endif - -class CLensFlareItem; -class LensFlareElementTreeModel; -class QMouseEvent; - -class CLensFlareElementTree - : public QTreeView -{ - Q_OBJECT - -public: - - CLensFlareElementTree(QWidget* pParent = nullptr); - - void RegisterListener(ILensFlareChangeElementListener* pListener) - { - if (pListener) - { - m_LensFlaresElementListeners.push_back(pListener); - } - } - - void UnregisterListener(ILensFlareChangeElementListener* pListener) - { - if (pListener == NULL) - { - return; - } - std::vector::iterator ii = m_LensFlaresElementListeners.begin(); - for (; ii != m_LensFlaresElementListeners.end(); ) - { - if (*ii == pListener) - { - ii = m_LensFlaresElementListeners.erase(ii); - } - else - { - ++ii; - } - } - } - - CLensFlareElement::LensFlareElementPtr FindLensFlareElement(IOpticsElementBasePtr pElement) const; - - void OnInternalVariableChange(IVariable* pVar); - - CLensFlareElement* GetCurrentLensFlareElement() const; - void UpdateProperty(); - void UpdateClipboard(const char* type, bool bPasteAtSameLevel); - - void SelectTreeItemByName(const QString& name); - - CLensFlareItem* GetLensFlareItem() const; - void InvalidateLensFlareItem(); - -protected: - void CallChangeListeners(); - - void OnDataChanged(const QModelIndex& index); - void OnRowsInserted(const QModelIndex& index, int first, int last); - void OnRowsRemoved(const QModelIndex& index, int first, int last); - - void OnNotifyTreeRClick(); - void OnTvnSelchangedTree(const QItemSelection& selected, const QItemSelection& deselected); - - XmlNodeRef CreateXML(const char* type) const; - bool GetClipboardList(const char* type, std::vector& outList) const; - - //! Only the basic operations like following methods must have routine for undoing. - void ElementChanged(CLensFlareElement* pPrevLensFlareElement); - ///////////////////////////////////////////////////////////////////////////////////////// - - void OnAddGroup(); - void OnCopy(); - void OnCut(); - void OnPaste(); - void OnClone(); - void OnRenameItem(); - void OnRemoveItem(); - void OnRemoveAll(); - void OnItemUp(); - void OnItemDown(); - void mousePressEvent(QMouseEvent* event); - void keyPressEvent(QKeyEvent* event); - - void Cut(bool bPasteAtSameLevel); - -private: - void SelectItem(const QModelIndex& index); - - std::vector m_LensFlaresElementListeners; - - QScopedPointer m_model; -}; - -class LensFlareElementTreeModel - : public QAbstractItemModel - , public ILensFlareChangeItemListener -{ - Q_OBJECT - -public: - LensFlareElementTreeModel(QObject* pParent = nullptr); - ~LensFlareElementTreeModel(); - - int rowCount(const QModelIndex& parent = {}) const override; - int columnCount(const QModelIndex& parent = {}) const override; - - Qt::ItemFlags flags(const QModelIndex& index) const override; - QVariant data(const QModelIndex& index, int role) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); - - QModelIndex index(int row, int column, const QModelIndex& parent = {}) const override; - QModelIndex parent(const QModelIndex& index) const override; - - bool removeRows(int row, int count, const QModelIndex& parent = {}) override; - - QStringList mimeTypes() const override; - QMimeData* mimeData(const QModelIndexList& indexes) const override; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) override; - Qt::DropActions supportedDragActions() const override; - Qt::DropActions supportedDropActions() const override; - - CLensFlareElement* GetLensFlareElement(const QModelIndex& index) const; - - QModelIndex GetTreeItemByName(const QString& name) const; - - void Paste(const QModelIndex& index, XmlNodeRef xmlNode); - void Cut(const QModelIndex& index, bool bPasteAtSameLevel); - - CLensFlareItem* GetLensFlareItem() const - { - return m_pLensFlareItem; - } - - void InvalidateLensFlareItem(); - - void RemoveAllElements(); - bool AddElement(const QModelIndex& index, int row, EFlareType flareType); - - bool MoveElement(CLensFlareElement* pElement, int row, const QModelIndex& parentIndex); - -private: - QModelIndex GetRootItem() const; - IOpticsElementBasePtr GetOpticsElementByTreeItem(const QModelIndex& index) const; - - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - - void UpdateLensFlareItem(CLensFlareItem* pLensFlareItem); - CLensFlareElement* UpdateLensFlareElementsRecusively(IOpticsElementBasePtr pOptics); - CLensFlareElement* CreateElement(IOpticsElementBasePtr pOptics); - void Reload(); - - void MakeValidElementName(const QString& seedName, QString& outValidName) const; - bool IsExistElement(const QString& name) const; - CLensFlareElement::LensFlareElementPtr InsertAtomicElement(int nIndex, EFlareType flareType, CLensFlareElement* pParentElement); - CLensFlareElement::LensFlareElementPtr AddElement(IOpticsElementBasePtr pOptics, CLensFlareElement* pParentElement); - CLensFlareElement* FindLensFlareElement(IOpticsElementBasePtr pOptics) const; - - QModelIndex GetTreeItemByOpticsElement(const IOpticsElementBasePtr pOptics) const; - void EnableElement(CLensFlareElement* pLensFlareElement, bool bEnable); - void RenameElement(CLensFlareElement* pLensFlareElement, const QString& newName); - void StoreUndo(const QString& undoDescription = ""); - - CLensFlareElement::LensFlareElementPtr m_pRootElement; - CLensFlareItem* m_pLensFlareItem; -}; - -Q_DECLARE_METATYPE(CLensFlareElement*) - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREELEMENTTREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.cpp deleted file mode 100644 index e20f1ac7cb..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareItem.h" - -// Editor -#include "LensFlareUtil.h" -#include "LensFlareEditor.h" -#include "LensFlareUndo.h" -#include "Objects/EntityObject.h" - - -CLensFlareItem::CLensFlareItem() -{ - m_pOptics = NULL; - CreateOptics(); -} - -CLensFlareItem::~CLensFlareItem() -{ -} - -void CLensFlareItem::Serialize(SerializeContext& ctx) -{ - if (ctx.bLoading) - { - CreateOptics(); - LensFlareUtil::FillOpticsFromXML(m_pOptics, ctx.node); - - for (int i = 0, iChildCount(ctx.node->getChildCount()); i < iChildCount; ++i) - { - AddChildOptics(m_pOptics, ctx.node->getChild(i)); - } - - CBaseLibraryItem::Serialize(ctx); - } - else - { - CBaseLibraryItem::Serialize(ctx); - } -} - -void CLensFlareItem::AddChildOptics(IOpticsElementBasePtr pParentOptics, const XmlNodeRef& pNode) -{ - if (pNode == NULL) - { - return; - } - - if (pNode->getTag() && strcmp(pNode->getTag(), "FlareItem")) - { - return; - } - - IOpticsElementBasePtr pOptics = LensFlareUtil::CreateOptics(pNode); - if (pOptics == NULL) - { - return; - } - - pParentOptics->AddElement(pOptics); - - for (int i = 0, iChildCount(pNode->getChildCount()); i < iChildCount; ++i) - { - AddChildOptics(pOptics, pNode->getChild(i)); - } -} - -void CLensFlareItem::CreateOptics() -{ - m_pOptics = gEnv->pOpticsManager->Create(eFT_Root); -} - -XmlNodeRef CLensFlareItem::CreateXmlData() const -{ - XmlNodeRef pRootNode = NULL; - if (LensFlareUtil::CreateXmlData(m_pOptics, pRootNode)) - { - pRootNode->setAttr("Name", m_pOptics->GetName().c_str()); - return pRootNode; - } - return NULL; -} - -void CLensFlareItem::SetName(const QString& name) -{ - QString newNameWithGroup; - QString newFullName; - LensFlareUtil::GetExpandedItemNames(this, LensFlareUtil::GetGroupNameFromName(name), LensFlareUtil::GetShortName(name), newNameWithGroup, newFullName); - - if (CUndo::IsRecording()) - { - CUndo::Record(new CUndoRenameLensFlareItem(GetFullName(), newFullName)); - } - - CBaseLibraryItem::SetName(name); - - if (m_pOptics) - { - m_pOptics->SetName(GetShortName().toUtf8().data()); - } -} - -void CLensFlareItem::UpdateLights(IOpticsElementBasePtr pSrcOptics) -{ - QString srcFullOpticsName = GetFullName(); - bool bUpdateChildren = false; - if (pSrcOptics == NULL) - { - if (m_pOptics == NULL) - { - return; - } - pSrcOptics = m_pOptics; - bUpdateChildren = true; - } - - std::vector lightEntities; - LensFlareUtil::GetLightEntityObjects(lightEntities); - - for (int i = 0, iLightSize(lightEntities.size()); i < iLightSize; ++i) - { - CEntityObject* pLightEntity = lightEntities[i]; - if (pLightEntity == NULL) - { - continue; - } - - IOpticsElementBasePtr pTargetOptics = pLightEntity->GetOpticsElement(); - if (pTargetOptics == NULL) - { - continue; - } - - QString targetFullOpticsName(pTargetOptics->GetName().c_str()); - if (srcFullOpticsName != targetFullOpticsName) - { - continue; - } - - QString srcOpticsName(pSrcOptics->GetName().c_str()); - IOpticsElementBasePtr pFoundOptics = NULL; - if (LensFlareUtil::GetShortName(targetFullOpticsName) == srcOpticsName) - { - pFoundOptics = pTargetOptics; - } - else - { - pFoundOptics = LensFlareUtil::FindOptics(pTargetOptics, srcOpticsName); - } - - if (pFoundOptics == NULL) - { - continue; - } - if (pFoundOptics->GetType() != pSrcOptics->GetType()) - { - continue; - } - - LensFlareUtil::CopyOptics(pSrcOptics, pFoundOptics, bUpdateChildren); - } -} - -void CLensFlareItem::ReplaceOptics(IOpticsElementBasePtr pNewData) -{ - if (pNewData == NULL) - { - return; - } - if (pNewData->GetType() != eFT_Root) - { - return; - } - CreateOptics(); - LensFlareUtil::CopyOptics(pNewData, m_pOptics); - m_pOptics->SetName(GetFullName().toUtf8().data()); - UpdateLights(); - - CLensFlareEditor* pLensFlareEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pLensFlareEditor == NULL) - { - return; - } - if (this != pLensFlareEditor->GetSelectedLensFlareItem()) - { - return; - } - pLensFlareEditor->UpdateLensFlareItem(this); - pLensFlareEditor->RemovePropertyItems(); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.h deleted file mode 100644 index 6d1eedb5f9..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItem.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEM_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEM_H -#pragma once - -class IOpticsElementBase; -class CEntityObject; - -#include "BaseLibraryItem.h" -#include "Include/IDataBaseItem.h" - -class CLensFlareItem - : public CBaseLibraryItem -{ -public: - - CLensFlareItem(); - ~CLensFlareItem(); - - EDataBaseItemType GetType() const - { - return EDB_TYPE_FLARE; - } - - void SetName(const QString& name); - void Serialize(SerializeContext& ctx); - - void CreateOptics(); - - IOpticsElementBasePtr GetOptics() const - { - return m_pOptics; - } - - void ReplaceOptics(IOpticsElementBasePtr pNewData); - - XmlNodeRef CreateXmlData() const; - void UpdateLights(IOpticsElementBasePtr pSrcOptics = NULL); - -private: - - void GetLightEntityObjects(std::vector& outEntityLights) const; - static void AddChildOptics(IOpticsElementBasePtr pParentOptics, const XmlNodeRef& pNode); - - IOpticsElementBasePtr m_pOptics; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEM_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.cpp deleted file mode 100644 index 34cb442a38..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareItemTree.h" - -// Editor -#include "LensFlareItem.h" -#include "ViewManager.h" -#include "Objects/EntityObject.h" - - -CLensFlareItemTree::CLensFlareItemTree(QWidget* pParent) - : QTreeView(pParent) -{ - setHeaderHidden(true); - setSelectionMode(QAbstractItemView::SingleSelection); - setContextMenuPolicy(Qt::CustomContextMenu); - setDragEnabled(true); - setAcceptDrops(true); - setDropIndicatorShown(true); - setDragDropMode(DragDrop); -} - -CLensFlareItemTree::~CLensFlareItemTree() -{ -} - -void CLensFlareItemTree::startDrag(Qt::DropActions supportedDropActions) -{ - QTreeView::startDrag(supportedDropActions); -} - -void CLensFlareItemTree::mousePressEvent(QMouseEvent* event) -{ - if (event->button() == Qt::LeftButton) - { - CUndo undo(tr("Changed lens flare item").toUtf8()); - QTreeView::mousePressEvent(event); - } - else - { - QTreeView::mousePressEvent(event); - } -} - -void CLensFlareItemTree::AssignLensFlareToLightEntity(CViewport* pViewport) const -{ - QModelIndexList selected = selectionModel()->selectedIndexes(); - if (selected.isEmpty()) - { - return; - } - - CLensFlareItem* pLensFlareItem = static_cast(selected.first().data(Qt::UserRole).value()); - - QPoint viewportPos = QCursor::pos(); - pViewport->ScreenToClient(viewportPos); - HitContext hit; - if (!pViewport->HitTest(viewportPos, hit)) - { - return; - } - - if (hit.object && qobject_cast(hit.object)) - { - CEntityObject* pEntity = (CEntityObject*)hit.object; - if (pEntity->IsLight()) - { - CUndo undo(tr("Assign a lens flare item to a light entity").toUtf8()); - pEntity->ApplyOptics(pLensFlareItem->GetFullName(), pLensFlareItem->GetOptics()); - } - } -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.h deleted file mode 100644 index 1139604163..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareItemTree.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEMTREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEMTREE_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "LensFlareElement.h" -#include "ILensFlareListener.h" - -#include -#endif - -class QMouseEvent; -class CLensFlareItem; - -class CLensFlareItemTree - : public QTreeView -{ - Q_OBJECT - -public: - CLensFlareItemTree(QWidget* pParent = nullptr); - ~CLensFlareItemTree(); - -protected: - void startDrag(Qt::DropActions supportedDropActions) override; - void mousePressEvent(QMouseEvent* event) override; - -private: - - void AssignLensFlareToLightEntity(CViewport* pViewport) const; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREITEMTREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.cpp deleted file mode 100644 index b575b4595c..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareLibrary.h" - -// Editor -#include "LensFlareItem.h" - - -bool CLensFlareLibrary::Save() -{ - return SaveLibrary("LensFlareLibrary"); -} - -bool CLensFlareLibrary::Load(const QString& filename) -{ - if (filename.isEmpty()) - { - return false; - } - SetFilename(filename); - XmlNodeRef root = XmlHelpers::LoadXmlFromFile(filename.toUtf8().data()); - if (!root) - { - return false; - } - Serialize(root, true); - return true; -} - -void CLensFlareLibrary::Serialize(XmlNodeRef& root, bool bLoading) -{ - if (bLoading) - { - RemoveAllItems(); - QString name = GetName(); - root->getAttr("Name", name); - SetName(name); - for (int i = 0; i < root->getChildCount(); i++) - { - XmlNodeRef itemNode = root->getChild(i); - CLensFlareItem* pLensFlareItem = new CLensFlareItem; - AddItem(pLensFlareItem); - CBaseLibraryItem::SerializeContext ctx(itemNode, bLoading); - pLensFlareItem->Serialize(ctx); - } - SetModified(false); - m_bNewLibrary = false; - } - else - { - root->setAttr("Name", GetName().toUtf8().data()); - - for (int i = 0; i < GetItemCount(); i++) - { - CLensFlareItem* pItem = (CLensFlareItem*)GetItem(i); - if(pItem) - { - CBaseLibraryItem::SerializeContext ctx(pItem->CreateXmlData(), bLoading); - root->addChild(ctx.node); - pItem->Serialize(ctx); - } - } - } -} - -IOpticsElementBasePtr CLensFlareLibrary::GetOpticsOfItem(const char* szflareName) -{ - IOpticsElementBasePtr pOptics = NULL; - for (int i = 0; i < GetItemCount(); i++) - { - CLensFlareItem* pItem = (CLensFlareItem*)GetItem(i); - - if (pItem->GetFullName() == szflareName) - { - pOptics = pItem->GetOptics(); - break; - } - } - - return pOptics; -} - - -void CLensFlareLibrary::OnInternalVariableChange([[maybe_unused]] IVariable* pVar) -{ - SetModified(true); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.h deleted file mode 100644 index 484ad3740a..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLibrary.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIBRARY_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIBRARY_H -#pragma once -#include "BaseLibrary.h" - -struct IVariable; - -class CRYEDIT_API CLensFlareLibrary - : public CBaseLibrary -{ -public: - CLensFlareLibrary(IBaseLibraryManager* pManager) - : CBaseLibrary(pManager) {}; - virtual bool Save(); - virtual bool Load(const QString& filename); - virtual void Serialize(XmlNodeRef& node, bool bLoading); - - IOpticsElementBasePtr GetOpticsOfItem(const char* szflareName); - - void OnInternalVariableChange(IVariable* pVar); -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIBRARY_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.cpp deleted file mode 100644 index 307364ea4f..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareLightEntityTree.h" - -// Editor -#include "Viewport.h" -#include "Include/IObjectManager.h" -#include "Objects/SelectionGroup.h" -#include "LensFlareItem.h" -#include "LensFlareEditor.h" - - -CLensFlareLightEntityTree::CLensFlareLightEntityTree(QWidget* pParent) - : QTreeView(pParent) - , m_model(new LensFlareLightEntityModel) -{ - setHeaderHidden(true); - - setModel(m_model.data()); - - connect(this, &QTreeView::doubleClicked, this, &CLensFlareLightEntityTree::OnTvnItemDoubleClicked); -} - -CLensFlareLightEntityTree::~CLensFlareLightEntityTree() -{ -} - -void CLensFlareLightEntityTree::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - m_model->OnLensFlareChangeItem(pLensFlareItem); -} - -void CLensFlareLightEntityTree::OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem) -{ - m_model->OnLensFlareDeleteItem(pLensFlareItem); -} - -void CLensFlareLightEntityTree::OnTvnItemDoubleClicked(const QModelIndex& index) -{ - CEntityObject* pObject = index.data(Qt::UserRole).value(); - - if (!qobject_cast(pObject)) - { - return; - } - - CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection(); - if (pSelection) - { - int iSelectionCount(pSelection->GetCount()); - if (iSelectionCount == 1) - { - if (pSelection->GetObject(0) == pObject) - { - CViewport* vp = GetIEditor()->GetActiveView(); - if (vp) - { - vp->CenterOnSelection(); - } - return; - } - } - } - - GetIEditor()->GetObjectManager()->ClearSelection(); - GetIEditor()->GetObjectManager()->SelectObject(pObject); -} - -LensFlareLightEntityModel::LensFlareLightEntityModel(QObject* pParent) - : QAbstractListModel(pParent) -{ - CLensFlareEditor::GetLensFlareEditor()->RegisterLensFlareItemChangeListener(this); - GetIEditor()->GetObjectManager()->AddObjectEventListener(this); -} - -LensFlareLightEntityModel::~LensFlareLightEntityModel() -{ - CLensFlareEditor::GetLensFlareEditor()->UnregisterLensFlareItemChangeListener(this); - GetIEditor()->GetObjectManager()->RemoveObjectEventListener(this); -} - -void LensFlareLightEntityModel::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - beginResetModel(); - - m_pLensFlareItem = pLensFlareItem; - m_lightEntities.clear(); - - if (m_pLensFlareItem) - { - std::vector lightEntities; - LensFlareUtil::GetLightEntityObjects(lightEntities); - - for (int i = 0, iEntitySize(lightEntities.size()); i < iEntitySize; ++i) - { - AddLightEntity(lightEntities[i]); - } - } - - endResetModel(); -} - -void LensFlareLightEntityModel::OnLensFlareDeleteItem([[maybe_unused]] CLensFlareItem* pLensFlareItem) -{ - beginResetModel(); - - m_lightEntities.clear(); - m_pLensFlareItem = NULL; - - endResetModel(); -} - -void LensFlareLightEntityModel::OnObjectEvent(CBaseObject* pObject, int nEvent) -{ - if (!qobject_cast(pObject)) - { - return; - } - - switch (nEvent) - { - case CBaseObject::ON_RENAME: - case CBaseObject::ON_DELETE: - { - auto it = std::find(std::begin(m_lightEntities), std::end(m_lightEntities), pObject); - if (it == std::end(m_lightEntities)) - { - return; - } - int row = std::distance(std::begin(m_lightEntities), it); - if (nEvent == CBaseObject::ON_RENAME) - { - emit dataChanged(index(row, 0), index(row, 0)); - } - else - { - beginRemoveRows({}, row, row); - m_lightEntities.erase(it); - endRemoveRows(); - } - } - break; - - case CBaseObject::ON_ADD: - if (AddLightEntity((CEntityObject*)pObject)) - { - int row = m_lightEntities.size() - 1; - beginInsertRows({}, row, row); - endInsertRows(); - } - break; - } -} - -bool LensFlareLightEntityModel::AddLightEntity(CEntityObject* pEntity) -{ - if (pEntity == NULL || m_pLensFlareItem == NULL) - { - return false; - } - - QString lensFlareName = pEntity->GetEntityPropertyString(CEntityObject::s_LensFlarePropertyName); - if (lensFlareName.isEmpty()) - { - return false; - } - - QString fullName = m_pLensFlareItem->GetFullName(); - if (fullName.isEmpty()) - { - return false; - } - - if (QString::compare(lensFlareName, fullName, Qt::CaseInsensitive)) - { - return false; - } - - m_lightEntities.push_back(pEntity); - - return true; -} - -int LensFlareLightEntityModel::rowCount(const QModelIndex&) const -{ - return m_lightEntities.size(); -} - -QVariant LensFlareLightEntityModel::data(const QModelIndex& index, int role) const -{ - const int row = index.row(); - - if (row < 0 || row >= m_lightEntities.size()) - { - return {}; - } - - auto pEntity = m_lightEntities[row]; - - switch (role) - { - case Qt::DisplayRole: - return pEntity->GetName(); - - case Qt::UserRole: - return QVariant::fromValue(pEntity); - } - - return {}; -} - -#include diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.h deleted file mode 100644 index 21a271c08f..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareLightEntityTree.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIGHTENTITYTREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIGHTENTITYTREE_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "ILensFlareListener.h" - -#include -#include -#include "IObjectManager.h" // for IObjectManager::EventListener -#include "Objects/EntityObject.h" -#endif - -class LensFlareLightEntityModel; - -class CLensFlareLightEntityTree - : public QTreeView -{ - Q_OBJECT - -public: - CLensFlareLightEntityTree(QWidget* pParent = nullptr); - ~CLensFlareLightEntityTree(); - - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - -protected: - void OnTvnItemDoubleClicked(const QModelIndex& index); - - QScopedPointer m_model; -}; - -class LensFlareLightEntityModel - : public QAbstractListModel - , public ILensFlareChangeItemListener - , public IObjectManager::EventListener -{ - Q_OBJECT - -public: - LensFlareLightEntityModel(QObject* pParent = nullptr); - ~LensFlareLightEntityModel(); - - int rowCount(const QModelIndex& parent = {}) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - -protected: - void OnObjectEvent(CBaseObject* pObject, int nEvent) override; - - bool AddLightEntity(CEntityObject* pEntity); - - std::vector m_lightEntities; - _smart_ptr m_pLensFlareItem; -}; - -Q_DECLARE_METATYPE(CEntityObject*) - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLARELIGHTENTITYTREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.cpp deleted file mode 100644 index c28832898f..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareManager.h" - -// AzCore -#include -#include - -// Editor -#include "LensFlareEditor.h" -#include "LensFlareItem.h" -#include "LensFlareLibrary.h" -#include "LensFlareUtil.h" - - -////////////////////////////////////////////////////////////////////////// -// CLensFlareManager implementation. -////////////////////////////////////////////////////////////////////////// -CLensFlareManager::CLensFlareManager() - : CBaseLibraryManager() -{ - m_bUniqNameMap = true; - m_pLevelLibrary = (CBaseLibrary*)AddLibrary("Level", true); - AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); -} - -////////////////////////////////////////////////////////////////////////// -CLensFlareManager::~CLensFlareManager() -{ - AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); -} - -////////////////////////////////////////////////////////////////////////// -void CLensFlareManager::ClearAll() -{ - CBaseLibraryManager::ClearAll(); - - m_pLevelLibrary = (CBaseLibrary*)AddLibrary("Level", true); -} - -////////////////////////////////////////////////////////////////////////// -CBaseLibraryItem* CLensFlareManager::MakeNewItem() -{ - return new CLensFlareItem; -} - -////////////////////////////////////////////////////////////////////////// -CBaseLibrary* CLensFlareManager::MakeNewLibrary() -{ - return new CLensFlareLibrary(this); -} - -////////////////////////////////////////////////////////////////////////// -QString CLensFlareManager::GetRootNodeName() -{ - return "FlareLibs"; -} - -////////////////////////////////////////////////////////////////////////// -QString CLensFlareManager::GetLibsPath() -{ - if (m_libsPath.isEmpty()) - { - m_libsPath += FLARE_LIBS_PATH; - } - - return m_libsPath; -} - -////////////////////////////////////////////////////////////////////////// -bool CLensFlareManager::LoadFlareItemByName(const QString& fullItemName, IOpticsElementBasePtr pDestOptics) -{ - if (pDestOptics == NULL) - { - return false; - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)LoadItemByName(fullItemName); - if (pLensFlareItem == NULL) - { - return false; - } - - LensFlareUtil::CopyOptics(pLensFlareItem->GetOptics(), pDestOptics, true); - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CLensFlareManager::Modified() -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - if (pEditor->GetCurrentLibrary()) - { - pEditor->GetCurrentLibrary()->SetModified(true); - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseLibrary* CLensFlareManager::LoadLibrary(const QString& filename, [[maybe_unused]] bool bReload) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - - QString fileNameWithGameFolder(filename); - - fileNameWithGameFolder.replace('\\', '/'); - - int nGamePathLength = static_cast(Path::GetEditingGameDataFolder().size()); - QString gamePathName; - if (nGamePathLength < filename.length()) - { - gamePathName = filename.left(nGamePathLength); - } - if (gamePathName != Path::GetEditingGameDataFolder().c_str()) - { - fileNameWithGameFolder.insert(0, "/"); - fileNameWithGameFolder.insert(0, Path::GetEditingGameDataFolder().c_str()); - } - - int nLibraryIndex(-1); - bool bSameAsCurrentLibrary(false); - - for (int i = 0; i < m_libs.size(); i++) - { - if (QString::compare(fileNameWithGameFolder, m_libs[i]->GetFilename(), Qt::CaseInsensitive) == 0) - { - IDataBaseLibrary* pExistingLib = m_libs[i]; - for (int j = 0; j < pExistingLib->GetItemCount(); j++) - { - UnregisterItem((CBaseLibraryItem*)pExistingLib->GetItem(j)); - } - pExistingLib->RemoveAllItems(); - nLibraryIndex = i; - if (pEditor) - { - bSameAsCurrentLibrary = pEditor->GetCurrentLibrary() == pExistingLib; - } - break; - } - } - - TSmartPtr pLib = MakeNewLibrary(); - if (!pLib->Load(filename)) - { - Error(QObject::tr("Failed to Load Item Library: %1").arg(filename).toUtf8().data()); - return NULL; - } - - if (nLibraryIndex != -1) - { - m_libs[nLibraryIndex] = pLib; - if (bSameAsCurrentLibrary && pEditor) - { - pEditor->ResetElementTreeControl(); - pEditor->SelectLibrary(pLib, true); - } - } - else - { - m_libs.push_back(pLib); - } - - pLib->SetFilename(filename); - - return pLib; -} - - -bool CLensFlareManager::IsLensFlareLibraryXML(const char* fileSourceFilePath) -{ - if ((!fileSourceFilePath) || (!AZStd::wildcard_match("*.xml", fileSourceFilePath))) - { - return false; - } - - using namespace AZ::IO; - - bool isLensFlareLibrary = false; - - // we are forced to read the asset to discover its type since "xml" was the chosen extension. - SystemFile::SizeType fileSize = SystemFile::Length(fileSourceFilePath); - if (fileSize > 0) - { - AZStd::vector buffer(fileSize + 1); - buffer[fileSize] = 0; - if (!AZ::IO::SystemFile::Read(fileSourceFilePath, buffer.data(), fileSize)) - { - return false; - } - - AZ::rapidxml::xml_document* xmlDoc = azcreate(AZ::rapidxml::xml_document, (), AZ::SystemAllocator, "LensFlareLibrary Temp XML Reader"); - if (xmlDoc->parse(buffer.data())) - { - AZ::rapidxml::xml_node* xmlRootNode = xmlDoc->first_node(); - if (xmlRootNode) - { - if (azstricmp(xmlRootNode->name(), "LensFlareLibrary") == 0) - { - isLensFlareLibrary = true; - } - } - } - - azdestroy(xmlDoc, AZ::SystemAllocator, AZ::rapidxml::xml_document); - } - - return isLensFlareLibrary; -} - - -AzToolsFramework::AssetBrowser::SourceFileDetails CLensFlareManager::GetSourceFileDetails(const char* fullSourceFileName) -{ - if (IsLensFlareLibraryXML(fullSourceFileName)) - { - return AzToolsFramework::AssetBrowser::SourceFileDetails("Icons/AssetBrowser/LensFlare_16.png"); - } - return AzToolsFramework::AssetBrowser::SourceFileDetails(); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.h deleted file mode 100644 index 9cc7c6fad2..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareManager.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREMANAGER_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREMANAGER_H -#pragma once - -#include "BaseLibraryManager.h" -#include - -class IOpticsElementBase; -class CLensFlareEditor; - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -class CRYEDIT_API CLensFlareManager - : public CBaseLibraryManager - , private AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - -{ -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - CLensFlareManager(); - virtual ~CLensFlareManager(); - - void ClearAll(); - - virtual bool LoadFlareItemByName(const QString& fullItemName, IOpticsElementBasePtr pDestOptics); - void Modified(); - //! Path to libraries in this manager. - QString GetLibsPath(); - IDataBaseLibrary* LoadLibrary(const QString& filename, bool bReload = false); - - static bool IsLensFlareLibraryXML(const char* fullFilePath); - -private: - CBaseLibraryItem* MakeNewItem(); - CBaseLibrary* MakeNewLibrary(); - - //! Root node where this library will be saved. - QString GetRootNodeName(); - QString m_libsPath; - - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - // AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - AzToolsFramework::AssetBrowser::SourceFileDetails GetSourceFileDetails(const char* fullSourceFileName) override; - virtual AZ::s32 GetPriority() const override { return 1; } // get our priority in before others. - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -}; - -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREMANAGER_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.h deleted file mode 100644 index 77ca781a30..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREREFERENCETREE_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREREFERENCETREE_H -#pragma once - -class CLensFlareReferenceTree - : public CXTTreeCtrl -{ -public: - - CLensFlareReferenceTree(); - ~CLensFlareReferenceTree(); - -private: - - DECLARE_MESSAGE_MAP() -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREREFERENCETREE_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.cpp deleted file mode 100644 index a6b35eba13..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareUndo.h" - -// Editor -#include "LensFlareEditor.h" -#include "LensFlareItem.h" -#include "LensFlareManager.h" -#include "LensFlareElementTree.h" - - -void RestoreLensFlareItem(CLensFlareItem* pLensFlareItem, IOpticsElementBasePtr pOptics, const QString& flarePathName) -{ - pLensFlareItem->ReplaceOptics(pOptics); - - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor) - { - if (pOptics->GetType() == eFT_Root) - { - pEditor->RenameLensFlareItem(pLensFlareItem, pLensFlareItem->GetGroupName(), LensFlareUtil::GetShortName(flarePathName)); - pEditor->UpdateLensFlareItem(pLensFlareItem); - } - } -} - -void ActivateLensFlareItem(CLensFlareItem* pLensFlareItem, bool bRestoreSelectInfo, const QString& selectedFlareItemName) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - if (pLensFlareItem == pEditor->GetLensFlareElementTree()->GetLensFlareItem()) - { - pEditor->UpdateLensFlareItem(pLensFlareItem); - if (bRestoreSelectInfo) - { - pEditor->SelectItemInLensFlareElementTreeByName(selectedFlareItemName); - } - } -} - -CUndoLensFlareItem::CUndoLensFlareItem(CLensFlareItem* pLensFlareItem, const QString& undoDescription) -{ - if (pLensFlareItem) - { - m_Undo.m_pOptics = LensFlareUtil::CreateOptics(pLensFlareItem->GetOptics()); - m_flarePathName = pLensFlareItem->GetFullName(); - m_Undo.m_bRestoreSelectInfo = false; - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor) - { - m_Undo.m_bRestoreSelectInfo = pEditor->GetSelectedLensFlareName(m_Undo.m_selectedFlareItemName); - } - m_undoDescription = undoDescription; - } -} - -CUndoLensFlareItem::~CUndoLensFlareItem() -{ -} - -void CUndoLensFlareItem::Undo(bool bUndo) -{ - if (bUndo) - { - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathName); - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor && pLensFlareItem) - { - m_Redo.m_bRestoreSelectInfo = false; - m_Redo.m_pOptics = LensFlareUtil::CreateOptics(pLensFlareItem->GetOptics()); - m_Redo.m_bRestoreSelectInfo = pEditor->GetSelectedLensFlareName(m_Redo.m_selectedFlareItemName); - } - } - Restore(m_Undo); -} - -void CUndoLensFlareItem::Redo() -{ - Restore(m_Redo); -} - -void CUndoLensFlareItem::Restore(const SData& data) -{ - if (data.m_pOptics == NULL) - { - return; - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathName); - if (pLensFlareItem == NULL) - { - return; - } - RestoreLensFlareItem(pLensFlareItem, data.m_pOptics, m_flarePathName); - ActivateLensFlareItem(pLensFlareItem, data.m_bRestoreSelectInfo, data.m_selectedFlareItemName); -} - -CUndoRenameLensFlareItem::CUndoRenameLensFlareItem(const QString& oldFullName, const QString& newFullName) -{ - m_undo.m_oldFullItemName = oldFullName; - m_undo.m_newFullItemName = newFullName; -} - -void CUndoRenameLensFlareItem::Undo(bool bUndo) -{ - if (bUndo) - { - m_redo.m_oldFullItemName = m_undo.m_newFullItemName; - m_redo.m_newFullItemName = m_undo.m_oldFullItemName; - } - - Rename(m_undo); -} - -void CUndoRenameLensFlareItem::Redo() -{ - Rename(m_redo); -} - -void CUndoRenameLensFlareItem::Rename(const SUndoDataStruct& data) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(data.m_newFullItemName); - if (pLensFlareItem == NULL) - { - return; - } - - int nDotPos = data.m_oldFullItemName.indexOf("."); - if (nDotPos == -1) - { - return; - } - - QString shortName(LensFlareUtil::GetShortName(data.m_oldFullItemName)); - QString groupName(LensFlareUtil::GetGroupNameFromFullName(data.m_oldFullItemName)); - pEditor->RenameLensFlareItem(pLensFlareItem, groupName, shortName); - if (pLensFlareItem->GetOptics()) - { - pLensFlareItem->GetOptics()->SetName(shortName.toUtf8().data()); - LensFlareUtil::UpdateOpticsName(pLensFlareItem->GetOptics()); - } - pEditor->UpdateLensFlareItem(pLensFlareItem); -} - -CUndoLensFlareElementSelection::CUndoLensFlareElementSelection(CLensFlareItem* pLensFlareItem, const QString& flareTreeItemFullName, const QString& undoDescription) -{ - if (pLensFlareItem) - { - m_flarePathNameForUndo = pLensFlareItem->GetFullName(); - m_flareTreeItemFullNameForUndo = flareTreeItemFullName; - m_undoDescription = undoDescription; - } -} - -void CUndoLensFlareElementSelection::Undo(bool bUndo) -{ - if (bUndo) - { - m_flarePathNameForRedo = m_flarePathNameForUndo; - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor) - { - pEditor->GetSelectedLensFlareName(m_flareTreeItemFullNameForRedo); - } - } - - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathNameForUndo); - if (pLensFlareItem == NULL) - { - return; - } - ActivateLensFlareItem(pLensFlareItem, true, m_flareTreeItemFullNameForUndo); -} - -void CUndoLensFlareElementSelection::Redo() -{ - CLensFlareItem* pLensFlareItem = (CLensFlareItem*)GetIEditor()->GetLensFlareManager()->FindItemByName(m_flarePathNameForRedo); - if (pLensFlareItem == NULL) - { - return; - } - ActivateLensFlareItem(pLensFlareItem, true, m_flareTreeItemFullNameForRedo); -} - -CUndoLensFlareItemSelectionChange::CUndoLensFlareItemSelectionChange(const QString& fullLensFlareItemName, const QString& undoDescription) -{ - m_FullLensFlareItemNameForUndo = fullLensFlareItemName; - m_undoDescription = undoDescription; -} - -void CUndoLensFlareItemSelectionChange::Undo(bool bUndo) -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - - if (bUndo) - { - QString currentFullName; - pEditor->GetFullSelectedFlareItemName(currentFullName); - m_FullLensFlareItemNameForRedo = currentFullName; - } - - pEditor->SelectLensFlareItem(m_FullLensFlareItemNameForUndo); -} - -void CUndoLensFlareItemSelectionChange::Redo() -{ - CLensFlareEditor* pEditor = CLensFlareEditor::GetLensFlareEditor(); - if (pEditor == NULL) - { - return; - } - pEditor->SelectLensFlareItem(m_FullLensFlareItemNameForRedo); -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.h deleted file mode 100644 index cf8f76c321..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUndo.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUNDO_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUNDO_H -#pragma once - -#include "Undo/IUndoObject.h" - -class CLensFlareItem; - -class CUndoLensFlareItem - : public IUndoObject -{ -public: - CUndoLensFlareItem(CLensFlareItem* pGroupItem, const QString& undoDescription = "Undo Lens Flare Tree"); - ~CUndoLensFlareItem(); - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - void Undo(bool bUndo); - void Redo(); - -private: - - QString m_undoDescription; - - struct SData - { - SData() - { - m_pOptics = NULL; - } - - QString m_selectedFlareItemName; - bool m_bRestoreSelectInfo; - IOpticsElementBasePtr m_pOptics; - }; - - QString m_flarePathName; - SData m_Undo; - SData m_Redo; - - void Restore(const SData& data); -}; - -class CUndoRenameLensFlareItem - : public IUndoObject -{ -public: - - CUndoRenameLensFlareItem(const QString& oldFullName, const QString& newFullName); - -protected: - - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - void Undo(bool bUndo); - void Redo(); - -private: - - QString m_undoDescription; - - struct SUndoDataStruct - { - QString m_oldFullItemName; - QString m_newFullItemName; - }; - - void Rename(const SUndoDataStruct& data); - - SUndoDataStruct m_undo; - SUndoDataStruct m_redo; -}; - -class CUndoLensFlareElementSelection - : public IUndoObject -{ -public: - CUndoLensFlareElementSelection(CLensFlareItem* pLensFlareItem, const QString& flareTreeItemFullName, const QString& undoDescription = "Undo Lens Flare Element Tree"); - ~CUndoLensFlareElementSelection(){} - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - void Undo(bool bUndo); - void Redo(); - -private: - - QString m_undoDescription; - - QString m_flarePathNameForUndo; - QString m_flareTreeItemFullNameForUndo; - - QString m_flarePathNameForRedo; - QString m_flareTreeItemFullNameForRedo; -}; - -class CUndoLensFlareItemSelectionChange - : public IUndoObject -{ -public: - CUndoLensFlareItemSelectionChange(const QString& fullLensFlareItemName, const QString& undoDescription = "Undo Lens Flare element selection"); - ~CUndoLensFlareItemSelectionChange(){} - -protected: - int GetSize() - { - return sizeof(*this); - } - QString GetDescription() { return m_undoDescription; }; - - void Undo(bool bUndo); - void Redo(); - -private: - QString m_undoDescription; - QString m_FullLensFlareItemNameForUndo; - QString m_FullLensFlareItemNameForRedo; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUNDO_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.cpp deleted file mode 100644 index e8ff29f987..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareUtil.h" - -// Editor -#include "Clipboard.h" -#include "Objects/EntityObject.h" -#include "Objects/SelectionGroup.h" -#include "Include/IObjectManager.h" - - -namespace LensFlareUtil -{ - IOpticsElementBasePtr CreateOptics(const XmlNodeRef& xmlNode) - { - IOpticsElementBasePtr pOpticsElement = NULL; - - const char* typeName; - if (!xmlNode->getAttr("Type", &typeName)) - { - return NULL; - } - - bool bEnable(true); - xmlNode->getAttr("Enable", bEnable); - - EFlareType flareType; - if (!GetFlareType(typeName, flareType)) - { - return NULL; - } - - pOpticsElement = gEnv->pOpticsManager->Create(flareType); - if (pOpticsElement == NULL) - { - return NULL; - } - - pOpticsElement->SetEnabled(bEnable); - - if (!FillOpticsFromXML(pOpticsElement, xmlNode)) - { - return NULL; - } - - return pOpticsElement; - } - - IOpticsElementBasePtr CreateOptics(IOpticsElementBasePtr pOptics, bool bForceTypeToGroup) - { - if (pOptics == NULL) - { - return NULL; - } - IOpticsElementBasePtr pNewOptics = NULL; - if (bForceTypeToGroup) - { - if (pOptics->GetType() == eFT_Root) - { - pNewOptics = gEnv->pOpticsManager->Create(eFT_Group); - } - } - if (pNewOptics == NULL) - { - pNewOptics = gEnv->pOpticsManager->Create(pOptics->GetType()); - if (pNewOptics == NULL) - { - return NULL; - } - } - CopyOptics(pOptics, pNewOptics, true); - return pNewOptics; - } - - bool FillOpticsFromXML(IOpticsElementBasePtr pOpticsElement, const XmlNodeRef& xmlNode) - { - if (!pOpticsElement) - { - return false; - } - - const char* name; - if (!xmlNode->getAttr("Name", &name)) - { - return false; - } - - const char* typeName; - if (!xmlNode->getAttr("Type", &typeName)) - { - return false; - } - EFlareType flareType; - if (!GetFlareType(typeName, flareType)) - { - return false; - } - if (flareType != pOpticsElement->GetType()) - { - return false; - } - - pOpticsElement->SetName(name); - - bool bEnable(true); - xmlNode->getAttr("Enable", bEnable); - pOpticsElement->SetEnabled(bEnable); - - XmlNodeRef pParamNode = xmlNode->findChild("Params"); - if (pParamNode == NULL) - { - return false; - } - - LensFlareUtil::FillParams(pParamNode, pOpticsElement); - return true; - } - - bool CreateXmlData(IOpticsElementBasePtr pOptics, XmlNodeRef& pOutNode) - { - pOutNode = gEnv->pSystem->CreateXmlNode("FlareItem"); - - if (pOptics == NULL || pOutNode == NULL) - { - return false; - } - - QString typeName; - if (!GetFlareTypeName(typeName, pOptics)) - { - return false; - } - - pOutNode->setAttr("Name", pOptics->GetName().c_str()); - pOutNode->setAttr("Type", typeName.toUtf8().data()); - pOutNode->setAttr("Enable", pOptics->IsEnabled()); - - XmlNodeRef pParamNode = pOutNode->createNode("Params"); - - CVarBlockPtr pVar; - SetVariablesTemplateFromOptics(pOptics, pVar); - - pVar->Serialize(pParamNode, false); - pOutNode->addChild(pParamNode); - - for (int i = 0, iElementCount(pOptics->GetElementCount()); i < iElementCount; ++i) - { - XmlNodeRef pNode = NULL; - IOpticsElementBasePtr pChildOptics = pOptics->GetElementAt(i); - if (!CreateXmlData(pChildOptics, pNode)) - { - continue; - } - - pOutNode->addChild(pNode); - } - - return true; - } - - void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar, std::vector& funcs) - { - if (pOptics == NULL) - { - return; - } - - SetVariablesTemplateFromOptics(pOptics, pRootVar); - - for (int i = 0, iNumVariables(pRootVar->GetNumVariables()); i < iNumVariables; ++i) - { - IVariable* pVariable = pRootVar->GetVariable(i); - if (pVariable == NULL) - { - continue; - } - for (int k = 0, iNumVariables2(pVariable->GetNumVariables()); k < iNumVariables2; ++k) - { - IVariable* pChildVariable(pVariable->GetVariable(k)); - if (pChildVariable == NULL) - { - continue; - } - for (int ii = 0, iSize(funcs.size()); ii < iSize; ++ii) - { - pChildVariable->AddOnSetCallback(funcs[ii]); - } - } - } - } - - extern void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar) - { - if (pOptics == NULL) - { - return; - } - - AZStd::vector paramGroups = pOptics->GetEditorParamGroups(); - pRootVar = new CVarBlock; - - for (int i = 0; i < paramGroups.size(); ++i) - { - CSmartVariableArray variableArray; - FuncVariableGroup* pGroup = ¶mGroups[i]; - if (pGroup == NULL) - { - continue; - } - - QString displayGroupName(pGroup->GetHumanName()); - if (displayGroupName == "Common") - { - FlareInfoArray::Props flareInfo = FlareInfoArray::Get(); - int nTypeIndex = (int)pOptics->GetType(); - if (nTypeIndex >= 0 && nTypeIndex < flareInfo.size) - { - displayGroupName += " : "; - displayGroupName += flareInfo.p[nTypeIndex].name; - } - } - - AddVariable(pRootVar, variableArray, pGroup->GetName(), displayGroupName.toUtf8().data(), ""); - - for (int k = 0; k < pGroup->GetVariableCount(); ++k) - { - IFuncVariable* pFuncVar = pGroup->GetVariable(k); - bool bHardMinLimitation = false; - - const std::pair range(pFuncVar->GetMin(), pFuncVar->GetMax()); - - if (pFuncVar->paramType == e_FLOAT) - { - CSmartVariable floatVar; - AddVariable(variableArray, floatVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - floatVar->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - floatVar->Set(pFuncVar->GetFloat()); - floatVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_INT) - { - CSmartVariable intVar; - AddVariable(variableArray, intVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - - bHardMinLimitation = HaveParameterLowBoundary(pFuncVar->name.c_str()); - intVar->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - - intVar->Set(pFuncVar->GetInt()); - intVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_BOOL) - { - CSmartVariable boolVar; - AddVariable(variableArray, boolVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - boolVar->Set(pFuncVar->GetBool()); - boolVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_VEC2) - { - CSmartVariable vec2Var; - AddVariable(variableArray, vec2Var, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - vec2Var->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - vec2Var->Set(pFuncVar->GetVec2()); - vec2Var->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_VEC3) - { - CSmartVariable vec3Var; - AddVariable(variableArray, vec3Var, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - vec3Var->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - vec3Var->Set(pFuncVar->GetVec3()); - vec3Var->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_VEC4) - { - CSmartVariable vec4Var; - AddVariable(variableArray, vec4Var, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str()); - vec4Var->SetLimits(range.first, range.second, 0, bHardMinLimitation, false); - vec4Var->Set(pFuncVar->GetVec4()); - vec4Var->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_COLOR) - { - CSmartVariable colorVar; - AddVariable(variableArray, colorVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str(), IVariable::DT_COLOR); - ColorF color(pFuncVar->GetColorF()); - Vec3 colorVec3(color.r, color.g, color.b); - colorVar->Set(colorVec3); - colorVar->SetUserData(MakeFuncKey(i, k)); - - CSmartVariable alphaVar; - QString alphaName(pFuncVar->name.c_str()); - alphaName += ".alpha"; - QString alphaHumanName(pFuncVar->humanName.c_str()); - alphaHumanName += " [alpha]"; - AddVariable(variableArray, alphaVar, alphaName.toUtf8().data(), alphaHumanName.toUtf8().data(), pFuncVar->description.c_str()); - alphaVar->SetLimits(0, 255, 0, bHardMinLimitation, false); - alphaVar->Set(color.a * 255.0f); - alphaVar->SetUserData(MakeFuncKey(i, k)); - } - else if (pFuncVar->paramType == e_MATRIX33) - { - // Reserved part - // This part is for future because Matrix33 type is suppose to be provided in a renderer side - } - else if (pFuncVar->paramType == e_TEXTURE2D || pFuncVar->paramType == e_TEXTURE3D || pFuncVar->paramType == e_TEXTURE_CUBE) - { - CSmartVariable textureVar; - ITexture* pTexture = pFuncVar->GetTexture(); - if (pTexture) - { - QString textureName = pTexture->GetName(); - textureVar->Set(textureName); - } - AddVariable(variableArray, textureVar, pFuncVar->name.c_str(), pFuncVar->humanName.c_str(), pFuncVar->description.c_str(), IVariable::DT_TEXTURE); - textureVar->SetUserData(MakeFuncKey(i, k)); - } - } - } - } - - void AddOptics(IOpticsElementBasePtr pParentOptics, const XmlNodeRef& xmlNode) - { - if (xmlNode == NULL) - { - return; - } - - if (strcmp(xmlNode->getTag(), "FlareItem")) - { - return; - } - - IOpticsElementBasePtr pOptics = CreateOptics(xmlNode); - if (pOptics == NULL) - { - return; - } - pParentOptics->AddElement(pOptics); - - for (int i = 0, iChildCount(xmlNode->getChildCount()); i < iChildCount; ++i) - { - AddOptics(pOptics, xmlNode->getChild(i)); - } - } - - void CopyVariable(IFuncVariable* pSrcVar, IFuncVariable* pDestVar) - { - if (!pSrcVar || !pDestVar) - { - return; - } - - if (pSrcVar->paramType != pDestVar->paramType) - { - return; - } - - if (pSrcVar->paramType == e_FLOAT) - { - float value = pSrcVar->GetFloat(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_BOOL) - { - bool value = pSrcVar->GetBool(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_INT) - { - int value = pSrcVar->GetInt(); - if (HaveParameterLowBoundary(pSrcVar->name.c_str())) - { - BoundaryProcess(value); - } - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_VEC2) - { - Vec2 value = pSrcVar->GetVec2(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_VEC3) - { - Vec3 value = pSrcVar->GetVec3(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_VEC4) - { - Vec4 value = pSrcVar->GetVec4(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_COLOR) - { - ColorF value = pSrcVar->GetColorF(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_MATRIX33) - { - Matrix33 value = pSrcVar->GetMatrix33(); - pDestVar->InvokeSetter((void*)&value); - } - else if (pSrcVar->paramType == e_TEXTURE2D || pSrcVar->paramType == e_TEXTURE3D || pSrcVar->paramType == e_TEXTURE_CUBE) - { - ITexture* value = pSrcVar->GetTexture(); - pDestVar->InvokeSetter((void*)value); - } - } - - void CopyOpticsAboutSameOpticsType(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics) - { - if (pSrcOptics->GetType() != pDestOptics->GetType()) - { - return; - } - - AZStd::vector srcVarGroups = pSrcOptics->GetEditorParamGroups(); - AZStd::vector destVarGroups = pDestOptics->GetEditorParamGroups(); - - if (srcVarGroups.size() != destVarGroups.size()) - { - return; - } - - pDestOptics->SetEnabled(pSrcOptics->IsEnabled()); - - for (int i = 0, iVarGroupSize(srcVarGroups.size()); i < iVarGroupSize; ++i) - { - FuncVariableGroup srcVarGroup = srcVarGroups[i]; - FuncVariableGroup destVarGroup = destVarGroups[i]; - - if (srcVarGroup.GetVariableCount() != destVarGroup.GetVariableCount()) - { - continue; - } - - for (int k = 0, iVarSize(srcVarGroup.GetVariableCount()); k < iVarSize; ++k) - { - IFuncVariable* pSrcVar = srcVarGroup.GetVariable(k); - IFuncVariable* pDestVar = destVarGroup.GetVariable(k); - CopyVariable(pSrcVar, pDestVar); - } - } - } - - bool FindGroupByName(AZStd::vector& groupList, const QString& name, int& outIndex) - { - for (int i = 0, iVarGroupSize(groupList.size()); i < iVarGroupSize; ++i) - { - if (name == groupList[i].GetName()) - { - outIndex = i; - return true; - } - } - return false; - } - - void CopyOpticsAboutDifferentOpticsType(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics) - { - if (pSrcOptics->GetType() == pDestOptics->GetType()) - { - return; - } - - AZStd::vector srcVarGroups = pSrcOptics->GetEditorParamGroups(); - AZStd::vector destVarGroups = pDestOptics->GetEditorParamGroups(); - - pDestOptics->SetEnabled(pSrcOptics->IsEnabled()); - - for (int i = 0, iVarGroupSize(destVarGroups.size()); i < iVarGroupSize; ++i) - { - FuncVariableGroup destVarGroup = destVarGroups[i]; - int nIndex = 0; - if (!FindGroupByName(srcVarGroups, destVarGroup.GetName(), nIndex)) - { - continue; - } - FuncVariableGroup srcVarGroup = srcVarGroups[nIndex]; - - for (int k = 0, iVarSize(destVarGroup.GetVariableCount()); k < iVarSize; ++k) - { - IFuncVariable* pDestVar = destVarGroup.GetVariable(k); - IFuncVariable* pSrcVar = srcVarGroup.FindVariable(pDestVar->name.c_str()); - CopyVariable(pSrcVar, pDestVar); - } - } - } - - void CopyOptics(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics, bool bReculsiveCopy) - { - if (pSrcOptics->GetType() == pDestOptics->GetType()) - { - CopyOpticsAboutSameOpticsType(pSrcOptics, pDestOptics); - } - else - { - CopyOpticsAboutDifferentOpticsType(pSrcOptics, pDestOptics); - } - - if (bReculsiveCopy) - { - pDestOptics->RemoveAll(); - for (int i = 0, iChildCount(pSrcOptics->GetElementCount()); i < iChildCount; ++i) - { - IOpticsElementBasePtr pSrcChildOptics = pSrcOptics->GetElementAt(i); - IOpticsElementBasePtr pNewOptics = gEnv->pOpticsManager->Create(pSrcChildOptics->GetType()); - if (pNewOptics == NULL) - { - continue; - } - pNewOptics->SetName(pSrcChildOptics->GetName().c_str()); - CopyOptics(pSrcChildOptics, pNewOptics, bReculsiveCopy); - pDestOptics->AddElement(pNewOptics); - } - } - } - - CEntityObject* GetSelectedLightEntity() - { - CBaseObject* pSelectedObj = GetIEditor()->GetSelectedObject(); - if (pSelectedObj == NULL) - { - return NULL; - } - if (!qobject_cast(pSelectedObj)) - { - return NULL; - } - CEntityObject* pEntity = (CEntityObject*)pSelectedObj; - if (!pEntity->IsLight()) - { - return NULL; - } - return pEntity; - } - - void GetSelectedLightEntities(std::vector& outLightEntities) - { - CSelectionGroup* pSelectionGroup = GetIEditor()->GetSelection(); - if (pSelectionGroup == NULL) - { - return; - } - int nSelectionCount = pSelectionGroup->GetCount(); - outLightEntities.reserve(nSelectionCount); - for (int i = 0; i < nSelectionCount; ++i) - { - CBaseObject* pSelectedObj = pSelectionGroup->GetObject(i); - if (!qobject_cast(pSelectedObj)) - { - continue; - } - CEntityObject* pEntity = (CEntityObject*)pSelectedObj; - if (!pEntity->IsLight()) - { - continue; - } - outLightEntities.push_back(pEntity); - } - } - - IOpticsElementBasePtr GetSelectedLightOptics() - { - CEntityObject* pEntity = GetSelectedLightEntity(); - if (pEntity == NULL) - { - return NULL; - } - IOpticsElementBasePtr pEntityOptics = pEntity->GetOpticsElement(); - if (pEntityOptics == NULL) - { - return NULL; - } - return pEntityOptics; - } - - IOpticsElementBasePtr FindOptics(IOpticsElementBasePtr pStartOptics, const QString& name) - { - if (pStartOptics == NULL) - { - return NULL; - } - - if (!QString::compare(pStartOptics->GetName().c_str(), name)) - { - return pStartOptics; - } - - for (int i = 0, iElementCount(pStartOptics->GetElementCount()); i < iElementCount; ++i) - { - IOpticsElementBasePtr pFoundOptics = FindOptics(pStartOptics->GetElementAt(i), name); - if (pFoundOptics) - { - return pFoundOptics; - } - } - - return NULL; - } - - void RemoveOptics(IOpticsElementBasePtr pOptics) - { - if (pOptics == NULL) - { - return; - } - - IOpticsElementBasePtr pParent = pOptics->GetParent(); - if (pParent == NULL) - { - return; - } - - for (int i = 0, iElementCount(pParent->GetElementCount()); i < iElementCount; ++i) - { - if (pOptics == pParent->GetElementAt(i)) - { - pParent->Remove(i); - break; - } - } - } - - void ChangeOpticsRootName(IOpticsElementBasePtr pOptics, const QString& newRootName) - { - if (pOptics == NULL) - { - return; - } - - QString opticsName = pOptics->GetName().c_str(); - QString opticsRootName; - - int nPos = opticsName.indexOf("."); - if (nPos == -1) - { - opticsRootName = opticsName; - } - else - { - opticsRootName = opticsName.left(nPos); - } - - opticsName.replace(opticsRootName, newRootName); - pOptics->SetName(opticsName.toUtf8().data()); - - for (int i = 0, iElementSize(pOptics->GetElementCount()); i < iElementSize; ++i) - { - ChangeOpticsRootName(pOptics->GetElementAt(i), newRootName); - } - } - - void UpdateClipboard(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList) - { - XmlNodeRef rootNode = CreateXMLFromClipboardData(type, groupName, bPasteAtSameLevel, dataList); - CClipboard clipboard(nullptr); - clipboard.Put(rootNode); - } - - XmlNodeRef CreateXMLFromClipboardData(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList) - { - XmlNodeRef rootNode = gEnv->pSystem->CreateXmlNode(); - rootNode->setTag("FlareDB"); - rootNode->setAttr("Type", type.toUtf8().data()); - rootNode->setAttr("GroupName", groupName.toUtf8().data()); - rootNode->setAttr("PasteAtSameLevel", bPasteAtSameLevel); - - for (int i = 0, iDataSize(dataList.size()); i < iDataSize; ++i) - { - XmlNodeRef xmlNode = gEnv->pSystem->CreateXmlNode(); - xmlNode->setTag("Data"); - dataList[i].FillXmlNode(xmlNode); - rootNode->addChild(xmlNode); - } - - return rootNode; - } - - void UpdateOpticsName(IOpticsElementBasePtr pOptics) - { - if (pOptics == NULL) - { - return; - } - - IOpticsElementBasePtr pParent = pOptics->GetParent(); - if (pParent) - { - QString oldName = pOptics->GetName().c_str(); - QString parentName = pParent->GetName().c_str(); - QString updatedName = parentName + QString(".") + GetShortName(oldName); - pOptics->SetName(updatedName.toUtf8().data()); - } - - for (int i = 0, iElementCount(pOptics->GetElementCount()); i < iElementCount; ++i) - { - UpdateOpticsName(pOptics->GetElementAt(i)); - } - } - - QString ReplaceLastName(const QString& fullName, const QString& shortName) - { - int nPos = fullName.lastIndexOf('.'); - if (nPos == -1) - { - return shortName; - } - QString newName = fullName.left(nPos + 1); - newName += shortName; - return newName; - } - - IFuncVariable* GetFuncVariable(IOpticsElementBasePtr pOptics, int nFuncKey) - { - if (pOptics == NULL) - { - return NULL; - } - - int nGroupIndex = (nFuncKey & 0xFFFF0000) >> 16; - int nVarIndex = (nFuncKey & 0x0000FFFF); - - AZStd::vector paramGroups = pOptics->GetEditorParamGroups(); - - if (nGroupIndex >= paramGroups.size()) - { - return NULL; - } - - FuncVariableGroup* pGroup = ¶mGroups[nGroupIndex]; - if (pGroup == NULL) - { - return NULL; - } - - if (nVarIndex >= pGroup->GetVariableCount()) - { - return NULL; - } - - return pGroup->GetVariable(nVarIndex); - } - - void GetLightEntityObjects(std::vector& outEntityLights) - { - std::vector pEntityObjects; - GetIEditor()->GetObjectManager()->FindObjectsOfType(&CEntityObject::staticMetaObject, pEntityObjects); - for (int i = 0, iObjectSize(pEntityObjects.size()); i < iObjectSize; ++i) - { - CEntityObject* pEntity = (CEntityObject*)pEntityObjects[i]; - if (pEntity == NULL) - { - continue; - } - if (pEntity->CheckFlags(OBJFLAG_DELETED)) - { - continue; - } - if (!pEntity->IsLight()) - { - continue; - } - outEntityLights.push_back(pEntity); - } - } - - void OutputOpticsDebug(IOpticsElementBasePtr pOptics) - { - QString opticsName; - opticsName = QStringLiteral("Optics Name : %1\n").arg(pOptics->GetName().c_str()); - OutputDebugString(opticsName.toUtf8().data()); - - AZStd::vector groupArray(pOptics->GetEditorParamGroups()); - for (int i = 0, iGroupCount(groupArray.size()); i < iGroupCount; ++i) - { - FuncVariableGroup* pGroup = &groupArray[i]; - - QString groupStr; - groupStr = QStringLiteral("\tGroup : %1\n").arg(pGroup->GetName()); - OutputDebugString(groupStr.toUtf8().data()); - - for (int k = 0, iParamCount(pGroup->GetVariableCount()); k < iParamCount; ++k) - { - IFuncVariable* pVar = pGroup->GetVariable(k); - if (pVar == NULL) - { - continue; - } - QString str; - if (pVar->paramType == e_FLOAT) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str()).arg(pVar->GetFloat()); - } - else if (pVar->paramType == e_INT) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str()).arg(pVar->GetInt()); - } - else if (pVar->paramType == e_BOOL) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str(), pVar->GetBool() ? "TRUE" : "FALSE"); - } - else if (pVar->paramType == e_VEC2) - { - str = QStringLiteral("\t\t%1 : %2,%3\n").arg(pVar->name.c_str()).arg(pVar->GetVec2().x).arg(pVar->GetVec2().y); - } - else if (pVar->paramType == e_VEC3) - { - str = QStringLiteral("\t\t%1 : %2,%3,%4\n").arg(pVar->name.c_str()).arg(pVar->GetVec3().x).arg(pVar->GetVec3().y).arg(pVar->GetVec3().z); - } - else if (pVar->paramType == e_VEC4) - { - str = QStringLiteral("\t\t%1 : %2,%3,%4,%5\n").arg(pVar->name.c_str()).arg(pVar->GetVec4().x).arg(pVar->GetVec4().y).arg(pVar->GetVec4().z); - } - else if (pVar->paramType == e_COLOR) - { - str = QStringLiteral("\t\t%1 : %2,%3,%4,%5\n").arg(pVar->name.c_str()).arg(pVar->GetColorF().r).arg(pVar->GetColorF().g).arg(pVar->GetColorF().b).arg(pVar->GetColorF().a); - } - else if (pVar->paramType == e_TEXTURE2D || pVar->paramType == e_TEXTURE3D || pVar->paramType == e_TEXTURE_CUBE) - { - if (pVar->GetTexture()) - { - str = QStringLiteral("\t\t%1 : %2\n").arg(pVar->name.c_str(), pVar->GetTexture()->GetName()); - } - else - { - str = QStringLiteral("\t\t%1 : NULL\n").arg(pVar->name.c_str()); - } - } - OutputDebugString(str.toUtf8().data()); - } - } - - for (int i = 0, iChildCount(pOptics->GetElementCount()); i < iChildCount; ++i) - { - OutputOpticsDebug(pOptics->GetElementAt(i)); - } - } - - void FillParams(XmlNodeRef& paramNode, IOpticsElementBase* pOptics) - { - if (pOptics == NULL) - { - return; - } - AZStd::vector groupArray(pOptics->GetEditorParamGroups()); - for (int i = 0, iGroupCount(paramNode->getChildCount()); i < iGroupCount; ++i) - { - XmlNodeRef groupNode = paramNode->getChild(i); - if (groupNode == NULL) - { - continue; - } - - int nGroupIndex(0); - if (!FindGroup(groupNode->getTag(), pOptics, nGroupIndex)) - { - continue; - } - - FuncVariableGroup* pGroup = &groupArray[nGroupIndex]; - for (int k = 0, iParamCount(pGroup->GetVariableCount()); k < iParamCount; ++k) - { - IFuncVariable* pVar = pGroup->GetVariable(k); - if (pVar == NULL) - { - continue; - } - - if (pVar->paramType == e_FLOAT) - { - float fValue(0); - if (groupNode->getAttr(pVar->name.c_str(), fValue)) - { - pVar->InvokeSetter((void*)&fValue); - } - } - else if (pVar->paramType == e_INT) - { - int nValue(0); - if (groupNode->getAttr(pVar->name.c_str(), nValue)) - { - pVar->InvokeSetter((void*)&nValue); - } - } - else if (pVar->paramType == e_BOOL) - { - bool bValue(false); - if (groupNode->getAttr(pVar->name.c_str(), bValue)) - { - pVar->InvokeSetter((void*)&bValue); - } - } - else if (pVar->paramType == e_VEC2) - { - Vec2 vec2Value; - if (groupNode->getAttr(pVar->name.c_str(), vec2Value)) - { - pVar->InvokeSetter((void*)&vec2Value); - } - } - else if (pVar->paramType == e_VEC3) - { - Vec3 vec3Value; - if (groupNode->getAttr(pVar->name.c_str(), vec3Value)) - { - pVar->InvokeSetter((void*)&vec3Value); - } - } - else if (pVar->paramType == e_VEC4) - { - const char* strVec4Value; - if (groupNode->getAttr(pVar->name.c_str(), &strVec4Value)) - { - Vec4 vec4Value; - ExtractVec4FromString(strVec4Value, vec4Value); - pVar->InvokeSetter((void*)&vec4Value); - } - } - else if (pVar->paramType == e_COLOR) - { - Vec3 vec3Value; - if (!groupNode->getAttr(pVar->name.c_str(), vec3Value)) - { - continue; - } - string alphaStr = string(pVar->name.c_str()) + ".alpha"; - int alpha; - if (!groupNode->getAttr(alphaStr.c_str(), alpha)) - { - continue; - } - ColorF color; - color.r = vec3Value.x; - color.g = vec3Value.y; - color.b = vec3Value.z; - color.a = (float)alpha / 255.0f; - pVar->InvokeSetter((void*)&color); - } - else if (pVar->paramType == e_MATRIX33) - { - //reserved - } - else if (pVar->paramType == e_TEXTURE2D || pVar->paramType == e_TEXTURE3D || pVar->paramType == e_TEXTURE_CUBE) - { - const char* textureName; - if (!groupNode->getAttr(pVar->name.c_str(), &textureName)) - { - continue; - } - ITexture* pTexture = NULL; - if (textureName && strlen(textureName) > 0) - { - pTexture = gEnv->pRenderer->EF_LoadTexture(textureName); - } - pVar->InvokeSetter((void*)pTexture); - if (pTexture) - { - pTexture->Release(); - } - } - } - } - } - - void GetExpandedItemNames(CBaseLibraryItem* item, const QString& groupName, const QString& itemName, QString& outNameWithGroup, QString& outFullName) - { - QString name; - if (!groupName.isEmpty()) - { - name = groupName + "."; - } - name += itemName; - QString fullName = name; - if (item->GetLibrary()) - { - fullName = item->GetLibrary()->GetName() + "." + name; - } - outNameWithGroup = name; - outFullName = fullName; - } - - QModelIndex GetTreeItemByHitTest(QTreeView& treeCtrl) - { - return treeCtrl.indexAt(treeCtrl.mapFromGlobal(QCursor::pos())); - } - - int FindOpticsIndexUnderParentOptics(IOpticsElementBasePtr pOptics, IOpticsElementBasePtr pParentOptics) - { - for (int i = 0, iElementSize(pParentOptics->GetElementCount()); i < iElementSize; ++i) - { - if (pParentOptics->GetElementAt(i) == pOptics) - { - return i + 1; - } - } - return -1; - } -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.h deleted file mode 100644 index d9fb3e380c..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareUtil.h +++ /dev/null @@ -1,363 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUTIL_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUTIL_H -#pragma once - -#include -#include - -#include "Util/Variable.h" - -#include "IFlares.h" -class CEntityObject; - -class QTreeView; - -#define LENSFLARE_ELEMENT_TREE "LensFlareElementTree" -#define LENSFLARE_ITEM_TREE "LensFlareItemTree" -#define FLARECLIPBOARDTYPE_COPY "Copy" -#define FLARECLIPBOARDTYPE_CUT "Cut" - -namespace LensFlareUtil -{ - inline bool IsElement(EFlareType type) - { - return type != eFT__Base__ && type != eFT_Root && type != eFT_Group; - } - inline bool IsGroup(EFlareType type) - { - return type == eFT_Root || type == eFT_Group; - } - inline bool IsValidFlare(EFlareType type) - { - return type >= eFT__Base__ && type < eFT_Max; - } - - inline void AddVariable(CVariableBase& varArray, CVariableBase& var, const char* varName, const char* humanVarName, const char* description, char dataType = IVariable::DT_SIMPLE) - { - if (varName) - { - var.SetName(varName); - } - if (humanVarName) - { - var.SetHumanName(humanVarName); - } - if (description) - { - var.SetDescription(description); - } - var.SetDataType(dataType); - varArray.AddVariable(&var); - } - - inline void AddVariable(CVarBlock* vars, CVariableBase& var, const char* varName, const char* humanVarName, const char* description, unsigned char dataType = IVariable::DT_SIMPLE) - { - if (varName) - { - var.SetName(varName); - } - if (humanVarName) - { - var.SetHumanName(humanVarName); - } - if (description) - { - var.SetDescription(description); - } - var.SetDataType(dataType); - vars->AddVariable(&var); - } - - inline bool GetFlareType(const QString& typeName, EFlareType& outType) - { - FlareInfoArray::Props array = FlareInfoArray::Get(); - for (size_t i = 0; i < array.size; ++i) - { - if (typeName == array.p[i].name) - { - outType = array.p[i].type; - return true; - } - } - return false; - } - - inline bool GetFlareTypeName(QString& outTypeName, IOpticsElementBasePtr pOptics) - { - if (pOptics == NULL) - { - return false; - } - - const FlareInfoArray::Props array = FlareInfoArray::Get(); - for (size_t i = 0; i < array.size; ++i) - { - if (array.p[i].type == pOptics->GetType()) - { - outTypeName = array.p[i].name; - return true; - } - } - - return false; - } - - inline QString GetShortName(const QString& name) - { - int nPos = name.lastIndexOf('.'); - if (nPos == -1) - { - return name; - } - return name.right(name.length() - nPos - 1); - } - - inline QString GetGroupNameFromName(const QString& name) - { - int nPos = name.lastIndexOf('.'); - if (nPos == -1) - { - return name; - } - return name.left(nPos); - } - - inline QString GetGroupNameFromFullName(const QString& fullItemName) - { - int nLastDotPos = fullItemName.lastIndexOf('.'); - if (nLastDotPos == -1) - { - return fullItemName; - } - - QString name = GetGroupNameFromName(fullItemName); - - int nFirstDotPos = name.indexOf('.'); - if (nFirstDotPos == -1) - { - return name; - } - - return name.right(name.length() - nFirstDotPos - 1); - } - - inline bool HaveParameterLowBoundary(const QString& paramName) - { - if (!QString::compare(paramName, "Noiseseed", Qt::CaseInsensitive) || !QString::compare(paramName, "translation", Qt::CaseInsensitive) || !QString::compare(paramName, "position", Qt::CaseInsensitive) || !QString::compare(paramName, "rotation", Qt::CaseInsensitive)) - { - return false; - } - return true; - } - - inline int MakeFuncKey(int nGroupIndex, int nVarIndex) - { - return (nGroupIndex << 16) | nVarIndex; - } - - template - inline void BoundaryProcess(T& fValue) - { - if (fValue < 0) - { - fValue = 0; - } - } - - inline void BoundaryProcess(Vec2& v) - { - if (v.x < 0) - { - v.x = 0; - } - if (v.y < 0) - { - v.y = 0; - } - } - - inline void BoundaryProcess(Vec3& v) - { - if (v.x < 0) - { - v.x = 0; - } - if (v.y < 0) - { - v.y = 0; - } - if (v.z < 0) - { - v.z = 0; - } - } - - inline void BoundaryProcess(Vec4& v) - { - if (v.x < 0) - { - v.x = 0; - } - if (v.y < 0) - { - v.y = 0; - } - if (v.z < 0) - { - v.z = 0; - } - if (v.w < 0) - { - v.w = 0; - } - } - - inline bool ExtractVec4FromString(const string& buffer, Vec4& outVec4) - { - int nCount(0); - string copiedBuffer(buffer); - int commaPos(0); - while (nCount < 4 || commaPos != -1) - { - commaPos = copiedBuffer.find(","); - string strV; - if (commaPos == -1) - { - strV = copiedBuffer; - } - else - { - strV = copiedBuffer.Left(commaPos); - strV += ","; - } - copiedBuffer.replace(0, commaPos + 1, ""); - outVec4[nCount++] = (float)atof(strV.c_str()); - } - return nCount == 4; - } - - void FillParams(XmlNodeRef& paramNode, IOpticsElementBase* pOptics); - - inline bool FindGroup(const char* groupName, IOpticsElementBase* pOptics, int& nOutGroupIndex) - { - if (groupName == NULL) - { - return false; - } - - AZStd::vector groupArray = pOptics->GetEditorParamGroups(); - for (int i = 0, iCount(groupArray.size()); i < iCount; ++i) - { - if (!_stricmp(groupArray[i].GetName(), groupName)) - { - nOutGroupIndex = i; - return true; - } - } - return false; - } - - struct SClipboardData - { - SClipboardData(){} - ~SClipboardData(){} - SClipboardData(const QString& from, const QString& lensFlareFullPath, const QString& lensOpticsPath) - : m_From(from) - , m_LensFlareFullPath(lensFlareFullPath) - , m_LensOpticsPath(lensOpticsPath) - { - } - - void FillXmlNode(XmlNodeRef node) - { - if (node == NULL) - { - return; - } - node->setAttr("From", m_From.toUtf8().data()); - node->setAttr("FlareFullPath", m_LensFlareFullPath.toUtf8().data()); - node->setAttr("OpticsPath", m_LensOpticsPath.toUtf8().data()); - } - - void FillThisFromXmlNode(XmlNodeRef node) - { - if (node == NULL) - { - return; - } - node->getAttr("From", m_From); - node->getAttr("FlareFullPath", m_LensFlareFullPath); - node->getAttr("OpticsPath", m_LensOpticsPath); - } - - QString m_From; - QString m_LensFlareFullPath; - QString m_LensOpticsPath; - }; - - struct SDragAndDropInfo - { - SDragAndDropInfo() - { - m_XMLContents = NULL; - m_bDragging = false; - } - ~SDragAndDropInfo() - { - Reset(); - } - void Reset() - { - m_XMLContents = NULL; - m_bDragging = false; - } - bool m_bDragging; - XmlNodeRef m_XMLContents; - }; - - inline SDragAndDropInfo& GetDragDropInfo() - { - static SDragAndDropInfo dragDropInfo; - return dragDropInfo; - } - - int FindOpticsIndexUnderParentOptics(IOpticsElementBasePtr pOptics, IOpticsElementBasePtr pParentOptics); - bool IsPointInWindow(const QWidget* pWindow, const QPoint& screenPos); - QModelIndex GetTreeItemByHitTest(QTreeView& treeCtrl); - QPoint GetDragCursorPos(QWidget* pWnd, const QPoint& point); - void GetExpandedItemNames(CBaseLibraryItem* item, const QString& groupName, const QString& itemName, QString& outNameWithGroup, QString& outFullName); - void GetSelectedLightEntities(std::vector& outLightEntities); - void GetLightEntityObjects(std::vector& outEntityLights); - IFuncVariable* GetFuncVariable(IOpticsElementBasePtr pOptics, int nFuncKey); - QString ReplaceLastName(const QString& fullName, const QString& shortName); - void UpdateOpticsName(IOpticsElementBasePtr pOptics); - XmlNodeRef CreateXMLFromClipboardData(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList); - void UpdateClipboard(const QString& type, const QString& groupName, bool bPasteAtSameLevel, std::vector& dataList); - void ChangeOpticsRootName(IOpticsElementBasePtr pOptics, const QString& newRootName); - void RemoveOptics(IOpticsElementBasePtr pOptics); - IOpticsElementBasePtr FindOptics(IOpticsElementBasePtr pStartOptics, const QString& name); - CEntityObject* GetSelectedLightEntity(); - IOpticsElementBasePtr GetSelectedLightOptics(); - IOpticsElementBasePtr CreateOptics(const XmlNodeRef& xmlNode); - IOpticsElementBasePtr CreateOptics(IOpticsElementBasePtr pOptics, bool bForceTypeToGroup = false); - bool FillOpticsFromXML(IOpticsElementBasePtr pOptics, const XmlNodeRef& xmlNode); - bool CreateXmlData(IOpticsElementBasePtr pOptics, XmlNodeRef& pOutNode); - void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar, std::vector& funcs); - void SetVariablesTemplateFromOptics(IOpticsElementBasePtr pOptics, CVarBlockPtr& pRootVar); - void CopyOptics(IOpticsElementBasePtr pSrcOptics, IOpticsElementBasePtr pDestOptics, bool bReculsiveCopy = true); - void OutputOpticsDebug(IOpticsElementBasePtr pOptics); -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREUTIL_H diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.cpp b/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.cpp deleted file mode 100644 index 05248b32f5..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "LensFlareView.h" - -// Editor -#include "LensFlareItem.h" -#include "LensFlareEditor.h" -#include "Objects/EntityObject.h" -#include "Material/MaterialManager.h" - - -CLensFlareView::CLensFlareView(QWidget* parent, Qt::WindowFlags f) - : CPreviewModelCtrl(parent, f) -{ - InitDialog(); -} - -CLensFlareView::~CLensFlareView() -{ - CLensFlareEditor::GetLensFlareEditor()->UnregisterLensFlareItemChangeListener(this); -} - -void CLensFlareView::InitDialog() -{ - CLensFlareEditor::GetLensFlareEditor()->RegisterLensFlareItemChangeListener(this); - - SetClearColor(ColorF(0, 0, 0, 0)); - SetGrid(true); - SetAxis(true); - EnableUpdate(true); - m_pLensFlareMaterial = GetIEditor()->GetMaterialManager()->LoadMaterial(CEntityObject::s_LensFlareMaterialName); - m_InitCameraPos = m_camera.GetPosition(); -} - -void CLensFlareView::RenderObject(_smart_ptr pMaterial, [[maybe_unused]] SRenderingPassInfo& passInfo) -{ - if (m_pLensFlareItem) - { - IOpticsElementBasePtr pOptics = m_pLensFlareItem->GetOptics(); - if (pOptics && m_pLensFlareMaterial) - { - _smart_ptr pMaterial = m_pLensFlareMaterial->GetMatInfo(); - if (pMaterial) - { - m_pRenderer->ForceUpdateGlobalShaderParameters(); - m_pRenderer->SetViewport(1, 1, m_pRenderer->GetWidth(), m_pRenderer->GetHeight()); - SShaderItem& shaderItem = pMaterial->GetShaderItem(); - SLensFlareRenderParam param; - param.pCamera = &m_camera; - param.pShader = shaderItem.m_pShader; - pOptics->Render(¶m, Vec3(0, 0, 0)); - } - } - } -} - -void CLensFlareView::OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem) -{ - if (m_pLensFlareItem != pLensFlareItem) - { - m_pLensFlareItem = pLensFlareItem; - Update(true); - m_bHaveAnythingToRender = m_pLensFlareItem != NULL; - } -} - -void CLensFlareView::OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem) -{ - if (m_pLensFlareItem == pLensFlareItem) - { - m_pLensFlareItem = NULL; - Update(); - m_bHaveAnythingToRender = false; - } -} - -void CLensFlareView::OnInternalVariableChange([[maybe_unused]] IVariable* pVar) -{ - Update(); -} - -void CLensFlareView::OnLensFlareChangeElement([[maybe_unused]] CLensFlareElement* pLensFlareElement) -{ - Update(); -} - -void CLensFlareView::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnCloseScene: - ReleaseObject(); - break; - } -} diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.h b/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.h deleted file mode 100644 index f514211046..0000000000 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareView.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREVIEW_H -#define CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREVIEW_H -#pragma once - -#include "ILensFlareListener.h" -#include "Controls/PreviewModelCtrl.h" - -class CLensFlareView - : public CPreviewModelCtrl - , public ILensFlareChangeItemListener - , public ILensFlareChangeElementListener -{ -public: - explicit CLensFlareView(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()); - ~CLensFlareView(); - - void OnInternalVariableChange(IVariable* pVar); - void OnEditorNotifyEvent(EEditorNotifyEvent event); - -protected: - - void InitDialog(); - void ProcessKeys(){} - void RenderObject(_smart_ptr pMaterial, SRenderingPassInfo& passInfo); - - void OnLensFlareChangeItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareDeleteItem(CLensFlareItem* pLensFlareItem); - void OnLensFlareChangeElement(CLensFlareElement* pLensFlareElement); - -private: - - QPoint m_prevPoint; - Vec3 m_InitCameraPos; - - _smart_ptr m_pLensFlareMaterial; - _smart_ptr m_pLensFlareItem; -}; -#endif // CRYINCLUDE_EDITOR_LENSFLAREEDITOR_LENSFLAREVIEW_H diff --git a/Code/Sandbox/Editor/LevelInfo.cpp b/Code/Sandbox/Editor/LevelInfo.cpp index 4b8a6d5cac..81441a3797 100644 --- a/Code/Sandbox/Editor/LevelInfo.cpp +++ b/Code/Sandbox/Editor/LevelInfo.cpp @@ -20,7 +20,6 @@ // Editor #include "Util/fastlib.h" -#include "Material/MaterialManager.h" // for CMaterialManager #include @@ -67,7 +66,6 @@ void CLevelInfo::Validate() // Validate level. ValidateObjects(); - ValidateMaterials(); if (m_pReport->GetErrorCount() == 0) { @@ -186,11 +184,3 @@ void CLevelInfo::ValidateObjects() } } } - -////////////////////////////////////////////////////////////////////////// -void CLevelInfo::ValidateMaterials() -{ - // Validate all objects - CBaseObjectsArray objects; - GetIEditor()->GetMaterialManager()->Validate(); -} diff --git a/Code/Sandbox/Editor/LevelInfo.h b/Code/Sandbox/Editor/LevelInfo.h index 0611ad652e..515a21886e 100644 --- a/Code/Sandbox/Editor/LevelInfo.h +++ b/Code/Sandbox/Editor/LevelInfo.h @@ -27,7 +27,6 @@ public: private: void ValidateObjects(); - void ValidateMaterials(); IErrorReport* m_pReport; }; diff --git a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h index 27ac7e8a46..6659e41122 100644 --- a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h @@ -91,12 +91,10 @@ public: MOCK_METHOD0(GetObjectManager, struct IObjectManager* ()); MOCK_METHOD0(GetSettingsManager, CSettingsManager* ()); MOCK_METHOD1(GetDBItemManager, IDataBaseManager* (EDataBaseItemType)); - MOCK_METHOD0(GetMaterialManager, CMaterialManager* ()); MOCK_METHOD0(GetMaterialManagerLibrary, IBaseLibraryManager* ()); MOCK_METHOD0(GetIEditorMaterialManager, IEditorMaterialManager* ()); MOCK_METHOD0(GetIconManager, IIconManager* ()); MOCK_METHOD0(GetMusicManager, CMusicManager* ()); - MOCK_METHOD0(GetLensFlareManager, CLensFlareManager* ()); MOCK_METHOD2(GetTerrainElevation, float(float , float )); MOCK_METHOD0(GetVegetationMap, class CVegetationMap* ()); MOCK_METHOD0(GetEditorQtApplication, Editor::EditorQtApplication* ()); diff --git a/Code/Sandbox/Editor/Lib/Tests/test_MaterialPythonFuncs.cpp b/Code/Sandbox/Editor/Lib/Tests/test_MaterialPythonFuncs.cpp deleted file mode 100644 index c27608b695..0000000000 --- a/Code/Sandbox/Editor/Lib/Tests/test_MaterialPythonFuncs.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "EditorDefs.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace MaterialPythonFuncsUnitTests -{ - - class MaterialPythonBindingsFixture - : public testing::Test - { - public: - AzToolsFramework::ToolsApplication m_app; - - void SetUp() override - { - AzFramework::Application::Descriptor appDesc; - appDesc.m_enableDrilling = false; - - m_app.Start(appDesc); - // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is - // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash - // in the unit tests. - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); - m_app.RegisterComponentDescriptor(AzToolsFramework::MaterialPythonFuncsHandler::CreateDescriptor()); - } - - void TearDown() override - { - m_app.Stop(); - } - }; - - TEST_F(MaterialPythonBindingsFixture, MaterialEditorCommands_ApiExists) - { - AZ::BehaviorContext* behaviorContext = m_app.GetBehaviorContext(); - ASSERT_TRUE(behaviorContext); - - EXPECT_TRUE(behaviorContext->m_methods.find("create") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("create_multi") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("convert_to_multi") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("duplicate_current") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("merge_selection") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("delete_current") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("get_submaterial") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("get_property") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("set_property") != behaviorContext->m_methods.end()); - } -} diff --git a/Code/Sandbox/Editor/LyViewPaneNames.h b/Code/Sandbox/Editor/LyViewPaneNames.h index 3ea793b9c7..fdbf8bf90c 100644 --- a/Code/Sandbox/Editor/LyViewPaneNames.h +++ b/Code/Sandbox/Editor/LyViewPaneNames.h @@ -44,7 +44,6 @@ namespace LyViewPane static const char* const TerrainTool = "Terrain Tool"; static const char* const TerrainTextureLayers = "Terrain Texture Layers"; static const char* const ParticleEditor = "Particle Editor"; - static const char* const LensFlareEditor = "Lens Flare Editor"; static const char* const TimeOfDayEditor = "Time Of Day"; static const char* const AudioControlsEditor = "Audio Controls Editor"; static const char* const SubstanceEditor = "Substance Editor"; diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index 0ac7da33a7..c266d37282 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -42,7 +42,6 @@ AZ_POP_DISABLE_WARNING #include #include #include -#include // AzToolsFramework #include @@ -91,17 +90,14 @@ AZ_POP_DISABLE_WARNING #include "TrackView/TrackViewDialog.h" #include "ErrorReportDialog.h" -#include "LensFlareEditor/LensFlareEditor.h" #include "TimeOfDayDialog.h" #include "Dialogs/PythonScriptsDialog.h" -#include "Material/MaterialManager.h" #include "EngineSettingsManager.h" #include "AzAssetBrowser/AzAssetBrowserWindow.h" #include "AssetEditor/AssetEditorWindow.h" #include "GridSettingsDialog.h" -#include "MaterialSender.h" #include "ActionManager.h" // uncomment this to show thumbnail demo widget @@ -1096,7 +1092,7 @@ void MainWindow::InitActions() QAction* saveLevelStatsAction = am->AddAction(ID_TOOLS_LOGMEMORYUSAGE, tr("Save Level Statistics")) .SetStatusTip(tr("Logs Editor memory usage.")); - if( saveLevelStatsAction && AZ::Interface::Get()) + if( saveLevelStatsAction ) { saveLevelStatsAction->setEnabled(false); } @@ -1192,13 +1188,6 @@ void MainWindow::InitActions() .SetIcon(Style::icon("Audio")) .SetApplyHoverEffect(); - if (!AZ::Interface::Get()) - { - am->AddAction(ID_TERRAIN_TIMEOFDAYBUTTON, tr("Time of Day Editor")) - .SetToolTip(tr("Open Time of Day")) - .SetApplyHoverEffect(); - } - am->AddAction(ID_OPEN_UICANVASEDITOR, tr(LyViewPane::UiEditor)) .SetToolTip(tr("Open UI Editor")) .SetApplyHoverEffect(); @@ -1655,11 +1644,6 @@ void MainWindow::RegisterStdViewClasses() AzAssetBrowserWindow::RegisterViewClass(); AssetEditorWindow::RegisterViewClass(); - if (!AZ::Interface::Get()) - { - CLensFlareEditor::RegisterViewClass(); - CTimeOfDayDialog::RegisterViewClass(); - } #ifdef ThumbnailDemo ThumbnailsSampleWidget::RegisterViewClass(); #endif diff --git a/Code/Sandbox/Editor/MatEditPreviewDlg.cpp b/Code/Sandbox/Editor/MatEditPreviewDlg.cpp deleted file mode 100644 index 4bac9b5e76..0000000000 --- a/Code/Sandbox/Editor/MatEditPreviewDlg.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MatEditPreviewDlg.h" - -// Qt -#include -#include -#include - -// Editor -#include "Material/MaterialManager.h" -#include "Material/MaterialPreviewModelView.h" - - -///////////////////////////////////////////////////////////////////////////// -// CMatEditPreviewDlg dialog - - -CMatEditPreviewDlg::CMatEditPreviewDlg(QWidget* parent) - : QDialog(parent) -{ - setAttribute(Qt::WA_DeleteOnClose); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - - setWindowTitle(tr("Material Preview")); - - /* create sub controls */ - m_previewCtrl.reset(new MaterialPreviewModelView(this)); - m_menubar.reset(new QMenuBar); - - /* configure layout */ - QVBoxLayout* layout = new QVBoxLayout(); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(m_menubar.data()); - layout->addWidget(m_previewCtrl.data()); - layout->setStretchFactor(m_previewCtrl.data(), 1); - setLayout(layout); - - GetIEditor()->GetMaterialManager()->AddListener(this); - - SetupMenuBar(); - - OnPreviewPlane(); - m_previewCtrl->SetMaterial(GetIEditor()->GetMaterialManager()->GetCurrentMaterial() ? GetIEditor()->GetMaterialManager()->GetCurrentMaterial()->GetMatInfo() : nullptr); - m_previewCtrl->Update(); -} - -CMatEditPreviewDlg::~CMatEditPreviewDlg() -{ - GetIEditor()->GetMaterialManager()->RemoveListener(this); -} - -QSize CMatEditPreviewDlg::sizeHint() const -{ - return QSize(450, 400); -} - -void CMatEditPreviewDlg::showEvent(QShowEvent* e) -{ - QDialog::showEvent(e); - resize(sizeHint()); // Because WindowDecorationWrapper resizes it to the minimum for some reason. -} - -////////////////////////////////////////////////////////////////////////// -void CMatEditPreviewDlg::SetupMenuBar() -{ - QMenu* menu; - QAction* action; - - menu = m_menubar->addMenu(tr("Preview")); - action = menu->addAction(tr("&Plane")); - connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewPlane); - action = menu->addAction(tr("&Sphere")); - connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewSphere); - action = menu->addAction(tr("&Box")); - connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewBox); - action = menu->addAction(tr("&Teapot")); - connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewTeapot); - action = menu->addAction(tr("&Custom")); - connect(action, &QAction::triggered, this, &CMatEditPreviewDlg::OnPreviewCustom); -} - -////////////////////////////////////////////////////////////////////////// -void CMatEditPreviewDlg::OnPreviewSphere() -{ - m_previewCtrl->LoadModelFile("Objects/MtlSphere.cgf"); -} - -////////////////////////////////////////////////////////////////////////// -void CMatEditPreviewDlg::OnPreviewBox() -{ - m_previewCtrl->LoadModelFile("Objects/MtlBox.cgf"); -} - -////////////////////////////////////////////////////////////////////////// -void CMatEditPreviewDlg::OnPreviewTeapot() -{ - m_previewCtrl->LoadModelFile("Objects/MtlTeapot.cgf"); -} - -////////////////////////////////////////////////////////////////////////// -void CMatEditPreviewDlg::OnPreviewPlane() -{ - m_previewCtrl->LoadModelFile("Objects/MtlPlane.cgf"); -} - -////////////////////////////////////////////////////////////////////////// -void CMatEditPreviewDlg::OnPreviewCustom() -{ - const QString fullFileName = - QFileDialog::getOpenFileName(this, tr("Custom Model"), QString(), tr("Objects (*.cgf);;All files (*.*)")); - if (!fullFileName.isNull()) - { - m_previewCtrl->LoadModelFile(fullFileName); - } -} - -///////////////////////////////////////////////////////////////////////////// -// CMatEditPreviewDlg message handlers - -void CMatEditPreviewDlg::OnDataBaseItemEvent([[maybe_unused]] IDataBaseItem* pItem, EDataBaseItemEvent event) -{ - switch (event) - { - case EDB_ITEM_EVENT_SELECTED: - case EDB_ITEM_EVENT_ADD: - case EDB_ITEM_EVENT_CHANGED: - m_previewCtrl->SetMaterial(GetIEditor()->GetMaterialManager()->GetCurrentMaterial() ? GetIEditor()->GetMaterialManager()->GetCurrentMaterial()->GetMatInfo() : nullptr); - break; - case EDB_ITEM_EVENT_DELETE: - m_previewCtrl->SetMaterial(nullptr); - break; - } -} - -#include diff --git a/Code/Sandbox/Editor/MatEditPreviewDlg.h b/Code/Sandbox/Editor/MatEditPreviewDlg.h deleted file mode 100644 index 870d1b901e..0000000000 --- a/Code/Sandbox/Editor/MatEditPreviewDlg.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_MATEDITPREVIEWDLG_H -#define CRYINCLUDE_EDITOR_MATEDITPREVIEWDLG_H - -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include - -#include "IDataBaseManager.h" -#endif - -class MaterialPreviewModelView; -class QMenuBar; - -// MatEditPreviewDlg.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CMatEditPreviewDlg dialog -class CMatEditPreviewDlg - : public QDialog - , public IDataBaseManagerListener -{ - Q_OBJECT - // Construction -public: - CMatEditPreviewDlg(QWidget* parent); // standard constructor - ~CMatEditPreviewDlg(); - - QSize sizeHint() const override; - void showEvent(QShowEvent*) override; - - //Functions - - virtual void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event); - -protected: - void SetupMenuBar(); - -private slots: - void OnPreviewSphere(); - void OnPreviewPlane(); - void OnPreviewBox(); - void OnPreviewTeapot(); - void OnPreviewCustom(); - -private: - QScopedPointer m_previewCtrl; - QScopedPointer m_menubar; -}; - -#endif // CRYINCLUDE_EDITOR_MATEDITPREVIEWDLG_H diff --git a/Code/Sandbox/Editor/Material/Material.cpp b/Code/Sandbox/Editor/Material/Material.cpp deleted file mode 100644 index 3d642a53dd..0000000000 --- a/Code/Sandbox/Editor/Material/Material.cpp +++ /dev/null @@ -1,1982 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "Material.h" - -// Editor -#include "MaterialHelpers.h" -#include "MaterialManager.h" -#include "UsedResources.h" -#include "ErrorReport.h" -#include "Include/ISourceControl.h" -#include "Undo/IUndoObject.h" - - -static SInputShaderResources defaultShaderResource; - -////////////////////////////////////////////////////////////////////////// -CMaterial::CMaterial(const QString& name, int nFlags) - : m_highlightFlags(0) - , m_dccMaterialHash(0) -{ - m_scFileAttributes = SCC_FILE_ATTRIBUTE_NORMAL; - - m_pParent = 0; - - m_shaderResources = defaultShaderResource; - m_shaderResources.m_LMaterial.m_Opacity = 1; - m_shaderResources.m_LMaterial.m_Diffuse.Set(1.0f, 1.0f, 1.0f, 1.0f); - m_shaderResources.m_LMaterial.m_Specular.Set(0.045f, 0.045f, 0.045f, 1.0f); // default 59 spec + div by Gamma exponent -> lin - m_shaderResources.m_LMaterial.m_Smoothness = 10.0f; - - m_mtlFlags = nFlags; - ZeroStruct(m_shaderItem); - - // Default shader. - m_shaderName = "Illum"; - m_nShaderGenMask = 0; - - m_name = name; - m_bRegetPublicParams = true; - m_bKeepPublicParamsValues = false; - m_bIgnoreNotifyChange = false; - m_bDummyMaterial = false; - - m_pMatInfo = NULL; - m_propagationFlags = 0; - - m_allowLayerActivation = true; -} - -CMaterial::CMaterial(const CMaterial& rhs) - : m_scFileAttributes{rhs.m_scFileAttributes} - , m_pParent{nullptr} - , m_shaderResources{rhs.m_shaderResources} - , m_mtlFlags{rhs.m_mtlFlags} - , m_shaderName{rhs.m_shaderName} - , m_nShaderGenMask{rhs.m_nShaderGenMask} - , m_bRegetPublicParams{rhs.m_bRegetPublicParams} - , m_bKeepPublicParamsValues{rhs.m_bKeepPublicParamsValues} - , m_bDummyMaterial{rhs.m_bDummyMaterial} - , m_pMatInfo{nullptr} - , m_propagationFlags{rhs.m_propagationFlags} - , m_allowLayerActivation{rhs.m_allowLayerActivation} - , m_dccMaterialHash(rhs.m_dccMaterialHash) -{ - ZeroStruct(m_shaderItem); - m_name = rhs.m_name; -} - -////////////////////////////////////////////////////////////////////////// -CMaterial::~CMaterial() -{ - if (IsModified()) - { - Save(false); - } - - // Release used shader. - SAFE_RELEASE(m_shaderItem.m_pShader); - SAFE_RELEASE(m_shaderItem.m_pShaderResources); - - if (m_pMatInfo) - { - m_pMatInfo->SetUserData(0); - m_pMatInfo = 0; - } - - if (!m_subMaterials.empty()) - { - for (int i = 0; i < m_subMaterials.size(); i++) - { - if (m_subMaterials[i]) - { - m_subMaterials[i]->m_pParent = NULL; - } - } - - m_subMaterials.clear(); - } - - if (!IsPureChild() && !(GetFlags() & MTL_FLAG_UIMATERIAL)) - { - // Unregister this material from manager. - // Don't use here local variable m_pManager. Manager can be destroyed. - if (GetIEditor()->GetMaterialManager()) - { - GetIEditor()->GetMaterialManager()->DeleteItem(this); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetName(const QString& name) -{ - if (name != m_name) - { - QString oldName = GetFullName(); - m_name = name; - - if (!IsPureChild()) - { - if (GetIEditor()->GetMaterialManager()) - { - GetIEditor()->GetMaterialManager()->OnRenameItem(this, oldName); - } - - if (m_pMatInfo) - { - GetIEditor()->Get3DEngine()->GetMaterialManager()->RenameMaterial(m_pMatInfo, GetName().toUtf8().data()); - } - } - else - { - if (m_pMatInfo) - { - m_pMatInfo->SetName(m_name.toUtf8().data()); - } - } - - NotifyChanged(); - } - - if (m_shaderItem.m_pShaderResources) - { - // Only for correct warning message purposes. - m_shaderItem.m_pShaderResources->SetMaterialName(m_name.toUtf8().data()); - } -} - - -////////////////////////////////////////////////////////////////////////// -QString CMaterial::GetFilename() const -{ - return GetIEditor()->GetMaterialManager()->MaterialToFilename(IsPureChild() && m_pParent ? m_pParent->m_name : m_name); -} - -////////////////////////////////////////////////////////////////////////// -int CMaterial::GetTextureFilenames(QStringList& outFilenames) const -{ - for (auto& iter : m_shaderResources.m_TexturesResourcesMap ) - { - const SEfResTexture* pTexture = (const SEfResTexture*) &(iter.second); - QString name = QtUtil::ToQString(pTexture->m_Name); - if (name.isEmpty()) - { - AZ_Warning("Shaders System", false, "Error: CMaterial::GetTextureFilenames - texture slot name does not exist for slot %d", iter.first ); - continue; - } - - // Collect image filenames - if (IResourceCompilerHelper::IsSourceImageFormatSupported(name.toUtf8().data())) - { - stl::push_back_unique(outFilenames, Path::GamePathToFullPath(name)); - } - - // collect source files used in DCC tools - QString dccFilename; - if (CFileUtil::CalculateDccFilename(name, dccFilename)) - { - stl::push_back_unique(outFilenames, Path::GamePathToFullPath(dccFilename)); - } - } - - if (IsMultiSubMaterial()) - { - for (int i = 0; i < GetSubMaterialCount(); ++i) - { - CMaterial* pSubMtl = GetSubMaterial(i); - if (pSubMtl) - { - pSubMtl->GetTextureFilenames(outFilenames); - } - } - } - - return outFilenames.size(); -} - -////////////////////////////////////////////////////////////////////////// -int CMaterial::GetAnyTextureFilenames(QStringList& outFilenames) const -{ - for ( auto& iter : m_shaderResources.m_TexturesResourcesMap ) - { - QString name = QtUtil::ToQString( iter.second.m_Name); - if (name.isEmpty()) - { - continue; - } - - // Collect any filenames - stl::push_back_unique(outFilenames, Path::GamePathToFullPath(name)); - } - - if (IsMultiSubMaterial()) - { - for (int i = 0; i < GetSubMaterialCount(); ++i) - { - CMaterial* pSubMtl = GetSubMaterial(i); - if (pSubMtl) - { - pSubMtl->GetAnyTextureFilenames(outFilenames); - } - } - } - - return outFilenames.size(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::UpdateFileAttributes(bool useSourceControl) -{ - QString filename = GetFilename(); - if (filename.isEmpty()) - { - return; - } - - m_scFileAttributes = CFileUtil::GetAttributes(filename.toUtf8().data(), useSourceControl); -} - -////////////////////////////////////////////////////////////////////////// -uint32 CMaterial::GetFileAttributes() -{ - if (IsDummy()) - { - return m_scFileAttributes; - } - - if (IsPureChild() && m_pParent) - { - return m_pParent->GetFileAttributes(); - } - - UpdateFileAttributes(); - return m_scFileAttributes; -}; - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetShaderName(const QString& shaderName) -{ - if (m_shaderName != shaderName) - { - m_bRegetPublicParams = true; - m_bKeepPublicParamsValues = false; - - RecordUndo("Change Shader"); - } - - m_shaderName = shaderName; - if (QString::compare(m_shaderName, "nodraw", Qt::CaseInsensitive) == 0) - { - m_mtlFlags |= MTL_FLAG_NODRAW; - } - else - { - m_mtlFlags &= ~MTL_FLAG_NODRAW; - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::CheckSpecialConditions() -{ - if (QString::compare(m_shaderName, "nodraw", Qt::CaseInsensitive) == 0) - { - m_mtlFlags |= MTL_FLAG_NODRAW; - } - else - { - m_mtlFlags &= ~MTL_FLAG_NODRAW; - } - - // If environment texture name have auto/nearest cubemap in it, force material to use auto cube-map for it. - SEfResTexture* pTextureRes = m_shaderResources.GetTextureResource(EFTT_ENV); - if (!pTextureRes) - return; - - if (!pTextureRes->m_Name.empty()) - { - const char* sAtPos; - sAtPos = strstr(pTextureRes->m_Name.c_str(), "auto_2d"); - if (sAtPos) - { - pTextureRes->m_Sampler.m_eTexType = eTT_Auto2D; // Force Auto-2D - } - sAtPos = strstr(pTextureRes->m_Name.c_str(), "nearest_cubemap"); - if (sAtPos) - { - pTextureRes->m_Sampler.m_eTexType = eTT_NearestCube; // Force Nearest Cubemap - } - } - - // Force auto 2D map if user sets texture type - if (pTextureRes->m_Sampler.m_eTexType == eTT_Auto2D) - { - pTextureRes->m_Name = "auto_2d"; - } - - // Force nearest cube map if user sets texture type - if (pTextureRes->m_Sampler.m_eTexType == eTT_NearestCube) - { - pTextureRes->m_Name = "nearest_cubemap"; - m_mtlFlags |= MTL_FLAG_REQUIRE_NEAREST_CUBEMAP; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterial::LoadShader() -{ - if (m_bDummyMaterial) - { - return true; - } - - CheckSpecialConditions(); - - GetIEditor()->GetErrorReport()->SetCurrentValidatorItem(this); - - m_shaderResources.m_ResFlags = m_mtlFlags; - - QString sShader = m_shaderName; - if (sShader.isEmpty()) - { - sShader = ""; - } - - QByteArray n = m_name.toUtf8(); - m_shaderResources.m_szMaterialName = n.data(); - SShaderItem newShaderItem = GetIEditor()->GetRenderer()->EF_LoadShaderItem(sShader.toUtf8().data(), false, 0, &m_shaderResources, m_nShaderGenMask); - - // Shader not found - if (newShaderItem.m_pShader && (newShaderItem.m_pShader->GetFlags() & EF_NOTFOUND) != 0) - { - CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_WARNING, "Failed to load shader \"%s\" in material \"%s\"", newShaderItem.m_pShader->GetName(), m_name.toUtf8().constData()); - } - - // Release previously used shader (Must be After new shader is loaded, for speed). - SAFE_RELEASE(m_shaderItem.m_pShader); - SAFE_RELEASE(m_shaderItem.m_pShaderResources); - - m_shaderItem = newShaderItem; - if (!m_shaderItem.m_pShader) - { - CErrorRecord err; - - err.error = QObject::tr("Failed to Load Shader %1").arg(m_shaderName); - err.pItem = this; - - GetIEditor()->GetErrorReport()->ReportError(err); - GetIEditor()->GetErrorReport()->SetCurrentValidatorItem(NULL); - return false; - } - - IShader* pShader = m_shaderItem.m_pShader; - m_nShaderGenMask = pShader->GetGenerationMask(); - if (pShader->GetFlags() & EF_NOPREVIEW) - { - m_mtlFlags |= MTL_FLAG_NOPREVIEW; - } - else - { - m_mtlFlags &= ~MTL_FLAG_NOPREVIEW; - } - - ////////////////////////////////////////////////////////////////////////// - // Reget shader parms. - ////////////////////////////////////////////////////////////////////////// - if (m_bRegetPublicParams) - { - if (m_bKeepPublicParamsValues) - { - m_bKeepPublicParamsValues = false; - m_publicVarsCache = XmlHelpers::CreateXmlNode("PublicParams"); - - MaterialHelpers::SetXmlFromShaderParams(m_shaderResources, m_publicVarsCache); - } - - m_shaderResources.m_ShaderParams = pShader->GetPublicParams(); - m_bRegetPublicParams = false; - } - - ////////////////////////////////////////////////////////////////////////// - // If we have XML node with public parameters loaded, apply it on shader parms. - ////////////////////////////////////////////////////////////////////////// - if (m_publicVarsCache) - { - MaterialHelpers::SetShaderParamsFromXml(m_shaderResources, m_publicVarsCache); - GetIEditor()->GetMaterialManager()->OnUpdateProperties(this, false); - m_publicVarsCache = 0; - } - - ////////////////////////////////////////////////////////////////////////// - // Set shader parms. - if (m_shaderItem.m_pShaderResources) - { - m_shaderItem.m_pShaderResources->SetShaderParams(&m_shaderResources, m_shaderItem.m_pShader); - } - ////////////////////////////////////////////////////////////////////////// - - gEnv->pRenderer->UpdateShaderItem(&m_shaderItem, nullptr); - - ////////////////////////////////////////////////////////////////////////// - // Set Shader Params for material layers - ////////////////////////////////////////////////////////////////////////// - if (m_pMatInfo) - { - UpdateMatInfo(); - } - - GetIEditor()->GetMaterialManager()->OnLoadShader(this); - GetIEditor()->GetErrorReport()->SetCurrentValidatorItem(NULL); - - return true; -} - -bool CMaterial::LoadMaterialLayers() -{ - if (!m_pMatInfo) - { - return false; - } - - if (m_shaderItem.m_pShader && m_shaderItem.m_pShaderResources) - { - // mask generation for base material shader - uint32 nMaskGenBase = m_shaderItem.m_pShader->GetGenerationMask(); - SShaderGen* pShaderGenBase = m_shaderItem.m_pShader->GetGenerationParams(); - - for (uint32 l(0); l < MTL_LAYER_MAX_SLOTS; ++l) - { - SMaterialLayerResources* pCurrLayer = &m_pMtlLayerResources[l]; - pCurrLayer->m_nFlags |= MTL_FLAG_NODRAW; - if (!pCurrLayer->m_shaderName.isEmpty()) - { - if (QString::compare(pCurrLayer->m_shaderName, "nodraw", Qt::CaseInsensitive) == 0) - { - // no shader = skip layer - pCurrLayer->m_shaderName.clear(); - continue; - } - - IShader* pNewShader = GetIEditor()->GetRenderer()->EF_LoadShader(pCurrLayer->m_shaderName.toUtf8().data(), 0); - - // Check if shader loaded - if (!pNewShader || (pNewShader->GetFlags() & EF_NOTFOUND) != 0) - { - CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_WARNING, "Failed to load material layer shader \"%s\" in material \"%s\"", pCurrLayer->m_shaderName.toUtf8().constData(), m_pMatInfo->GetName()); - if (!pNewShader) - { - continue; - } - } - - if (!pCurrLayer->m_pMatLayer) - { - pCurrLayer->m_pMatLayer = m_pMatInfo->CreateLayer(); - } - - // mask generation for base material shader - uint64 nMaskGenLayer = 0; - SShaderGen* pShaderGenLayer = pNewShader->GetGenerationParams(); - if (pShaderGenBase && pShaderGenLayer) - { - for (int nLayerBit(0); nLayerBit < pShaderGenLayer->m_BitMask.size(); ++nLayerBit) - { - SShaderGenBit* pLayerBit = pShaderGenLayer->m_BitMask[nLayerBit]; - - for (int nBaseBit(0); nBaseBit < pShaderGenBase->m_BitMask.size(); ++nBaseBit) - { - SShaderGenBit* pBaseBit = pShaderGenBase->m_BitMask[nBaseBit]; - - // Need to check if flag name is common to both shaders (since flags values can be different), if so activate it on this layer - if (nMaskGenBase & pBaseBit->m_Mask) - { - if (!pLayerBit->m_ParamName.empty() && !pBaseBit->m_ParamName.empty()) - { - if (pLayerBit->m_ParamName == pBaseBit->m_ParamName) - { - nMaskGenLayer |= pLayerBit->m_Mask; - break; - } - } - } - } - } - } - - // Reload with proper flags - SShaderItem newShaderItem = GetIEditor()->GetRenderer()->EF_LoadShaderItem(pCurrLayer->m_shaderName.toUtf8().data(), false, 0, &pCurrLayer->m_shaderResources, nMaskGenLayer); - if (!newShaderItem.m_pShader || (newShaderItem.m_pShader->GetFlags() & EF_NOTFOUND) != 0) - { - CryWarning(VALIDATOR_MODULE_EDITOR, VALIDATOR_WARNING, "Failed to load material layer shader \"%s\" in material \"%s\"", pCurrLayer->m_shaderName.toUtf8().data(), m_pMatInfo->GetName()); - if (!newShaderItem.m_pShader) - { - continue; - } - } - - SShaderItem& pCurrShaderItem = pCurrLayer->m_pMatLayer->GetShaderItem(); - - if (newShaderItem.m_pShader) - { - newShaderItem.m_pShader->AddRef(); - } - - // Release previously used shader (Must be After new shader is loaded, for speed). - SAFE_RELEASE(pCurrShaderItem.m_pShader); - SAFE_RELEASE(pCurrShaderItem.m_pShaderResources); - SAFE_RELEASE(newShaderItem.m_pShaderResources); - - pCurrShaderItem.m_pShader = newShaderItem.m_pShader; - // Copy resources from base material - pCurrShaderItem.m_pShaderResources = m_shaderItem.m_pShaderResources->Clone(); - pCurrShaderItem.m_nTechnique = newShaderItem.m_nTechnique; - pCurrShaderItem.m_nPreprocessFlags = newShaderItem.m_nPreprocessFlags; - - // set default params - if (pCurrLayer->m_bRegetPublicParams) - { - pCurrLayer->m_shaderResources.m_ShaderParams = pCurrShaderItem.m_pShader->GetPublicParams(); - } - - pCurrLayer->m_bRegetPublicParams = false; - - if (pCurrLayer->m_publicVarsCache) - { - MaterialHelpers::SetShaderParamsFromXml(pCurrLayer->m_shaderResources, pCurrLayer->m_publicVarsCache); - pCurrLayer->m_publicVarsCache = 0; - } - - if (pCurrShaderItem.m_pShaderResources) - { - pCurrShaderItem.m_pShaderResources->SetShaderParams(&pCurrLayer->m_shaderResources, pCurrShaderItem.m_pShader); - } - - // Activate layer - pCurrLayer->m_nFlags &= ~MTL_FLAG_NODRAW; - } - } - - return true; - } - - return false; -} - -////////////////////////////////////////////////////////////////////////// - -void CMaterial::UpdateMaterialLayers() -{ - if (m_pMatInfo && m_shaderItem.m_pShaderResources) - { - m_pMatInfo->SetLayerCount(MTL_LAYER_MAX_SLOTS); - - uint8 nMaterialLayerFlags = 0; - - for (int l(0); l < MTL_LAYER_MAX_SLOTS; ++l) - { - SMaterialLayerResources* pCurrLayer = &m_pMtlLayerResources[l]; - if (pCurrLayer && !pCurrLayer->m_shaderName.isEmpty() && pCurrLayer->m_pMatLayer) - { - pCurrLayer->m_pMatLayer->SetFlags(pCurrLayer->m_nFlags); - m_pMatInfo->SetLayer(l, pCurrLayer->m_pMatLayer); - - if ((pCurrLayer->m_nFlags & MTL_LAYER_USAGE_NODRAW)) - { - if (!QString::compare(pCurrLayer->m_shaderName, "frozenlayerwip", Qt::CaseInsensitive)) - { - nMaterialLayerFlags |= MTL_LAYER_FROZEN; - } - } - } - } - - if (m_shaderItem.m_pShaderResources) - { - m_shaderItem.m_pShaderResources->SetMtlLayerNoDrawFlags(nMaterialLayerFlags); - } - } -} - -void CMaterial::UpdateMatInfo() -{ - if (m_pMatInfo) - { - // Mark material invalid. - m_pMatInfo->SetFlags(m_mtlFlags); - m_pMatInfo->SetShaderItem(m_shaderItem); - m_pMatInfo->SetShaderName(m_shaderName.toUtf8().constData()); - m_pMatInfo->SetSurfaceType(m_surfaceType.toUtf8().constData()); - - LoadMaterialLayers(); - UpdateMaterialLayers(); - - m_pMatInfo->SetMaterialLinkName(m_linkedMaterial.toUtf8().data()); - - if (IsMultiSubMaterial()) - { - m_pMatInfo->SetSubMtlCount(m_subMaterials.size()); - for (unsigned int i = 0; i < m_subMaterials.size(); i++) - { - if (m_subMaterials[i]) - { - m_pMatInfo->SetSubMtl(i, m_subMaterials[i]->GetMatInfo()); - } - else - { - m_pMatInfo->SetSubMtl(i, NULL); - } - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -CVarBlock* CMaterial::GetPublicVars(SInputShaderResources& pShaderResources) -{ - return MaterialHelpers::GetPublicVars(pShaderResources); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetShaderParamPublicScript() -{ - IShader* pShader = m_shaderItem.m_pShader; - - if (!pShader) - { - return; - } - - if (m_shaderResources.m_ShaderParams.size() == 0 || pShader->GetPublicParams().size() == 0) - { - return; - } - - // We want to inspect public shader param and paste the m_script into our shader resource param script - for (int i = 0; i < m_shaderResources.m_ShaderParams.size(); ++i) - { - SShaderParam ¤tShaderParam = m_shaderResources.m_ShaderParams.at(i); - for (int j = 0; j < pShader->GetPublicParams().size(); ++j) - { - const SShaderParam &publicShaderParam = pShader->GetPublicParams().at(j); - if ((currentShaderParam.m_Name == publicShaderParam.m_Name) && (currentShaderParam.m_Type == publicShaderParam.m_Type)) - { - currentShaderParam.m_Script = publicShaderParam.m_Script; - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetPublicVars(CVarBlock* pPublicVars, CMaterial* pMtl) -{ - if (!pMtl->GetShaderResources().m_ShaderParams.empty()) - { - RecordUndo("Set Public Vars"); - } - - MaterialHelpers::SetPublicVars(pPublicVars, pMtl->GetShaderResources(), pMtl->GetShaderItem().m_pShaderResources, pMtl->GetShaderItem().m_pShader); - - GetIEditor()->GetMaterialManager()->OnUpdateProperties(this, false); -} - -////////////////////////////////////////////////////////////////////////// -CVarBlock* CMaterial::GetShaderGenParamsVars() -{ - return MaterialHelpers::GetShaderGenParamsVars(GetShaderItem().m_pShader, m_nShaderGenMask); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetShaderGenParamsVars(CVarBlock* pBlock) -{ - RecordUndo("Change Shader GenMask"); - - uint64 nGenMask = MaterialHelpers::SetShaderGenParamsVars(GetShaderItem().m_pShader, pBlock); - if (m_nShaderGenMask != nGenMask) - { - m_bRegetPublicParams = true; - m_bKeepPublicParamsValues = true; - m_nShaderGenMask = nGenMask; - } -} - -////////////////////////////////////////////////////////////////////////// -unsigned int CMaterial::GetTexmapUsageMask() const -{ - int mask = 0; - if (m_shaderItem.m_pShader) - { - IShader* pTempl = m_shaderItem.m_pShader; - if (pTempl) - { - mask = pTempl->GetUsedTextureTypes(); - } - } - return mask; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::Update() -{ - // Reload shader item with new resources and shader. - LoadShader(); - - // Mark library as modified. - SetModified(); - - GetIEditor()->SetModifiedFlag(); - - // When modifying pure child, mark his parent as modified. - if (IsPureChild() && m_pParent) - { - m_pParent->SetModified(); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -void CMaterial::Serialize(SerializeContext& ctx) -{ - //CBaseLibraryItem::Serialize( ctx ); - - XmlNodeRef node = ctx.node; - if (ctx.bLoading) - { - m_bIgnoreNotifyChange = true; - m_bRegetPublicParams = true; - - SInputShaderResources& sr = m_shaderResources; - m_shaderResources = defaultShaderResource; - - // Loading - int flags = m_mtlFlags; - if (node->getAttr("MtlFlags", flags)) - { - m_mtlFlags &= ~(MTL_FLAGS_SAVE_MASK); - m_mtlFlags |= (flags & (MTL_FLAGS_SAVE_MASK)); - } - - uint32 dccMaterialHash = 0; - node->getAttr("DccMaterialHash", dccMaterialHash); - SetDccMaterialHash(dccMaterialHash); - - if (!IsMultiSubMaterial()) - { - node->getAttr("Shader", m_shaderName); - node->getAttr("GenMask", m_nShaderGenMask); - - if (!(m_mtlFlags & MTL_64BIT_SHADERGENMASK)) - { - uint32 nShaderGenMask = 0; - node->getAttr("GenMask", nShaderGenMask); - m_nShaderGenMask = nShaderGenMask; - } - else - { - node->getAttr("GenMask", m_nShaderGenMask); - } - - // Remap flags if needed - if (!(m_mtlFlags & MTL_64BIT_SHADERGENMASK)) - { - m_nShaderGenMask = GetIEditor()->GetRenderer()->EF_GetRemapedShaderMaskGen(m_shaderName.toUtf8().data(), m_nShaderGenMask); - m_mtlFlags |= MTL_64BIT_SHADERGENMASK; - } - - if (node->getAttr("StringGenMask", m_pszShaderGenMask)) - { - m_nShaderGenMask = GetIEditor()->GetRenderer()->EF_GetShaderGlobalMaskGenFromString(m_shaderName.toUtf8().data(), m_pszShaderGenMask.toUtf8().data(), m_nShaderGenMask); // get common mask gen - } - else - { - // version doens't has string gen mask yet ? Remap flags if needed - m_nShaderGenMask = GetIEditor()->GetRenderer()->EF_GetRemapedShaderMaskGen(m_shaderName.toUtf8().data(), m_nShaderGenMask, ((m_mtlFlags & MTL_64BIT_SHADERGENMASK) != 0)); - } - m_mtlFlags |= MTL_64BIT_SHADERGENMASK; - - node->getAttr("SurfaceType", m_surfaceType); - node->getAttr("LayerAct", m_allowLayerActivation); - - MaterialHelpers::SetLightingFromXml(sr, node); - - MaterialHelpers::SetTexturesFromXml(sr, node); - MaterialHelpers::MigrateXmlLegacyData(sr, node); - } - - ////////////////////////////////////////////////////////////////////////// - // Check if we have a link name and if any propagation settings were - // present - ////////////////////////////////////////////////////////////////////////// - XmlNodeRef pLinkName = node->findChild("MaterialLinkName"); - if (pLinkName) - { - m_linkedMaterial = pLinkName->getAttr("name"); - } - else - { - m_linkedMaterial = QString(); - } - - XmlNodeRef pPropagationFlags = node->findChild("MaterialPropagationFlags"); - if (pPropagationFlags) - { - pPropagationFlags->getAttr("flags", m_propagationFlags); - } - else - { - m_propagationFlags = 0; - } - - ////////////////////////////////////////////////////////////////////////// - // Check if we have vertex deform. - ////////////////////////////////////////////////////////////////////////// - MaterialHelpers::SetVertexDeformFromXml(m_shaderResources, node); - - // Serialize sub materials. - - const auto ResizeSubMaterials = [this](size_t count) - { - for (size_t i = count; i < m_subMaterials.size(); ++i) - { - if (auto& pSubMtl = m_subMaterials[i]) - { - pSubMtl->m_pParent = nullptr; - } - } - m_subMaterials.resize(count); - }; - - XmlNodeRef childsNode = node->findChild("SubMaterials"); - if (childsNode && !ctx.bIgnoreChilds) - { - QString name; - int nSubMtls = childsNode->getChildCount(); - ResizeSubMaterials(nSubMtls); - for (int i = 0; i < nSubMtls; i++) - { - auto& pSubMtl = m_subMaterials[i]; - XmlNodeRef mtlNode = childsNode->getChild(i); - if (mtlNode->isTag("Material")) - { - mtlNode->getAttr("Name", name); - if (pSubMtl && pSubMtl->IsPureChild()) - { - pSubMtl->SetName(name); - } - else - { - if (pSubMtl) - { - pSubMtl->m_pParent = nullptr; - } - - pSubMtl = new CMaterial(name, MTL_FLAG_PURE_CHILD); - pSubMtl->m_pParent = this; - } - - SerializeContext childCtx(ctx); - childCtx.node = mtlNode; - pSubMtl->Serialize(childCtx); - - pSubMtl->m_shaderResources.m_SortPrio = nSubMtls - i - 1; - } - else - { - if (pSubMtl) - { - pSubMtl->m_pParent = nullptr; - pSubMtl = nullptr; - } - - if (mtlNode->getAttr("Name", name)) - { - CMaterial* pMtl = GetIEditor()->GetMaterialManager()->LoadMaterial(name); - if (pMtl && !pMtl->IsMultiSubMaterial()) - { - pSubMtl = pMtl; - } - } - } - } - - m_subMaterials.erase(std::remove(m_subMaterials.begin(), m_subMaterials.end(), nullptr), m_subMaterials.end()); - } - else - { - ResizeSubMaterials(0); - } - - UpdateMatInfo(); - - ////////////////////////////////////////////////////////////////////////// - // Load public parameters. - ////////////////////////////////////////////////////////////////////////// - m_publicVarsCache = node->findChild("PublicParams"); - - ////////////////////////////////////////////////////////////////////////// - // Load material layers data - ////////////////////////////////////////////////////////////////////////// - XmlNodeRef mtlLayersNode = node->findChild("MaterialLayers"); - if (mtlLayersNode) - { - int nChildCount = min((int) MTL_LAYER_MAX_SLOTS, (int) mtlLayersNode->getChildCount()); - for (int l = 0; l < nChildCount; ++l) - { - XmlNodeRef layerNode = mtlLayersNode->getChild(l); - if (layerNode) - { - if (layerNode->getAttr("Name", m_pMtlLayerResources[l].m_shaderName)) - { - m_pMtlLayerResources[l].m_bRegetPublicParams = true; - - bool bNoDraw = false; - layerNode->getAttr("NoDraw", bNoDraw); - - m_pMtlLayerResources[l].m_publicVarsCache = layerNode->findChild("PublicParams"); - - if (bNoDraw) - { - m_pMtlLayerResources[l].m_nFlags |= MTL_LAYER_USAGE_NODRAW; - } - else - { - m_pMtlLayerResources[l].m_nFlags &= ~MTL_LAYER_USAGE_NODRAW; - } - - - bool bFadeOut = false; - layerNode->getAttr("FadeOut", bFadeOut); - if (bFadeOut) - { - m_pMtlLayerResources[l].m_nFlags |= MTL_LAYER_USAGE_FADEOUT; - } - else - { - m_pMtlLayerResources[l].m_nFlags &= ~MTL_LAYER_USAGE_FADEOUT; - } - } - } - } - } - - if (ctx.bUndo) - { - LoadShader(); - UpdateMatInfo(); - } - - m_bIgnoreNotifyChange = false; - - // If copy pasting or undo send update event. - if (ctx.bCopyPaste || ctx.bUndo) - { - NotifyChanged(); - } - - // NotifyChanged calls SetModified but since we just loaded it, its not actually changed. - SetModified(false); - } - else // If !ctx.bLoading - { - int extFlags = MTL_64BIT_SHADERGENMASK; - { - const QString& name = GetName(); - const size_t len = name.length(); - if (len > 4 && strstri(name.toUtf8().data() + (len - 4), "_con")) - { - extFlags |= MTL_FLAG_CONSOLE_MAT; - } - } - - // Saving. - node->setAttr("MtlFlags", m_mtlFlags | extFlags); - node->setAttr("DccMaterialHash", GetDccMaterialHash()); - - if (!IsMultiSubMaterial()) - { - // store shader gen bit mask string - m_pszShaderGenMask = GetIEditor()->GetRenderer()->EF_GetStringFromShaderGlobalMaskGen(m_shaderName.toUtf8().data(), m_nShaderGenMask).c_str(); - - node->setAttr("Shader", m_shaderName.toUtf8().data()); - node->setAttr("GenMask", m_nShaderGenMask); - node->setAttr("StringGenMask", m_pszShaderGenMask.toUtf8().data()); - node->setAttr("SurfaceType", m_surfaceType.toUtf8().data()); - - //if (!m_shaderName.IsEmpty() && (stricmp(m_shaderName,"nodraw") != 0)) - { - MaterialHelpers::SetXmlFromLighting(m_shaderResources, node); - MaterialHelpers::SetXmlFromTextures(m_shaderResources, node); - } - } - - ////////////////////////////////////////////////////////////////////////// - // Save out the link name if present and the propagation flags - ////////////////////////////////////////////////////////////////////////// - if (!m_linkedMaterial.isEmpty()) - { - XmlNodeRef pLinkName = node->newChild("MaterialLinkName"); - pLinkName->setAttr("name", m_linkedMaterial.toUtf8().data()); - } - - if (m_propagationFlags) - { - XmlNodeRef pPropagationFlags = node->newChild("MaterialPropagationFlags"); - pPropagationFlags->setAttr("flags", m_propagationFlags); - } - - ////////////////////////////////////////////////////////////////////////// - // Check if we have vertex deform. - ////////////////////////////////////////////////////////////////////////// - MaterialHelpers::SetXmlFromVertexDeform(m_shaderResources, node); - - if (GetSubMaterialCount() > 0) - { - // Serialize sub materials. - - // Let's not serialize empty submaterials at the end of the list. - // Note that IDs of the remaining submaterials stay intact. - int count = GetSubMaterialCount(); - while (count > 0 && !GetSubMaterial(count - 1)) - { - --count; - } - - XmlNodeRef childsNode = node->newChild("SubMaterials"); - - for (int i = 0; i < count; ++i) - { - CMaterial* const pSubMtl = GetSubMaterial(i); - if (pSubMtl && pSubMtl->IsPureChild()) - { - XmlNodeRef mtlNode = childsNode->newChild("Material"); - mtlNode->setAttr("Name", pSubMtl->GetName().toUtf8().data()); - SerializeContext childCtx(ctx); - childCtx.node = mtlNode; - pSubMtl->Serialize(childCtx); - } - else - { - XmlNodeRef mtlNode = childsNode->newChild("MaterialRef"); - if (pSubMtl) - { - mtlNode->setAttr("Name", pSubMtl->GetName().toUtf8().data()); - } - } - } - } - - ////////////////////////////////////////////////////////////////////////// - // Save public parameters. - ////////////////////////////////////////////////////////////////////////// - if (m_publicVarsCache) - { - node->addChild(m_publicVarsCache); - } - else if (!m_shaderResources.m_ShaderParams.empty()) - { - XmlNodeRef publicsNode = node->newChild("PublicParams"); - MaterialHelpers::SetXmlFromShaderParams(m_shaderResources, publicsNode); - } - - ////////////////////////////////////////////////////////////////////////// - // Save material layers data - ////////////////////////////////////////////////////////////////////////// - - bool bMaterialLayers = false; - for (int l(0); l < MTL_LAYER_MAX_SLOTS; ++l) - { - if (!m_pMtlLayerResources[l].m_shaderName.isEmpty()) - { - bMaterialLayers = true; - break; - } - } - - if (bMaterialLayers) - { - XmlNodeRef mtlLayersNode = node->newChild("MaterialLayers"); - for (int l(0); l < MTL_LAYER_MAX_SLOTS; ++l) - { - XmlNodeRef layerNode = mtlLayersNode->newChild("Layer"); - if (!m_pMtlLayerResources[l].m_shaderName.isEmpty()) - { - layerNode->setAttr("Name", m_pMtlLayerResources[l].m_shaderName.toUtf8().data()); - layerNode->setAttr("NoDraw", m_pMtlLayerResources[l].m_nFlags & MTL_LAYER_USAGE_NODRAW); - layerNode->setAttr("FadeOut", m_pMtlLayerResources[l].m_nFlags & MTL_LAYER_USAGE_FADEOUT); - - if (m_pMtlLayerResources[l].m_publicVarsCache) - { - layerNode->addChild(m_pMtlLayerResources[l].m_publicVarsCache); - } - else if (!m_pMtlLayerResources[l].m_shaderResources.m_ShaderParams.empty()) - { - XmlNodeRef publicsNode = layerNode->newChild("PublicParams"); - MaterialHelpers::SetXmlFromShaderParams(m_pMtlLayerResources[l].m_shaderResources, publicsNode); - } - } - } - } - - if (GetSubMaterialCount() == 0 || GetParent()) - { - node->setAttr("LayerAct", m_allowLayerActivation); - } - } -} - -/* -////////////////////////////////////////////////////////////////////////// -void CMaterial::SerializePublics( XmlNodeRef &node,bool bLoading ) -{ -if (bLoading) -{ -} -else -{ -if (m_shaderParams.empty()) -return; -XmlNodeRef publicsNode = node->newChild( "PublicParams" ); - -for (int i = 0; i < m_shaderParams.size(); i++) -{ -XmlNodeRef paramNode = node->newChild( "Param" ); -SShaderParam *pParam = &m_shaderParams[i]; -paramNode->setAttr( "Name",pParam->m_Name ); -switch (pParam->m_Type) -{ -case eType_BYTE: -paramNode->setAttr( "Value",(int)pParam->m_Value.m_Byte ); -paramNode->setAttr( "Type",(int)pParam->m_Value.m_Byte ); -break; -case eType_SHORT: -paramNode->setAttr( "Value",(int)pParam->m_Value.m_Short ); -break; -case eType_INT: -paramNode->setAttr( "Value",(int)pParam->m_Value.m_Int ); -break; -case eType_FLOAT: -paramNode->setAttr( "Value",pParam->m_Value.m_Float ); -break; -case eType_STRING: -paramNode->setAttr( "Value",pParam->m_Value.m_String ); -break; -case eType_FCOLOR: -paramNode->setAttr( "Value",Vec3(pParam->m_Value.m_Color[0],pParam->m_Value.m_Color[1],pParam->m_Value.m_Color[2]) ); -break; -case eType_VECTOR: -paramNode->setAttr( "Value",Vec3(pParam->m_Value.m_Vector[0],pParam->m_Value.m_Vector[1],pParam->m_Value.m_Vector[2]) ); -break; -} -} -} -} -*/ - -////////////////////////////////////////////////////////////////////////// -void CMaterial::AssignToEntity(IRenderNode* pEntity) -{ - assert(pEntity); - pEntity->SetMaterial(GetMatInfo()); -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterial::IsBreakable2D() const -{ - if ((GetFlags() & MTL_FLAG_NODRAW) != 0) - { - return false; - } - - const QString& surfaceTypeName = GetSurfaceTypeName(); - if (ISurfaceTypeManager* pSurfaceManager = GetIEditor()->Get3DEngine()->GetMaterialManager()->GetSurfaceTypeManager()) - { - ISurfaceType* pSurfaceType = pSurfaceManager->GetSurfaceTypeByName(surfaceTypeName.toUtf8().data()); - if (pSurfaceType && pSurfaceType->GetBreakable2DParams() != 0) - { - return true; - } - } - - int count = GetSubMaterialCount(); - for (int i = 0; i < count; ++i) - { - const CMaterial* pSub = GetSubMaterial(i); - if (!pSub) - { - continue; - } - if (pSub->IsBreakable2D()) - { - return true; - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetFromMatInfo(_smart_ptr pMatInfo) -{ - assert(pMatInfo); - - m_shaderName = ""; - - ClearMatInfo(); - SetModified(true); - - m_mtlFlags = pMatInfo->GetFlags(); - if (m_mtlFlags & MTL_FLAG_MULTI_SUBMTL) - { - // Create sub materials. - SetSubMaterialCount(pMatInfo->GetSubMtlCount()); - for (int i = 0; i < GetSubMaterialCount(); i++) - { - _smart_ptr pChildMatInfo = pMatInfo->GetSubMtl(i); - if (!pChildMatInfo) - { - continue; - } - - if (pChildMatInfo->GetFlags() & MTL_FLAG_PURE_CHILD) - { - CMaterial* existingChild = GetSubMaterial(i); - if (existingChild) - { - existingChild->SetFromMatInfo(pChildMatInfo); - } - else - { - CMaterial* pChild = new CMaterial(pChildMatInfo->GetName(), pChildMatInfo->GetFlags()); - pChild->SetFromMatInfo(pChildMatInfo); - SetSubMaterial(i, pChild); - } - } - else - { - CMaterial* pChild = GetIEditor()->GetMaterialManager()->LoadMaterial(pChildMatInfo->GetName()); - pChild->SetFromMatInfo(pChildMatInfo); - SetSubMaterial(i, pChild); - } - } - } - else - { - SetShaderItem(pMatInfo->GetShaderItem()); - - if (m_shaderItem.m_pShaderResources) - { - m_shaderResources = SInputShaderResources(m_shaderItem.m_pShaderResources); - } - if (m_shaderItem.m_pShader) - { - // Get name of template. - IShader* pTemplShader = m_shaderItem.m_pShader; - if (pTemplShader) - { - m_nShaderGenMask = pTemplShader->GetGenerationMask(); - } - } - m_shaderName = pMatInfo->GetShaderName(); - ISurfaceType* pSurfaceType = pMatInfo->GetSurfaceType(); - if (pSurfaceType) - { - m_surfaceType = pSurfaceType->GetName(); - } - else - { - m_surfaceType = ""; - } - } - - // Mark as not modified. - SetModified(false); - - // Material link names - if (const char* szLinkName = pMatInfo->GetMaterialLinkName()) - { - m_linkedMaterial = szLinkName; - } - - ////////////////////////////////////////////////////////////////////////// - // Assign mat info. - m_pMatInfo = pMatInfo; - m_pMatInfo->SetUserData(this); - AddRef(); // Let IMaterial keep a reference to us. -} - -////////////////////////////////////////////////////////////////////////// -int CMaterial::GetSubMaterialCount() const -{ - return m_subMaterials.size(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetSubMaterialCount(int nSubMtlsCount) -{ - RecordUndo("Multi Material Change"); - m_subMaterials.resize(nSubMtlsCount); - UpdateMatInfo(); - NotifyChanged(); -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterial::GetSubMaterial(int index) const -{ - const int nSubMats = m_subMaterials.size(); - assert(index >= 0 && index < nSubMats); - - if (index < 0 || index >= nSubMats) - { - return NULL; - } - - return m_subMaterials[index]; -} - -////////////////////////////////////////////////////////////////////////// -int CMaterial::FindMaterialIndex(const QString& name) -{ - for (int i = 0; i < m_subMaterials.size(); ++i) - { - if (m_subMaterials[i]->GetName().compare(name) == 0) - { - return i; - } - } - - return -1; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetSubMaterial(int nSlot, CMaterial* mtl) -{ - RecordUndo("Multi Material Change"); - assert(nSlot >= 0 && nSlot < m_subMaterials.size()); - if (mtl) - { - if (mtl->IsMultiSubMaterial()) - { - return; - } - if (mtl->IsPureChild()) - { - mtl->m_pParent = this; - } - } - - if (m_subMaterials[nSlot]) - { - m_subMaterials[nSlot]->m_pParent = NULL; - } - m_subMaterials[nSlot] = mtl; - - if (!m_subMaterials[nSlot]) - { - m_subMaterials.erase(m_subMaterials.begin() + nSlot); - } - - UpdateMatInfo(); - NotifyChanged(); -} - -////////////////////////////////////////////////////////////////////////// -// This method will populate for the material editor the name and tool tip of the -// different textures of the current material -//CVarBlock* CMaterial::UpdateTextureNames(AZStd::unordered_map& textureVarsMap) -CVarBlock* CMaterial::UpdateTextureNames(CSmartVariableArray textureVars[EFTT_MAX]) -{ - CVarBlock* pTextureSlots = new CVarBlock; - IShader* pTemplShader = m_shaderItem.m_pShader; - int nTech = max(0, m_shaderItem.m_nTechnique); - SShaderTexSlots* pShaderSlots = pTemplShader ? pTemplShader->GetUsedTextureSlots(nTech) : nullptr; - - for (EEfResTextures nTexSlot = EEfResTextures(0); nTexSlot < EFTT_MAX; nTexSlot = EEfResTextures(nTexSlot + 1)) - { - if (!MaterialHelpers::IsAdjustableTexSlot((EEfResTextures)nTexSlot)) - { // do not take into account virtual slots (such as smoothness - normal's alpha) - // in theory this case should not happen as it is filtered from the source list. - continue; - } - - IVariable* pVar = textureVars[nTexSlot].GetVar(); - SShaderTextureSlot* pSlot = pShaderSlots ? pShaderSlots->m_UsedTextureSlots[nTexSlot] : nullptr; - - // If slot is NULL, fall back to default name - name here is the context name (i.e. diffuse, normal..) - // and not the actual texture file name - pVar->SetName(pSlot && pSlot->m_Name.length() ? pSlot->m_Name.c_str() : MaterialHelpers::LookupTexName((EEfResTextures) nTexSlot)); - pVar->SetDescription(pSlot && pSlot->m_Description.length() ? pSlot->m_Description.c_str() : MaterialHelpers::LookupTexDesc((EEfResTextures)nTexSlot)); - - int flags = pVar->GetFlags(); - - // TODO: slot->m_TexType gives expected sampler type (2D vs Cube etc). Could check/extract this here. - - // Not sure why this needs COLLAPSED added again, but without this all the slots expand - flags |= IVariable::UI_COLLAPSED; - - //clear the auto-expand flag if there is no texture assigned. - SEfResTexture* pTextureRes = m_shaderResources.GetTextureResource(nTexSlot); - bool noTextureName = (!pTextureRes ? true : pTextureRes->m_Name.empty()); - - if (noTextureName) - { - flags &= ~IVariable::UI_AUTO_EXPAND; - } - - // if slot is NULL, but we have reflection information, this slot isn't used - make the variable invisible - // unless there's a texture in the slot - if (pShaderSlots && !pSlot && noTextureName) - { - flags |= IVariable::UI_INVISIBLE; - } - else - { - flags &= ~IVariable::UI_INVISIBLE; - } - - pVar->SetFlags(flags); - - pTextureSlots->AddVariable(pVar); - } - - return pTextureSlots; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::ClearAllSubMaterials() -{ - RecordUndo("Multi Material Change"); - for (int i = 0; i < m_subMaterials.size(); i++) - { - if (m_subMaterials[i]) - { - m_subMaterials[i]->m_pParent = NULL; - m_subMaterials[i] = NULL; - } - } - UpdateMatInfo(); - NotifyChanged(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::Validate() -{ - if (IsDummy()) - { - CErrorRecord err; - err.error = QObject::tr("Material %1 file not found").arg(GetName()); - err.pItem = this; - GetIEditor()->GetErrorReport()->ReportError(err); - } - // Reload shader. - LoadShader(); - - // Validate sub materials. - for (int i = 0; i < m_subMaterials.size(); i++) - { - if (m_subMaterials[i]) - { - m_subMaterials[i]->Validate(); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::GatherUsedResources(CUsedResources& resources) -{ - if (!IsUsed()) - { - return; - } - - SInputShaderResources& sr = GetShaderResources(); - for (auto iter = sr.m_TexturesResourcesMap.begin(); iter != sr.m_TexturesResourcesMap.end(); ++iter) - { - SEfResTexture* pTexture = &iter->second; - if (!pTexture->m_Name.empty()) - { - resources.Add(pTexture->m_Name.c_str()); - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterial::CanModify(bool bSkipReadOnly) -{ - if (m_bDummyMaterial) - { - return false; - } - - if (IsPureChild() && GetParent()) - { - return GetParent()->CanModify(bSkipReadOnly); - } - - if (bSkipReadOnly) - { - // If read only or in pack, do not save. - if (m_scFileAttributes & (SCC_FILE_ATTRIBUTE_READONLY | SCC_FILE_ATTRIBUTE_INPAK)) - { - return false; - } - - // Managed file must be checked out. - if ((m_scFileAttributes & SCC_FILE_ATTRIBUTE_MANAGED) && !(m_scFileAttributes & SCC_FILE_ATTRIBUTE_CHECKEDOUT)) - { - return false; - } - } - else - { - // Only if in pack. - if (m_scFileAttributes & (SCC_FILE_ATTRIBUTE_INPAK)) - { - return false; - } - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterial::Save(bool bSkipReadOnly, const QString& fullPath) -{ - // Save our parent - if (IsPureChild()) - { - if (m_pParent) - { - return m_pParent->Save(bSkipReadOnly); - } - return false; - } - - if (m_mtlFlags & MTL_FLAG_UIMATERIAL) - { - return false; - } - - GetFileAttributes(); - - if (bSkipReadOnly && IsModified()) - { - // If read only or in pack, do not save. - if (m_scFileAttributes & (SCC_FILE_ATTRIBUTE_READONLY | SCC_FILE_ATTRIBUTE_INPAK)) - { - gEnv->pLog->LogError("Can't save material %s (read-only)", GetName().toUtf8().constData()); - } - - // Managed file must be checked out. - if ((m_scFileAttributes & SCC_FILE_ATTRIBUTE_MANAGED) && !(m_scFileAttributes & SCC_FILE_ATTRIBUTE_CHECKEDOUT)) - { - gEnv->pLog->LogError("Can't save material %s (need to check out)", GetName().toUtf8().constData()); - } - } - - if (!CanModify(bSkipReadOnly)) - { - return false; - } - - - // If filename is empty do not not save. - if (GetFilename().isEmpty()) - { - return false; - } - - // Save material XML to a file that corresponds to the material name with extension .mtl. - XmlNodeRef mtlNode = XmlHelpers::CreateXmlNode("Material"); - CBaseLibraryItem::SerializeContext ctx(mtlNode, false); - Serialize(ctx); - - bool saveSucceeded = false; - if (fullPath.isEmpty()) - { - // If no filepath was specified, get the filename using the relative path/unique identifier of this material - saveSucceeded = XmlHelpers::SaveXmlNode(GetIEditor()->GetFileUtil(), mtlNode, GetFilename().toUtf8().data()); - } - else - { - // If a filepath was specified, save to the specified location - saveSucceeded = XmlHelpers::SaveXmlNode(GetIEditor()->GetFileUtil(), mtlNode, fullPath.toUtf8().data()); - } - - if (saveSucceeded) - { - // If material successfully saved, clear modified flag. - SetModified(false); - for (int i = 0; i < GetSubMaterialCount(); ++i) - { - CMaterial* pSubMaterial = GetSubMaterial(i); - if (pSubMaterial) - { - pSubMaterial->SetModified(false); - } - } - } - else - { - AZ_Warning("Material Editor", false, "Material '%s' failed to save successfully. Check that the file is writable and has been successfully checked out in source control.", m_name.toUtf8().data()); - } - - return saveSucceeded; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::ClearMatInfo() -{ - m_pMatInfo = nullptr; -} - -////////////////////////////////////////////////////////////////////////// -_smart_ptr CMaterial::GetMatInfo(bool bUseExistingEngineMaterial) -{ - if (!m_pMatInfo) - { - if (m_bDummyMaterial) - { - m_pMatInfo = GetIEditor()->Get3DEngine()->GetMaterialManager()->GetDefaultMaterial(); - AddRef(); // Always keep dummy materials. - return m_pMatInfo; - } - - if (!IsMultiSubMaterial() && !m_shaderItem.m_pShader) - { - LoadShader(); - } - - if (!IsPureChild()) - { - if (bUseExistingEngineMaterial) - { - m_pMatInfo = GetIEditor()->Get3DEngine()->GetMaterialManager()->FindMaterial(GetName().toUtf8().data()); - } - - if (!m_pMatInfo) - { - m_pMatInfo = GetIEditor()->Get3DEngine()->GetMaterialManager()->CreateMaterial(GetName().toUtf8().data(), m_mtlFlags); - } - } - else - { - // Pure child should not be registered with the name. - m_pMatInfo = GetIEditor()->Get3DEngine()->GetMaterialManager()->CreateMaterial("", m_mtlFlags); - m_pMatInfo->SetName(GetName().toUtf8().data()); - } - m_mtlFlags = m_pMatInfo->GetFlags(); - UpdateMatInfo(); - - if (m_pMatInfo->GetUserData() != this) - { - m_pMatInfo->SetUserData(this); - AddRef(); // Let IMaterial keep a reference to us. - } - } - - return m_pMatInfo; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::NotifyChanged() -{ - if (m_bIgnoreNotifyChange) - { - return; - } - - if (!CanModify() && !IsModified() && CUndo::IsRecording()) - { - // Display Warning message. - Warning("Modifying read only material %s\r\nChanges will not be saved!", GetName().toUtf8().data()); - } - - SetModified(); - - GetIEditor()->GetMaterialManager()->OnItemChanged(this); -} - -////////////////////////////////////////////////////////////////////////// -class CUndoMaterial - : public IUndoObject -{ -public: - CUndoMaterial(CMaterial* pMaterial, const char* undoDescription, bool bForceUpdate) - { - assert(pMaterial); - - // Stores the current state of this object. - m_undoDescription = undoDescription; - - m_bIsSubMaterial = pMaterial->IsPureChild(); - - if (m_bIsSubMaterial) - { - CMaterial* pParentMaterial = pMaterial->GetParent(); - assert(pParentMaterial && !pParentMaterial->IsPureChild()); - if (pParentMaterial && !pParentMaterial->IsPureChild()) - { - bool bFound = false; - const int subMaterialCount = pParentMaterial->GetSubMaterialCount(); - for (int i = 0; i < subMaterialCount; ++i) - { - CMaterial* pSubMaterial = pParentMaterial->GetSubMaterial(i); - if (pSubMaterial == pMaterial) - { - bFound = true; - m_subMaterialName = pSubMaterial->GetName(); - break; - } - } - assert(bFound); - m_mtlName = pParentMaterial->GetName(); - } - } - else - { - m_mtlName = pMaterial->GetName(); - } - - // Save material XML to a file that corresponds to the material name with extension .mtl. - m_undo = XmlHelpers::CreateXmlNode("Material"); - CBaseLibraryItem::SerializeContext ctx(m_undo, false); - pMaterial->Serialize(ctx); - m_bForceUpdate = bForceUpdate; - } - -protected: - virtual void Release() { delete this; }; - - virtual int GetSize() - { - return sizeof(*this) + m_undoDescription.length() + m_mtlName.length(); - } - - virtual QString GetDescription() { return m_undoDescription; }; - - virtual void Undo(bool bUndo) - { - CMaterial* pMaterial = GetMaterial(); - - assert(pMaterial); - if (!pMaterial) - { - return; - } - - if (bUndo) - { - // Save current object state. - m_redo = XmlHelpers::CreateXmlNode("Material"); - CBaseLibraryItem::SerializeContext ctx(m_redo, false); - pMaterial->Serialize(ctx); - } - - CBaseLibraryItem::SerializeContext ctx(m_undo, true); - ctx.bUndo = bUndo; - pMaterial->Serialize(ctx); - - if (m_bForceUpdate && bUndo) - { - GetIEditor()->GetMaterialManager()->OnUpdateProperties(pMaterial, true); - } - } - - virtual void Redo() - { - CMaterial* pMaterial = GetMaterial(); - - if (!pMaterial) - { - return; - } - - CBaseLibraryItem::SerializeContext ctx(m_redo, true); - ctx.bUndo = true; - pMaterial->Serialize(ctx); - - if (m_bForceUpdate) - { - GetIEditor()->GetMaterialManager()->OnUpdateProperties(pMaterial, true); - } - } - -private: - CMaterial* GetMaterial() - { - CMaterial* pMaterial = (CMaterial*)GetIEditor()->GetMaterialManager()->FindItemByName(m_mtlName); - assert(pMaterial); - - if (pMaterial && m_bIsSubMaterial) - { - bool bFound = false; - const int subMaterialCount = pMaterial->GetSubMaterialCount(); - for (int i = 0; i < subMaterialCount; ++i) - { - CMaterial* pSubMaterial = pMaterial->GetSubMaterial(i); - if (pSubMaterial && (pSubMaterial->GetName() == m_subMaterialName)) - { - bFound = true; - pMaterial = pSubMaterial; - break; - } - } - assert(bFound && pMaterial); - } - - return pMaterial; - } - - QString m_undoDescription; - QString m_mtlName; - bool m_bIsSubMaterial; - QString m_subMaterialName; - XmlNodeRef m_undo; - XmlNodeRef m_redo; - bool m_bForceUpdate; -}; - -////////////////////////////////////////////////////////////////////////// -void CMaterial::RecordUndo(const char* sText, bool bForceUpdate) -{ - if (CUndo::IsRecording()) - { - CUndo::Record(new CUndoMaterial(this, sText, bForceUpdate)); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::OnMakeCurrent() -{ - UpdateFileAttributes(false); - - // If Shader not yet loaded, load it now. - if (!m_shaderItem.m_pShader) - { - LoadShader(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetSurfaceTypeName(const QString& surfaceType) -{ - m_surfaceType = surfaceType; - UpdateMatInfo(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::Reload() -{ - if (IsPureChild()) - { - if (m_pParent) - { - m_pParent->Reload(); - } - return; - } - if (IsDummy()) - { - return; - } - - XmlNodeRef mtlNode = GetISystem()->LoadXmlFromFile(GetFilename().toUtf8().data()); - if (!mtlNode) - { - return; - } - CBaseLibraryItem::SerializeContext serCtx(mtlNode, true); - serCtx.bUndo = true; // Simulate undo. - Serialize(serCtx); - - // was called by Simulate undo. - //UpdateMatInfo(); - //NotifyChanged(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::LinkToMaterial(const QString& name) -{ - m_linkedMaterial = name; - UpdateMatInfo(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::DisableHighlightForFrame() -{ - SetHighlightFlags(0); -} - -static ColorF Interpolate(const ColorF& a, const ColorF& b, float phase) -{ - const float oneMinusPhase = 1.0f - phase; - return ColorF(b.r * phase + a.r * oneMinusPhase, - b.g * phase + a.g * oneMinusPhase, - b.b * phase + a.b * oneMinusPhase, - b.a * phase + a.a * oneMinusPhase); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::UpdateHighlighting() -{ - if (!(GetFlags() & MTL_FLAG_NODRAW)) - { - const CInputLightMaterial& original = m_shaderResources.m_LMaterial; - CInputLightMaterial lm = original; - - ColorF highlightColor(0.0f, 0.0f, 0.0f, 1.0f); - float highlightIntensity = 0.0f; - - MAKE_SURE(GetIEditor()->GetMaterialManager(), return ); - GetIEditor()->GetMaterialManager()->GetHighlightColor(&highlightColor, &highlightIntensity, m_highlightFlags); - - if (m_shaderItem.m_pShaderResources) - { - ColorF diffuseColor = Interpolate(original.m_Diffuse, highlightColor, highlightIntensity); - ColorF emissiveColor = Interpolate(original.m_Emittance, highlightColor, highlightIntensity); - ColorF specularColor = Interpolate(original.m_Specular, highlightColor, highlightIntensity); - - // [Shader System TO DO] remove this hard coded association! - m_shaderItem.m_pShaderResources->SetColorValue(EFTT_DIFFUSE, diffuseColor); - m_shaderItem.m_pShaderResources->SetColorValue(EFTT_SPECULAR, specularColor); - m_shaderItem.m_pShaderResources->SetColorValue(EFTT_EMITTANCE, emissiveColor); - - m_shaderItem.m_pShaderResources->UpdateConstants(m_shaderItem.m_pShader); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterial::SetHighlightFlags(int highlightFlags) -{ - m_highlightFlags = highlightFlags; - - UpdateHighlighting(); -} - - -void CMaterial::SetShaderItem(const SShaderItem& shaderItem) -{ - SAFE_RELEASE(m_shaderItem.m_pShader); - SAFE_RELEASE(m_shaderItem.m_pShaderResources); - - m_shaderItem = shaderItem; - if (m_shaderItem.m_pShader) - { - m_shaderItem.m_pShader->AddRef(); - } - if (m_shaderItem.m_pShaderResources) - { - m_shaderItem.m_pShaderResources->AddRef(); - } -} diff --git a/Code/Sandbox/Editor/Material/Material.h b/Code/Sandbox/Editor/Material/Material.h deleted file mode 100644 index b311744e14..0000000000 --- a/Code/Sandbox/Editor/Material/Material.h +++ /dev/null @@ -1,315 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIAL_H -#define CRYINCLUDE_EDITOR_MATERIAL_MATERIAL_H -#pragma once - -#include -#include -#include "BaseLibraryItem.h" -#include "Include/IEditorMaterial.h" -#include "Util/Variable.h" -#include - -// forward declarations, -class CMaterialManager; -class CVarBlock; - -enum eMTL_PROPAGATION -{ - MTL_PROPAGATE_OPACITY = 1 << 0, - MTL_PROPAGATE_LIGHTING = 1 << 1, - MTL_PROPAGATE_ADVANCED = 1 << 2, - MTL_PROPAGATE_TEXTURES = 1 << 3, - MTL_PROPAGATE_SHADER_PARAMS = 1 << 4, - MTL_PROPAGATE_SHADER_GEN = 1 << 5, - MTL_PROPAGATE_VERTEX_DEF = 1 << 6, - MTL_PROPAGATE_LAYER_PRESETS = 1 << 7, - MTL_PROPAGATE_MATERIAL_SETTINGS = 1 << 8, - MTL_PROPAGATE_ALL = ( - MTL_PROPAGATE_OPACITY | - MTL_PROPAGATE_LIGHTING | - MTL_PROPAGATE_ADVANCED | - MTL_PROPAGATE_TEXTURES | - MTL_PROPAGATE_SHADER_PARAMS | - MTL_PROPAGATE_SHADER_GEN | - MTL_PROPAGATE_VERTEX_DEF | - MTL_PROPAGATE_LAYER_PRESETS | - MTL_PROPAGATE_MATERIAL_SETTINGS), - MTL_PROPAGATE_RESERVED = 1 << 9 -}; - -/** CMaterial class - Every Material is a member of material library. - Materials can have child sub materials, - Sub materials are applied to the same geometry of the parent material in the other material slots. -*/ - -struct SMaterialLayerResources -{ - SMaterialLayerResources() - : m_nFlags(MTL_LAYER_USAGE_REPLACEBASE) - , m_bRegetPublicParams(true) - , m_pMatLayer(0) - { - } - - uint8 m_nFlags; - bool m_bRegetPublicParams; - QString m_shaderName; - - _smart_ptr< IMaterialLayer > m_pMatLayer; - SInputShaderResources m_shaderResources; - XmlNodeRef m_publicVarsCache; -}; - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -class CRYEDIT_API CMaterial - : public IEditorMaterial -{ -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - ////////////////////////////////////////////////////////////////////////// - CMaterial(const QString& name, int nFlags = 0); - CMaterial(const CMaterial& rhs); - ~CMaterial(); - - virtual EDataBaseItemType GetType() const { return EDB_TYPE_MATERIAL; }; - - void SetName(const QString& name); - - ////////////////////////////////////////////////////////////////////////// - QString GetFullName() const { return m_name; }; - - ////////////////////////////////////////////////////////////////////////// - // File properties of the material. - ////////////////////////////////////////////////////////////////////////// - QString GetFilename() const; - - //! Collect filenames of texture sources used in material - //! Return number of filenames - int GetTextureFilenames(QStringList& outFilenames) const; - int GetAnyTextureFilenames(QStringList& outFilenames) const; - - void UpdateFileAttributes(bool useSourceControl = true); - uint32 GetFileAttributes(); - ////////////////////////////////////////////////////////////////////////// - - //! Sets one or more material flags from EMaterialFlags enum. - void SetFlags(int flags) { m_mtlFlags = flags; }; - //! Query this material flags. - virtual int GetFlags() const { return m_mtlFlags; } - bool IsMultiSubMaterial() const { return (m_mtlFlags & MTL_FLAG_MULTI_SUBMTL) != 0; }; - bool IsPureChild() const { return (m_mtlFlags & MTL_FLAG_PURE_CHILD) != 0; } - - // Check if material is used. - bool IsUsed() const { /*return m_nUseCount > 0 || (m_mtlFlags & MTL_FLAG_ALWAYS_USED);*/ return true; }; - - virtual void GatherUsedResources(CUsedResources& resources); - - //! Set name of shader used by this material. - void SetShaderName(const QString& shaderName); - //! Get name of shader used by this material. - QString GetShaderName() const { return m_shaderName; }; - - virtual SInputShaderResources& GetShaderResources() { return m_shaderResources; }; - - //! Get public parameters of material in variable block. - CVarBlock* GetPublicVars(SInputShaderResources& pShaderResources); - - //! Set the shader public param m_script variable into our own m_script, script contains min/max for a given shader param value - void SetShaderParamPublicScript(); - - //! Sets variable block of public shader parameters. - //! VarBlock must be in same format as returned by GetPublicVars(). - void SetPublicVars(CVarBlock* pPublicVars, CMaterial* pMtl); - - //! Update names/descriptions in this variable array, return a variable block for replacing - CVarBlock* UpdateTextureNames(CSmartVariableArray textureVars[EFTT_MAX]); -// [Shader System] - Do To: add back with map usage: CVarBlock* UpdateTextureNames(AZStd::unordered_map& textureVarsMap); - - ////////////////////////////////////////////////////////////////////////// - CVarBlock* GetShaderGenParamsVars(); - void SetShaderGenParamsVars(CVarBlock* pBlock); - uint64 GetShaderGenMask() { return m_nShaderGenMask; } - void SetShaderGenMask(uint64 mask) { m_nShaderGenMask = mask; } - - //! Return variable block of shader params. - SShaderItem& GetShaderItem() { return m_shaderItem; }; - - //! Return material layers resources - SMaterialLayerResources* GetMtlLayerResources() { return m_pMtlLayerResources; }; - - //! Get texture map usage mask for shader in this material. - unsigned int GetTexmapUsageMask() const; - - //! Load new shader. - bool LoadShader(); - - //! Reload shader, update all shader parameters. - virtual void Update(); - - // Reload material settings from file. - // NOTICE: The function will remove all the sub-materials and recreate them! - void Reload(); - - //! Serialize material settings to xml. - virtual void Serialize(SerializeContext& ctx); - - //! Assign this material to static geometry. - void AssignToEntity(IRenderNode* pEntity); - - ////////////////////////////////////////////////////////////////////////// - // Surface types. - ////////////////////////////////////////////////////////////////////////// - virtual void SetSurfaceTypeName(const QString& surfaceType); - virtual const QString& GetSurfaceTypeName() const { return m_surfaceType; }; - bool IsBreakable2D() const; - - ////////////////////////////////////////////////////////////////////////// - // Child Sub materials. - ////////////////////////////////////////////////////////////////////////// - //! Get number of sub materials childs. - int GetSubMaterialCount() const; - //! Set number of sub materials childs. - void SetSubMaterialCount(int nSubMtlsCount); - //! Get sub material child by index. - CMaterial* GetSubMaterial(int index) const; - //! Find sub material index by name - int FindMaterialIndex(const QString& name); - // Set a material to the sub materials slot. - // Use NULL material pointer to clear slot. - void SetSubMaterial(int nSlot, CMaterial* mtl); - //! Remove all sub materials, does not change number of sub material slots. - void ClearAllSubMaterials(); - - //! Return pointer to engine material. - virtual _smart_ptr GetMatInfo(bool bUseExistingEngineMaterial = true); - // Clear stored pointer to engine material. - void ClearMatInfo(); - - //! Validate materials for errors. - void Validate(); - - // Check if material file can be modified. - // Will check file attributes if it is not read only. - bool CanModify(bool bSkipReadOnly = true); - - // Save material to file. - virtual bool Save(bool bSkipReadOnly = true, const QString& fullPath = ""); - - // Dummy material is just a placeholder item for materials that have not been found on disk. - void SetDummy(bool bDummy) { m_bDummyMaterial = bDummy; } - bool IsDummy() const { return m_bDummyMaterial != 0; } - - // Called by material manager when material selected as a current material. - void OnMakeCurrent(); - - void SetFromMatInfo(_smart_ptr pMatInfo); - - // Link a submaterial by name (used for value propagation in CMaterialUI) - void LinkToMaterial(const QString& name); - const QString& GetLinkedMaterialName() { return m_linkedMaterial; } - - // Return parent material for submaterial - CMaterial* GetParent() const {return m_pParent; } - - //! Loads material layers - bool LoadMaterialLayers(); - //! Updates material layers - void UpdateMaterialLayers(); - - void SetHighlightFlags(int highlightFlags); - void UpdateHighlighting(); - virtual void DisableHighlightForFrame(); - void RecordUndo(const char* sText, bool bForceUpdate = false); - - int GetPropagationFlags() const { return m_propagationFlags; } - void SetPropagationFlags(const int flags) { m_propagationFlags = flags; } - - bool LayerActivationAllowed() const { return m_allowLayerActivation; } - void SetLayerActivation(bool allowed) { m_allowLayerActivation = allowed; } - - uint32 GetDccMaterialHash() const { return m_dccMaterialHash; } - void SetDccMaterialHash(AZ::u32 hash) { m_dccMaterialHash = hash; } - void SetShaderItem(const SShaderItem& shaderItem); - -private: - void UpdateMatInfo(); - void CheckSpecialConditions(); - - void NotifyChanged(); - -private: - ////////////////////////////////////////////////////////////////////////// - // Variables. - ////////////////////////////////////////////////////////////////////////// - QString m_shaderName; - QString m_surfaceType; - QString m_linkedMaterial; - - //! Material flags. - int m_mtlFlags; - - // Hash for DCC material attributes, used to check if .dccmtl has changed - // If so, the source .mtl file will need to be rebuilt - uint32 m_dccMaterialHash; - - // Parent material, Only valid for Pure Childs. - CMaterial* m_pParent; - - ////////////////////////////////////////////////////////////////////////// - // Shader resources. - ////////////////////////////////////////////////////////////////////////// - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - SShaderItem m_shaderItem; - SInputShaderResources m_shaderResources; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - //CVarBlockPtr m_shaderParamsVar; - //! Common shader flags. - uint64 m_nShaderGenMask; - QString m_pszShaderGenMask; - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - SMaterialLayerResources m_pMtlLayerResources[MTL_LAYER_MAX_SLOTS]; - - _smart_ptr m_pMatInfo; - - XmlNodeRef m_publicVarsCache; - - //! Array of sub materials. - std::vector<_smart_ptr > m_subMaterials; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - int m_nUseCount; - uint32 m_scFileAttributes; - - unsigned char m_highlightFlags; - - // The propagation flags are a bit combination of the MTL_PROPAGATION enum above - // and determine which properties get propagated to an optional linked material - // during ui editing - int m_propagationFlags; - - //! Material Used in level. - unsigned int m_bDummyMaterial : 1; // Dummy material, name specified but material file not found. - unsigned int m_bIgnoreNotifyChange : 1; // Do not send notifications about changes. - unsigned int m_bRegetPublicParams : 1; - unsigned int m_bKeepPublicParamsValues : 1; - - bool m_allowLayerActivation; -}; - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIAL_H diff --git a/Code/Sandbox/Editor/Material/MaterialBrowser.cpp b/Code/Sandbox/Editor/Material/MaterialBrowser.cpp deleted file mode 100644 index e39a29a47d..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialBrowser.cpp +++ /dev/null @@ -1,1792 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MaterialBrowser.h" - -// Qt -#include - -// AzQtComponents -#include - -// AzToolsFramework -#include - -// Editor -#include "MaterialManager.h" -#include "Clipboard.h" -#include "MaterialImageListCtrl.h" -#include "StringDlg.h" - -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -#include -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - -enum -{ - MENU_UNDEFINED = CMaterialImageListCtrl::MaterialBrowserWidgetActionsStart, - MENU_CUT, - MENU_COPY, - MENU_COPY_NAME, - MENU_PASTE, - MENU_EXPLORE, - MENU_DUPLICATE, - MENU_EXTRACT, - MENU_RENAME, - MENU_DELETE, - MENU_RESET, - MENU_ASSIGNTOSELECTION, - MENU_SELECTASSIGNEDOBJECTS, - MENU_NUM_SUBMTL, - MENU_ADDNEW, - MENU_ADDNEW_MULTI, - MENU_CONVERT_TO_MULTI, - MENU_SUBMTL_MAKE, - MENU_SUBMTL_CLEAR, - MENU_SAVE_TO_FILE, - MENU_SAVE_TO_FILE_MULTI, - MENU_MERGE, - - MENU_SCM_ADD, - MENU_SCM_CHECK_OUT, - MENU_SCM_UNDO_CHECK_OUT, - MENU_SCM_GET_LATEST, - MENU_SCM_GET_LATEST_TEXTURES, -}; - -static QAction* CreateTreeViewAction(const char* text, const QKeySequence& shortcut, QWidget* shortcutContext, MaterialBrowserWidget* widget, void (MaterialBrowserWidget::*slot)()) -{ - QAction* action = new QAction(text, shortcutContext); - action->setShortcut(shortcut); - QObject::connect(action, &QAction::triggered, widget, slot); - widget->addAction(action); - return action; -} - -////////////////////////////////////////////////////////////////////////// -MaterialBrowserWidget::MaterialBrowserWidget(QWidget* parent) - : QWidget(parent) - , m_ui(new Ui::MaterialBrowser) - , m_filterModel(new MaterialBrowserFilterModel(this)) -{ - using namespace AzToolsFramework::AssetBrowser; - - m_ui->setupUi(this); - - // create some permanent (for the life of this widget) actions for shortcut handling - m_cutAction = CreateTreeViewAction("Cut", QKeySequence::Cut, m_ui->treeView, this, &MaterialBrowserWidget::OnCut); - m_copyAction = CreateTreeViewAction("Copy", QKeySequence::Copy, m_ui->treeView, this, &MaterialBrowserWidget::OnCopy); - m_pasteAction = CreateTreeViewAction("Paste", QKeySequence::Paste, m_ui->treeView, this, &MaterialBrowserWidget::OnPaste); - m_duplicateAction = CreateTreeViewAction("Duplicate", QKeySequence(Qt::CTRL + Qt::Key_D), m_ui->treeView, this, &MaterialBrowserWidget::OnDuplicate); - m_deleteAction = CreateTreeViewAction("Delete", QKeySequence::Delete, m_ui->treeView, this, &MaterialBrowserWidget::DeleteItem); - m_renameItemAction = CreateTreeViewAction("Rename", Qt::Key_F2, m_ui->treeView, this, &MaterialBrowserWidget::OnRenameItem); - m_addNewMaterialAction = CreateTreeViewAction("Add New Material", Qt::Key_Insert, m_ui->treeView, this, &MaterialBrowserWidget::OnAddNewMaterial); - - MaterialBrowserWidgetBus::Handler::BusConnect(); - - // Get the asset browser model - AssetBrowserComponentRequestBus::BroadcastResult(m_assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel); - AZ_Assert(m_assetBrowserModel, "Failed to get filebrowser model"); - - // Set up the filter model - m_filterModel->setSourceModel(m_assetBrowserModel); - m_ui->treeView->setModel(m_filterModel.data()); - m_ui->treeView->SetThumbnailContext("MaterialBrowser"); - m_ui->treeView->SetShowSourceControlIcons(true); - - m_ui->m_searchWidget->Setup(true, false); - m_filterModel->SetSearchFilter(m_ui->m_searchWidget); - connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel.data(), &MaterialBrowserFilterModel::SearchFilterUpdated); - - // Call LoadState to initialize the AssetBrowserTreeView's QTreeViewStateSaver - // This must be done BEFORE StartRecordUpdateJobs(). A race condition from the update jobs was causing a 5-10% crash/hang when opening the Material Editor. - m_ui->treeView->SetName("MaterialBrowserTreeView"); - - // Override the AssetBrowserTreeView's custom context menu - disconnect(m_ui->treeView, &QWidget::customContextMenuRequested, 0, 0); - connect(m_ui->treeView, &QWidget::customContextMenuRequested, this, [=](const QPoint& point) - { - CMaterialBrowserRecord record; - TryGetSelectedRecord(record); - ShowContextMenu(record, point); - }); - - connect(m_ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MaterialBrowserWidget::OnSelectionChanged); - //Wait for the signal emitted on record update jobs finished, then we can restore the selection for the previous selected item - connect(this, SIGNAL(refreshSelection()), this, SLOT(OnRefreshSelection())); - - connect(this, SIGNAL(materialAdded()), this, SLOT(OnMaterialAdded())); - - m_bIgnoreSelectionChange = false; - m_bItemsValid = true; - - m_pMatMan = GetIEditor()->GetMaterialManager(); - m_pMatMan->AddListener(this); - m_pListener = NULL; - - m_viewType = VIEW_LEVEL; - m_pMaterialImageListCtrl = NULL; - m_pLastActiveMultiMaterial = 0; - - m_bNeedReload = false; - - m_bHighlightMaterial = false; - m_timeOfHighlight = 0; - - m_bShowOnlyCheckedOut = false; - - GetIEditor()->RegisterNotifyListener(this); -} - -////////////////////////////////////////////////////////////////////////// -MaterialBrowserWidget::~MaterialBrowserWidget() -{ - m_filterModel->CancelRecordUpdateJobs(); - m_filterModel->deleteLater(); - m_ui->treeView->SaveState(); - GetIEditor()->UnregisterNotifyListener(this); - - m_pMaterialImageListCtrl = NULL; - m_pMatMan->RemoveListener(this); - ClearItems(); - - if (m_bHighlightMaterial) - { - m_pMatMan->SetHighlightedMaterial(0); - } - - MaterialBrowserWidgetBus::Handler::BusDisconnect(); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::ClearItems() -{ - m_bIgnoreSelectionChange = true; - - if (m_pMaterialImageListCtrl) - { - QMaterialImageListModel* materialModel = - qobject_cast(m_pMaterialImageListCtrl->model()); - Q_ASSERT(materialModel); - materialModel->DeleteAllItems(); - } - - m_pLastActiveMultiMaterial = nullptr; - m_delayedSelection = nullptr; - - m_bIgnoreSelectionChange = false; -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::TryLoadRecordMaterial(CMaterialBrowserRecord& record) -{ - // If material already loaded ignore. - if (record.m_material) - { - return; - } - - m_bIgnoreSelectionChange = true; - // Try to load material for it. - record.m_material = m_pMatMan->LoadMaterial(record.GetRelativeFilePath().c_str(), false); - - m_filterModel->SetRecord(record); - m_bIgnoreSelectionChange = false; -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::TickRefreshMaterials() -{ - if (m_bHighlightMaterial) - { - uint32 t = GetTickCount(); - if ((t - m_timeOfHighlight) > 300) - { - m_bHighlightMaterial = false; - m_pMatMan->SetHighlightedMaterial(0); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnIdleUpdate: - { - TickRefreshMaterials(); - } - break; - case eNotify_OnBeginLoad: - { - //Need to make sure the selection is cleared before clearing the record map - SetSelectedItem(nullptr, nullptr, true); - m_filterModel->ClearRecordMap(); - } - break; - case eNotify_OnCloseScene: - { - m_filterModel->ShowOnlyLevelMaterials(false, true); - ClearItems(); - m_ui->treeView->SaveState(); - //Need to make sure the selection is cleared before clearing the record map - SetSelectedItem(nullptr, nullptr, true); - m_filterModel->ClearRecordMap(); - } - break; - case eNotify_OnEndNewScene: - case eNotify_OnEndSceneOpen: - { - m_filterModel->ShowOnlyLevelMaterials(false, true); - m_filterModel->StartRecordUpdateJobs(); - if (m_ui->treeView->IsTreeViewSavingReady()) - { - m_ui->treeView->ApplyTreeViewSnapshot(); - } - } - break; - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::SetSelectedItem(_smart_ptr material, const TMaterialBrowserRecords* pMarkedRecords, bool selectInTreeView) -{ - if (m_bIgnoreSelectionChange) - { - return; - } - - m_bIgnoreSelectionChange = true; - if (pMarkedRecords) - { - m_markedRecords = *pMarkedRecords; - } - else - { - m_markedRecords.clear(); - } - - m_pMatMan->SetCurrentFolder(""); - - _smart_ptr selectedMaterial = material; - if (material && material->IsPureChild()) - { - selectedMaterial = material->GetParent(); - } - - // Clear the delayed selection whenever a new material is selected - m_delayedSelection = nullptr; - - // In some cases, such as when SetSelectedItem is called from the material picker or the rollup bar, - // the material has not yet been selected in the tree-view, so that item must be selected here - bool validSelection = false; - if (selectInTreeView) - { - if (!selectedMaterial) - { - // Clear the current selection so that the upcoming call to RefreshSelected() - // doesn't try to refresh the previously selected material which may be invalid - m_ui->treeView->clearSelection(); - m_ui->treeView->setCurrentIndex(QModelIndex()); - } - else if (m_markedRecords.size() > 0) - { - QItemSelection selection; - for (CMaterialBrowserRecord record : m_markedRecords) - { - QModelIndex currentIndex = m_filterModel->GetIndexFromMaterial(record.m_material); - if (currentIndex.isValid()) - { - selection.push_back(QItemSelectionRange(currentIndex)); - validSelection = true; - } - } - m_ui->treeView->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect); - } - else - { - QModelIndex currentIndex = m_filterModel->GetIndexFromMaterial(selectedMaterial); - if (currentIndex.isValid()) - { - m_ui->treeView->selectionModel()->setCurrentIndex(currentIndex, QItemSelectionModel::ClearAndSelect); - validSelection = true; - - // Now that the parent material is selected in the browser, - // select the appropriate sub-material in the material preview window - if (selectedMaterial == material->GetParent()) - { - for (int i = 0; i < selectedMaterial->GetSubMaterialCount(); ++i) - { - if (material == selectedMaterial->GetSubMaterial(i)) - { - m_selectedSubMaterialIndex = i; - break; - } - } - } - } - else - { - // Hold on to a pointer to this material, listen for the MaterialFinishedProcessing event, - // and attempt to re-select this material if it finishes processing in the background - m_delayedSelection = selectedMaterial; - } - } - } - - RefreshSelected(); - - if (!selectedMaterial) - { - QModelIndex current = m_ui->treeView->currentIndex(); - QString path; - while (current.isValid()) - { - path = '/' + current.data().toString() + path; - current = current.parent(); - } - m_pMatMan->SetCurrentFolder((Path::GetEditingGameDataFolder() + path.toUtf8().data()).c_str()); - } - else - { - if (selectedMaterial->IsMultiSubMaterial() && m_selectedSubMaterialIndex >= 0) - { - selectedMaterial = selectedMaterial->GetSubMaterial(m_selectedSubMaterialIndex); - } - } - - if (m_pListener) - { - // Don't call the listener event if we attempted to select an item in the tree view and failed - // to prevent the material parameter editor from switching to a new material if it wasn't actually selected - if (!selectInTreeView || validSelection) - { - m_pListener->OnBrowserSelectItem(selectedMaterial, false); - } - //Update the selected item if no material is selected in tree view - else if (!selectedMaterial && selectInTreeView) - { - m_pListener->OnBrowserSelectItem(nullptr, false); - } - } - - m_timeOfHighlight = GetTickCount(); - m_pMatMan->SetHighlightedMaterial(selectedMaterial); - if (selectedMaterial) - { - m_bHighlightMaterial = true; - } - - std::vector<_smart_ptr > markedMaterials; - if (pMarkedRecords) - { - for (size_t i = 0; i < pMarkedRecords->size(); ++i) - { - markedMaterials.push_back((*pMarkedRecords)[i].m_material); - } - } - m_pMatMan->SetMarkedMaterials(markedMaterials); - - m_bIgnoreSelectionChange = false; -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::SelectItem(IDataBaseItem* pItem, [[maybe_unused]] IDataBaseItem* pParentItem) -{ - if (m_bIgnoreSelectionChange) - { - return; - } - - if (!pItem) - { - return; - } - - _smart_ptr material = static_cast(pItem); - SetSelectedItem(material, 0, true); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnDuplicate() -{ - GetIEditor()->GetMaterialManager()->Command_Merge(); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnCut() -{ - CMaterialBrowserRecord record; - bool found = TryGetSelectedRecord(record); - if (found) - { - OnCopy(); - DeleteItem(record); - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnCopyName() -{ - _smart_ptr pMtl = GetCurrentMaterial(); - if (pMtl) - { - CClipboard clipboard(this); - clipboard.PutString(pMtl->GetName(), "Material Name"); - } -} - -void MaterialBrowserWidget::ShowOnlyLevelMaterials(bool levelOnly) -{ - m_filterModel->ShowOnlyLevelMaterials(levelOnly); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnCopy() -{ - _smart_ptr pMtl = GetCurrentMaterial(); - if (pMtl) - { - CClipboard clipboard(this); - XmlNodeRef node = XmlHelpers::CreateXmlNode("Material"); - node->setAttr("Name", pMtl->GetName().toUtf8().data()); - CBaseLibraryItem::SerializeContext ctx(node, false); - ctx.bCopyPaste = true; - pMtl->Serialize(ctx); - clipboard.Put(node); - } -} - -////////////////////////////////////////////////////////////////////////// -bool MaterialBrowserWidget::CanPaste() const -{ - CClipboard clipboard(nullptr); - if (clipboard.IsEmpty()) - { - return false; - } - XmlNodeRef node = clipboard.Get(); - if (!node) - { - return false; - } - - if (strcmp(node->getTag(), "Material") == 0) - { - return true; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnPaste() -{ - CClipboard clipboard(this); - if (clipboard.IsEmpty()) - { - return; - } - XmlNodeRef node = clipboard.Get(); - if (!node) - { - return; - } - - if (strcmp(node->getTag(), "Material") == 0) - { - if (!m_pMatMan->GetCurrentMaterial()) - { - GetIEditor()->GetMaterialManager()->Command_Create(); - } - - _smart_ptr pMtl = m_pMatMan->GetCurrentMaterial(); - if (pMtl) - { - // This is material node. - CBaseLibraryItem::SerializeContext serCtx(node, true); - serCtx.bCopyPaste = true; - serCtx.bUniqName = true; - pMtl->Serialize(serCtx); - - SelectItem(pMtl, NULL); - pMtl->Save(); - pMtl->Reload(); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnAddNewMaterial() -{ - GetIEditor()->GetMaterialManager()->Command_Create(); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnAddNewMultiMaterial() -{ - GetIEditor()->GetMaterialManager()->Command_CreateMulti(); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnMergeMaterials() -{ - GetIEditor()->GetMaterialManager()->Command_Merge(); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnConvertToMulti() -{ - GetIEditor()->GetMaterialManager()->Command_ConvertToMulti(); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::DeleteItem() -{ - CMaterialBrowserRecord record; - bool found = TryGetSelectedRecord(record); - if (found) - { - DeleteItem(record); - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnResetItem() -{ - if (QMessageBox::question(this, tr("Reset Material"), tr("Reset Material to default?")) == QMessageBox::Yes) - { - _smart_ptr pMtl = GetCurrentMaterial(); - int index; - - pMtl->GetSubMaterialCount() > 0 ? index = pMtl->GetSubMaterialCount() : index = 1; - - if (pMtl) - { - for (int i = 0; i < index; i++) - { - pMtl->GetSubMaterialCount() > 0 ? pMtl->GetSubMaterial(i)->Reload() : pMtl->Reload(); - TickRefreshMaterials(); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::DeleteItem(const CMaterialBrowserRecord& record) -{ - _smart_ptr pMtl = record.m_material; - if (pMtl) - { - if (m_selectedSubMaterialIndex >= 0) - { - pMtl = pMtl->GetSubMaterial(m_selectedSubMaterialIndex); - OnClearSubMtlSlot(pMtl); - } - else - { - GetIEditor()->GetMaterialManager()->Command_Delete(); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnRenameItem() -{ - _smart_ptr pMtl = GetCurrentMaterial(); - if (!pMtl) - { - return; - } - - if (pMtl->IsPureChild()) - { - StringDlg dlg(tr("Enter New Sub-Material Name"), this); - dlg.SetString(pMtl->GetName()); - dlg.SetCheckCallback([this](QString name) -> bool - { - static const int MAX_REASONABLE_MATERIAL_NAME = 128; - if (name.length() >= MAX_REASONABLE_MATERIAL_NAME) - { - QMessageBox::warning(this, tr("Name too long"), tr("Please enter a name less than %1 characters").arg(MAX_REASONABLE_MATERIAL_NAME)); - return false; - } - return true; - }); - - if (dlg.exec() == QDialog::Accepted) - { - pMtl->SetName(dlg.GetString()); - pMtl->Save(); - pMtl->Reload(); - } - } - else - { - if ((pMtl->GetFileAttributes() & SCC_FILE_ATTRIBUTE_MANAGED) && - !(pMtl->GetFileAttributes() & SCC_FILE_ATTRIBUTE_CHECKEDOUT)) - { - if (QMessageBox::Cancel == QMessageBox::information(this, tr("Confirm"), tr("Only checked-out files can be renamed. Check out and mark for delete before rename it?"), QMessageBox::Ok | QMessageBox::Cancel)) - { - return; - } - } - - QFileInfo info(pMtl->GetFilename()); - QString filename = info.fileName(); - if (!CFileUtil::SelectSaveFile("Material Files (*.mtl)", "mtl", info.path(), filename)) - { - return; - } - - QString itemName = m_pMatMan->FilenameToMaterial(Path::GetRelativePath(filename)); - if (itemName.isEmpty()) - { - return; - } - - if (m_pMatMan->FindItemByName(itemName)) - { - Warning("Material with name %s already exist", itemName.toUtf8().data()); - return; - } - - if (pMtl->GetFileAttributes() & SCC_FILE_ATTRIBUTE_MANAGED) - { - if (pMtl->GetFileAttributes() & SCC_FILE_ATTRIBUTE_CHECKEDOUT) - { - if (QMessageBox::Cancel == QMessageBox::information(this, tr("Confirm"), tr("The original file will be marked for delete and the new named file will be marked for integration."), QMessageBox::Ok | QMessageBox::Cancel)) - { - return; - } - } - else - { - CFileUtil::CheckoutFile(pMtl->GetFilename().toUtf8().data(), this); - } - - if (!CFileUtil::RenameFile(pMtl->GetFilename().toUtf8().data(), filename.toUtf8().data())) - { - QMessageBox::critical(this, tr("Error"), tr("Could not rename file in Source Control.")); - } - } - - - // Delete file on disk. - if (!pMtl->GetFilename().isEmpty()) - { - QFile::remove(pMtl->GetFilename()); - } - pMtl->SetName(itemName); - pMtl->Save(); - SetSelectedItem(pMtl, 0, true); - } -} - - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnSetSubMtlCount(const CMaterialBrowserRecord& record) -{ - _smart_ptr pMtl = record.m_material; - if (!pMtl) - { - return; - } - - if (!pMtl->IsMultiSubMaterial()) - { - return; - } - - int num = pMtl->GetSubMaterialCount(); - bool ok = false; - num = QInputDialog::getInt(this, tr("Number of Sub Materials"), QStringLiteral(""), num, 0, MAX_SUB_MATERIALS, 1, &ok); - if (ok) - { - if (num != pMtl->GetSubMaterialCount()) - { - if (m_selectedSubMaterialIndex >= num) - { - m_selectedSubMaterialIndex = num - 1; - } - - CUndo undo("Set SubMtl Count"); - pMtl->SetSubMaterialCount(num); - - for (int i = 0; i < num; i++) - { - if (pMtl->GetSubMaterial(i) == 0) - { - // Allocate pure childs for all empty slots. - QString name; - name = QStringLiteral("SubMtl%1").arg(i + 1); - _smart_ptr pChild = new CMaterial(name, MTL_FLAG_PURE_CHILD); - pMtl->SetSubMaterial(i, pChild); - } - } - } - } -} - - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::DoSourceControlOp(CMaterialBrowserRecord& record, ESourceControlOp scmOp) -{ - if (!GetIEditor()->IsSourceControlAvailable()) - { - return; - } - - _smart_ptr pMtl = record.m_material; - - if (pMtl && pMtl->IsPureChild()) - { - pMtl = pMtl->GetParent(); - } - - if (scmOp == ESCM_IMPORT) // don't save unless you're doing an operation which writes. - { - if (pMtl && pMtl->IsModified()) - { - pMtl->Save(); - } - } - - QString path = pMtl ? pMtl->GetFilename() : QString(); - - if (path.isEmpty()) - { - return; - } - - bool bRes = true; - switch (scmOp) - { - case ESCM_IMPORT: - if (pMtl) - { - QStringList filenames; - int nTextures = pMtl->GetTextureFilenames(filenames); - for (int i = 0; i < nTextures; ++i) - { - CFileUtil::CheckoutFile(filenames[i].toUtf8().data(), this); - } - - bRes = CFileUtil::CheckoutFile(path.toUtf8().data(), this); - } - break; - case ESCM_CHECKOUT: - { - if (pMtl && (pMtl->GetFileAttributes() & SCC_FILE_ATTRIBUTE_BYANOTHER)) - { - AZStd::string otherUser("another user"); - AzToolsFramework::SourceControlFileInfo fileInfo; - if (CFileUtil::GetFileInfoFromSourceControl(pMtl->GetFilename().toUtf8().data(), fileInfo, this)) - { - // Sanity check the source control api reports the file is checked out by another - AZ_Assert(fileInfo.HasFlag(AzToolsFramework::SCF_OtherOpen), "File attributes reporting incorrectly"); - otherUser = fileInfo.m_StatusUser; - } - - if (QMessageBox::question(this, QString(), tr("This file is checked out by %1. Try to continue?").arg(otherUser.c_str())) != QMessageBox::Yes) - { - return; - } - } - bRes = CFileUtil::GetLatestFromSourceControl(path.toUtf8().data(), this); - if (bRes) - { - bRes = CFileUtil::CheckoutFile(path.toUtf8().data(), this); - } - } - break; - case ESCM_UNDO_CHECKOUT: - bRes = CFileUtil::RevertFile(path.toUtf8().data(), this); - break; - case ESCM_GETLATEST: - bRes = CFileUtil::GetLatestFromSourceControl(path.toUtf8().data(), this); - break; - case ESCM_GETLATESTTEXTURES: - if (pMtl) - { - QString message; - QStringList filenames; - int nTextures = pMtl->GetTextureFilenames(filenames); - for (int i = 0; i < nTextures; ++i) - { - bRes = CFileUtil::GetLatestFromSourceControl(filenames[i].toUtf8().data(), this); - message += Path::GetRelativePath(filenames[i], true) + (bRes ? " [OK]" : " [Fail]") + "\n"; - } - QMessageBox::information(this, QString(), message.isEmpty() ? tr("No files are affected") : message); - } - return; - } - - if (!bRes) - { - QMessageBox::critical(this, tr("Error"), tr("Source Control Operation Failed.\r\nCheck if Source Control Provider correctly setup and working directory is correct.")); - return; - } - - // force the cache to be rebuilt next time we repaint - record.InitializeSourceControlAttributes(); - m_filterModel->SetRecord(record); - - if (pMtl) - { - pMtl->Reload(); - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnMakeSubMtlSlot(const CMaterialBrowserRecord& record) -{ - if (m_selectedSubMaterialIndex >= 0) - { - _smart_ptr parentMaterial = record.m_material; - if (parentMaterial && parentMaterial->IsMultiSubMaterial()) - { - const QString str = tr("Making new material will override material currently assigned to the slot %1 of %2\r\nMake new sub material?") - .arg(m_selectedSubMaterialIndex).arg(parentMaterial->GetName()); - if (QMessageBox::question(this, tr("Confirm Override"), str) == QMessageBox::Yes) - { - QString name = tr("SubMtl%1") - .arg(m_selectedSubMaterialIndex + 1); - _smart_ptr pMtl = new CMaterial(name, MTL_FLAG_PURE_CHILD); - parentMaterial->SetSubMaterial(m_selectedSubMaterialIndex, pMtl); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnClearSubMtlSlot(_smart_ptr subMaterial) -{ - if (subMaterial && m_selectedSubMaterialIndex >= 0) - { - _smart_ptr parentMaterial = subMaterial->GetParent(); - if (parentMaterial && parentMaterial->IsMultiSubMaterial()) - { - const QString str = tr("Clear Sub-Material Slot %1 of %2?").arg(m_selectedSubMaterialIndex).arg(parentMaterial->GetName()); - if (QMessageBox::question(this, tr("Clear Sub-Material"), str) == QMessageBox::Yes) - { - CUndo undo("Material Change"); - SetSubMaterial(parentMaterial, m_selectedSubMaterialIndex, 0); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::SetSubMaterial(_smart_ptr parentMaterial, int slot, _smart_ptr subMaterial) -{ - if (parentMaterial && parentMaterial->IsMultiSubMaterial()) - { - // If the last sub-material is being removed, select the 2nd to last sub-material - if (!subMaterial && slot == parentMaterial->GetSubMaterialCount() - 1) - { - m_selectedSubMaterialIndex = slot - 1; - } - parentMaterial->SetSubMaterial(slot, subMaterial); - } -} - - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event) -{ - if (m_bIgnoreSelectionChange) - { - return; - } - - if (!pItem) - { - return; - } - - - switch (event) - { - case EDB_ITEM_EVENT_ADD: - break; - case EDB_ITEM_EVENT_DELETE: - { - if (pItem) - { - //If the deleted item is selected, remove selection - CMaterial* pMtl = static_cast(pItem); - CMaterial* selectedMaterial = GetCurrentMaterial(); - if (selectedMaterial && selectedMaterial->IsPureChild()) - { - selectedMaterial = selectedMaterial->GetParent(); - } - if (pMtl == selectedMaterial) - { - SetSelectedItem(nullptr, nullptr, true); - } - } - } - break; - case EDB_ITEM_EVENT_CHANGED: - { - CMaterial* pMtl = static_cast(pItem); - CMaterial* selectedMaterial = GetCurrentMaterial(); - if (selectedMaterial && selectedMaterial->IsPureChild()) - { - selectedMaterial = selectedMaterial->GetParent(); - } - // If this is a sub material, refresh parent - if (pMtl->IsPureChild()) - { - pMtl = pMtl->GetParent(); - } - - if (pMtl == selectedMaterial) - { - if (pMtl->IsMultiSubMaterial()) - { - m_pLastActiveMultiMaterial = NULL; - } - RefreshSelected(); - } - m_bItemsValid = false; - } - break; - case EDB_ITEM_EVENT_SELECTED: - { - SelectItem(pItem, NULL); - } - break; - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::SetImageListCtrl(CMaterialImageListCtrl* pCtrl) -{ - m_pMaterialImageListCtrl = pCtrl; - if (m_pMaterialImageListCtrl) - { - connect(m_pMaterialImageListCtrl->selectionModel(), &QItemSelectionModel::currentChanged, - this, &MaterialBrowserWidget::OnSubMaterialSelectedInPreviewPane); - - connect(m_pMaterialImageListCtrl, &QAbstractItemView::clicked, - this, &MaterialBrowserWidget::OnSubMaterialSelectedInPreviewPane); - - m_pMaterialImageListCtrl->SetMaterialBrowserWidget(this); - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnSaveToFile(bool bMulti) -{ - _smart_ptr pCurrentMaterial = GetCurrentMaterial(); - if (pCurrentMaterial) - { - QString startPath = GetIEditor()->GetSearchPath(EDITOR_PATH_MATERIALS); - QString filename; - if (!CFileUtil::SelectSaveFile("Material Files (*.mtl)", "mtl", startPath, filename)) - { - return; - } - QFileInfo info(filename); - QString itemName = info.baseName(); - itemName = Path::MakeGamePath(itemName); - - if (m_pMatMan->FindItemByName(itemName)) - { - Warning("Material with name %s already exist", itemName.toUtf8().data()); - return; - } - int flags = pCurrentMaterial->GetFlags(); - if (bMulti) - { - flags |= MTL_FLAG_MULTI_SUBMTL; - } - - pCurrentMaterial->SetFlags(flags); - - if (pCurrentMaterial->IsDummy()) - { - pCurrentMaterial->ClearMatInfo(); - pCurrentMaterial->SetDummy(false); - } - pCurrentMaterial->SetModified(true); - pCurrentMaterial->Save(); - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::RefreshSelected() -{ - CMaterialBrowserRecord record; - bool found = TryGetSelectedRecord(record); - _smart_ptr pMtl = nullptr; - if (!found) - { - ClearImageListControlSelection(); - return; - } - else - { - pMtl = record.m_material; - } - - if (m_pMaterialImageListCtrl) - { - QMaterialImageListModel* materialModel = - qobject_cast(m_pMaterialImageListCtrl->model()); - Q_ASSERT(materialModel); - - materialModel->InvalidateMaterial(pMtl); - if (pMtl) - { - _smart_ptr pMultiMtl = nullptr; - if (pMtl->IsMultiSubMaterial()) - { - // It's possible that the currently selected sub-material index is beyond the range of the current multi-material if, for example, - // the last sub-material was selected but then the source .mtl file was changed to have fewer total sub-materials - if (m_selectedSubMaterialIndex >= pMtl->GetSubMaterialCount()) - { - // If that's the case, select the last sub-material - // If the sub-material count has dropped to 0, setting m_selectedSubMaterialIndex to -1 will cause the parent material to be selected - m_selectedSubMaterialIndex = pMtl->GetSubMaterialCount() - 1; - } - - pMultiMtl = pMtl; - if (m_selectedSubMaterialIndex >= 0) - { - pMtl = pMtl->GetSubMaterial(m_selectedSubMaterialIndex); - } - } - - if (m_pLastActiveMultiMaterial != pMultiMtl || pMultiMtl == nullptr) - { - // A new material was selected, so the previewer needs to be cleared - materialModel->DeleteAllItems(); - // If the new material was not a multi-material, add it to the previewer - if (pMultiMtl == nullptr) - { - materialModel->AddMaterial(pMtl); - } - } - - // If a new multi-material was selected - if (m_pLastActiveMultiMaterial != pMultiMtl && pMultiMtl != nullptr) - { - // Add all of its submaterials to the previewer - for (size_t i = 0; i < pMultiMtl->GetSubMaterialCount(); i++) - { - if (pMultiMtl->GetSubMaterial(i)) - { - materialModel->AddMaterial(pMultiMtl->GetSubMaterial(i), reinterpret_cast(i)); - } - } - m_pMaterialImageListCtrl->selectionModel()->clear(); - - // If a sub-material was selected in the material browser, select it in the previewer - QModelIndex modelIndex; - if (m_selectedSubMaterialIndex >= 0) - { - modelIndex = materialModel->index(m_selectedSubMaterialIndex, 0); - } - m_pMaterialImageListCtrl->selectionModel()->select(modelIndex, QItemSelectionModel::SelectCurrent); - } - - m_pMaterialImageListCtrl->SelectMaterial(pMtl); - m_pLastActiveMultiMaterial = pMultiMtl; - } - else - { - ClearSelection(materialModel); - } - } -} - -void MaterialBrowserWidget::ClearImageListControlSelection() -{ - QMaterialImageListModel* materialModel = - qobject_cast(m_pMaterialImageListCtrl->model()); - Q_ASSERT(materialModel); - - ClearSelection(materialModel); -} - -void MaterialBrowserWidget::ClearSelection(QMaterialImageListModel* materialModel) -{ - materialModel->DeleteAllItems(); - m_pLastActiveMultiMaterial = nullptr; -} - -////////////////////////////////////////////////////////////////////////// - -void MaterialBrowserWidget::AddContextMenuActionsMultiSelect(QMenu& menu) const -{ - int numMaterialsSelected = 0; - for (int i = 0; i < m_markedRecords.size(); ++i) - { - if (m_markedRecords[i].m_material) - { - ++numMaterialsSelected; - } - } - const QString itemsSelected = tr(" (%1 Materials Selected)").arg(numMaterialsSelected); - menu.addAction(itemsSelected)->setEnabled(false); - menu.addSeparator(); - - if (numMaterialsSelected >= 2) // ... and at least two materials - { - menu.addAction(tr("Merge"))->setData(MENU_MERGE); - } - else - { - menu.addAction(tr("Merge (Select two or more)"))->setEnabled(false); - } -} - -void MaterialBrowserWidget::AddContextMenuActionsNoSelection(QMenu& menu) const -{ - QAction* action = menu.addAction(tr("Paste")); - action->setShortcut(QKeySequence::Paste); - action->setData(MENU_PASTE); - action->setEnabled(CanPaste()); - - menu.addSeparator(); - menu.addAction(tr("Add New Material"))->setData(MENU_ADDNEW); - menu.addAction(tr("Add New Multi Material"))->setData(MENU_ADDNEW_MULTI); - if (GetIEditor()->IsSourceControlAvailable()) - { - menu.addSeparator(); - menu.addAction(tr("Source Control"))->setEnabled(false); - menu.addAction(tr("Check Out"))->setData(MENU_SCM_CHECK_OUT); - menu.addAction(tr("Undo Check Out"))->setData(MENU_SCM_UNDO_CHECK_OUT); - menu.addAction(tr("Get Latest Version"))->setData(MENU_SCM_GET_LATEST); - } -} - -void MaterialBrowserWidget::AddContextMenuActionsSingleSelection(QMenu& menu, _smart_ptr material) const -{ - if (material) - { - if (material->IsMultiSubMaterial()) - { - if (m_selectedSubMaterialIndex >= 0) - { - AddContextMenuActionsSubMaterial(menu, material, material->GetSubMaterial(m_selectedSubMaterialIndex)); - } - else - { - AddContextMenuActionsMultiMaterial(menu); - AddContextMenuActionsCommon(menu, material); - } - } - else if (material->IsPureChild()) - { - AddContextMenuActionsSubMaterial(menu, material->GetParent(), material); - } - else - { - AddContextMenuActionsSingleMaterial(menu); - AddContextMenuActionsCommon(menu, material); - } - } -} - -void MaterialBrowserWidget::AddContextMenuActionsSubMaterial(QMenu& menu, _smart_ptr parentMaterial, _smart_ptr subMaterial) const -{ - bool enabled = true; - - if (parentMaterial) - { - uint32 nFileAttr = parentMaterial->GetFileAttributes(); - if (nFileAttr & SCC_FILE_ATTRIBUTE_READONLY) - { - enabled = false; - } - } - - QAction* action = menu.addAction(tr("Reset sub-material to default")); - action->setData(MENU_SUBMTL_MAKE); - action->setEnabled(enabled); - - menu.addSeparator(); - - action = menu.addAction(tr("Cut")); - action->setShortcut(QKeySequence::Cut); - action->setData(MENU_CUT); - action->setEnabled(enabled); - - action = menu.addAction(tr("Copy")); - action->setShortcut(QKeySequence::Copy); - action->setData(MENU_COPY); - - action = menu.addAction(tr("Paste")); - action->setShortcut(QKeySequence::Paste); - action->setData(MENU_PASTE); - action->setEnabled(CanPaste() && enabled); - - action = menu.addAction(tr("Rename\tF2")); - action->setData(MENU_RENAME); - action->setEnabled(enabled); - - action = menu.addAction(tr("Delete")); - action->setData(MENU_SUBMTL_CLEAR); - action->setEnabled(enabled); -} - -void MaterialBrowserWidget::AddContextMenuActionsMultiMaterial(QMenu& menu) const -{ - menu.addAction(tr("Set Number of Sub-Materials"))->setData(MENU_NUM_SUBMTL); - menu.addSeparator(); -} - -void MaterialBrowserWidget::AddContextMenuActionsSingleMaterial(QMenu& menu) const -{ - menu.addAction(tr("Convert To Multi Material"))->setData(MENU_CONVERT_TO_MULTI); - menu.addSeparator(); -} - -void MaterialBrowserWidget::AddContextMenuActionsCommon(QMenu& menu, _smart_ptr material) const -{ - uint32 fileAttributes = material->GetFileAttributes(); - - bool modificationsEnabled = true; - if (fileAttributes & SCC_FILE_ATTRIBUTE_READONLY) - { - modificationsEnabled = false; - } - - QAction* action = menu.addAction(tr("Cut")); - action->setShortcut(QKeySequence::Cut); - action->setData(MENU_CUT); - action = menu.addAction(tr("Copy")); - action->setShortcut(QKeySequence::Copy); - action->setData(MENU_COPY); - action = menu.addAction(tr("Paste")); - action->setShortcut(QKeySequence::Paste); - action->setData(MENU_PASTE); - action->setEnabled(CanPaste() && modificationsEnabled); - menu.addAction(tr("Copy Path to Clipboard"))->setData(MENU_COPY_NAME); - if (fileAttributes & SCC_FILE_ATTRIBUTE_INPAK) - { - menu.addAction(tr("Extract"))->setData(MENU_EXTRACT); - } - else - { - menu.addAction(tr("Explore"))->setData(MENU_EXPLORE); - } - menu.addSeparator(); - action = menu.addAction(tr("Duplicate")); - action->setShortcut(tr("Ctrl+D")); - action->setData(MENU_DUPLICATE); - menu.addAction(tr("Rename\tF2"))->setData(MENU_RENAME); - action = menu.addAction(tr("Delete")); - action->setShortcut(QKeySequence::Delete); - action->setData(MENU_DELETE); - menu.addSeparator(); - menu.addAction(tr("Assign to Selected Objects"))->setData(MENU_ASSIGNTOSELECTION); - menu.addAction(tr("Select Assigned Objects"))->setData(MENU_SELECTASSIGNEDOBJECTS); - menu.addSeparator(); - - menu.addAction(tr("Add New Material"))->setData(MENU_ADDNEW); - menu.addAction(tr("Add New Multi Material"))->setData(MENU_ADDNEW_MULTI); - menu.addAction(tr("Merge (Select two or more)"))->setEnabled(false); - - AddContextMenuActionsSourceControl(menu, material, fileAttributes); -} - -void MaterialBrowserWidget::AddContextMenuActionsSourceControl(QMenu& menu, _smart_ptr material, uint32 fileAttributes) const -{ - if (GetIEditor()->IsSourceControlAvailable()) - { - menu.addSeparator(); - - if (fileAttributes & SCC_FILE_ATTRIBUTE_INPAK) - { - menu.addAction(tr(" Material In Pak (Read Only)"))->setEnabled(false); - } - else - { - menu.addAction(tr(" Source Control"))->setEnabled(false); - if (!(fileAttributes & SCC_FILE_ATTRIBUTE_MANAGED)) - { - menu.addAction(tr("Add To Source Control"))->setData(MENU_SCM_ADD); - } - } - QAction* action = nullptr; - if (fileAttributes & SCC_FILE_ATTRIBUTE_MANAGED) - { - action = menu.addAction(tr("Check Out")); - action->setData(MENU_SCM_CHECK_OUT); - action->setEnabled(fileAttributes & SCC_FILE_ATTRIBUTE_READONLY || fileAttributes & SCC_FILE_ATTRIBUTE_INPAK); - action = menu.addAction(tr("Undo Check Out")); - action->setData(MENU_SCM_UNDO_CHECK_OUT); - action->setEnabled(fileAttributes & SCC_FILE_ATTRIBUTE_CHECKEDOUT); - menu.addAction(tr("Get Latest Version"))->setData(MENU_SCM_GET_LATEST); - } - - if (material) - { - QStringList filenames; - int nTextures = material->GetTextureFilenames(filenames); - action = menu.addAction(tr("Get Textures")); - action->setData(MENU_SCM_GET_LATEST_TEXTURES); - action->setEnabled(nTextures > 0); - } - } -} - -void MaterialBrowserWidget::ShowContextMenu(const CMaterialBrowserRecord& record, const QPoint& point) -{ - _smart_ptr material = record.m_material; - - // Create pop up menu. - QMenu menu; - if (m_markedRecords.size() >= 2) // it makes sense when we have at least two items selected - { - AddContextMenuActionsMultiSelect(menu); - } - else if (!material) // click on root, background or folder - { - AddContextMenuActionsNoSelection(menu); - } - else - { - // When right-clicking a single item in the material browser, select the parent material that was clicked, rather than the currently selected sub-material - // The context menu for sub-materials will be handled by the image list control rather than the material browser widget - m_selectedSubMaterialIndex = -1; - SetSelectedItem(material, nullptr, true); - AddContextMenuActionsSingleSelection(menu, material); - } - QAction* action = menu.exec(m_ui->treeView->mapToGlobal(point)); - const int cmd = action ? action->data().toInt() : 0; - - OnContextMenuAction(cmd, material); -} - -void MaterialBrowserWidget::OnContextMenuAction(int command, _smart_ptr material) -{ - CMaterialBrowserRecord record; - TryGetSelectedRecord(record); - switch (command) - { - case MENU_UNDEFINED: - return; // do nothing - case MENU_CUT: - OnCut(); - break; - case MENU_COPY: - OnCopy(); - break; - case MENU_COPY_NAME: - OnCopyName(); - break; - case MENU_PASTE: - OnPaste(); - break; - case MENU_EXPLORE: - { - if (material && material->IsPureChild()) - { - material = material->GetParent(); - } - - if (material) - { - QString fullPath = material->GetFilename(); - AzQtComponents::ShowFileOnDesktop(fullPath); - } - } - break; - case MENU_EXTRACT: - { - if (material && material->IsPureChild()) - { - material = material->GetParent(); - } - - if (material) - { - QString fullPath = material->GetFilename(); - if (CFileUtil::ExtractFile(fullPath, true, fullPath.toUtf8().data())) - { - AzQtComponents::ShowFileOnDesktop(fullPath); - } - } - } - break; - case MENU_DUPLICATE: - OnDuplicate(); - break; - case MENU_RENAME: - OnRenameItem(); - break; - case MENU_DELETE: - DeleteItem(record); - break; - case MENU_RESET: - OnResetItem(); - break; - case MENU_ASSIGNTOSELECTION: - { - CUndo undo("Assign Material To Selection"); - GetIEditor()->GetMaterialManager()->Command_AssignToSelection(); - break; - } - case MENU_SELECTASSIGNEDOBJECTS: - { - CUndo undo("Select Objects With Current Material"); - GetIEditor()->GetMaterialManager()->Command_SelectAssignedObjects(); - break; - } - case MENU_NUM_SUBMTL: - OnSetSubMtlCount(record); - break; - case MENU_ADDNEW: - OnAddNewMaterial(); - break; - case MENU_ADDNEW_MULTI: - OnAddNewMultiMaterial(); - break; - case MENU_CONVERT_TO_MULTI: - OnConvertToMulti(); - break; - case MENU_MERGE: - OnMergeMaterials(); - break; - - case MENU_SUBMTL_MAKE: - OnMakeSubMtlSlot(record); - break; - case MENU_SUBMTL_CLEAR: - OnClearSubMtlSlot(material); - break; - - case MENU_SCM_ADD: - DoSourceControlOp(record, ESCM_IMPORT); - break; - case MENU_SCM_CHECK_OUT: - DoSourceControlOp(record, ESCM_CHECKOUT); - break; - case MENU_SCM_UNDO_CHECK_OUT: - DoSourceControlOp(record, ESCM_UNDO_CHECKOUT); - break; - case MENU_SCM_GET_LATEST: - DoSourceControlOp(record, ESCM_GETLATEST); - break; - case MENU_SCM_GET_LATEST_TEXTURES: - DoSourceControlOp(record, ESCM_GETLATESTTEXTURES); - break; - - case MENU_SAVE_TO_FILE: - OnSaveToFile(false); - break; - case MENU_SAVE_TO_FILE_MULTI: - OnSaveToFile(true); - break; - //case MENU_MAKE_SUBMTL: OnAddNewMultiMaterial(); break; - } -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::PopulateItems() -{ - if (m_bIgnoreSelectionChange) - { - return; - } - - if (m_bItemsValid) - { - return; - } - - m_bItemsValid = true; - m_bIgnoreSelectionChange = true; - - IDataBaseItem* pSelection = m_pMatMan->GetSelectedItem(); - IDataBaseItem* pSelectionParent = m_pMatMan->GetSelectedParentItem(); - - m_bIgnoreSelectionChange = false; - - if (pSelection) - { - SelectItem(pSelection, pSelectionParent); - if (m_bHighlightMaterial) - { - m_bHighlightMaterial = false; - m_pMatMan->SetHighlightedMaterial(0); - } - } -} - -void MaterialBrowserWidget::StartRecordUpdateJobs() -{ - m_filterModel->StartRecordUpdateJobs(); -} - -////////////////////////////////////////////////////////////////////////// -uint32 MaterialBrowserWidget::MaterialNameToCrc32(const QString& str) -{ - return CCrc32::ComputeLowercase(str.toUtf8()); -} - -////////////////////////////////////////////////////////////////////////// -bool MaterialBrowserWidget::TryGetSelectedRecord(CMaterialBrowserRecord& record) -{ - QVariant variant = m_filterModel->data(m_ui->treeView->currentIndex(), Qt::UserRole); - if (variant.isValid()) - { - record = variant.value(); - return true; - } - - return false; -} - -////////////////////////////////////////////////////////////////////////// -_smart_ptr MaterialBrowserWidget::GetCurrentMaterial() -{ - CMaterialBrowserRecord record; - bool found = TryGetSelectedRecord(record); - if (found && record.m_material) - { - if (record.m_material->IsMultiSubMaterial() && m_selectedSubMaterialIndex >= 0) - { - return record.m_material->GetSubMaterial(m_selectedSubMaterialIndex); - } - else - { - return record.m_material; - } - } - - return m_pMatMan->GetCurrentMaterial(); -} - -////////////////////////////////////////////////////////////////////////// -AZStd::string MaterialBrowserWidget::GetSelectedMaterialID() -{ - CMaterialBrowserRecord record; - bool found = TryGetSelectedRecord(record); - if (found) - { - return record.GetRelativeFilePath(); - } - return AZStd::string(); -} - -////////////////////////////////////////////////////////////////////////// -void MaterialBrowserWidget::OnSelectionChanged() -{ - m_selectedSubMaterialIndex = -1; - TMaterialBrowserRecords markedRecords; - - CMaterialBrowserRecord record; - bool found = TryGetSelectedRecord(record); - for (const QModelIndex& row : m_ui->treeView->selectionModel()->selectedRows()) - { - QVariant userRole = row.data(Qt::UserRole); - if (userRole.isValid()) - { - CMaterialBrowserRecord currentRecord = userRole.value(); - markedRecords.push_back(currentRecord); - } - } - - if (!found && !markedRecords.empty()) - { - record = markedRecords.front(); - found = true; - } - if (found) - { - // Since the call to SetSelectedItem is coming from an OnSelectionChanged event, the appropriate - // element of the tree view has already been selected. Pass in false for the selectInTreeView argument - // to prevent SetSelectedItem from trying to re-select the material in the browser - SetSelectedItem(record.m_material, &markedRecords, false); - } -} - -void MaterialBrowserWidget::OnRefreshSelection() -{ - // force RefreshSelected to repopulate by setting m_pLastActiveMultiMaterial to null - // so it thinks we selected a new material. - m_pLastActiveMultiMaterial = nullptr; - - //If no material is selected, clear preview. - if (!GetCurrentMaterial()) - { - if (m_pMaterialImageListCtrl) - { - QMaterialImageListModel* materialModel = - qobject_cast(m_pMaterialImageListCtrl->model()); - Q_ASSERT(materialModel); - materialModel->DeleteAllItems(); - } - } - - RefreshSelected(); - - // Force update the material dialog - if (m_pListener) - { - m_pListener->OnBrowserSelectItem(GetCurrentMaterial(), true); - } -} - -void MaterialBrowserWidget::OnMaterialAdded() -{ - if (m_delayedSelection) - { - SetSelectedItem(m_delayedSelection, nullptr, true); - - // Force update the material dialog - if (m_pListener) - { - m_pListener->OnBrowserSelectItem(GetCurrentMaterial(), true); - } - } -} - -void MaterialBrowserWidget::OnSubMaterialSelectedInPreviewPane(const QModelIndex& current) -{ - if (!m_pMaterialImageListCtrl) - { - return; - } - - QMaterialImageListModel* materialModel = - qobject_cast(m_pMaterialImageListCtrl->model()); - Q_ASSERT(materialModel); - - int nSlot = (INT_PTR)materialModel->UserDataFromIndex(current); - if (nSlot < 0) - { - return; - } - - CMaterialBrowserRecord record; - bool found = TryGetSelectedRecord(record); - if (!found || !record.m_material) - { - return; - } - - if (!record.m_material->IsMultiSubMaterial()) - { - return; // must be multi sub material. - } - if (nSlot >= record.m_material->GetSubMaterialCount()) - { - return; - } - - if (nSlot == m_selectedSubMaterialIndex) - { - return; - } - - m_selectedSubMaterialIndex = nSlot; - - SetSelectedItem(record.m_material, nullptr, false); -} - -void MaterialBrowserWidget::SaveCurrentMaterial() -{ - // Saving might open a modal dialog asking to overwrite, therefore don't run this from DTOR, might crash - - _smart_ptr pCurrentMtl = GetCurrentMaterial(); - if (pCurrentMtl && pCurrentMtl->IsModified()) - { - pCurrentMtl->Save(); - } -} - -void MaterialBrowserWidget::expandAllNotMatchingIndexes(const QModelIndex& parent) -{ - if (!parent.isValid()) - { - m_ui->treeView->collapseAll(); - } - - const int rowCount = m_ui->treeView->model()->rowCount(parent); - for (int row = 0; row < rowCount; ++row) - { - const QModelIndex index = m_ui->treeView->model()->index(row, 0, parent); - const QString text = index.data().toString(); - bool contains = true; - m_ui->treeView->setExpanded(index, !contains); - if (!contains) - { - expandAllNotMatchingIndexes(index); - } - } -} - -void MaterialBrowserWidget::MaterialAddFinished() -{ - emit materialAdded(); -} - -void MaterialBrowserWidget::MaterialFinishedProcessing(_smart_ptr material, const QPersistentModelIndex& filterModelIndex) -{ - // If the currently selected material finished processing - if (filterModelIndex.isValid() && filterModelIndex == m_ui->treeView->currentIndex()) - { - // Stash the delayed selection so that it is not cleared just because the currently selected material finished processing - _smart_ptr tempDelayedSelection = m_delayedSelection; - - // Re-select the material to update the material dialogue - // but ignore the tree-view selection since the current index is already the correct one for this material - SetSelectedItem(material, nullptr, false); - - // Force update the material dialog - if (m_pListener) - { - m_pListener->OnBrowserSelectItem(GetCurrentMaterial(), true); - } - - if (material != m_delayedSelection) - { - // If the current selection that just finished processing was not the delayed selection, restore the delayed selection - m_delayedSelection = tempDelayedSelection; - } - } - // If there was a failed attempt to select the material before it finished processing - else if (m_delayedSelection && m_delayedSelection == material) - { - // Re-select the material to update the material dialogue - // and also select the material in the tree-view - SetSelectedItem(material, nullptr, true); - - // Force update the material dialog - if (m_pListener) - { - m_pListener->OnBrowserSelectItem(GetCurrentMaterial(), true); - } - } -} - -void MaterialBrowserWidget::MaterialRecordUpdateFinished() -{ - //The event is sent by a AZJob working thread, need to emit a signal here for qt to catch later. - //It can make sure all the qt functions need to be called at this point are only executed in the qt thread. - emit refreshSelection(); -} - - -#include diff --git a/Code/Sandbox/Editor/Material/MaterialBrowser.h b/Code/Sandbox/Editor/Material/MaterialBrowser.h deleted file mode 100644 index d02045bacd..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialBrowser.h +++ /dev/null @@ -1,248 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALBROWSER_H -#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALBROWSER_H -#pragma once - - -#if !defined(Q_MOC_RUN) -#include "Include/IDataBaseManager.h" -#include "Material/Material.h" -#include "Material/MaterialBrowserFilterModel.h" - -#include -#include -#include -#include - -#include -#endif - -class CMaterial; - -class MaterialBrowserWidget; -class CMaterialImageListCtrl; -class QMaterialImageListModel; - -class QTreeView; -class QAction; - -struct IDataBaseItem; -class CMaterialBrowserRecord; -typedef std::vector TMaterialBrowserRecords; - -namespace AzToolsFramework -{ - namespace AssetBrowser - { - class AssetBrowserModel; - class AssetBrowserFilterModel; - class AssetTypeFilter; - } -} - -enum ESccFileAttributes; - -namespace Ui -{ - class MaterialBrowser; -} - - -////////////////////////////////////////////////////////////////////////// -struct IMaterialBrowserListener -{ - virtual void OnBrowserSelectItem(IDataBaseItem* pItem, bool bForce) = 0; -}; - -////////////////////////////////////////////////////////////////////////// -// MaterialBrowserWidget -////////////////////////////////////////////////////////////////////////// -class MaterialBrowserFilterModel; - -class MaterialBrowserWidget - : public QWidget - , public IDataBaseManagerListener - , public IEditorNotifyListener - , public MaterialBrowserWidgetBus::Handler -{ - Q_OBJECT - -public: - enum EViewType - { - VIEW_LEVEL = 0, - VIEW_ALL = 1, - }; - - enum EFilter - { - eFilter_Materials = 0x01, - eFilter_Textures = 0x02, - eFilter_Materials_And_Textures = 0x03, - eFilter_Submaterials = 0x04 - }; - - MaterialBrowserWidget(QWidget* parent); - ~MaterialBrowserWidget(); - - void SetListener(IMaterialBrowserListener* pListener) { m_pListener = pListener; } - - EViewType GetViewType() const { return m_viewType; }; - - void ClearItems(); - - void SelectItem(IDataBaseItem* pItem, IDataBaseItem* pParentItem); - void DeleteItem(); - - void PopulateItems(); - void StartRecordUpdateJobs(); - - bool ShowCheckedOutRecursive(TMaterialBrowserRecords* pRecords); - - void ShowOnlyLevelMaterials(bool levelOnly); - - void OnCopy(); - void OnCopyName(); - void OnPaste(); - void OnCut(); - void OnDuplicate(); - void OnAddNewMaterial(); - void OnAddNewMultiMaterial(); - void OnConvertToMulti(); - void OnMergeMaterials(); - -public slots: - void OnSelectionChanged(); - void OnSubMaterialSelectedInPreviewPane(const QModelIndex& current); - void SaveCurrentMaterial(); - void OnRefreshSelection(); - void OnMaterialAdded(); - -signals: - void refreshSelection(); - void materialAdded(); - -public: - void OnUpdateShowCheckedOut(); - bool CanPaste() const; - - void SetImageListCtrl(CMaterialImageListCtrl* pCtrl); - - ////////////////////////////////////////////////////////////////////////// - // IDataBaseManagerListener implementation. - ////////////////////////////////////////////////////////////////////////// - virtual void OnDataBaseItemEvent(IDataBaseItem* pItem, EDataBaseItemEvent event); - ////////////////////////////////////////////////////////////////////////// - - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); - void AddContextMenuActionsSingleSelection(QMenu &menu, _smart_ptr material) const; - void OnContextMenuAction(int command, _smart_ptr material); - - // MaterialBrowserWidgetBus event handlers - void MaterialAddFinished() override; - void MaterialFinishedProcessing(_smart_ptr material, const QPersistentModelIndex &filterModelIndex) override; - void MaterialRecordUpdateFinished() override; - -protected: - // Item definition. - enum ESourceControlOp - { - ESCM_IMPORT, - ESCM_CHECKOUT, - ESCM_UNDO_CHECKOUT, - ESCM_GETLATEST, - ESCM_GETLATESTTEXTURES, - }; - - void DeleteItem(const CMaterialBrowserRecord &record); - void SetSelectedItem(_smart_ptr material, const TMaterialBrowserRecords* pMarkedRecords, bool selectInTreeView); - void OnAddSubMtl(); - void OnSelectAssignedObjects(); - void OnAssignMaterialToSelection(); - void OnRenameItem(); - void OnResetItem(); - void OnSetSubMtlCount(const CMaterialBrowserRecord &record); - - void DoSourceControlOp(CMaterialBrowserRecord &record, ESourceControlOp); - - void OnMakeSubMtlSlot(const CMaterialBrowserRecord &record); - void OnClearSubMtlSlot(_smart_ptr subMaterial); - void SetSubMaterial(_smart_ptr parentMaterial, int slot, _smart_ptr subMaterial); - - void OnSaveToFile(bool bMulti); - - void RefreshSelected(); - - void TickRefreshMaterials(); - void TryLoadRecordMaterial(CMaterialBrowserRecord &record); - - void ShowContextMenu(const CMaterialBrowserRecord &record, const QPoint& point); - _smart_ptr GetCurrentMaterial(); - - uint32 MaterialNameToCrc32(const QString& str); - - bool TryGetSelectedRecord(CMaterialBrowserRecord &record); - AZStd::string GetSelectedMaterialID(); - -private: - void expandAllNotMatchingIndexes(const QModelIndex& parent = QModelIndex()); - void ClearImageListControlSelection(); - void ClearSelection(QMaterialImageListModel* materialModel); - QMenu *InitializeSearchMenu(); - - void AddContextMenuActionsMultiSelect(QMenu &menu) const; - void AddContextMenuActionsNoSelection(QMenu &menu) const; - void AddContextMenuActionsSubMaterial(QMenu &menu, _smart_ptr parentMaterial, _smart_ptr subMaterial) const; - void AddContextMenuActionsMultiMaterial(QMenu &menu) const; - void AddContextMenuActionsSingleMaterial(QMenu &menu) const; - void AddContextMenuActionsCommon(QMenu &menu, _smart_ptr material) const; - void AddContextMenuActionsSourceControl(QMenu &menu, _smart_ptr material, uint32 fileAttributes) const; - - QScopedPointer m_ui; - - AzToolsFramework::AssetBrowser::AssetBrowserModel* m_assetBrowserModel; - QSharedPointer m_filterModel; - int m_selectedSubMaterialIndex = -1; - - bool m_bIgnoreSelectionChange; - bool m_bItemsValid; - - CMaterialManager* m_pMatMan; - IMaterialBrowserListener* m_pListener; - CMaterialImageListCtrl* m_pMaterialImageListCtrl; - - EViewType m_viewType; - bool m_bNeedReload; - - bool m_bHighlightMaterial; - uint32 m_timeOfHighlight; - - TMaterialBrowserRecords m_markedRecords; - - _smart_ptr m_pLastActiveMultiMaterial; - _smart_ptr m_delayedSelection; - - bool m_bShowOnlyCheckedOut; - - QAction* m_cutAction; - QAction* m_copyAction; - QAction* m_pasteAction; - QAction* m_duplicateAction; - QAction* m_deleteAction; - QAction* m_renameItemAction; - QAction* m_addNewMaterialAction; -}; - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALBROWSER_H diff --git a/Code/Sandbox/Editor/Material/MaterialBrowser.ui b/Code/Sandbox/Editor/Material/MaterialBrowser.ui deleted file mode 100644 index 44e4e135ef..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialBrowser.ui +++ /dev/null @@ -1,87 +0,0 @@ - - - MaterialBrowser - - - - 0 - 0 - 250 - 400 - - - - Form - - - - 0 - - - 2 - - - 0 - - - 0 - - - - - - - - 0 - 0 - - - - - 147 - 22 - - - - - - - - - - - 0 - 0 - - - - Qt::CustomContextMenu - - - QAbstractItemView::ExtendedSelection - - - false - - - - - - - - AzToolsFramework::AssetBrowser::SearchWidget - QWidget -
AzToolsFramework/AssetBrowser/Search/SearchWidget.h
- 1 -
- - AzToolsFramework::AssetBrowser::AssetBrowserTreeView - QTreeView -
AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h
-
-
- - - - -
diff --git a/Code/Sandbox/Editor/Material/MaterialBrowserFilterModel.cpp b/Code/Sandbox/Editor/Material/MaterialBrowserFilterModel.cpp deleted file mode 100644 index 9f145c4daf..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialBrowserFilterModel.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "EditorDefs.h" - -#include "MaterialBrowserFilterModel.h" - -// AzFramework -#include - -// AzToolsFramework -#include -#include -#include -#include - -// Editor -#include "MaterialBrowserSearchFilters.h" -#include "MaterialManager.h" - - -namespace -{ - // how often to re-query source control status of an item after querying it, in seconds. - // note that using a source control operation on an item invalidates the cache and will immediately - // refresh its status regardless of this value, so it can be pretty high. - qint64 g_timeRefreshSCCStatus = 60; -} - -#define IDC_MATERIAL_TREECTRL 3 - -////////////////////////////////////////////////////////////////////////// -#define ITEM_IMAGE_SHARED_MATERIAL 0 -#define ITEM_IMAGE_SHARED_MATERIAL_SELECTED 1 -#define ITEM_IMAGE_FOLDER 2 -#define ITEM_IMAGE_FOLDER_OPEN 3 -#define ITEM_IMAGE_MATERIAL 4 -#define ITEM_IMAGE_MATERIAL_SELECTED 5 -#define ITEM_IMAGE_MULTI_MATERIAL 6 -#define ITEM_IMAGE_MULTI_MATERIAL_SELECTED 7 - - -#define ITEM_IMAGE_OVERLAY_CGF 8 -#define ITEM_IMAGE_OVERLAY_INPAK 9 -#define ITEM_IMAGE_OVERLAY_READONLY 10 -#define ITEM_IMAGE_OVERLAY_ONDISK 11 -#define ITEM_IMAGE_OVERLAY_LOCKED 12 -#define ITEM_IMAGE_OVERLAY_CHECKEDOUT 13 -#define ITEM_IMAGE_OVERLAY_NO_CHECKOUT 14 -////////////////////////////////////////////////////////////////////////// - -AZ::Data::AssetId GetMaterialProductAssetIdFromAssetBrowserEntry(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* assetEntry) -{ - using namespace AzToolsFramework::AssetBrowser; - - if (assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source || - assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product) - { - AZStd::vector products; - assetEntry->GetChildrenRecursively(products); - - // Cache the material asset type because this function is called for every submaterial when searching. - // AssetType is a POD struct so it should be fine to leave it as a static that gets destroyed during library unload/program termination. - static AZ::Data::AssetType materialAssetType = AZ::Data::AssetType::CreateNull(); - if (materialAssetType.IsNull()) - { - EBusFindAssetTypeByName materialAssetTypeResult("Material"); - AZ::AssetTypeInfoBus::BroadcastResult(materialAssetTypeResult, &AZ::AssetTypeInfo::GetAssetType); - AZ_Assert(materialAssetTypeResult.Found(), "Could not find asset type for material asset"); - materialAssetType = materialAssetTypeResult.GetAssetType(); - } - - for (const auto* product : products) - { - if (product->GetAssetType() == materialAssetType) - { - return product->GetAssetId(); - } - } - } - return AZ::Data::AssetId(); -} - -MaterialBrowserFilterModel::MaterialBrowserFilterModel(QObject* parent) - : AzToolsFramework::AssetBrowser::AssetBrowserFilterModel(parent) -{ - using namespace AzToolsFramework::AssetBrowser; - using namespace AzToolsFramework::MaterialBrowser; - - MaterialBrowserSourceControlBus::Handler::BusConnect(); - AssetBrowserModelNotificationBus::Handler::BusConnect(); - MaterialBrowserRequestBus::Handler::BusConnect(); - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_00.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_01.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_02.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_03.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_04.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_05.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_06.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/material_07.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_00.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_01.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_02.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_03.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_04.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_05.png")); - m_imageList.push_back(QPixmap(":/MaterialBrowser/images/filestatus_06.png")); - - - // Create an asset type filter for materials - AssetTypeFilter* assetTypeFilter = new AssetTypeFilter(); - assetTypeFilter->SetAssetType("Material"); - assetTypeFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down); //this will make sure folders that contain materials are displayed - m_assetTypeFilter = FilterConstType(assetTypeFilter); - - // Create search filters. SetSearchFilter stores these filters so that they are deleted when this object is deleted. - m_subMaterialSearchFilter = new SubMaterialSearchFilter(this); - m_levelMaterialSearchFilter = new LevelMaterialSearchFilter(this); - - InitializeRecordUpdateJob(); -} - -MaterialBrowserFilterModel::~MaterialBrowserFilterModel() -{ - SAFE_DELETE(m_jobCancelGroup); - SAFE_DELETE(m_jobContext); - SAFE_DELETE(m_jobManager); - - AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler::BusDisconnect(); - MaterialBrowserSourceControlBus::Handler::BusDisconnect(); - AzToolsFramework::MaterialBrowser::MaterialBrowserRequestBus::Handler::BusDisconnect(); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); -} - -void MaterialBrowserFilterModel::UpdateRecord(const QModelIndex& filterModelIndex) -{ - using namespace AzToolsFramework::AssetBrowser; - - if (filterModelIndex.isValid()) - { - QModelIndex modelIndex = mapToSource(filterModelIndex); - - AssetBrowserEntry* assetEntry = static_cast(modelIndex.internalPointer()); - - if (assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source || - assetEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product) - { - AZStd::vector products; - assetEntry->GetChildrenRecursively(products); - - for (const auto* product : products) - { - if (!m_assetTypeFilter->Match(product)) - { - continue; - } - MaterialBrowserRecordAssetBrowserData assetBrowserData; - assetBrowserData.assetId = product->GetAssetId(); - assetBrowserData.relativeFilePath = product->GetRelativePath(); - assetBrowserData.fullSourcePath = product->GetFullPath(); - assetBrowserData.modelIndex = modelIndex; - assetBrowserData.filterModelIndex = filterModelIndex; - UpdateRecord(assetBrowserData); - } - } - } -} - -void MaterialBrowserFilterModel::UpdateRecord(const MaterialBrowserRecordAssetBrowserData& assetBrowserData) -{ - CMaterialBrowserRecord record; - record.SetAssetBrowserData(assetBrowserData); - record.m_material = GetIEditor()->GetMaterialManager()->LoadMaterial(record.GetRelativeFilePath().c_str()); - SetRecord(record); -} - -void MaterialBrowserFilterModel::UpdateSourceControlFileInfoCallback(const AZ::Data::AssetId& assetId, const AzToolsFramework::SourceControlFileInfo& info) -{ - CMaterialBrowserRecord record; - bool found = m_materialRecordMap.find(assetId, &record); - if (found) - { - // Update the cached source control attributes for the record - record.m_lastCachedSCCAttributes = info; - record.m_lastCachedFileAttributes = static_cast(CFileUtil::GetAttributes(record.GetFullSourcePath().c_str(), false)); - record.m_lastCheckedSCCAttributes = QDateTime::currentDateTime(); - - // Update the record - m_materialRecordMap.erase(assetId); - m_materialRecordMap.insert(AZStd::pair(record.GetAssetId(), record)); - - QueueDataChangedEvent(record.GetFilterModelIndex()); - } -} - -void MaterialBrowserFilterModel::UpdateSourceControlLastCheckedTime(const AZ::Data::AssetId& assetId, const QDateTime& dateTime) -{ - CMaterialBrowserRecord record; - bool found = m_materialRecordMap.find(assetId, &record); - if (found) - { - // Update the record - record.m_lastCheckedSCCAttributes = dateTime; - m_materialRecordMap.erase(assetId); - m_materialRecordMap.insert(AZStd::pair(record.GetAssetId(), record)); - } -} - -QVariant MaterialBrowserFilterModel::data(const QModelIndex& index, int role /* = Qt::DisplayRole*/) const -{ - // Should return data from an AssetBrowserEntry, or get material specific info from that data - if (index.isValid()) - { - // Use the base AssetBrowserFilterModel::data function for display role - if (role != AzToolsFramework::AssetBrowser::AssetBrowserModel::Roles::EntryRole) - { - QModelIndex modelIndex = mapToSource(index); - AzToolsFramework::AssetBrowser::AssetBrowserEntry* assetEntry = static_cast(modelIndex.internalPointer()); - - AZ::Data::AssetId assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(assetEntry); - if (assetId.IsValid()) - { - CMaterialBrowserRecord record; - bool found = m_materialRecordMap.find(assetId, &record); - - if (role == Qt::UserRole) - { - if (found) - { - return QVariant::fromValue(record); - } - else - { - return QVariant(); - } - } - } - } - } - // If the role is Qt::DisplayRole, the item a folder, or the material has not been parsed yet, fall back on the default data result from the underlying AssetBrowserModel - return AzToolsFramework::AssetBrowser::AssetBrowserFilterModel::data(index, role); -} - -void MaterialBrowserFilterModel::GetRelativeFilePaths(AZStd::vector& files) const -{ - GetRelativeFilePathsRecursive(files, this); -} - -void MaterialBrowserFilterModel::GetRelativeFilePathsRecursive(AZStd::vector& files, - const MaterialBrowserFilterModel* model, const QModelIndex& parent) const -{ - using namespace AzToolsFramework::AssetBrowser; - - for (int r = 0; r < model->rowCount(parent); ++r) - { - QModelIndex index = model->index(r, 0, parent); - QModelIndex modelIndex = model->mapToSource(index); - - if (model->hasChildren(index)) - { - GetRelativeFilePathsRecursive(files, model, index); - } - else - { - AssetBrowserEntry* assetEntry = static_cast(modelIndex.internalPointer()); - - AZStd::vector products; - assetEntry->GetChildrenRecursively(products); - - for (const auto* product : products) - { - if (!m_assetTypeFilter->Match(product)) - { - continue; - } - MaterialBrowserRecordAssetBrowserData item; - item.assetId = product->GetAssetId(); - item.fullSourcePath = product->GetFullPath(); - item.relativeFilePath = product->GetRelativePath(); - item.modelIndex = modelIndex; - item.filterModelIndex = index; - files.push_back(item); - } - } - } -} - -QModelIndex MaterialBrowserFilterModel::GetIndexFromMaterial(_smart_ptr material) const -{ - CMaterialBrowserRecord record; - bool found = TryGetRecordFromMaterial(material, record); - if (found) - { - return record.GetFilterModelIndex(); - } - return QModelIndex(); -} - -QModelIndex MaterialBrowserFilterModel::GetFilterModelIndex(const AZ::Data::AssetId& assetId) const -{ - QModelIndex filterModelIndex; - if (TryGetFilterModelIndexRecursive(filterModelIndex, assetId, this)) - { - return filterModelIndex; - } - - return QModelIndex(); -} - -bool MaterialBrowserFilterModel::TryGetFilterModelIndexRecursive(QModelIndex& filterModelIndex, - const AZ::Data::AssetId& assetId, const MaterialBrowserFilterModel* model, const QModelIndex& parent) const -{ - using namespace AzToolsFramework::AssetBrowser; - - // Walk through the filter model to find the product entry with the corresponding assetId - for (int r = 0; r < model->rowCount(parent); ++r) - { - QModelIndex index = model->index(r, 0, parent); - QModelIndex modelIndex = model->mapToSource(index); - - if (model->hasChildren(index)) - { - if (TryGetFilterModelIndexRecursive(filterModelIndex, assetId, model, index)) - { - return true; - } - } - else - { - // Check to see if the current entry is the one we're looking for - AssetBrowserEntry* assetEntry = static_cast(modelIndex.internalPointer()); - - AZStd::vector products; - assetEntry->GetChildrenRecursively(products); - - for (const auto* product : products) - { - if (assetId == product->GetAssetId()) - { - filterModelIndex = index; - return true; - } - } - } - } - - return false; -} - -void MaterialBrowserFilterModel::EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) -{ - // If the entry is a product material - if (entry->GetEntryType() == AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product && m_assetTypeFilter->Match(entry)) - { - // capture the data here, so that entry cannot disappear before we actually get to the job. - MaterialBrowserRecordAssetBrowserData assetBrowserData; - assetBrowserData.assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(entry); - assetBrowserData.relativeFilePath = entry->GetRelativePath(); - assetBrowserData.fullSourcePath = entry->GetFullPath(); - assetBrowserData.filterModelIndex = GetFilterModelIndex(assetBrowserData.assetId); - - // Create a job to add/update the entry in the underlying map - AZ::Job* updateEntryJob = AZ::CreateJobFunction([this, assetBrowserData]() - { - CMaterialBrowserRecord record; - record.SetAssetBrowserData(assetBrowserData); - record.m_material = GetIEditor()->GetMaterialManager()->LoadMaterialWithFullSourcePath(record.GetRelativeFilePath().c_str(), record.GetFullSourcePath().c_str()); - SetRecord(record); - MaterialBrowserWidgetBus::Broadcast(&MaterialBrowserWidgetEvents::MaterialAddFinished); - }, true, m_jobContext); - - // Start the job immediately - AZ::Job* currentJob = m_jobContext->GetJobManager().GetCurrentJob(); - if (currentJob) - { - // Suspend the current job until the new job completes so that - // if a new material is created by the user it's ready to use sooner - currentJob->StartAsChild(updateEntryJob); - currentJob->WaitForChildren(); - } - else - { - updateEntryJob->Start(); - } - } -} - - -void MaterialBrowserFilterModel::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) -{ - CMaterialBrowserRecord record; - bool found = m_materialRecordMap.find(assetId, &record); - if (found) - { - record.m_material->Reload(); - //Send out event to notify UI update if it's currently selected - MaterialBrowserWidgetBus::Broadcast(&MaterialBrowserWidgetEvents::MaterialFinishedProcessing, record.m_material, record.GetFilterModelIndex()); - } -} - -bool MaterialBrowserFilterModel::HasRecord(const AZ::Data::AssetId& assetId) -{ - return m_materialRecordMap.find(assetId); -} - -bool MaterialBrowserFilterModel::IsMultiMaterial(const AZ::Data::AssetId& assetId) -{ - CMaterialBrowserRecord record; - bool found = m_materialRecordMap.find(assetId, &record); - if (found) - { - if (record.m_material && record.m_material->IsMultiSubMaterial()) - { - return true; - } - } - return false; -} - -bool MaterialBrowserFilterModel::TryGetRecordFromMaterial(_smart_ptr material, CMaterialBrowserRecord& record) const -{ - if (material) - { - // Get the relative path for the material - bool pathFound = false; - AZStd::string relativePath; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(pathFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetRelativeProductPathFromFullSourceOrProductPath, material->GetFilename().toUtf8().data(), relativePath); - AZ_Assert(pathFound, "Failed to get engine relative path from %s", material->GetFilename().toUtf8().data()); - - // Get the assetId from the relative path - AZ::Data::AssetId assetId; - - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, relativePath.c_str(), GetIEditor()->GetMaterialManager()->GetMaterialAssetType(), false); - - return TryGetRecordFromAssetId(assetId, record); - } - - return false; -} - -bool MaterialBrowserFilterModel::TryGetRecordFromAssetId(const AZ::Data::AssetId& assetId, CMaterialBrowserRecord& record) const -{ - bool recordFound = m_materialRecordMap.find(assetId, &record); - return recordFound; -} - -void MaterialBrowserFilterModel::SetRecord(const CMaterialBrowserRecord& record) -{ - m_materialRecordMap.erase(record.GetAssetId()); - m_materialRecordMap.insert({ record.GetAssetId(), record }); - - QueueDataChangedEvent(record.GetFilterModelIndex()); -} - -void MaterialBrowserFilterModel::SetSearchFilter(const AzToolsFramework::AssetBrowser::SearchWidget* searchWidget) -{ - /* - * The filter matches the following rule: - * A. If the entry is a material - * 1. The material's name matches the search text - * 2. The sub material's name matches the search text - * B. If the entry is a folder: - * 1. The folder's name matches the search text - * 2. The folder contains a material matching A - * 3. The folder contains a folder matching B.1 & B.2 - */ - - using namespace AzToolsFramework::AssetBrowser; - - m_searchWidget = searchWidget; - - // Create a search filter where a search text either matches entry/entry parent's name or sub material name - CompositeFilter* nameFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::OR); - QSharedPointer searchWidgetFilter = m_searchWidget->GetFilter(); - // The default setting for search widget filter is Down - // Since now we only need to match for the entry itself in this filter, set back to None - searchWidgetFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::None); - nameFilter->AddFilter(FilterConstType(m_subMaterialSearchFilter)); - nameFilter->AddFilter(FilterConstType(searchWidgetFilter)); - - EntryTypeFilter* productsFilter = new EntryTypeFilter(); - productsFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Product); - InverseFilter* noProductsFilter = new InverseFilter(); - noProductsFilter->SetFilter(FilterConstType(productsFilter)); - - // Create a filter where the entry needs to match the previous name filter and it needs to be material itself or it contains material. - CompositeFilter* isMaterialAndMatchesSearchFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND); - isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(nameFilter)); - isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(m_assetTypeFilter)); - isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(noProductsFilter)); - isMaterialAndMatchesSearchFilter->AddFilter(FilterConstType(m_levelMaterialSearchFilter)); - // Make sure any folder contains the matching result is included - isMaterialAndMatchesSearchFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down); - - // Set the filter for the MaterialBrowserFilterModel - SetFilter(FilterConstType(isMaterialAndMatchesSearchFilter)); -} - -void MaterialBrowserFilterModel::ShowOnlyLevelMaterials(bool levelOnly, bool invalidateFilterNow) -{ - m_levelMaterialSearchFilter->ShowOnlyLevelMaterials(levelOnly); - if (levelOnly) - { - m_levelMaterialSearchFilter->CacheLoadedMaterials(); - } - - if (invalidateFilterNow) - { - // we need to invalid the filter immediately, for example this is used when we are changing level, otherwise - // the current filter is used when getting file paths for all of the materials as part of StartRecordUpdateJobs. - invalidateFilter(); - } - else - { - filterUpdatedSlot(); - } -} - -void MaterialBrowserFilterModel::SearchFilterUpdated() -{ - m_subMaterialSearchFilter->SetFilterString(m_searchWidget->textFilter()); - filterUpdatedSlot(); -} - -void MaterialBrowserFilterModel::QueueDataChangedEvent(const QPersistentModelIndex& filterModelIndex) -{ - // Queue a data changed event to be executed on the main thread - AZStd::function emitDataChanged = - [this, filterModelIndex]() - { - if (filterModelIndex.isValid()) - { - Q_EMIT dataChanged(filterModelIndex, filterModelIndex); - } - }; - - AZ::TickBus::QueueFunction(emitDataChanged); -} - -void MaterialBrowserFilterModel::InitializeRecordUpdateJob() -{ - AZ::JobManagerDesc desc; - AZ::JobManagerThreadDesc threadDesc; - for (size_t i = 0; i < AZStd::thread::hardware_concurrency(); ++i) - { - desc.m_workerThreads.push_back(threadDesc); - } - - // Check to ensure these have not already been initialized. - AZ_Error("Material Browser", !m_jobManager && !m_jobCancelGroup && !m_jobContext, "MaterialBrowserFilterModel::InitializeRecordUpdateJob is being called again after it has already been initialized"); - m_jobManager = aznew AZ::JobManager(desc); - m_jobCancelGroup = aznew AZ::JobCancelGroup(); - m_jobContext = aznew AZ::JobContext(*m_jobManager, *m_jobCancelGroup); -} - -void MaterialBrowserFilterModel::StartRecordUpdateJobs() -{ - // Generate a list of file paths, assetId's, and asset browser model indices - // This must be done on the main thread, otherwise it can lead to a crash when the tree view UI is being initialized - AZStd::vector files; - GetRelativeFilePaths(files); - - // Kick off the background process that will iterate over the list of file paths and update the material record map - m_mainUpdateRecordJob = aznew MaterialBrowserUpdateJobCreator(this, files, m_jobContext); - m_mainUpdateRecordJob->Start(); -} - -void MaterialBrowserFilterModel::CancelRecordUpdateJobs() -{ - m_jobContext->GetCancelGroup()->Cancel(); - m_jobContext->GetCancelGroup()->Reset(); -} - -void MaterialBrowserFilterModel::ClearRecordMap() -{ - CancelRecordUpdateJobs(); - m_materialRecordMap.clear(); -} - -MaterialBrowserUpdateJobCreator::MaterialBrowserUpdateJobCreator(MaterialBrowserFilterModel* model, AZStd::vector& files, AZ::JobContext* context /*= NULL*/) - : Job(true, context) - , m_files(files) - , m_filterModel(model) -{ -} - -void MaterialBrowserUpdateJobCreator::Process() -{ - // Split the files to be processed evenly among threads - int numJobs = GetContext()->GetJobManager().GetNumWorkerThreads(); - int materialsPerJob = (m_files.size() / numJobs) + 1; - - for (auto it = m_files.begin(); it <= m_files.end(); it += materialsPerJob) - { - // Create a subset of the list of material files to be processed by another job - auto start = it; - auto end = it + materialsPerJob; - if (end > m_files.end()) - { - end = m_files.end(); - } - AZStd::vector subset(start, end); - - if (subset.size() > 0) - { - AZ::Job* materialBrowserUpdateJob = aznew MaterialBrowserUpdateJob(m_filterModel, subset, GetContext()); - StartAsChild(materialBrowserUpdateJob); - } - } - - WaitForChildren(); - - MaterialBrowserWidgetBus::Broadcast(&MaterialBrowserWidgetEvents::MaterialRecordUpdateFinished); -} - -MaterialBrowserUpdateJob::MaterialBrowserUpdateJob(MaterialBrowserFilterModel* model, AZStd::vector& files, AZ::JobContext* context /*= NULL*/) - : Job(true, context) - , m_filterModel(model) - , m_files(files) -{ -} - -void MaterialBrowserUpdateJob::Process() -{ - for (size_t i = 0; i < m_files.size(); ++i) - { - // Early out when the job is cancelled - if (IsCancelled()) - { - return; - } - CMaterialBrowserRecord record; - record.SetAssetBrowserData(m_files[i]); - - // Get the writable status of the file, but don't update source control status until it is actually needed - record.m_lastCachedFileAttributes = static_cast(CFileUtil::GetAttributes(record.GetFullSourcePath().c_str(), false)); - - record.m_material = GetIEditor()->GetMaterialManager()->LoadMaterialWithFullSourcePath(record.GetRelativeFilePath().c_str(), record.GetFullSourcePath().c_str()); - m_filterModel->SetRecord(record); - } -} diff --git a/Code/Sandbox/Editor/Material/MaterialBrowserFilterModel.h b/Code/Sandbox/Editor/Material/MaterialBrowserFilterModel.h deleted file mode 100644 index afb7f8a7ce..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialBrowserFilterModel.h +++ /dev/null @@ -1,240 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include - - -#include -#include - -namespace AZ -{ - class Job; - class JobManager; - class JobCancelGroup; - class JobContext; -} - -class SubMaterialSearchFilter; -class LevelMaterialSearchFilter; - -////////////////////////////////////////////////////////////////////////// -// Item class for browser. -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -struct MaterialBrowserRecordAssetBrowserData -{ - AZ::Data::AssetId assetId; - AZStd::string relativeFilePath; - AZStd::string fullSourcePath; - QPersistentModelIndex modelIndex; - QPersistentModelIndex filterModelIndex; -}; - -class CMaterialBrowserRecord -{ -public: - CMaterialBrowserRecord() - { - InitializeSourceControlAttributes(); - } - - CMaterialBrowserRecord(const CMaterialBrowserRecord &rhs) - : m_material(rhs.m_material) - , m_lastCachedSCCAttributes(rhs.m_lastCachedSCCAttributes) - , m_lastCachedFileAttributes(rhs.m_lastCachedFileAttributes) - , m_lastCheckedSCCAttributes(rhs.m_lastCheckedSCCAttributes) - , m_assetBrowserData(rhs.m_assetBrowserData) - { - } - - AZ::Data::AssetId GetAssetId() const { return m_assetBrowserData.assetId; } - AZStd::string GetRelativeFilePath() const { return m_assetBrowserData.relativeFilePath; } - AZStd::string GetFullSourcePath() const { return m_assetBrowserData.fullSourcePath; } - QPersistentModelIndex GetModelIndex() const { return m_assetBrowserData.modelIndex; } - QPersistentModelIndex GetFilterModelIndex() const { return m_assetBrowserData.filterModelIndex; } - void SetAssetBrowserData(const MaterialBrowserRecordAssetBrowserData &assetBrowserData) { m_assetBrowserData = assetBrowserData; } - void InitializeSourceControlAttributes() - { - // Force an update by setting the last update time to 1 / 1 / 1 - m_lastCachedSCCAttributes = AzToolsFramework::SourceControlFileInfo(); - m_lastCachedFileAttributes = SCC_FILE_ATTRIBUTE_INVALID; - m_lastCheckedSCCAttributes = QDate(1, 1, 1).startOfDay(); - } -public: - _smart_ptr m_material = nullptr; - AzToolsFramework::SourceControlFileInfo m_lastCachedSCCAttributes; - ESccFileAttributes m_lastCachedFileAttributes; - QDateTime m_lastCheckedSCCAttributes; - -private: - MaterialBrowserRecordAssetBrowserData m_assetBrowserData; -}; -Q_DECLARE_METATYPE(CMaterialBrowserRecord) - - -//! MaterialBrowserSourceControlEvents -//! This bus informs the material browser filter model -//! when an ASYNC source control command has completed -class MaterialBrowserSourceControlEvents - : public AZ::EBusTraits -{ -public: - typedef AZStd::recursive_mutex MutexType; - - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; // there's only one listener - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // theres only one listener - virtual ~MaterialBrowserSourceControlEvents() {} - - //! Signals the callback for the GetFileInfo source control op - virtual void UpdateSourceControlFileInfoCallback(const AZ::Data::AssetId &assetId, const AzToolsFramework::SourceControlFileInfo& fileInfo) = 0; - //! Updates the timestamp for when the source control status was last checked - virtual void UpdateSourceControlLastCheckedTime(const AZ::Data::AssetId &assetId, const QDateTime &dateTime) = 0; -}; - -using MaterialBrowserSourceControlBus = AZ::EBus; - -//! MaterialBrowserWidgetEvents -//! This bus is used to send events to the material browser widget -class MaterialBrowserWidgetEvents - : public AZ::EBusTraits -{ -public: - typedef AZStd::recursive_mutex MutexType; - - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; // there's only one listener - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // theres only one listener - virtual ~MaterialBrowserWidgetEvents() {} - - //! Indicates that a material has finished being processed by the asset processor - virtual void MaterialFinishedProcessing(_smart_ptr material, const QPersistentModelIndex &filterModelIndex) = 0; - - //! Indicates that a material has finished being added to the material browser - virtual void MaterialAddFinished() = 0; - - //! Indicates that the material record update for initially populating the material browser has finished - virtual void MaterialRecordUpdateFinished() = 0; -}; - -using MaterialBrowserWidgetBus = AZ::EBus; - -/** -* Get the product material assetId for a given AssetBrowserEntry -* If there is no valid product material, the material has not been processed, or there are multiple product materials -* and thus there is not an individual material that can be assumed based on the source, an invalid assetId is returned -* @param assetEntry An asset entry that may be a source or a product -* @return The assetId of the product material. -*/ -AZ::Data::AssetId GetMaterialProductAssetIdFromAssetBrowserEntry(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* assetEntry); - -class MaterialBrowserFilterModel - : public AzToolsFramework::AssetBrowser::AssetBrowserFilterModel - , public MaterialBrowserSourceControlBus::Handler - , public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler - , public AzToolsFramework::MaterialBrowser::MaterialBrowserRequestBus::Handler - , private AzFramework::AssetCatalogEventBus::Handler -{ -public: - AZ_CLASS_ALLOCATOR(MaterialBrowserFilterModel, AZ::SystemAllocator, 0); - MaterialBrowserFilterModel(QObject* parent); - ~MaterialBrowserFilterModel(); - void UpdateRecord(const QModelIndex& filterModelIndex); - void UpdateRecord(const MaterialBrowserRecordAssetBrowserData &assetBrowserData); - void UpdateSourceControlFileInfoCallback(const AZ::Data::AssetId &assetId, const AzToolsFramework::SourceControlFileInfo& info) override; - void UpdateSourceControlLastCheckedTime(const AZ::Data::AssetId &assetId, const QDateTime &dateTime) override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - bool TryGetRecordFromMaterial(_smart_ptr material, CMaterialBrowserRecord& record) const; - bool TryGetRecordFromAssetId(const AZ::Data::AssetId &assetId, CMaterialBrowserRecord& record) const; - void SetRecord(const CMaterialBrowserRecord& record); - void SetSearchFilter(const AzToolsFramework::AssetBrowser::SearchWidget* searchWidget); - void StartRecordUpdateJobs(); - void CancelRecordUpdateJobs(); - void ClearRecordMap(); - void GetRelativeFilePaths(AZStd::vector &files) const; - QModelIndex GetIndexFromMaterial(_smart_ptr material) const; - QModelIndex GetFilterModelIndex(const AZ::Data::AssetId &assetId) const; - - // AssetBrowserModelNotificationBus event handlers - void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override; - - void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override; - // MaterialBrowserRequestBus - bool HasRecord(const AZ::Data::AssetId& assetId) override; - bool IsMultiMaterial(const AZ::Data::AssetId& assetId) override; - - void ShowOnlyLevelMaterials(bool levelOnly, bool invalidateFilterNow = false); - - public Q_SLOTS: - void SearchFilterUpdated(); - -private: - void GetRelativeFilePathsRecursive(AZStd::vector &files, const MaterialBrowserFilterModel* model, const QModelIndex &parent = QModelIndex()) const; - bool TryGetFilterModelIndexRecursive(QModelIndex &filterModelIndex, const AZ::Data::AssetId &assetId, const MaterialBrowserFilterModel* model, const QModelIndex &parent = QModelIndex()) const; - void QueueDataChangedEvent(const QPersistentModelIndex &filterModelIndex); - AZStd::concurrent_unordered_map m_materialRecordMap; - QVector m_imageList; - AzToolsFramework::AssetBrowser::FilterConstType m_assetTypeFilter; - SubMaterialSearchFilter* m_subMaterialSearchFilter; - LevelMaterialSearchFilter* m_levelMaterialSearchFilter; - const AzToolsFramework::AssetBrowser::SearchWidget* m_searchWidget; - - void InitializeRecordUpdateJob(); - AZ::JobManager* m_jobManager = nullptr; - AZ::JobCancelGroup* m_jobCancelGroup = nullptr; - AZ::JobContext* m_jobContext = nullptr; - AZ::Job* m_mainUpdateRecordJob = nullptr; -}; - -/** -* Job that walks through a MaterialBrowserFilterModel to generate a list of files, -* then divides the list amongst child jobs for processing -*/ -class MaterialBrowserUpdateJobCreator - : public AZ::Job -{ -public: - AZ_CLASS_ALLOCATOR(MaterialBrowserUpdateJobCreator, AZ::ThreadPoolAllocator, 0); - - MaterialBrowserUpdateJobCreator(MaterialBrowserFilterModel* model, AZStd::vector& files, AZ::JobContext* context = nullptr); - void Process() override; -private: - MaterialBrowserFilterModel* m_filterModel; - AZStd::vector m_files; -}; - -/** -* Job that walks through a list of material files, loads them, and then populates -* the MaterialBrowserFilterModel's map of material data -*/ -class MaterialBrowserUpdateJob - : public AZ::Job -{ -public: - AZ_CLASS_ALLOCATOR(MaterialBrowserUpdateJob, AZ::ThreadPoolAllocator, 0); - - MaterialBrowserUpdateJob(MaterialBrowserFilterModel* model, AZStd::vector &files, AZ::JobContext* context = nullptr); - void Process() override; -private: - MaterialBrowserFilterModel* m_filterModel; - AZStd::vector m_files; -}; - diff --git a/Code/Sandbox/Editor/Material/MaterialBrowserSearchFilters.cpp b/Code/Sandbox/Editor/Material/MaterialBrowserSearchFilters.cpp deleted file mode 100644 index cf2d3449d1..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialBrowserSearchFilters.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "EditorDefs.h" - -#include "MaterialBrowserSearchFilters.h" - -// Editor -#include "MaterialBrowserFilterModel.h" -#include "Material.h" - - -SubMaterialSearchFilter::SubMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel) - : m_filterModel(filterModel) -{ - AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down); -} - -void SubMaterialSearchFilter::SetFilterString(const QString& filterString) -{ - m_filterString = filterString; -} - -QString SubMaterialSearchFilter::GetNameInternal() const -{ - return "SubMaterialSearchFilter"; -} - -bool SubMaterialSearchFilter::MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const -{ - // All entries match if there is no search string - if (m_filterString.isEmpty()) - { - return true; - } - - if (m_filterModel) - { - // Get the product material for the given asset browser entry - AZ::Data::AssetId assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(entry); - if (assetId.IsValid()) - { - CMaterialBrowserRecord record; - bool found = m_filterModel->TryGetRecordFromAssetId(assetId, record); - if (found) - { - // If there is a valid product material, check to see if any of its sub-materials match the search string - if (record.m_material) - { - for (int i = 0; i < record.m_material->GetSubMaterialCount(); ++i) - { - CMaterial* subMaterial = record.m_material->GetSubMaterial(i); - if (subMaterial) - { - // If any of the product sub-materials matches the string, return true for this entry - if (subMaterial->GetName().contains(m_filterString, Qt::CaseInsensitive)) - { - return true; - } - } - } - } - } - } - } - return false; -} - -LevelMaterialSearchFilter::LevelMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel) - : m_filterModel(filterModel) -{ - AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::SetFilterPropagation(AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter::PropagateDirection::Down); -} - -QString LevelMaterialSearchFilter::GetNameInternal() const -{ - return "LoadedMaterialSearchFilter"; -} - -void LevelMaterialSearchFilter::CacheLoadedMaterials() -{ - m_localMap.clear(); - - AZStd::vector foundRenderNodes; - unsigned int numFoundObjects = 0; - - numFoundObjects = GetIEditor()->Get3DEngine()->GetObjectsByFlags(0); - foundRenderNodes.resize(numFoundObjects, nullptr); - GetIEditor()->Get3DEngine()->GetObjectsByFlags(0, foundRenderNodes.data()); - - AZStd::vector<_smart_ptr> materials; - materials.reserve(foundRenderNodes.size()); - for (IRenderNode* renderNode : foundRenderNodes) - { - renderNode->GetMaterials(materials); - } - - for (size_t i = 0; i < materials.size(); ++i) - { - if (materials[i]) - { - m_localMap[materials[i]->GetName()] = materials[i]; - } - } -} - -bool LevelMaterialSearchFilter::MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const -{ - // All entries match if show level materials isn't selected - if (!m_onlyShowLevelMaterials) - { - return true; - } - - // Get the product material for the given asset browser entry - AZ::Data::AssetId assetId = GetMaterialProductAssetIdFromAssetBrowserEntry(entry); - if (assetId.IsValid() && m_filterModel) - { - CMaterialBrowserRecord record; - bool found = m_filterModel->TryGetRecordFromAssetId(assetId, record); - if (found && record.m_material) - { - // If there is a valid product material, check to see if it is used by the level - return m_localMap.find(record.m_material->GetName()) != m_localMap.end(); - } - } - - return false; -} - -#include diff --git a/Code/Sandbox/Editor/Material/MaterialBrowserSearchFilters.h b/Code/Sandbox/Editor/Material/MaterialBrowserSearchFilters.h deleted file mode 100644 index 4326e66218..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialBrowserSearchFilters.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include -#include -#endif - -class MaterialBrowserFilterModel; - -//! Filter that checks the name of each sub-material in a material to see if it contains the filter string -class SubMaterialSearchFilter - : public AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter -{ - Q_OBJECT -public: - SubMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel); - ~SubMaterialSearchFilter() override = default; - - void SetFilterString(const QString& filterString); - -protected: - QString GetNameInternal() const override; - bool MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override; - -private: - bool TextMatchesFilter(const QString &text) const; - QString m_filterString = ""; - const MaterialBrowserFilterModel* m_filterModel = nullptr; -}; - -class LevelMaterialSearchFilter - : public AzToolsFramework::AssetBrowser::AssetBrowserEntryFilter -{ - Q_OBJECT -public: - LevelMaterialSearchFilter(const MaterialBrowserFilterModel* filterModel); - ~LevelMaterialSearchFilter() override = default; - - void ShowOnlyLevelMaterials(bool onlyLevel) { m_onlyShowLevelMaterials = onlyLevel; } - - void CacheLoadedMaterials(); - -protected: - QString GetNameInternal() const override; - bool MatchInternal(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) const override; - -private: - bool m_onlyShowLevelMaterials = false; - const MaterialBrowserFilterModel* m_filterModel = nullptr; - using MaterialMap = QHash >; - MaterialMap m_localMap; -}; diff --git a/Code/Sandbox/Editor/Material/MaterialDialog.qrc b/Code/Sandbox/Editor/Material/MaterialDialog.qrc deleted file mode 100644 index c99e5b052a..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialDialog.qrc +++ /dev/null @@ -1,23 +0,0 @@ - - - images/material_browser_00.png - images/material_browser_01.png - images/material_browser_02.png - images/material_browser_03.png - images/material_00.png - images/material_01.png - images/material_02.png - images/material_03.png - images/material_04.png - images/material_05.png - images/material_06.png - images/material_07.png - images/filestatus_00.png - images/filestatus_01.png - images/filestatus_02.png - images/filestatus_03.png - images/filestatus_04.png - images/filestatus_05.png - images/filestatus_06.png - - diff --git a/Code/Sandbox/Editor/Material/MaterialHelpers.cpp b/Code/Sandbox/Editor/Material/MaterialHelpers.cpp deleted file mode 100644 index 8f9311a27a..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialHelpers.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MaterialHelpers.h" - -namespace MaterialHelpers -{ - ////////////////////////////////////////////////////////////////////////// - static void ParsePublicParamsScript(const char* sUIScript, IVariable* pVar) - { - string uiscript = sUIScript; - string element[3]; - int p1 = 0; - string itemToken = uiscript.Tokenize(";", p1); - while (!itemToken.empty()) - { - int nElements = 0; - int p2 = 0; - string token = itemToken.Tokenize(" \t\r\n=", p2); - while (!token.empty()) - { - element[nElements++] = token; - if (nElements == 2) - { - element[nElements] = itemToken.substr(p2); - element[nElements].Trim(" =\t\""); - break; - } - token = itemToken.Tokenize(" \t\r\n=", p2); - } - - float minLimit, maxLimit; - pVar->GetLimits(minLimit, maxLimit); - - if (azstricmp(element[1], "UIWidget") == 0) - { - if (azstricmp(element[2], "Color") == 0) - { - pVar->SetDataType(IVariable::DT_COLOR); - } - } - else if (azstricmp(element[1], "UIHelp") == 0) - { - string help = element[2]; - help.replace("\\n", "\n"); - pVar->SetDescription(help); - } - else if (azstricmp(element[1], "UIName") == 0) - { - pVar->SetHumanName(element[2].c_str()); - } - else if (azstricmp(element[1], "UIMin") == 0) - { - pVar->SetLimits(atof(element[2]), maxLimit); - } - else if (azstricmp(element[1], "UIMax") == 0) - { - pVar->SetLimits(minLimit, atof(element[2])); - } - else if (azstricmp(element[1], "UIStep") == 0) - { - } - - itemToken = uiscript.Tokenize(";", p1); - } - } - - ////////////////////////////////////////////////////////////////////////// - static void AddRealNameToDescription(IVariable* pIVar, const SShaderParam* pParam) - { - // In order to help the user discover the true names of parameters, info they need using certain script functions, - // we embed the real parameter name in the description. - QString description = pIVar->GetDescription(); - if (!description.isEmpty()) - { - description += "\n"; - } - description += "(Script Param Name = "; - description += pParam->m_Name.c_str(); - description += ")"; - pIVar->SetDescription(description); - } - - ////////////////////////////////////////////////////////////////////////// - CVarBlock* GetPublicVars(SInputShaderResources& pShaderResources) - { - if (pShaderResources.m_ShaderParams.empty()) - { - return 0; - } - - CVarBlock* pPublicVars = new CVarBlock; - for (int i = 0; i < pShaderResources.m_ShaderParams.size(); i++) - { - IVariable* pIVar = NULL; - SShaderParam* pParam = &pShaderResources.m_ShaderParams[i]; - - switch (pParam->m_Type) - { - case eType_BYTE: - pIVar = new CVariable(pParam->m_Value.m_Byte); - break; - case eType_SHORT: - pIVar = new CVariable(pParam->m_Value.m_Short); - break; - case eType_INT: - pIVar = new CVariable(pParam->m_Value.m_Int); - break; - case eType_FLOAT: - pIVar = new CVariable(pParam->m_Value.m_Float); - break; - /* case eType_STRING: - pIVar = new CVariable(pParam->m_Value.m_String); - break; */ - case eType_FCOLOR: - pIVar = new CVariable(Vec3(pParam->m_Value.m_Color[0], pParam->m_Value.m_Color[1], pParam->m_Value.m_Color[2])); - pIVar->SetDataType(IVariable::DT_COLOR); - break; - case eType_FCOLORA: - pIVar = new CVariable(Vec4(pParam->m_Value.m_Color[0], pParam->m_Value.m_Color[1], pParam->m_Value.m_Color[2], pParam->m_Value.m_Color[3])); - pIVar->SetDataType(IVariable::DT_COLORA); - break; - case eType_VECTOR: - pIVar = new CVariable(Vec3(pParam->m_Value.m_Vector[0], pParam->m_Value.m_Vector[1], pParam->m_Value.m_Vector[2])); - break; - default: - break; - } - - if (pIVar) - { - pIVar->SetName(pParam->m_Name.c_str()); - pPublicVars->AddVariable(pIVar); - - if (pParam->m_Script.size()) - { - ParsePublicParamsScript(pParam->m_Script.c_str(), pIVar); - } - - AddRealNameToDescription(pIVar, pParam); - } - } - - return pPublicVars; - } - - void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources) - { - assert(pPublicVars); - - if (pInputShaderResources.m_ShaderParams.empty()) - { - return; - } - - int numVars = pPublicVars->GetNumVariables(); - - for (int i = 0; i < numVars; i++) - { - if (i >= numVars) - { - break; - } - - IVariable* pVar = pPublicVars->GetVariable(i); - SShaderParam* pParam = NULL; - for (int j = 0; j < pInputShaderResources.m_ShaderParams.size(); j++) - { - if (QString::compare(pVar->GetName(), pInputShaderResources.m_ShaderParams[j].m_Name.c_str()) == 0) - { - pParam = &pInputShaderResources.m_ShaderParams[j]; - break; - } - } - if (!pParam) - { - continue; - } - - switch (pParam->m_Type) - { - case eType_BYTE: - if (pVar->GetType() == IVariable::INT) - { - int val = 0; - pVar->Get(val); - pParam->m_Value.m_Byte = val; - } - break; - case eType_SHORT: - if (pVar->GetType() == IVariable::INT) - { - int val = 0; - pVar->Get(val); - pParam->m_Value.m_Short = val; - } - break; - case eType_INT: - if (pVar->GetType() == IVariable::INT) - { - int val = 0; - pVar->Get(val); - pParam->m_Value.m_Int = val; - } - break; - case eType_FLOAT: - if (pVar->GetType() == IVariable::FLOAT) - { - float val = 0; - pVar->Get(val); - pParam->m_Value.m_Float = val; - } - break; - /* - case eType_STRING: - if (pVar->GetType() == IVariable::STRING) - { - CString str; - int val = 0; - pVar->Get(val); - pParam->m_Value.m_Byte = val; - } - break; - */ - case eType_FCOLOR: - case eType_FCOLORA: - if (pVar->GetType() == IVariable::VECTOR4 && (pVar->GetDataType() == IVariable::DT_COLOR || pVar->GetDataType() == IVariable::DT_COLORA)) - { - Vec4 val(0, 0, 0, 0); - pVar->Get(val); - pParam->m_Value.m_Color[0] = val.x; - pParam->m_Value.m_Color[1] = val.y; - pParam->m_Value.m_Color[2] = val.z; - pParam->m_Value.m_Color[3] = val.w; - } - else if (pVar->GetType() == IVariable::VECTOR && (pVar->GetDataType() == IVariable::DT_COLOR || pVar->GetDataType() == IVariable::DT_COLORA)) - { - Vec3 val(0, 0, 0); - pVar->Get(val); - pParam->m_Value.m_Color[0] = val.x; - pParam->m_Value.m_Color[1] = val.y; - pParam->m_Value.m_Color[2] = val.z; - } - break; - case eType_VECTOR: - if (pVar->GetType() == IVariable::VECTOR) - { - Vec3 val(0, 0, 0); - pVar->Get(val); - pParam->m_Value.m_Vector[0] = val.x; - pParam->m_Value.m_Vector[1] = val.y; - pParam->m_Value.m_Vector[2] = val.z; - } - break; - default: - break; - } - } - } - - void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources, IRenderShaderResources* pRenderShaderResources, IShader* pShader) - { - SetPublicVars(pPublicVars, pInputShaderResources); - - // Set shader params. - if (pRenderShaderResources) - { - pRenderShaderResources->SetShaderParams(&pInputShaderResources, pShader); - } - } - - ////////////////////////////////////////////////////////////////////////// - CVarBlock* GetShaderGenParamsVars(IShader* pShader, uint64 nShaderGenMask) - { - IShader* pTemplShader = pShader; - if (!pTemplShader) - { - return 0; - } - - SShaderGen* pShaderGen = pTemplShader->GetGenerationParams(); - if (!pShaderGen) - { - return 0; - } - - CVarBlock* pBlock = new CVarBlock; - for (int i = 0; i < pShaderGen->m_BitMask.size(); i++) - { - SShaderGenBit* pGenBit = pShaderGen->m_BitMask[i]; - if (pGenBit->m_Flags & SHGF_HIDDEN) - { - continue; - } - if (!pGenBit->m_ParamProp.empty()) - { - CVariable* pVar = new CVariable; - pBlock->AddVariable(pVar); - pVar->SetName(pGenBit->m_ParamProp.c_str()); - *pVar = (pGenBit->m_Mask & nShaderGenMask) != 0; - pVar->SetDescription(pGenBit->m_ParamDesc.c_str()); - } - } - - /* - // make sure if no valid generation parameters to not create new tab - if (!pBlock->GetVarsCount()) - { - SAFE_DELETE(pBlock); - return 0; - } - */ - - return pBlock; - } - - ////////////////////////////////////////////////////////////////////////// - uint64 SetShaderGenParamsVars(IShader* pShader, CVarBlock* pBlock) - { - IShader* pTemplShader = pShader; - if (!pTemplShader) - { - return 0; - } - - SShaderGen* pShaderGen = pTemplShader->GetGenerationParams(); - if (!pShaderGen) - { - return 0; - } - - uint64 nGenMask = 0; - - for (int i = 0; i < pShaderGen->m_BitMask.size(); i++) - { - SShaderGenBit* pGenBit = pShaderGen->m_BitMask[i]; - if (pGenBit->m_Flags & SHGF_HIDDEN) - { - continue; - } - - if (!pGenBit->m_ParamProp.empty()) - { - IVariable* pVar = pBlock->FindVariable(pGenBit->m_ParamProp.c_str()); - if (!pVar) - { - continue; - } - bool bFlagOn = false; - pVar->Get(bFlagOn); - if (bFlagOn) - { - nGenMask |= pGenBit->m_Mask; - } - } - } - - return nGenMask; - } -} diff --git a/Code/Sandbox/Editor/Material/MaterialHelpers.h b/Code/Sandbox/Editor/Material/MaterialHelpers.h deleted file mode 100644 index 0f0228db7a..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialHelpers.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once - -#include "Material.h" - -namespace MaterialHelpers -{ - ////////////////////////////////////////////////////////////////////////// - //! Get public parameters of material in variable block. - CVarBlock* GetPublicVars(SInputShaderResources& pShaderResources); - - //! Sets variable block of public shader parameters. - //! VarBlock must be in same format as returned by GetPublicVars(). - void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources); - void SetPublicVars(CVarBlock* pPublicVars, SInputShaderResources& pInputShaderResources, IRenderShaderResources* pRenderShaderResources, IShader* pShader); - - ////////////////////////////////////////////////////////////////////////// - CVarBlock* GetShaderGenParamsVars(IShader* pShader, uint64 nShaderGenMask); - uint64 SetShaderGenParamsVars(IShader* pShader, CVarBlock* pBlock); - - ////////////////////////////////////////////////////////////////////////// - // [Shader System TO DO] change the usage of these functions to retrieve by slot name - inline EEfResTextures FindTexSlot(const char* texName) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().FindTexSlot(texName); } - inline const char* FindTexName(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().FindTexName(texSlot); } - inline const char* LookupTexName(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().LookupTexName(texSlot); } - inline const char* LookupTexDesc(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().LookupTexDesc(texSlot); } - - //-------------------------------------------------------------------------- - // Adjustable means that the slot is not virtual, i.e. using a sub-channel from another - // slot (for example - smoothness that uses the normal's alpha) - inline bool IsAdjustableTexSlot(EEfResTextures texSlot) { return GetIEditor()->Get3DEngine()->GetMaterialHelpers().IsAdjustableTexSlot(texSlot); } - - ////////////////////////////////////////////////////////////////////////// - inline void SetTexModFromXml(SEfTexModificator& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetTexModFromXml(pShaderResources, node); } - inline void SetXmlFromTexMod(const SEfTexModificator& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromTexMod(pShaderResources, node); } - - ////////////////////////////////////////////////////////////////////////// - inline void SetTexturesFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetTexturesFromXml(pShaderResources, node); } - inline void SetXmlFromTextures( SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromTextures(pShaderResources, node); } - - ////////////////////////////////////////////////////////////////////////// - inline void SetVertexDeformFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetVertexDeformFromXml(pShaderResources, node); } - inline void SetXmlFromVertexDeform(const SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromVertexDeform(pShaderResources, node); } - - ////////////////////////////////////////////////////////////////////////// - inline void SetLightingFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetLightingFromXml(pShaderResources, node); } - inline void SetXmlFromLighting(const SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromLighting(pShaderResources, node); } - - ////////////////////////////////////////////////////////////////////////// - inline void SetShaderParamsFromXml(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetShaderParamsFromXml(pShaderResources, node); } - inline void SetXmlFromShaderParams(const SInputShaderResources& pShaderResources, XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().SetXmlFromShaderParams(pShaderResources, node); } - - ////////////////////////////////////////////////////////////////////////// - inline void MigrateXmlLegacyData(SInputShaderResources& pShaderResources, const XmlNodeRef& node) { GetIEditor()->Get3DEngine()->GetMaterialHelpers().MigrateXmlLegacyData(pShaderResources, node); } -} diff --git a/Code/Sandbox/Editor/Material/MaterialImageListCtrl.cpp b/Code/Sandbox/Editor/Material/MaterialImageListCtrl.cpp deleted file mode 100644 index 6ebc85c1bc..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialImageListCtrl.cpp +++ /dev/null @@ -1,834 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MaterialImageListCtrl.h" - -// Qt -#include - -// Editor -#include "Material.h" -#include "MaterialManager.h" -#include "MaterialPreviewModelView.h" -#include "MaterialBrowser.h" -#include "Util/Image.h" - -#define ME_BG_TEXTURE "Materials/Stripes.dds" - - -#define MATERIAL_EDITOR_SPHERE_MODEL_FILE "Objects/MtlSphere.cgf" -#define MATERIAL_EDITOR_SPHERE_CAMERA_RADIUS 1.6f -#define MATERIAL_EDITOR_SPHERE_CAMERA_FROM_DIRECTION Vec3(0.1f, -1.0f, -0.1f) - -#define MATERIAL_EDITOR_BOX_MODEL_FILE "Objects/MtlBox.cgf" -#define MATERIAL_EDITOR_BOX_CAMERA_RADIUS 2.0f -#define MATERIAL_EDITOR_BOX_CAMERA_FROM_DIRECTION Vec3(0.75f, -0.75f, -0.5f) - -#define MATERIAL_EDITOR_TEAPOT_MODEL_FILE "Objects/MtlTeapot.cgf" -#define MATERIAL_EDITOR_TEAPOT_CAMERA_RADIUS 1.6f -#define MATERIAL_EDITOR_TEAPOT_CAMERA_FROM_DIRECTION Vec3(0.1f, -0.75f, -0.25f) - -#define MATERIAL_EDITOR_PLANE_MODEL_FILE "Objects/MtlPlane.cgf" -#define MATERIAL_EDITOR_PLANE_CAMERA_RADIUS 1.6f -#define MATERIAL_EDITOR_PLANE_CAMERA_FROM_DIRECTION Vec3(-0.5f, 0.5f, -0.5f) - -#define MATERIAL_EDITOR_SWATCH_MODEL_FILE "Objects/MtlSwatch.cgf" -#define MATERIAL_EDITOR_SWATCH_CAMERA_RADIUS 1.0f -#define MATERIAL_EDITOR_SWATCH_CAMERA_FROM_DIRECTION Vec3(0.0f, 0.0f, -1.0f) - - -_smart_ptr ResolveTerrainLayerPreviewMaterial(_smart_ptr material, _smart_ptr pMatPreview) -{ - if (!QString::compare(material->GetShaderName(), "Terrain.Layer")) - { - XmlNodeRef node = XmlHelpers::CreateXmlNode("Material"); - CBaseLibraryItem::SerializeContext ctx(node, false); - material->Serialize(ctx); - - if (!pMatPreview) - { - int flags = 0; - if (node->getAttr("MtlFlags", flags)) - { - flags |= MTL_FLAG_UIMATERIAL; - node->setAttr("MtlFlags", flags); - } - pMatPreview = GetIEditor()->GetMaterialManager()->CreateMaterial("_NewPreview_", node); - } - else - { - CBaseLibraryItem::SerializeContext ctx2(node, true); - pMatPreview->Serialize(ctx2); - } - pMatPreview->SetShaderName("Illum"); - pMatPreview->Update(); - return pMatPreview; - } - else - { - return material; - } -} - -struct QMaterialImageListModel::Item -{ - QImage image; - void* pUserData; - QPoint position; - QSize size; - _smart_ptr pMaterial; - QStringList vVisibleTextures; -}; - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::OnCreate() -{ - // m_largePreviewCtrl is used to draw the 3D preview for the selected material - m_largePreviewCtrl.reset(new MaterialPreviewModelView(this)); - m_largePreviewCtrl->hide(); - // m_renderCtrl is used to draw all the sub-materials - m_renderCtrl.reset(new MaterialPreviewModelView(this, false /* disable idle updates since this is only used to create the preview list images */)); - m_renderCtrl->UnSetFlag(CPreviewModelView::PreviewModelViewFlag::SHOW_GRID); - m_renderCtrl->UnSetFlag(CPreviewModelView::PreviewModelViewFlag::SHOW_GRID_AXIS); - - if (gEnv->pSystem) - { - gEnv->pSystem->GetISystemEventDispatcher()->RegisterListener(this); - } - - // m_resizeTimer is used to stall updateGeometries being called via resizeEvents until RESIZE_TIMEOUT ms after resizing - // This prevents an Editor freeze caused by constant resizing of the Material Editor when viewing - // a high sub-material count material (LY-58389) - m_resizeTimer = new QTimer(this); - connect(m_resizeTimer, &QTimer::timeout, this, &CMaterialImageListCtrl::ResizeTimeout); -} - -void CMaterialImageListCtrl::resizeEvent([[maybe_unused]] QResizeEvent* event) -{ - m_resizeTimer->stop(); - m_resizeTimer->start(RESIZE_TIMEOUT); -} - -void CMaterialImageListCtrl::ResizeTimeout() -{ - m_resizeTimer->stop(); - updateGeometries(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::OnDestroy() -{ - if (gEnv->pSystem) - { - gEnv->pSystem->GetISystemEventDispatcher()->RemoveListener(this); - } -} - -////////////////////////////////////////////////////////////////////////// -CMaterialImageListCtrl::CMaterialImageListCtrl(QWidget* parent) - : CImageListCtrl(parent) -{ - OnCreate(); -} - -////////////////////////////////////////////////////////////////////////// -CMaterialImageListCtrl::~CMaterialImageListCtrl() -{ - OnDestroy(); -} - -////////////////////////////////////////////////////////////////////////// -QModelIndex QMaterialImageListModel::AddMaterial(CMaterial* pMaterial, void* pUserData) -{ - Item* pItem = new Item; - pItem->pMaterial = pMaterial; - pItem->pUserData = pUserData; - pMaterial->GetAnyTextureFilenames(pItem->vVisibleTextures); - - const int row = m_items.count(); - beginInsertRows(QModelIndex(), row, row); - m_items.insert(row, pItem); - endInsertRows(); - - return index(row, 0); -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::SetMaterial(int nItemIndex, CMaterial* pMaterial, void* pUserData) -{ - assert(nItemIndex <= (int)m_items.size()); - Item* pItem = m_items.at(nItemIndex); - - pItem->vVisibleTextures.clear(); - pItem->pMaterial = pMaterial; - pItem->pUserData = pUserData; - pMaterial->GetAnyTextureFilenames(pItem->vVisibleTextures); - pItem->image = QImage(); - - QModelIndex idx = index(nItemIndex, 0); - emit dataChanged(idx, idx, QVector() << Qt::DisplayRole << Qt::DecorationRole); -} - -////////////////////////////////////////////////////////////////////////// -QModelIndex QMaterialImageListModel::FindMaterial(CMaterial* const pMaterial) -{ - for (int i = 0; i < m_items.count(); i++) - { - Item* item = m_items[i]; - if (pMaterial == item->pMaterial) - { - return index(i, 0); - } - } - return QModelIndex(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::SelectMaterial(CMaterial* pMaterial) -{ - // Force the material to load the highest resolution textures - pMaterial->GetMatInfo()->DisableTextureStreaming(); - - selectionModel()->clearSelection(); - - QMaterialImageListModel* materialModel = qobject_cast(model()); - Q_ASSERT(materialModel); - - QModelIndex index = materialModel->FindMaterial(pMaterial); - if (index.isValid()) - { - selectionModel()->select(index, QItemSelectionModel::SelectCurrent); - m_largePreviewMaterial = pMaterial; - } - else - { - // If the parent material was selected, set the first sub-material as the large preview's material so it has something to render - if (pMaterial->GetSubMaterialCount() > 0) - { - m_largePreviewMaterial = pMaterial->GetSubMaterial(0); - } - } - - GenerateAllImages(); -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::InvalidateMaterial(CMaterial* pMaterial) -{ - QModelIndex idx = FindMaterial(pMaterial); - Item* pItem = ItemFromIndex(idx); - if ((pItem) && (m_renderCtrl)) - { - if (pMaterial) - { - // Ensure the full resolution textures are loaded for the material editor - pMaterial->GetMatInfo()->DisableTextureStreaming(); - } - - pItem->vVisibleTextures.clear(); - pMaterial->GetAnyTextureFilenames(pItem->vVisibleTextures); - pItem->image = QImage(); - GenerateImage(pItem); - - emit dataChanged(idx, idx, QVector() << Qt::DecorationRole); - } -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::DeleteAllItems() -{ - if (m_renderCtrl) - { - m_renderCtrl->SetMaterial(nullptr); - } - beginResetModel(); - qDeleteAll(m_items); - m_items.clear(); - endResetModel(); -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::GenerateImage(Item* pItem) -{ - // Make a bitmap from image. - Q_ASSERT(pItem); - if (!m_renderCtrl || !pItem->size.isValid()) - { - return; - } - if (pItem->image.size() == pItem->size) - { - return; - } - - Item* pMtlItem = pItem; - - CImageEx image; - - bool bPreview = false; - if (pMtlItem->pMaterial) - { - if (!(pMtlItem->pMaterial->GetFlags() & MTL_FLAG_NOPREVIEW)) - { - if (!m_renderCtrl->GetStaticModel()) - { - AZ_Warning("Material Editor", false, "Preview renderer has no object loaded!"); - return; - } - - // keep m_renderCtrl off screen, but visible - m_renderCtrl->setGeometry(QRect(-QPoint(pItem->size.width(), pItem->size.height()), pItem->size)); - - _smart_ptr matPreview = ResolveTerrainLayerPreviewMaterial(pItem->pMaterial, m_pMatPreview); - - m_renderCtrl->SetMaterial(matPreview->GetMatInfo()); - m_renderCtrl->GetImageOffscreen(image, pMtlItem->size); - } - bPreview = true; - } - - if (!bPreview) - { - image.Allocate(pItem->size.width(), pItem->size.height()); - image.Clear(); - } - - pItem->image = QImage(image.GetWidth(), image.GetHeight(), QImage::Format_RGB32); - memcpy(pItem->image.bits(), image.GetData(), image.GetSize()); -} - - -#define MENU_USE_DEFAULT 1 -#define MENU_USE_BOX 2 -#define MENU_USE_PLANE 3 -#define MENU_USE_SPHERE 4 -#define MENU_USE_TEAPOT 5 -#define MENU_BG_BLACK 6 -#define MENU_BG_GRAY 7 -#define MENU_BG_WHITE 8 -#define MENU_BG_TEXTURE 9 -#define MENU_USE_BACKLIGHT 10 - - - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::contextMenuEvent(QContextMenuEvent* event) -{ - QAction* action; - QMenu menu; - - action = menu.addAction(tr("Use Default Object")); - action->setData(ModelDefault); - action->setCheckable(true); - action->setChecked(m_modelType == ModelType::Default); - - action = menu.addAction(tr("Use Plane")); - action->setData(ModelPlane); - action->setCheckable(true); - action->setChecked(m_modelType == ModelType::Plane); - - action = menu.addAction(tr("Use Box")); - action->setData(ModelBox); - action->setCheckable(true); - action->setChecked(m_modelType == ModelType::Box); - - action = menu.addAction(tr("Use Sphere")); - action->setData(ModelSphere); - action->setCheckable(true); - action->setChecked(m_modelType == ModelType::Sphere); - - action = menu.addAction(tr("Use Teapot")); - action->setData(ModelTeapot); - action->setCheckable(true); - action->setChecked(m_modelType == ModelType::Teapot); - - menu.addSeparator(); - - // If there is a currently selected material - if (m_materialBrowserWidget && m_largePreviewMaterial) - { - // Add context menu actions that are common to both the material browser and the preview swatches - m_materialBrowserWidget->AddContextMenuActionsSingleSelection(menu, m_largePreviewMaterial); - } - - action = menu.exec(mapToGlobal(event->pos())); - if (!action) - { - return; - } - - int cmd = action->data().toInt(); - switch (cmd) - { - case ModelDefault: - m_modelType = ModelType::Default; - LoadModel(); - break; - case ModelPlane: - m_modelType = ModelType::Plane; - LoadModel(); - break; - case ModelBox: - m_modelType = ModelType::Box; - LoadModel(); - break; - case ModelSphere: - m_modelType = ModelType::Sphere; - LoadModel(); - break; - case ModelTeapot: - m_modelType = ModelType::Teapot; - LoadModel(); - break; - default: - // If there is a currently selected material - if (m_materialBrowserWidget && m_largePreviewMaterial) - { - // Handle context menu actions that are common to both the material browser and the preview swatches - m_materialBrowserWidget->OnContextMenuAction(cmd, m_largePreviewMaterial); - } - break; - } - - QMaterialImageListModel* materialModel = - qobject_cast(model()); - Q_ASSERT(materialModel); - - materialModel->GenerateImages(); - update(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::LoadModel() -{ - switch (m_modelType) - { - case ModelType::Default: - case ModelType::Sphere: - m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_SPHERE_MODEL_FILE); - m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_SPHERE_CAMERA_RADIUS, MATERIAL_EDITOR_SPHERE_CAMERA_FROM_DIRECTION); - break; - case ModelType::Box: - m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_BOX_MODEL_FILE); - m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_BOX_CAMERA_RADIUS, MATERIAL_EDITOR_BOX_CAMERA_FROM_DIRECTION); - break; - case ModelType::Teapot: - m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_TEAPOT_MODEL_FILE); - m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_TEAPOT_CAMERA_RADIUS, MATERIAL_EDITOR_TEAPOT_CAMERA_FROM_DIRECTION); - break; - case ModelType::Plane: - m_largePreviewCtrl->LoadModelFile(MATERIAL_EDITOR_PLANE_MODEL_FILE); - m_largePreviewCtrl->SetCameraLookAt(MATERIAL_EDITOR_PLANE_CAMERA_RADIUS, MATERIAL_EDITOR_PLANE_CAMERA_FROM_DIRECTION); - break; - } - - GenerateAllImages(); -} - - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::updateGeometries() -{ - ClearItemGeometries(); - m_updatingGeometries = true; - - if (!model()) - { - return; - } - - const int rowCount = model()->rowCount(); - if (!rowCount) - { - m_largePreviewCtrl->hide(); - m_largePreviewMaterial = nullptr; - return; - } - m_largePreviewCtrl->setParent(nullptr); - m_largePreviewCtrl->setParent(this); - m_largePreviewCtrl->show(); - - const int bwidth = BorderSize().width(); - const int bheight = BorderSize().height(); - m_largePreviewCtrl->move(bwidth, bheight); - - QRect rc = viewport()->contentsRect() - .adjusted(bwidth, bheight, -bwidth, -bheight); - - int cy = rc.height(); - - // Preview item is big. - if (model()->rowCount() > 0) - { - QSize size(cy, rc.height()); - m_largePreviewCtrl->SetSize(size); - m_largePreviewCtrl->resize(size); - rc.setLeft(rc.left() + cy + bwidth * 2); - m_largePreviewCtrl->show(); - } - - int cx = rc.width() - bwidth; - - int itemSize = cy; - - // Adjust all other bitmaps as tight as possible. - int numItems = model()->rowCount(); - int div = 0; - for (div = 1; div < 1000 && itemSize > 0; div++) - { - int nX = cx / (itemSize + 2); - if (nX >= numItems) - { - break; - } - if (nX > 0) - { - int nY = numItems / nX + 1; - if (nY * (itemSize + 2) < cy) - { - //itemSize = itemSize -= 2; - break; - } - } - itemSize = itemSize -= 2; - } - if (itemSize < 0) - { - itemSize = 0; - } - - QPoint pos(rc.topLeft()); - const QSize size(itemSize, itemSize); - m_renderCtrl->SetSize(size); - for (int row = 0; row < numItems; ++row) - { - QModelIndex index = model()->index(row, 0); - SetItemGeometry(index, QRect(pos, size)); - model()->setData(index, pos, QMaterialImageListModel::PositionRole); - model()->setData(index, size, Qt::SizeHintRole); - pos.rx() += itemSize + 2; - if (pos.rx() + itemSize >= rc.right()) - { - pos.rx() = rc.left(); - pos.ry() += itemSize + 2; - } - } - - m_updatingGeometries = false; - update(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::setModel(QAbstractItemModel* model) -{ - QMaterialImageListModel* materialModel = qobject_cast(model); - if (materialModel) - { - materialModel->SetPreviewModelCtrl(m_renderCtrl.data()); - } - - CImageListCtrl::setModel(model); - - auto delegate = qobject_cast(itemDelegate()); - // in case the delegate misses a pixmap we can generate it (done only once not at every painting) - connect(delegate, SIGNAL(invalidPixmapGenerated(const QModelIndex&)), materialModel, SLOT(GenerateImage(const QModelIndex&))); - connect(model, &QAbstractItemModel::dataChanged, this, &CMaterialImageListCtrl::ModelDataChanged); -} - -void CMaterialImageListCtrl::ModelDataChanged(const QModelIndex& index) -{ - // Prevent the hundreads of resize calls done in a row - // to trigger a new image computation that we already have - if (m_updatingGeometries) - { - return; - } - - GenerateImage(index); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::showEvent(QShowEvent* event) -{ - CImageListCtrl::showEvent(event); - - if (!m_largePreviewCtrl->GetStaticModel()) - { - LoadModel(); - } - if (!m_renderCtrl->GetStaticModel()) - { - m_renderCtrl->LoadModelFile(MATERIAL_EDITOR_SWATCH_MODEL_FILE); - m_renderCtrl->SetCameraLookAt(MATERIAL_EDITOR_SWATCH_CAMERA_RADIUS, MATERIAL_EDITOR_SWATCH_CAMERA_FROM_DIRECTION); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialImageListCtrl::OnSystemEvent(ESystemEvent event, UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam) -{ - switch (event) - { - // Toggle visibility of this control whenever the main editor window has a change of focus. - case ESYSTEM_EVENT_CHANGE_FOCUS: - { - setAttribute(Qt::WA_WState_Visible, (wparam != 0)); - break; - } - } - ; -} - -void CMaterialImageListCtrl::UpdateLargePreview() -{ - if (m_largePreviewMaterial) - { - m_largePreviewCtrl->SetMaterial(ResolveTerrainLayerPreviewMaterial(m_largePreviewMaterial, m_tempTerrainMaterial)->GetMatInfo()); - m_largePreviewCtrl->show(); - m_largePreviewCtrl->update(); - } -} - -void CMaterialImageListCtrl::GenerateImage(const QModelIndex& index) -{ - QMaterialImageListModel* materialModel = - qobject_cast(model()); - Q_ASSERT(materialModel); - if (m_largePreviewMaterial == materialModel->MaterialFromIndex(index)) - { - UpdateLargePreview(); - } - - materialModel->SetPreviewModelCtrl(m_renderCtrl.data()); - materialModel->GenerateImage(index); - update(); -} - -void CMaterialImageListCtrl::GenerateAllImages() -{ - QMaterialImageListModel* materialModel = - qobject_cast(model()); - Q_ASSERT(materialModel); - - UpdateLargePreview(); - - materialModel->SetPreviewModelCtrl(m_renderCtrl.data()); - materialModel->GenerateImages(); - update(); -} - -////////////////////////////////////////////////////////////////////////// -QMaterialImageListModel::QMaterialImageListModel(QObject* parent) - : QAbstractListModel(parent) - , m_renderCtrl(nullptr) -{ - BusConnect(AZ_CRC("dds", 0x780234cb)); -} - -////////////////////////////////////////////////////////////////////////// -QMaterialImageListModel::~QMaterialImageListModel() -{ - BusDisconnect(); - - qDeleteAll(m_items); -} - -////////////////////////////////////////////////////////////////////////// -MaterialPreviewModelView* QMaterialImageListModel::PreviewModelCtrl() const -{ - return m_renderCtrl; -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::SetPreviewModelCtrl(MaterialPreviewModelView* ctrl) -{ - if (m_renderCtrl) - { - disconnect(m_renderCtrl, &MaterialPreviewModelView::destroyed, - this, &QMaterialImageListModel::ClearPreviewModelCtrl); - } - - m_renderCtrl = ctrl; - - if (m_renderCtrl) - { - connect(m_renderCtrl, &MaterialPreviewModelView::destroyed, - this, &QMaterialImageListModel::ClearPreviewModelCtrl); - } -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::ClearPreviewModelCtrl() -{ - m_renderCtrl = nullptr; -} - -////////////////////////////////////////////////////////////////////////// -int QMaterialImageListModel::rowCount(const QModelIndex& parent) const -{ - if (parent.isValid()) - { - return 0; - } - - return m_items.count(); -} - -////////////////////////////////////////////////////////////////////////// -QVariant QMaterialImageListModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - { - return QVariant(); - } - - Item* pItem = m_items.at(index.row()); - Q_ASSERT(pItem); - - switch (role) - { - case Qt::DisplayRole: - return pItem->pMaterial->GetShortName(); - - case Qt::DecorationRole: - return QPixmap::fromImage(pItem->image); - - case PositionRole: - return pItem->position; - - case Qt::SizeHintRole: - return pItem->size; - - default: - break; - } - - return QVariant(); -} - -////////////////////////////////////////////////////////////////////////// -bool QMaterialImageListModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (!index.isValid()) - { - return false; - } - - Item* pItem = ItemFromIndex(index); - if (!pItem) - { - return false; - } - - if (Qt::SizeHintRole == role) - { - pItem->size = value.toSize(); - emit dataChanged(index, index, QVector() << Qt::DecorationRole << Qt::SizeHintRole); - return true; - } - - if (PositionRole == role) - { - pItem->position = value.toPoint(); - } - - return false; -} - -////////////////////////////////////////////////////////////////////////// -Qt::ItemFlags QMaterialImageListModel::flags(const QModelIndex& index) const -{ - return QAbstractListModel::flags(index); -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* QMaterialImageListModel::MaterialFromIndex(QModelIndex index) const -{ - Item* pItem = ItemFromIndex(index); - if (!pItem) - { - return nullptr; - } - - return pItem->pMaterial; -} - -////////////////////////////////////////////////////////////////////////// -void* QMaterialImageListModel::UserDataFromIndex(QModelIndex index) const -{ - Item* pItem = ItemFromIndex(index); - if (!pItem) - { - return nullptr; - } - - return pItem->pUserData; -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::GenerateImages() -{ - if ((!m_renderCtrl) || (m_items.isEmpty())) - { - return; - } - - for (Item* materialImageListItem : m_items) - { - GenerateImage(materialImageListItem); - } -} - -void QMaterialImageListModel::GenerateImage(const QModelIndex& index) -{ - if ((!m_renderCtrl) || (m_items.isEmpty())) - { - return; - } - - GenerateImage(ItemFromIndex(index)); -} - -////////////////////////////////////////////////////////////////////////// -QMaterialImageListModel::Item* QMaterialImageListModel::ItemFromIndex(QModelIndex index) const -{ - if (!index.isValid()) - { - return nullptr; - } - - return m_items.at(index.row()); -} - -////////////////////////////////////////////////////////////////////////// -void QMaterialImageListModel::OnFileChanged(AZStd::string assetPath) -{ - const int rowCount = m_items.count(); - - // update all previews who's texture(s) changed - for (int row = 0; row < rowCount; ++row) - { - Item* pItem = m_items.at(row); - - QStringList::const_iterator textureIt = std::find(pItem->vVisibleTextures.begin(), pItem->vVisibleTextures.end(), assetPath.c_str()); - if (textureIt != pItem->vVisibleTextures.end()) - { - pItem->image = QImage(); - QModelIndex idx = index(row, 0); - emit dataChanged(idx, idx, QVector() << Qt::DecorationRole); - } - } -} - -#include diff --git a/Code/Sandbox/Editor/Material/MaterialImageListCtrl.h b/Code/Sandbox/Editor/Material/MaterialImageListCtrl.h deleted file mode 100644 index fe9742fb53..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialImageListCtrl.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALIMAGELISTCTRL_H -#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALIMAGELISTCTRL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "Controls/ImageListCtrl.h" -#include -#include "Material.h" -#include "IRenderer.h" // IAsyncTextureCompileListener -#include "IResourceCompilerHelper.h" -#include - -#include -#include -#endif - -class MaterialPreviewModelView; -class MaterialBrowserWidget; - -////////////////////////////////////////////////////////////////////////// -class CMaterialImageListCtrl - : public CImageListCtrl - , public ISystemEventListener -{ - Q_OBJECT -public: - - enum class ModelType - { - Default, - Box, - Sphere, - Teapot, - Plane - }; - - enum MenuAction - { - ModelDefault = 0, - ModelPlane, - ModelBox, - ModelSphere, - ModelTeapot, - // Context menu actions that are common to both the material browser and the preview swatches - // are handled by the same switch statement, so they need to be unique. This sets the starting point for the common actions - MaterialBrowserWidgetActionsStart - }; - - CMaterialImageListCtrl(QWidget* parent = nullptr); - ~CMaterialImageListCtrl(); - - void setModel(QAbstractItemModel* model) override; - - void EnableAutoRefresh(bool autoRefreshState, unsigned int refreshInterval); - void SelectMaterial(CMaterial* pMaterial); - void LoadModel(); - void SetMaterialBrowserWidget(MaterialBrowserWidget* materialBrowserWidget){ m_materialBrowserWidget = materialBrowserWidget; } - // ISystemEventListener - // Due to the material editor working on a ProcessEvents -> Timer based system, rather than the OnIdle update event loops - // that the other editor windows use, make sure that when the editor loses focus that the Material Editor itself loses focus. - // This will pause updates/renderings in the material editor when it does not have focus. - // This prevents certain materials from re-creating themselves and eventually overflowing a few resource buffers. - // The main window cleans up those resources during its main update, which is bypassed when the window does not have focus. - virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam); - // ~ISystemEventListener - - // Override resizeEvent and use this const to rate limit it such that it only fires RESIZE_TIMEOUT ms after resizing stops - static const int RESIZE_TIMEOUT = 100; - void resizeEvent(QResizeEvent* event) override; - -public slots: - void ModelDataChanged(const QModelIndex& index); - void ResizeTimeout(); -protected: - void OnCreate(); - void OnDestroy(); - - void contextMenuEvent(QContextMenuEvent* event) override; - void showEvent(QShowEvent* event) override; - void updateGeometries() override; - -private: - void GenerateImage(const QModelIndex& index); - void GenerateAllImages(); - void UpdateLargePreview(); - - QScopedPointer m_largePreviewCtrl; // Used to draw the main 3D preview viewport for the selected sub-material - _smart_ptr m_largePreviewMaterial; - _smart_ptr m_tempTerrainMaterial; - QScopedPointer m_renderCtrl; // Used to draw the swatches for all the sub-materials - int m_nColor; - bool m_updatingGeometries = false; - ModelType m_modelType = ModelType::Default; - MaterialBrowserWidget* m_materialBrowserWidget; - QTimer* m_resizeTimer; // Used to stall a resizeEvent from firing until RESIZE_TIMEOUT ms have passed since resizing stopped -}; - -class QMaterialImageListModel - : public QAbstractListModel - , public AzFramework::LegacyAssetEventBus::Handler -{ - struct Item; - Q_OBJECT - -public: - enum CustomRoles - { - PositionRole = Qt::UserRole - }; - - QMaterialImageListModel(QObject* parent = nullptr); - ~QMaterialImageListModel(); - - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - Qt::ItemFlags flags(const QModelIndex& index) const override; - - QModelIndex AddMaterial(CMaterial* pMaterial, void* pUserData = nullptr); - void SetMaterial(int nItemIndex, CMaterial* pMaterial, void* pUserData = nullptr); - QModelIndex FindMaterial(CMaterial* pMaterial); - void InvalidateMaterial(CMaterial* pMaterial); - void DeleteAllItems(); - - MaterialPreviewModelView* PreviewModelCtrl() const; - void SetPreviewModelCtrl(MaterialPreviewModelView* ctrl); - - CMaterial* MaterialFromIndex(QModelIndex index) const; - void* UserDataFromIndex(QModelIndex index) const; - -public slots: - void GenerateImages(); - void GenerateImage(const QModelIndex& index); - -protected: - void GenerateImage(Item* pItem); - Item* ItemFromIndex(QModelIndex index) const; - -private slots: - void ClearPreviewModelCtrl(); - -private: - void OnFileChanged(AZStd::string assetPath) override; - -private: - _smart_ptr m_pMatPreview; - QPointer m_renderCtrl; - QVector m_items; -}; - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALIMAGELISTCTRL_H diff --git a/Code/Sandbox/Editor/Material/MaterialLibrary.cpp b/Code/Sandbox/Editor/Material/MaterialLibrary.cpp deleted file mode 100644 index 351eee5c63..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialLibrary.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MaterialLibrary.h" - -// Editor -#include "BaseLibraryItem.h" - - -////////////////////////////////////////////////////////////////////////// -// CMaterialLibrary implementation. -////////////////////////////////////////////////////////////////////////// -bool CMaterialLibrary::Save() -{ - return SaveLibrary("MaterialLibrary"); -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialLibrary::Load(const QString& filename) -{ - if (filename.isEmpty()) - { - return false; - } - SetFilename(filename); - XmlNodeRef root = XmlHelpers::LoadXmlFromFile(filename.toUtf8().data()); - if (!root) - { - return false; - } - - Serialize(root, true); - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialLibrary::Serialize([[maybe_unused]] XmlNodeRef& root, [[maybe_unused]] bool bLoading) -{ - /* - if (bLoading) - { - // Loading. - CString name = GetName(); - root->getAttr( "Name",name ); - SetName( name ); - for (int i = 0; i < root->getChildCount(); i++) - { - XmlNodeRef itemNode = root->getChild(i); - CMaterial *material = new CMaterial(itemNode->getAttr("Name")); - AddItem( material ); - CBaseLibraryItem::SerializeContext ctx( itemNode,bLoading ); - material->Serialize( ctx ); - } - SetModified(false); - } - else - { - // Saving. - root->setAttr( "Name",GetName() ); - root->setAttr( "SandboxVersion",(const char*)GetIEditor()->GetFileVersion().ToFullString() ); - // Serialize prototypes. - for (int i = 0; i < GetItemCount(); i++) - { - CMaterial *pMtl = (CMaterial*)GetItem(i); - // Save materials with parents under thier parent xml node. - if (pMtl->GetParent()) - continue; - - XmlNodeRef itemNode = root->newChild( "Material" ); - CBaseLibraryItem::SerializeContext ctx( itemNode,bLoading ); - GetItem(i)->Serialize( ctx ); - } - } - */ -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -void CMaterialLibrary::AddItem(IDataBaseItem* item, bool bRegister) -{ - CBaseLibraryItem* pLibItem = (CBaseLibraryItem*)item; - // Check if item is already assigned to this library. - if (pLibItem->GetLibrary() != this) - { - pLibItem->SetLibrary(this); - if (bRegister) - { - m_pManager->RegisterItem(pLibItem); - } - m_items.push_back(pLibItem); - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CMaterialLibrary::GetItem(int index) -{ - assert(index >= 0 && index < m_items.size()); - return m_items[index]; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialLibrary::RemoveItem(IDataBaseItem* item) -{ - for (int i = 0; i < m_items.size(); i++) - { - if (m_items[i] == item) - { - m_items.erase(m_items.begin() + i); - SetModified(); - break; - } - } -} - -////////////////////////////////////////////////////////////////////////// -IDataBaseItem* CMaterialLibrary::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 NULL; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialLibrary::RemoveAllItems() -{ - AddRef(); - for (int i = 0; i < m_items.size(); i++) - { - // Clear library item. - m_items[i]->SetLibrary(NULL); - } - m_items.clear(); - Release(); -} diff --git a/Code/Sandbox/Editor/Material/MaterialLibrary.h b/Code/Sandbox/Editor/Material/MaterialLibrary.h deleted file mode 100644 index 5a80500e94..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialLibrary.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALLIBRARY_H -#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALLIBRARY_H -#pragma once - -#include "BaseLibrary.h" - -/** Library of prototypes. -*/ -class CRYEDIT_API CMaterialLibrary - : public CBaseLibrary -{ -public: - CMaterialLibrary(IBaseLibraryManager* pManager) - : CBaseLibrary(pManager) {}; - virtual bool Save(); - virtual bool Load(const QString& filename); - virtual void Serialize(XmlNodeRef& node, bool bLoading); - - ////////////////////////////////////////////////////////////////////////// - // CBaseLibrary override. - ////////////////////////////////////////////////////////////////////////// - void AddItem(IDataBaseItem* item, bool bRegister = true); - int GetItemCount() const { return m_items.size(); } - IDataBaseItem* GetItem(int index); - void RemoveItem(IDataBaseItem* item); - void RemoveAllItems(); - IDataBaseItem* FindItem(const QString& name); -private: - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - std::vector m_items; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALLIBRARY_H diff --git a/Code/Sandbox/Editor/Material/MaterialManager.cpp b/Code/Sandbox/Editor/Material/MaterialManager.cpp deleted file mode 100644 index 51460ff34a..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialManager.cpp +++ /dev/null @@ -1,2095 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MaterialManager.h" - -// Qt -#include - -// AzCore -#include - -// AzFramework -#include - -// AzToolsFramework -#include -#include -#include - -// Editor -#include "MainWindow.h" -#include "MaterialLibrary.h" -#include "MaterialSender.h" -#include "MaterialUtils.h" -#include "ModelViewport.h" -#include "ISourceControl.h" -#include "UsedResources.h" -#include "Viewport.h" -#include "Commands/CommandManager.h" -#include "Include/IObjectManager.h" -#include "Objects/BaseObject.h" -#include "Objects/SelectionGroup.h" - - -static const char* MATERIALS_LIBS_PATH = "Materials/"; -static unsigned int s_highlightUpdateCounter = 0; - -// Convert a material name into a material identifier (no extension, no gamename, etc) so that it can be compared -// in the hash. -static QString UnifyMaterialName(const QString& source) -{ - char tempBuffer[AZ_MAX_PATH_LEN]; - azstrncpy(tempBuffer, AZ_ARRAY_SIZE(tempBuffer), source.toUtf8().data(), AZ_ARRAY_SIZE(tempBuffer) - 1); - MaterialUtils::UnifyMaterialName(tempBuffer); - return QString(tempBuffer); -} - -struct SHighlightMode -{ - float m_colorHue; - float m_period; - bool m_continuous; -}; - -static SHighlightMode g_highlightModes[] = { - { 0.70f, 0.8f, true }, // purple - { 0.25f, 0.75f, false }, // green - { 0.0, 0.75f, true } // red -}; - -class CMaterialHighlighter -{ -public: - void Start(CMaterial* pMaterial, int modeFlag); - void Stop(CMaterial* pMaterial, int modeFlag); - void GetHighlightColor(ColorF* color, float* intensity, int flags); - - void ClearMaterials() { m_materials.clear(); }; - void RestoreMaterials(); - void Update(); -private: - struct SHighlightOptions - { - int m_modeFlags; - }; - - typedef std::map Materials; - Materials m_materials; -}; - -AZStd::string DccMaterialToSourcePath(const AZStd::string& relativeDccMaterialPath) -{ - AZStd::string fullSourcePath; - bool sourcePathFound = false; - - // Get source path using relative .dccmtl path - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourcePathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, relativeDccMaterialPath, fullSourcePath); - - if (sourcePathFound) - { - // Set source path extension to ".mtl" - AzFramework::StringFunc::Path::ReplaceExtension(fullSourcePath, MATERIAL_FILE_EXT); - } - return fullSourcePath; -} - - -void CMaterialHighlighter::Start(CMaterial* pMaterial, int modeFlag) -{ - Materials::iterator it = m_materials.find(pMaterial); - if (it == m_materials.end()) - { - SHighlightOptions& options = m_materials[pMaterial]; - options.m_modeFlags = modeFlag; - } - else - { - SHighlightOptions& options = it->second; - options.m_modeFlags |= modeFlag; - } -} - -void CMaterialHighlighter::Stop(CMaterial* pMaterial, int modeFlag) -{ - if (pMaterial) - { - pMaterial->SetHighlightFlags(0); - } - - Materials::iterator it = m_materials.find(pMaterial); - if (it == m_materials.end()) - { - return; - } - - SHighlightOptions& options = it->second; - MAKE_SURE((options.m_modeFlags & modeFlag) != 0, return ); - - options.m_modeFlags &= ~modeFlag; - if (options.m_modeFlags == 0) - { - m_materials.erase(it); - } -} - -void CMaterialHighlighter::RestoreMaterials() -{ - for (Materials::iterator it = m_materials.begin(); it != m_materials.end(); ++it) - { - if (it->first) - { - it->first->SetHighlightFlags(0); - } - } -} - -void CMaterialHighlighter::Update() -{ - unsigned int counter = s_highlightUpdateCounter; - - Materials::iterator it; - for (it = m_materials.begin(); it != m_materials.end(); ++it) - { - // Only update each material every 4 frames - if (counter++ % 4 == 0) - { - it->first->SetHighlightFlags(it->second.m_modeFlags); - } - } - - s_highlightUpdateCounter = (s_highlightUpdateCounter + 1) % 4; -} - -void CMaterialHighlighter::GetHighlightColor(ColorF* color, float* intensity, int flags) -{ - MAKE_SURE(color != 0, return ); - MAKE_SURE(intensity != 0, return ); - - *intensity = 0.0f; - - if (flags == 0) - { - return; - } - - int flagIndex = 0; - while (flags) - { - if ((flags & 1) != 0) - { - break; - } - flags = flags >> 1; - ++flagIndex; - } - - MAKE_SURE(flagIndex < sizeof(g_highlightModes) / sizeof(g_highlightModes[0]), return ); - - const SHighlightMode& mode = g_highlightModes[flagIndex]; - float t = GetTickCount() / 1000.0f; - float h = mode.m_colorHue; - float s = 1.0f; - float v = 1.0f; - - color->fromHSV(h + sinf(t * g_PI2 * 5.0f) * 0.025f, s, v); - color->a = 1.0f; - - if (mode.m_continuous) - { - *intensity = fabsf(sinf(t * g_PI2 / mode.m_period)); - } - else - { - *intensity = max(0.0f, sinf(t * g_PI2 / mode.m_period)); - } -} - - -////////////////////////////////////////////////////////////////////////// -// CMaterialManager implementation. -////////////////////////////////////////////////////////////////////////// -CMaterialManager::CMaterialManager(CRegistrationContext& regCtx) - : m_pHighlighter(new CMaterialHighlighter) - , m_highlightMask(eHighlight_All) - , m_currentFolder("") - , m_joinThreads(false) -{ - m_bUniqGuidMap = false; - m_bUniqNameMap = true; - - m_bEditorUiReady = false; - m_bSourceControlErrorReported = false; - m_sourceControlFunctionQueued = false; - m_pLevelLibrary = (CBaseLibrary*)AddLibrary("Level", true); - - m_MatSender = new CMaterialSender(true); - - EBusFindAssetTypeByName materialResult("Material"); //from MaterialAssetTypeInfo.cpp, case insensitive - AZ::AssetTypeInfoBus::BroadcastResult(materialResult, &AZ::AssetTypeInfo::GetAssetType); - m_materialAssetType = materialResult.GetAssetType(); - - EBusFindAssetTypeByName dccMaterialResult("DccMaterial"); //from MaterialAssetTypeInfo.cpp, case insensitive - AZ::AssetTypeInfoBus::BroadcastResult(dccMaterialResult, &AZ::AssetTypeInfo::GetAssetType); - m_dccMaterialAssetType = dccMaterialResult.GetAssetType(); - - RegisterCommands(regCtx); - AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); - AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler::BusConnect(); - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); -} - -////////////////////////////////////////////////////////////////////////// -CMaterialManager::~CMaterialManager() -{ - AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler::BusDisconnect(); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); - AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); - - delete m_pHighlighter; - m_pHighlighter = 0; - - if (gEnv->p3DEngine) - { - gEnv->p3DEngine->GetMaterialManager()->SetListener(NULL); - } - - if (m_MatSender) - { - delete m_MatSender; - m_MatSender = 0; - } - - // Terminate thread that saves dcc materials. - m_joinThreads = true; - if (m_bEditorUiReady) - { - m_dccMaterialSaveSemaphore.release(); - m_dccMaterialSaveThread.join(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Set3DEngine() -{ - if (gEnv->p3DEngine) - { - gEnv->p3DEngine->GetMaterialManager()->SetListener(this); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::ClearAll() -{ - SetCurrentMaterial(NULL); - CBaseLibraryManager::ClearAll(); - - m_pLevelLibrary = (CBaseLibrary*)AddLibrary("Level", true); -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::CreateMaterial(const QString& sMaterialName,const XmlNodeRef& node, int nMtlFlags, [[maybe_unused]] unsigned long nLoadingFlags) -{ - CMaterial* pMaterial = new CMaterial(sMaterialName, nMtlFlags); - - if (node) - { - CBaseLibraryItem::SerializeContext serCtx(node, true); - serCtx.bUniqName = true; - pMaterial->Serialize(serCtx); - } - if (!pMaterial->IsPureChild() && !(pMaterial->GetFlags() & MTL_FLAG_UIMATERIAL)) - { - RegisterItem(pMaterial); - } - - return pMaterial; -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::CreateMaterial(const char* sMaterialName,const XmlNodeRef& node, int nMtlFlags, unsigned long nLoadingFlags) -{ - return CreateMaterial(QString(sMaterialName), node, nMtlFlags, nLoadingFlags); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Export(XmlNodeRef& node) -{ - XmlNodeRef libs = node->newChild("MaterialsLibrary"); - for (int i = 0; i < GetLibraryCount(); i++) - { - IDataBaseLibrary* pLib = GetLibrary(i); - // Level libraries are saved in in level. - XmlNodeRef libNode = libs->newChild("Library"); - - // Export library. - libNode->setAttr("Name", pLib->GetName().toUtf8().data()); - } -} - -////////////////////////////////////////////////////////////////////////// -int CMaterialManager::ExportLib(CMaterialLibrary* pLib, XmlNodeRef& libNode) -{ - int num = 0; - // Export library. - libNode->setAttr("Name", pLib->GetName().toUtf8().data()); - libNode->setAttr("File", pLib->GetFilename().toUtf8().data()); - char version[50]; - GetIEditor()->GetFileVersion().ToString(version, AZ_ARRAY_SIZE(version)); - libNode->setAttr("SandboxVersion", version); - - // Serialize prototypes. - for (int j = 0; j < pLib->GetItemCount(); j++) - { - CMaterial* pMtl = (CMaterial*)pLib->GetItem(j); - - // Only export real used materials. - if (pMtl->IsDummy() || !pMtl->IsUsed() || pMtl->IsPureChild()) - { - continue; - } - - XmlNodeRef itemNode = libNode->newChild("Material"); - itemNode->setAttr("Name", pMtl->GetName().toUtf8().data()); - num++; - } - return num; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SetSelectedItem(IDataBaseItem* pItem) -{ - m_pSelectedItem = (CBaseLibraryItem*)pItem; - SetCurrentMaterial((CMaterial*)pItem); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SetCurrentMaterial(CMaterial* pMtl) -{ - if (m_pCurrentMaterial) - { - // Changing current material. save old one. - if (m_pCurrentMaterial->IsModified()) - { - m_pCurrentMaterial->Save(); - } - } - - m_pCurrentMaterial = pMtl; - if (m_pCurrentMaterial) - { - m_pCurrentMaterial->OnMakeCurrent(); - m_pCurrentEngineMaterial = m_pCurrentMaterial->GetMatInfo(); - } - else - { - m_pCurrentEngineMaterial = 0; - } - - m_pSelectedItem = pMtl; - m_pSelectedParent = pMtl ? pMtl->GetParent() : NULL; - - NotifyItemEvent(m_pCurrentMaterial, EDB_ITEM_EVENT_SELECTED); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SetCurrentFolder(const QString& folder) -{ - m_currentFolder = folder; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SetMarkedMaterials(const std::vector<_smart_ptr >& markedMaterials) -{ - m_markedMaterials = markedMaterials; -} - -void CMaterialManager::OnLoadShader(CMaterial* pMaterial) -{ - RemoveFromHighlighting(pMaterial, eHighlight_All); - AddForHighlighting(pMaterial); -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::GetCurrentMaterial() const -{ - return m_pCurrentMaterial; -} - -////////////////////////////////////////////////////////////////////////// -CBaseLibraryItem* CMaterialManager::MakeNewItem() -{ - CMaterial* pMaterial = new CMaterial("", 0); - return pMaterial; -} -////////////////////////////////////////////////////////////////////////// -CBaseLibrary* CMaterialManager::MakeNewLibrary() -{ - return new CMaterialLibrary(this); -} -////////////////////////////////////////////////////////////////////////// -QString CMaterialManager::GetRootNodeName() -{ - return "MaterialsLibs"; -} -////////////////////////////////////////////////////////////////////////// -QString CMaterialManager::GetLibsPath() -{ - if (m_libsPath.isEmpty()) - { - m_libsPath = MATERIALS_LIBS_PATH; - } - return m_libsPath; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::ReportDuplicateItem(CBaseLibraryItem* pItem, CBaseLibraryItem* pOldItem) -{ - QString sLibName; - if (pOldItem->GetLibrary()) - { - sLibName = pOldItem->GetLibrary()->GetName(); - } - CErrorRecord err; - err.pItem = (CMaterial*)pOldItem; - err.error = QObject::tr("Material %1 with the duplicate name to the loaded material %2 ignored").arg(pItem->GetName(), pOldItem->GetName()); - GetIEditor()->GetErrorReport()->ReportError(err); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Serialize([[maybe_unused]] XmlNodeRef& node, bool bLoading) -{ - //CBaseLibraryManager::Serialize( node,bLoading ); - if (bLoading) - { - } - else - { - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - CBaseLibraryManager::OnEditorNotifyEvent(event); - switch (event) - { - case eNotify_OnInit: - InitMatSender(); - break; - case eNotify_OnIdleUpdate: - m_pHighlighter->Update(); - break; - case eNotify_OnBeginGameMode: - m_pHighlighter->RestoreMaterials(); - break; - case eNotify_OnEndGameMode: - ReloadDirtyMaterials(); - break; - case eNotify_OnBeginNewScene: - SetCurrentMaterial(0); - break; - case eNotify_OnBeginSceneOpen: - SetCurrentMaterial(0); - break; - case eNotify_OnMissionChange: - SetCurrentMaterial(0); - break; - case eNotify_OnCloseScene: - SetCurrentMaterial(0); - m_pHighlighter->ClearMaterials(); - break; - case eNotify_OnQuit: - SetCurrentMaterial(0); - if (gEnv->p3DEngine) - { - gEnv->p3DEngine->GetMaterialManager()->SetListener(NULL); - } - break; - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::ReloadDirtyMaterials() -{ - if (!GetIEditor()->Get3DEngine()) - { - return; - } - - IMaterialManager* runtimeMaterialManager = GetIEditor()->Get3DEngine()->GetMaterialManager(); - - uint32 mtlCount = 0; - - runtimeMaterialManager->GetLoadedMaterials(NULL, mtlCount); - - if (mtlCount > 0) - { - AZStd::vector<_smart_ptr> allMaterials; - - allMaterials.reserve(mtlCount); - - [[maybe_unused]] uint32 mtlCountPrev = mtlCount; - runtimeMaterialManager->GetLoadedMaterials(&allMaterials, mtlCount); - AZ_Assert(mtlCountPrev == mtlCount && mtlCount == allMaterials.size(), "It appears GetLoadedMaterials was not used correctly."); - - for (size_t i = 0; i < mtlCount; ++i) - { - _smart_ptr pMtl = allMaterials[i]; - if (pMtl && pMtl->IsDirty()) - { - runtimeMaterialManager->ReloadMaterial(pMtl); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::LoadMaterial(const QString& sMaterialName, bool bMakeIfNotFound) -{ - LOADING_TIME_PROFILE_SECTION(GetISystem()); - - QString sMaterialNameClear = UnifyMaterialName(sMaterialName); - QString fullSourcePath = MaterialToFilename(sMaterialNameClear); - QString relativePath = PathUtil::ReplaceExtension(sMaterialNameClear.toUtf8().data(), MATERIAL_FILE_EXT).c_str(); - - return LoadMaterialInternal(sMaterialNameClear, fullSourcePath, relativePath, bMakeIfNotFound); -} - -////////////////////////////////////////////////////////////////////////// -XmlNodeRef CMaterialManager::LoadXmlNode(const QString &fullSourcePath, const QString &relativeFilePath) -{ - XmlNodeRef materialNode = GetISystem()->LoadXmlFromFile(fullSourcePath.toUtf8().data()); - if (!materialNode) - { - // try again with the product file in case its present - materialNode = GetISystem()->LoadXmlFromFile(relativeFilePath.toUtf8().data()); - } - return materialNode; -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::LoadMaterialWithFullSourcePath(const QString& relativeFilePath, const QString& fullSourcePath, bool makeIfNotFound /*= true*/) -{ - QString materialNameClear = UnifyMaterialName(relativeFilePath); - return LoadMaterialInternal(materialNameClear, fullSourcePath, relativeFilePath, makeIfNotFound); -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::LoadMaterialInternal(const QString &materialNameClear, const QString &fullSourcePath, const QString &relativeFilePath, bool makeIfNotFound) -{ - // Note: We are loading from source files here, not from compiled assets, so there is no need to query the asset system for compilation status, etc. - - // Load material with this name if not yet loaded. - CMaterial* pMaterial = (CMaterial*)FindItemByName(materialNameClear); - if (pMaterial) - { - // If this is a dummy material that was created before for not found mtl file - // try reload the mtl file again to get valid material data. - if (pMaterial->IsDummy()) - { - XmlNodeRef mtlNode = GetISystem()->LoadXmlFromFile(fullSourcePath.toUtf8().data()); - if (mtlNode) - { - DeleteMaterial(pMaterial); - pMaterial = CreateMaterial(materialNameClear, mtlNode); - } - } - return pMaterial; - } - - XmlNodeRef mtlNode = LoadXmlNode(fullSourcePath, relativeFilePath); - - if (mtlNode) - { - pMaterial = CreateMaterial(materialNameClear, mtlNode); - } - else - { - if (makeIfNotFound) - { - pMaterial = new CMaterial(materialNameClear); - pMaterial->SetDummy(true); - RegisterItem(pMaterial); - - CErrorRecord err; - err.error = QObject::tr("Material %1 not found").arg(materialNameClear); - GetIEditor()->GetErrorReport()->ReportError(err); - } - } - - return pMaterial; -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::LoadMaterial(const char* sMaterialName, bool bMakeIfNotFound) -{ - return LoadMaterial(QString(sMaterialName), bMakeIfNotFound); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::AddSourceFileOpeners(const char* fullSourceFileName, [[maybe_unused]] const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) -{ - using namespace AzToolsFramework; - using namespace AzToolsFramework::AssetBrowser; - - // disable if other project is active - if (AzFramework::Render::RenderSystemRequestBus::HasHandlers()) - { - return; - } - - if (AZStd::wildcard_match("*.mtl", fullSourceFileName)) - { - // we can handle these! - auto materialCallback = [this](const char* fullSourceFileNameInCall, const AZ::Uuid& sourceUUIDInCall) - { - const SourceAssetBrowserEntry* fullDetails = SourceAssetBrowserEntry::GetSourceByUuid(sourceUUIDInCall); - if (fullDetails) - { - CMaterial* materialFile = LoadMaterialWithFullSourcePath(QString::fromUtf8(fullDetails->GetRelativePath().c_str()), QString::fromUtf8(fullSourceFileNameInCall), false); - if (materialFile) - { - OpenViewPane("Material Editor"); - SetCurrentMaterial(materialFile); // the material browser pane should be able to deal with this. - } - } - }; - - openers.push_back({ "O3DE_MaterialEditor", "Open In Material Editor...", QIcon(), materialCallback }); - } -} - -////////////////////////////////////////////////////////////////////////// -static bool MaterialRequiresSurfaceType(CMaterial* pMaterial) -{ - // Do not enforce Surface Type... - - // ...over editor UI materials - if ((pMaterial->GetFlags() & MTL_FLAG_UIMATERIAL) != 0) - { - return false; - } - - // ...over SKY - if (pMaterial->GetShaderName() == "DistanceCloud" || - pMaterial->GetShaderName() == "Sky" || - pMaterial->GetShaderName() == "SkyHDR") - { - return false; - } - // ...over terrain materials - if (pMaterial->GetShaderName() == "Terrain.Layer") - { - return false; - } - // ...over vegetation - if (pMaterial->GetShaderName() == "Vegetation") - { - return false; - } - - // ...over decals - bool requiresSurfaceType = true; - CVarBlock* pShaderGenParams = pMaterial->GetShaderGenParamsVars(); - if (pShaderGenParams) - { - if (IVariable* pVar = pShaderGenParams->FindVariable("Decal")) - { - int value = 0; - pVar->Get(value); - if (value) - { - requiresSurfaceType = false; - } - } - // The function GetShaderGenParamsVars allocates a new CVarBlock object, so let's clean it up here - delete pShaderGenParams; - } - return requiresSurfaceType; -} - -////////////////////////////////////////////////////////////////////////// -int CMaterialManager::GetHighlightFlags(CMaterial* pMaterial) const -{ - if (pMaterial == NULL) - { - return 0; - } - - if ((pMaterial->GetFlags() & MTL_FLAG_NODRAW) != 0) - { - return 0; - } - - int result = 0; - - if (pMaterial == m_pHighlightMaterial) - { - result |= eHighlight_Pick; - } - - const QString& surfaceTypeName = pMaterial->GetSurfaceTypeName(); - if (surfaceTypeName.isEmpty() && MaterialRequiresSurfaceType(pMaterial)) - { - result |= eHighlight_NoSurfaceType; - } - - if (GetIEditor()->Get3DEngine()) - { - if (ISurfaceTypeManager* pSurfaceManager = GetIEditor()->Get3DEngine()->GetMaterialManager()->GetSurfaceTypeManager()) - { - const ISurfaceType* pSurfaceType = pSurfaceManager->GetSurfaceTypeByName(surfaceTypeName.toUtf8().data()); - if (pSurfaceType && pSurfaceType->GetBreakability() != 0) - { - result |= eHighlight_Breakable; - } - } - } - - return result; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::AddForHighlighting(CMaterial* pMaterial) -{ - if (pMaterial == NULL) - { - return; - } - - int highlightFlags = (GetHighlightFlags(pMaterial) & m_highlightMask); - if (highlightFlags != 0) - { - m_pHighlighter->Start(pMaterial, highlightFlags); - } - - int count = pMaterial->GetSubMaterialCount(); - for (int i = 0; i < count; ++i) - { - CMaterial* pChild = pMaterial->GetSubMaterial(i); - if (!pChild) - { - continue; - } - - AddForHighlighting(pChild); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::RemoveFromHighlighting(CMaterial* pMaterial, int mask) -{ - if (pMaterial == NULL) - { - return; - } - - m_pHighlighter->Stop(pMaterial, mask); - - int count = pMaterial->GetSubMaterialCount(); - for (int i = 0; i < count; ++i) - { - CMaterial* pChild = pMaterial->GetSubMaterial(i); - if (!pChild) - { - continue; - } - - RemoveFromHighlighting(pChild, mask); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::UpdateHighlightedMaterials() -{ - IDataBaseItemEnumerator* pEnum = CBaseLibraryManager::GetItemEnumerator(); - if (!pEnum) - { - return; - } - - CMaterial* pMaterial = (CMaterial*)pEnum->GetFirst(); - while (pMaterial) - { - RemoveFromHighlighting(pMaterial, eHighlight_All); - AddForHighlighting(pMaterial); - pMaterial = (CMaterial*)pEnum->GetNext(); - } - - pEnum->Release(); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::OnRequestMaterial(_smart_ptr pMatInfo) -{ - const char* pcName = pMatInfo->GetName(); - CMaterial* pMaterial = (CMaterial*) pMatInfo->GetUserData(); - - if (!pMaterial && pcName && *pcName) - { - pMaterial = LoadMaterial(pcName, false); - } - - if (pMaterial) - { - _smart_ptr pNewMatInfo = pMaterial->GetMatInfo(true); - assert(pNewMatInfo == pMatInfo); - //Only register if the material is not registered - if (!pMaterial->IsRegistered()) - { - RegisterItem(pMaterial); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::OnCreateMaterial(_smart_ptr pMatInfo) -{ - CMaterial* existingMaterial = static_cast(FindItemByName(UnifyMaterialName(pMatInfo->GetName()))); - bool materialAlreadyExists = existingMaterial != nullptr; - - // If its not a sub-material or a UI material - if (!(pMatInfo->GetFlags() & MTL_FLAG_PURE_CHILD) && !(pMatInfo->GetFlags() & MTL_FLAG_UIMATERIAL)) - { - // Create a new editor material if it doesn't exist - if (!materialAlreadyExists) - { - CMaterial* pMaterial = new CMaterial(pMatInfo->GetName()); - pMaterial->SetFromMatInfo(pMatInfo); - RegisterItem(pMaterial); - - AddForHighlighting(pMaterial); - } - else - { - // If the material already exists, re-set its values from the engine material that was just re-loaded - existingMaterial->SetFromMatInfo(pMatInfo); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::OnDeleteMaterial(_smart_ptr pMaterial) -{ - CMaterial* pMtl = (CMaterial*)pMaterial->GetUserData(); - if (pMtl) - { - RemoveFromHighlighting(pMtl, eHighlight_All); - DeleteMaterial(pMtl); - } -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialManager::IsCurrentMaterial(_smart_ptr pMaterial) const -{ - if (!pMaterial) - { - return false; - } - - CMaterial* pMtl = static_cast(pMaterial->GetUserData()); - bool currentMaterial = (pMtl == m_pCurrentMaterial); - - if (pMtl->GetParent()) - { - currentMaterial |= (pMtl->GetParent() == m_pCurrentMaterial); - } - - for (size_t subMatIdx = 0; subMatIdx < pMtl->GetMatInfo()->GetSubMtlCount(); ++subMatIdx) - { - if (static_cast(pMtl->GetMatInfo()->GetSubMtl(subMatIdx)->GetUserData()) == m_pCurrentMaterial) - { - currentMaterial = true; - break; - } - } - - return currentMaterial; -} - - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::FromIMaterial(_smart_ptr engineMaterial) -{ - if (!engineMaterial) - { - return nullptr; - } - CMaterial* editorMaterial = (CMaterial*)engineMaterial->GetUserData(); - if (!editorMaterial) - { - // If the user data isn't set, check for an existing material with the same name - editorMaterial = static_cast(FindItemByName(UnifyMaterialName(engineMaterial->GetName()))); - } - return editorMaterial; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SaveAllLibs() -{ -} - -////////////////////////////////////////////////////////////////////////// -QString CMaterialManager::FilenameToMaterial(const QString& filename) -{ - // Convert a full or relative path to a normalized name that can be used in a hash (so lowercase, relative path, correct slashes, remove extension) - // note that it may already be an asset path, if so, don't add the overhead of calling into the AP and convert it. - // if it starts with an alias (@) or if its an absolute file path, we need to convert it. Otherwise we really don't... - QString name = filename; - if (name.startsWith(QChar('@')) || AZ::IO::PathView(name.toUtf8().data()).IsAbsolute()) - { - name = Path::FullPathToGamePath(filename); // convert any full path to a relative path instead. - } - QByteArray n = name.toUtf8(); - MaterialUtils::UnifyMaterialName(n.data()); // Utility function used by all other parts of the code to unify slashes, lowercase, and remove extension - - return QString::fromUtf8(n); -} - -////////////////////////////////////////////////////////////////////////// -QString CMaterialManager::MaterialToFilename(const QString& sMaterialName) -{ - QString materialWithExtension = Path::ReplaceExtension(sMaterialName, MATERIAL_FILE_EXT); - QString fileName = Path::GamePathToFullPath(materialWithExtension); - const int mtlExtensionLength = strlen(MATERIAL_FILE_EXT); - if (fileName.right(mtlExtensionLength).toLower() != MATERIAL_FILE_EXT) - { - // we got something back which is not a mtl, fall back heuristic: - AZStd::string pathName(fileName.toUtf8().data()); - AZStd::string fileNameOfMaterial; - AzFramework::StringFunc::Path::StripFullName(pathName); // remove the filename of the path to the FBX file so now it just contains the folder of the fbx file. - AzFramework::StringFunc::Path::GetFullFileName(materialWithExtension.toUtf8().data(), fileNameOfMaterial); // remove the path part of the material so it only contains the file name - AZStd::string finalName; - AzFramework::StringFunc::Path::Join(pathName.c_str(), fileNameOfMaterial.c_str(), finalName); - fileName = finalName.c_str(); - } - return fileName; -} - -////////////////////////////////////////////////////////////////////////// -const AZ::Data::AssetType& CMaterialManager::GetMaterialAssetType() -{ - return m_materialAssetType; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::DeleteMaterial(CMaterial* pMtl) -{ - assert(pMtl); - _smart_ptr _ref(pMtl); - if (pMtl == GetCurrentMaterial()) - { - SetCurrentMaterial(NULL); - } - - DeleteItem(pMtl); - - // Delete it from all sub materials. - for (int i = 0; i < m_pLevelLibrary->GetItemCount(); i++) - { - CMaterial* pMultiMtl = (CMaterial*)m_pLevelLibrary->GetItem(i); - if (pMultiMtl->IsMultiSubMaterial()) - { - for (int slot = 0; slot < pMultiMtl->GetSubMaterialCount(); slot++) - { - if (pMultiMtl->GetSubMaterial(slot) == pMultiMtl) - { - // Clear this sub material slot. - pMultiMtl->SetSubMaterial(slot, 0); - } - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::RemoveMaterialFromDisk(const char * fileName) -{ - using namespace AzToolsFramework; - if (fileName) - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestDelete, fileName, - [](bool success, const SourceControlFileInfo& info) - { - //If the file is not managed by source control, delete it locally - if (!success && !info.IsManaged()) - { - QFile::remove(info.m_filePath.c_str()); - } - } - ); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::RegisterCommands(CRegistrationContext& regCtx) -{ - CommandManagerHelper::RegisterCommand(regCtx.pCommandManager, "material", "duplicate", "", "", AZStd::bind(&CMaterialManager::Command_Duplicate, this)); - CommandManagerHelper::RegisterCommand(regCtx.pCommandManager, "material", "merge", "", "", AZStd::bind(&CMaterialManager::Command_Merge, this)); - CommandManagerHelper::RegisterCommand(regCtx.pCommandManager, "material", "delete", "", "", AZStd::bind(&CMaterialManager::Command_Delete, this)); - CommandManagerHelper::RegisterCommand(regCtx.pCommandManager, "material", "assign_to_selection", "", "", AZStd::bind(&CMaterialManager::Command_AssignToSelection, this)); - CommandManagerHelper::RegisterCommand(regCtx.pCommandManager, "material", "select_assigned_objects", "", "", AZStd::bind(&CMaterialManager::Command_SelectAssignedObjects, this)); - CommandManagerHelper::RegisterCommand(regCtx.pCommandManager, "material", "select_from_object", "", "", AZStd::bind(&CMaterialManager::Command_SelectFromObject, this)); -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialManager::SelectSaveMaterial(QString& itemName, QString& fullSourcePath, const char* defaultStartPath) -{ - QString startPath; - if (defaultStartPath && defaultStartPath[0] != '\0') - { - startPath = defaultStartPath; - } - else - { - startPath = GetIEditor()->GetSearchPath(EDITOR_PATH_MATERIALS); - } - - if (!CFileUtil::SelectSaveFile("Material Files (*.mtl)", "mtl", startPath, fullSourcePath)) - { - return false; - } - - itemName = FilenameToMaterial(fullSourcePath); - if (itemName.isEmpty()) - { - return false; - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::SelectNewMaterial(int nMtlFlags, [[maybe_unused]] const char* sStartPath) -{ - QString path = m_pCurrentMaterial ? Path::GetPath(m_pCurrentMaterial->GetFilename()) : m_currentFolder; - QString itemName; - QString fullPath; - if (!SelectSaveMaterial(itemName, fullPath, path.toUtf8().data())) - { - return 0; - } - - if (FindItemByName(itemName)) - { - Warning("Material with name %s already exist", itemName.toUtf8().data()); - return 0; - } - - _smart_ptr mtl = CreateMaterial(itemName, XmlNodeRef(), nMtlFlags); - mtl->Update(); - bool skipReadOnly = true; - mtl->Save(skipReadOnly, fullPath); - SetCurrentMaterial(mtl); - return mtl; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_Create() -{ - SelectNewMaterial(0); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_CreateMulti() -{ - SelectNewMaterial(MTL_FLAG_MULTI_SUBMTL); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_ConvertToMulti() -{ - CMaterial* pMaterial = GetCurrentMaterial(); - - if (pMaterial && pMaterial->GetSubMaterialCount() == 0) - { - CMaterial* pSubMat = new CMaterial(*pMaterial); - pSubMat->SetName(pSubMat->GetShortName()); - pSubMat->SetFlags(pSubMat->GetFlags() | MTL_FLAG_PURE_CHILD); - - pMaterial->SetFlags(MTL_FLAG_MULTI_SUBMTL); - pMaterial->SetSubMaterialCount(1); - pMaterial->SetSubMaterial(0, pSubMat); - - pMaterial->Save(); - pMaterial->Reload(); - SetSelectedItem(pSubMat); - } - else - { - Warning(pMaterial ? "azlmbr.legacy.material.convert_to_multi called on invalid material setup" : "azlmbr.legacy.material.convert_to_multi called while no material selected"); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_Duplicate() -{ - CMaterial* pSrcMtl = GetCurrentMaterial(); - - if (!pSrcMtl) - { - CErrorRecord err; - err.error = "azlmbr.legacy.material.duplicate called while no materials selected"; - GetIEditor()->GetErrorReport()->ReportError(err); - return; - } - - if (GetIEditor()->IsSourceControlAvailable()) - { - uint32 attrib = pSrcMtl->GetFileAttributes(); - - if ((attrib & SCC_FILE_ATTRIBUTE_INPAK) && (attrib & SCC_FILE_ATTRIBUTE_MANAGED) && !(attrib & SCC_FILE_ATTRIBUTE_NORMAL)) - { - // Get latest for making folders with right case - CFileUtil::GetLatestFromSourceControl(pSrcMtl->GetFilename().toUtf8().data()); - } - } - - if (pSrcMtl != 0 && !pSrcMtl->IsPureChild()) - { - QString newUniqueRelativePath = MakeUniqueItemName(pSrcMtl->GetName()); - - // Create a new material. - _smart_ptr pMtl = DuplicateMaterial(newUniqueRelativePath.toUtf8().data(), pSrcMtl); - if (pMtl) - { - // Get the new filename from the relative path - AZStd::string newFileName; - AzFramework::StringFunc::Path::GetFileName(newUniqueRelativePath.toUtf8().data(), newFileName); - - // Get the full path to the original material, so we know which folder to put the new material in - AZStd::string newFullFilePath = pSrcMtl->GetFilename().toUtf8().data(); - - // Replace the original material filename with the filename from the new relative path + the material file extension to get the new full file path - AzFramework::StringFunc::Path::ReplaceFullName(newFullFilePath, newFileName.c_str(), MATERIAL_FILE_EXT); - - AzFramework::StringFunc::Path::Normalize(newFullFilePath); - - const bool skipReadOnly = true; - pMtl->Save(skipReadOnly, newFullFilePath.c_str()); - SetSelectedItem(pMtl); - } - } -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CMaterialManager::DuplicateMaterial(const char* newName, CMaterial* pOriginal) -{ - if (!newName) - { - assert(0 && "NULL newName passed into CMaterialManager::DuplicateMaterial"); - return 0; - } - if (!pOriginal) - { - assert(0 && "NULL pOriginal passed into CMaterialManager::DuplicateMaterial"); - return 0; - } - - - XmlNodeRef node = GetISystem()->CreateXmlNode("Material"); - CBaseLibraryItem::SerializeContext ctx(node, false); - ctx.bCopyPaste = true; - pOriginal->Serialize(ctx); - - return CreateMaterial(newName, node, pOriginal->GetFlags()); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::GenerateUniqueSubmaterialName(const CMaterial* pSourceMaterial, const CMaterial* pTargetMaterial, QString& uniqueSubmaterialName) const -{ - QString sourceMaterialName = pSourceMaterial->GetName(); - - // We don't need the whole path to the material, just the base name - QFileInfo filename(sourceMaterialName); - sourceMaterialName = filename.baseName(); - - uniqueSubmaterialName = sourceMaterialName; - size_t nameIndex = 0; - - bool nameUpdated = true; - while (nameUpdated) - { - nameUpdated = false; - for (size_t k = 0; k < pTargetMaterial->GetSubMaterialCount(); ++k) - { - CMaterial* pSubMaterial = pTargetMaterial->GetSubMaterial(k); - if (pSubMaterial && pSubMaterial->GetName() == uniqueSubmaterialName) - { - ++nameIndex; - uniqueSubmaterialName = QStringLiteral("%1%2").arg(sourceMaterialName).arg(nameIndex, 2, 10, QLatin1Char('0')); - nameUpdated = true; - break; - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialManager::DuplicateAsSubMaterialAtIndex(CMaterial* pSourceMaterial, CMaterial* pTargetMaterial, int subMaterialIndex) -{ - if (pSourceMaterial && pTargetMaterial && pTargetMaterial->GetSubMaterialCount() > subMaterialIndex) - { - // Resolve name collisions between the source material and the submaterials in the target material - QString newSubMaterialName; - GenerateUniqueSubmaterialName(pSourceMaterial, pTargetMaterial, newSubMaterialName); - - // Mark the material to be duplicated as a PURE_CHILD since it is being duplicated as a submaterial - int sourceMaterialFlags = pSourceMaterial->GetFlags(); - pSourceMaterial->SetFlags(sourceMaterialFlags | MTL_FLAG_PURE_CHILD); - - CMaterial* pNewSubMaterial = DuplicateMaterial(newSubMaterialName.toUtf8().data(), pSourceMaterial); - pTargetMaterial->SetSubMaterial(subMaterialIndex, pNewSubMaterial); - - // Reset the flags of the source material to their original values - pSourceMaterial->SetFlags(sourceMaterialFlags); - return true; - } - - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_Merge() -{ - QString itemName; - QString fullPath; - QString defaultMaterialPath; - if (m_pCurrentMaterial) - { - defaultMaterialPath = Path::GetPath(m_pCurrentMaterial->GetFilename()); - } - if (!SelectSaveMaterial(itemName, fullPath, defaultMaterialPath.toUtf8().data())) - { - return; - } - - _smart_ptr pNewMaterial = CreateMaterial(itemName, XmlNodeRef(), MTL_FLAG_MULTI_SUBMTL); - - size_t totalSubMaterialCount = 0; - for (_smart_ptr pMaterial : m_markedMaterials) - { - if (pMaterial->IsMultiSubMaterial()) - { - totalSubMaterialCount += pMaterial->GetSubMaterialCount(); - } - else - { - totalSubMaterialCount++; - } - } - pNewMaterial->SetSubMaterialCount(totalSubMaterialCount); - - size_t subMaterialIndex = 0; - for (_smart_ptr pMaterial : m_markedMaterials) - { - if (pMaterial->IsMultiSubMaterial()) - { - // Loop through each submaterial and duplicate it as a submaterial in the new material - for (size_t j = 0; j < pMaterial->GetSubMaterialCount(); ++j) - { - CMaterial* pSubMaterial = pMaterial->GetSubMaterial(j); - if (DuplicateAsSubMaterialAtIndex(pSubMaterial, pNewMaterial, subMaterialIndex)) - { - ++subMaterialIndex; - } - } - } - else - { - // Duplicate the material as a submaterial in the new material - if (DuplicateAsSubMaterialAtIndex(pMaterial, pNewMaterial, subMaterialIndex)) - { - ++subMaterialIndex; - } - } - } - - pNewMaterial->Update(); - const bool skipReadOnly = true; - pNewMaterial->Save(skipReadOnly, fullPath); - SetCurrentMaterial(pNewMaterial); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_Delete() -{ - CMaterial* pMtl = GetCurrentMaterial(); - if (pMtl) - { - CUndo undo("Delete Material"); - QString str = QObject::tr("Delete Material %1?\r\nNote: Material file %2 will also be deleted.") - .arg(pMtl->GetName(), pMtl->GetFilename()); - if (QMessageBox::question(QApplication::activeWindow(), QObject::tr("Delete Confirmation"), str) == QMessageBox::Yes) - { - AZStd::string matName = pMtl->GetFilename().toUtf8().data(); - DeleteMaterial(pMtl); - RemoveMaterialFromDisk(matName.c_str()); - SetCurrentMaterial(0); - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_AssignToSelection() -{ - CMaterial* pMtl = GetCurrentMaterial(); - if (pMtl) - { - CUndo undo("Assign Material"); - CSelectionGroup* pSel = GetIEditor()->GetSelection(); - if (pMtl->IsPureChild()) - { - const QString title = QObject::tr("Assign Submaterial"); - const QString message = QObject::tr("You can assign submaterials to objects only for preview purpose. This assignment will not be saved with the level and will not be exported to the game."); - if (QMessageBox::information(QApplication::activeWindow(), title, message, QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel) - { - return; - } - } - if (!pSel->IsEmpty()) - { - for (int i = 0; i < pSel->GetCount(); i++) - { - pSel->GetObject(i)->SetMaterial(pMtl); - } - } - } - CViewport* pViewport = GetIEditor()->GetActiveView(); - if (pViewport) - { - pViewport->Drop(QPoint(-1, -1), pMtl); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_ResetSelection() -{ - CSelectionGroup* pSel = GetIEditor()->GetSelection(); - if (!pSel->IsEmpty()) - { - CUndo undo("Reset Material"); - for (int i = 0; i < pSel->GetCount(); i++) - { - pSel->GetObject(i)->SetMaterial(0); - } - } - CViewport* pViewport = GetIEditor()->GetActiveView(); - if (pViewport) - { - pViewport->Drop(QPoint(-1, -1), 0); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_SelectAssignedObjects() -{ - CMaterial* pMtl = GetCurrentMaterial(); - if (pMtl) - { - CUndo undo("Select Object(s)"); - CBaseObjectsArray objects; - GetIEditor()->GetObjectManager()->GetObjects(objects); - for (int i = 0; i < objects.size(); i++) - { - CBaseObject* pObject = objects[i]; - if (pObject->GetMaterial() == pMtl || pObject->GetRenderMaterial() == pMtl) - { - if (pObject->IsHidden() || pObject->IsFrozen()) - { - continue; - } - GetIEditor()->GetObjectManager()->SelectObject(pObject); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::Command_SelectFromObject() -{ - if (GetIEditor()->IsInPreviewMode()) - { - CViewport* pViewport = GetIEditor()->GetActiveView(); - if (CModelViewport* p = viewport_cast(pViewport)) - { - CMaterial* pMtl = p->GetMaterial(); - SetCurrentMaterial(pMtl); - } - return; - } - - CSelectionGroup* pSel = GetIEditor()->GetSelection(); - if (pSel->IsEmpty()) - { - return; - } - - for (int i = 0; i < pSel->GetCount(); i++) - { - CMaterial* pMtl = pSel->GetObject(i)->GetRenderMaterial(); - if (pMtl) - { - SetCurrentMaterial(pMtl); - return; - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::PickPreviewMaterial() -{ - XmlNodeRef data = XmlHelpers::CreateXmlNode("ExportMaterial"); - CMaterial* pMtl = GetCurrentMaterial(); - if (!pMtl) - { - return; - } - - if (pMtl->IsPureChild() && pMtl->GetParent()) - { - pMtl = pMtl->GetParent(); - } - - if (pMtl->GetFlags() & MTL_FLAG_WIRE) - { - data->setAttr("Flag_Wire", 1); - } - if (pMtl->GetFlags() & MTL_FLAG_2SIDED) - { - data->setAttr("Flag_2Sided", 1); - } - - data->setAttr("Name", pMtl->GetName().toUtf8().data()); - data->setAttr("FileName", pMtl->GetFilename().toUtf8().data()); - - XmlNodeRef node = data->newChild("Material"); - - CBaseLibraryItem::SerializeContext serCtx(node, false); - pMtl->Serialize(serCtx); - - - if (!pMtl->IsMultiSubMaterial()) - { - XmlNodeRef texturesNode = node->findChild("Textures"); - if (texturesNode) - { - for (int i = 0; i < texturesNode->getChildCount(); i++) - { - XmlNodeRef texNode = texturesNode->getChild(i); - QString file; - if (texNode->getAttr("File", file)) - { - texNode->setAttr("File", Path::GamePathToFullPath(file).toUtf8().data()); - } - } - } - } - else - { - XmlNodeRef childsNode = node->findChild("SubMaterials"); - if (childsNode) - { - int nSubMtls = childsNode->getChildCount(); - for (int i = 0; i < nSubMtls; i++) - { - XmlNodeRef node2 = childsNode->getChild(i); - XmlNodeRef texturesNode = node2->findChild("Textures"); - if (texturesNode) - { - for (int ii = 0; ii < texturesNode->getChildCount(); ii++) - { - XmlNodeRef texNode = texturesNode->getChild(ii); - QString file; - if (texNode->getAttr("File", file)) - { - texNode->setAttr("File", Path::GamePathToFullPath(file).toUtf8().data()); - } - } - } - } - } - } - - - m_MatSender->SendMessage(eMSM_GetSelectedMaterial, data); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SyncMaterialEditor() -{ -#if defined(AZ_PLATFORM_WINDOWS) - if (!m_MatSender) - { - return; - } - - if (!m_MatSender->GetMessage()) - { - return; - } - - if (m_MatSender->m_h.msg == eMSM_Create) - { - XmlNodeRef node = m_MatSender->m_node->findChild("Material"); - if (!node) - { - return; - } - - QString sMtlName; - QString sMaxFile; - - XmlNodeRef root = m_MatSender->m_node; - root->getAttr("Name", sMtlName); - root->getAttr("MaxFile", sMaxFile); - - int IsMulti = 0; - root->getAttr("IsMulti", IsMulti); - - int nMtlFlags = 0; - if (IsMulti) - { - nMtlFlags |= MTL_FLAG_MULTI_SUBMTL; - } - - if (root->haveAttr("Flag_Wire")) - { - nMtlFlags |= MTL_FLAG_WIRE; - } - if (root->haveAttr("Flag_2Sided")) - { - nMtlFlags |= MTL_FLAG_2SIDED; - } - - _smart_ptr pMtl = SelectNewMaterial(nMtlFlags, Path::GetPath(sMaxFile).toUtf8().data()); - - if (!pMtl) - { - return; - } - - if (!IsMulti) - { - node->delAttr("Shader"); // Remove shader attribute. - XmlNodeRef texturesNode = node->findChild("Textures"); - if (texturesNode) - { - for (int i = 0; i < texturesNode->getChildCount(); i++) - { - XmlNodeRef texNode = texturesNode->getChild(i); - QString file; - if (texNode->getAttr("File", file)) - { - //make path relative to the project specific game folder - QString newfile = Path::MakeGamePath(file); - if (!newfile.isEmpty()) - { - file = newfile; - } - texNode->setAttr("File", file.toUtf8().data()); - } - } - } - } - else - { - XmlNodeRef childsNode = node->findChild("SubMaterials"); - if (childsNode) - { - int nSubMtls = childsNode->getChildCount(); - for (int i = 0; i < nSubMtls; i++) - { - XmlNodeRef node2 = childsNode->getChild(i); - node2->delAttr("Shader"); // Remove shader attribute. - XmlNodeRef texturesNode = node2->findChild("Textures"); - if (texturesNode) - { - for (int ii = 0; ii < texturesNode->getChildCount(); ii++) - { - XmlNodeRef texNode = texturesNode->getChild(ii); - QString file; - if (texNode->getAttr("File", file)) - { - //make path relative to the project specific game folder - QString newfile = Path::MakeGamePath(file); - if (!newfile.isEmpty()) - { - file = newfile; - } - texNode->setAttr("File", file.toUtf8().data()); - } - } - } - } - } - } - - CBaseLibraryItem::SerializeContext ctx(node, true); - ctx.bUndo = true; - pMtl->Serialize(ctx); - - pMtl->Update(); - - SetCurrentMaterial(0); - SetCurrentMaterial(pMtl); - } - - if (m_MatSender->m_h.msg == eMSM_GetSelectedMaterial) - { - PickPreviewMaterial(); - } -#endif -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::InitMatSender() -{ - //MatSend(true); - m_MatSender->Create(); - QWidget* mainWindow = MainWindow::instance(); - m_MatSender->SetupWindows(mainWindow, mainWindow); - XmlNodeRef node = XmlHelpers::CreateXmlNode("Temp"); - m_MatSender->SendMessage(eMSM_Init, node); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::GotoMaterial([[maybe_unused]] CMaterial* pMaterial) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::GotoMaterial([[maybe_unused]] _smart_ptr pMtl) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SetHighlightedMaterial(CMaterial* pMtl) -{ - if (m_pHighlightMaterial) - { - RemoveFromHighlighting(m_pHighlightMaterial, eHighlight_Pick); - } - - m_pHighlightMaterial = pMtl; - if (m_pHighlightMaterial) - { - AddForHighlighting(m_pHighlightMaterial); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::HighlightedMaterialChanged(CMaterial* pMtl) -{ - if (!pMtl) - { - return; - } - - RemoveFromHighlighting(pMtl, eHighlight_All); - AddForHighlighting(pMtl); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::SetHighlightMask(int highlightMask) -{ - if (m_highlightMask != highlightMask) - { - m_highlightMask = highlightMask; - - UpdateHighlightedMaterials(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialManager::GatherResources(_smart_ptr pMaterial, CUsedResources& resources) -{ - if (!pMaterial) - { - return; - } - - int nSubMtlCount = pMaterial->GetSubMtlCount(); - if (nSubMtlCount > 0) - { - for (int i = 0; i < nSubMtlCount; i++) - { - GatherResources(pMaterial->GetSubMtl(i), resources); - } - } - else - { - SShaderItem& shItem = pMaterial->GetShaderItem(); - if (shItem.m_pShaderResources) - { - SInputShaderResources res; - shItem.m_pShaderResources->ConvertToInputResource(&res); - - for (auto& iter : res.m_TexturesResourcesMap ) - { - SEfResTexture* pTexture = &(iter.second); - if (!pTexture->m_Name.empty()) - { - resources.Add(pTexture->m_Name.c_str()); - } - } - gEnv->pRenderer->EF_ReleaseInputShaderResource(&res); - } - } -} - -/////////////////////////////////////////////////////////////////////////// -void CMaterialManager::GetHighlightColor(ColorF* color, float* intensity, int flags) -{ - MAKE_SURE(m_pHighlighter, return ); - m_pHighlighter->GetHighlightColor(color, intensity, flags); -} - -/////////////////////////////////////////////////////////////////////////// -// This will be called when the editor welcome screen is displayed. -// At this point the editor is ready for UI events, which means we can -// process .dccmtl paths and display error to the user if necessary -bool CMaterialManager::SkipEditorStartupUI() -{ - // Editor started - m_bEditorUiReady = true; - - // If we have any file paths buffered - if (m_sourceControlBuffer.size() > 0) - { - // Start queuing - QueueSourceControlTick(); - } - - // Launch thread responsible for saving cached - // .dccmtl files as source .mtl files - StartDccMaterialSaveThread(); - - // Never want to skip Startup UI - return false; -} - -/////////////////////////////////////////////////////////////////////////// -// Queues the function TickSourceControl() to be exectued next frame -void CMaterialManager::QueueSourceControlTick() -{ - // If TickSourceControl is not currently queued - if (!m_sourceControlFunctionQueued) - { - // Queue it - AZStd::function tickFunction = [this]() - { - TickSourceControl(); - }; - AZ::SystemTickBus::QueueFunction(tickFunction); - - // Stop further queues as TickSourceControl will queue itself - // until there are no more paths in the buffer to process - m_sourceControlFunctionQueued = true; - } -} - -/////////////////////////////////////////////////////////////////////////// -// Takes a single path from m_sourceControlBuffer and passes it to -// DccMaterialSourceControlCheck(). Then if there are more paths -// remaining in the buffer, it will queue itself for execution next -// frame. The reason for doing only one material every tick is to avoid -// flooding source control with too many requests and stalling the editor -void CMaterialManager::TickSourceControl() -{ - m_sourceControlFunctionQueued = false; - AZStd::string filePath; - bool moreRemaining = false; - - { - AZStd::lock_guard lock(m_sourceControlBufferMutex); - - if (m_sourceControlBuffer.size() < 1) - { - return; - } - - filePath = m_sourceControlBuffer.back(); - m_sourceControlBuffer.pop_back(); - moreRemaining = !m_sourceControlBuffer.empty(); - } - - // Process it - DccMaterialSourceControlCheck(filePath); - - // If there are more paths to check - if (moreRemaining) - { - // Queue again - QueueSourceControlTick(); - } -} - -/////////////////////////////////////////////////////////////////////////// -// Launches new thread running the DccMaterialSaveThreadFunc() function -void CMaterialManager::StartDccMaterialSaveThread() -{ - AZStd::thread_desc threadDesc; - threadDesc.m_name = "Dcc Material Save Thread"; - - m_dccMaterialSaveThread = AZStd::thread( - [this]() - { - DccMaterialSaveThreadFunc(); - }, - &threadDesc); -} - -/////////////////////////////////////////////////////////////////////////// -// Will save all the .dccmtl file paths in the buffer to source .mtl -// Runs on a separate thread so as not to stall the main thread -void CMaterialManager::DccMaterialSaveThreadFunc() -{ - while (true) - { - m_dccMaterialSaveSemaphore.acquire(); - - // Exit condition, set to true in destructor - if (m_joinThreads) - { - return; - } - - AZStd::vector dccMaterialPaths; - - // Lock the buffer and copy file paths locally - { - AZStd::lock_guard lock(m_dccMaterialSaveMutex); - dccMaterialPaths.reserve(m_dccMaterialSaveBuffer.size()); - for (AZStd::string& fileName : m_dccMaterialSaveBuffer) - { - dccMaterialPaths.push_back(fileName); - } - m_dccMaterialSaveBuffer.clear(); - } - - // Save all the buffered .dccmtl files - for (AZStd::string& fileName : dccMaterialPaths) - { - SaveDccMaterial(fileName); - } - - // Clear local strings - dccMaterialPaths.clear(); - } -} - -/////////////////////////////////////////////////////////////////////////// -// Async source control request. If successful, the callback will add the -// file name to the buffer for processing by the Dcc Material Save Thread -void CMaterialManager::DccMaterialSourceControlCheck(const AZStd::string& relativeDccMaterialPath) -{ - AZStd::string fullSourcePath = DccMaterialToSourcePath(relativeDccMaterialPath); - - if (!DccMaterialRequiresSave(relativeDccMaterialPath, fullSourcePath)) - { - // Source .mtl update not required, early out - return; - } - - // Create callback for source control operation (see SCCommandBus::Broadcast below) - AzToolsFramework::SourceControlResponseCallback callback = - [this, relativeDccMaterialPath, fullSourcePath](bool success, const AzToolsFramework::SourceControlFileInfo& info) - { - if (success || !info.IsReadOnly()) - { - // File needs saving, add it to the buffer for processing by the dcc material thread - - // Lock access to the buffer - AZStd::lock_guard lock(m_dccMaterialSaveMutex); - - // Add file path - m_dccMaterialSaveBuffer.push_back(relativeDccMaterialPath); - - // Notify thread there's work to do - m_dccMaterialSaveSemaphore.release(); - } - else - { - QString errorMessage = QObject::tr("Could not check out read-only file %1 in source control. Either check your source control configuration or disable source control.").arg(QString::fromUtf8(fullSourcePath.c_str())); - - // Alter error message slightly if source control is disabled - bool isSourceControlActive = false; - AzToolsFramework::SourceControlConnectionRequestBus::BroadcastResult(isSourceControlActive, &AzToolsFramework::SourceControlConnectionRequestBus::Events::IsActive); - - if (!isSourceControlActive) - { - errorMessage = QObject::tr("Could not check out read-only file %1 because source control is disabled. Either enable source control or check out the file manually to make it writable.").arg(QString::fromUtf8(fullSourcePath.c_str())); - } - - // Pop open an error message box if this is the first error we encounter - if (!m_bSourceControlErrorReported) - { - // Report warning in message box - QString errorTitle = QStringLiteral("Dcc Material Error"); - QMessageBox::warning(QApplication::activeWindow(), errorTitle, errorMessage, QMessageBox::Cancel); - - // Only report source control error box to the user once, - // no need to spam them for every material - m_bSourceControlErrorReported = true; - } - - AZ_Error("Rendering", false, errorMessage.toUtf8().data()); - } - }; - - // Request edit from source control (happens asynchronously) - using SCCommandBus = AzToolsFramework::SourceControlCommandBus; - SCCommandBus::Broadcast(&SCCommandBus::Events::RequestEdit, fullSourcePath.c_str(), true, callback); -} - -/////////////////////////////////////////////////////////////////////////// -// Handles when .dccmtl is created -void CMaterialManager::EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* assetEntry) -{ - if (assetEntry->GetEntryType() != AzToolsFramework::AssetBrowser::AssetBrowserEntry::AssetEntryType::Product) - { - // Ignore non-product entries - return; - } - const AzToolsFramework::AssetBrowser::ProductAssetBrowserEntry* productAssetEntry = azrtti_cast(assetEntry); - if (productAssetEntry && productAssetEntry->GetAssetType() != m_dccMaterialAssetType) - { - // Ignore types that aren't .dccmtl - return; - } - - AddDccMaterialPath(productAssetEntry->GetRelativePath()); -} - -/////////////////////////////////////////////////////////////////////////// -// Handles when .dccmtl is edited -void CMaterialManager::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) -{ - AZ::Data::AssetInfo assetInfo; - EBUS_EVENT_RESULT(assetInfo, AZ::Data::AssetCatalogRequestBus, GetAssetInfoById, assetId); - - if (assetInfo.m_assetType != m_dccMaterialAssetType) - { - // Ignore types that aren't .dccmtl - return; - } - - AddDccMaterialPath(assetInfo.m_relativePath); -} - -/////////////////////////////////////////////////////////////////////////// -void CMaterialManager::AddDccMaterialPath(const AZStd::string relativeDccMaterialPath) -{ - if (relativeDccMaterialPath.empty()) - { - return; - } - - // Lock access to the buffer - AZStd::lock_guard lock(m_sourceControlBufferMutex); - - // Add file path - m_sourceControlBuffer.push_back(relativeDccMaterialPath); - - if (m_bEditorUiReady) - { - QueueSourceControlTick(); - } -} - -/////////////////////////////////////////////////////////////////////////// -// Given the path of a .dccmtl in cache, save it as a source .mtl -void CMaterialManager::SaveDccMaterial(const AZStd::string& relativeDccMaterialPath) -{ - // __________________________________________________ - // Load .dccmtl - - XmlNodeRef dccNode = GetISystem()->LoadXmlFromFile(relativeDccMaterialPath.c_str()); - - if (!dccNode) - { - AZ_Error("MaterialManager", false, "CMaterialManager::SaveDccMaterial: Failed to load XML node from .dccmtl file: %s", relativeDccMaterialPath.c_str()); - return; - } - - // __________________________________________________ - // Save as source .mtl file - - AZStd::string fullSourcePath = DccMaterialToSourcePath(relativeDccMaterialPath); - bool saveSuccessful = dccNode->saveToFile(fullSourcePath.c_str()); - - if (!saveSuccessful) - { - AZ_Error("MaterialManager", false, "CMaterialManager::SaveDccMaterial: Failed to save source .mtl from .dccmtl file: %s", relativeDccMaterialPath.c_str()); - } -} - -/////////////////////////////////////////////////////////////////////////// -// Compares the hash values from .dccmtl and source .mtl to determine if -// .dccmtl has changed and needs to be saved. -bool CMaterialManager::DccMaterialRequiresSave(const AZStd::string& relativeDccMaterialPath, const AZStd::string& fullSourcePath) -{ - // __________________________________________________ - // Get Source Hash - - AZ::u32 sourceHash = 0; - - // Check if material is already loaded - QString unifiedName = UnifyMaterialName(QString(relativeDccMaterialPath.c_str())); - CMaterial* sourceMaterial = (CMaterial*)FindItemByName(unifiedName); - - if (sourceMaterial && !sourceMaterial->IsDummy()) - { - sourceHash = sourceMaterial->GetDccMaterialHash(); - } - else - { - XmlNodeRef sourceNode = GetISystem()->LoadXmlFromFile(fullSourcePath.c_str()); - if (sourceNode) - { - sourceNode->getAttr("DccMaterialHash", sourceHash); - } - else - { - // Couldn't find source node or material, so we need to save the dcc material as a source material - // No need to check the dcc material hash, just return true - return true; - } - } - - // __________________________________________________ - // Get DCC material Hash - - AZ::u32 dccHash = 0; - XmlNodeRef dccNode = GetISystem()->LoadXmlFromFile(relativeDccMaterialPath.c_str()); - - if (!dccNode) - { - AZ_Error("MaterialManager", false, "CMaterialManager::DccMaterialRequiresSave: Failed to load XML node from .dccmtl file: %s", relativeDccMaterialPath.c_str()); - return false; - } - - dccNode->getAttr("DccMaterialHash", dccHash); - - // __________________________________________________ - // Compare hash values - - // Only update if .dccmtl hash is different from the source hash - return (dccHash != sourceHash); -} - diff --git a/Code/Sandbox/Editor/Material/MaterialManager.h b/Code/Sandbox/Editor/Material/MaterialManager.h deleted file mode 100644 index a9dcabfa40..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialManager.h +++ /dev/null @@ -1,300 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H -#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H -#pragma once - -#include "BaseLibraryManager.h" -#include "Material.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -class CMaterial; -class CMaterialLibrary; -class CMaterialHighlighter; - -namespace AZ -{ - struct Uuid; -} - -namespace AzToolsFramework -{ - namespace AssetBrowser - { - struct SourceFileOpenerDetails; - typedef AZStd::vector SourceFileOpenerList; - } -} - -enum EHighlightMode -{ - eHighlight_Pick = BIT(0), - eHighlight_Breakable = BIT(1), - eHighlight_NoSurfaceType = BIT(2), - eHighlight_All = 0xFFFFFFFF -}; - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -/** Manages all entity prototypes and material libraries. -*/ -class CRYEDIT_API CMaterialManager - : public IEditorMaterialManager - , public CBaseLibraryManager - , public IMaterialManagerListener - , protected AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - , public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler - , public AzFramework::AssetCatalogEventBus::Handler - , public AzToolsFramework::EditorEvents::Bus::Handler -{ -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - - //! Notification callback. - typedef AZStd::function NotifyCallback; - - CMaterialManager(CRegistrationContext& regCtx); - ~CMaterialManager(); - - void Set3DEngine(); - - // Clear all prototypes and material libraries. - void ClearAll(); - - ////////////////////////////////////////////////////////////////////////// - // Materials. - ////////////////////////////////////////////////////////////////////////// - - // Loads material. - CMaterial* LoadMaterial(const QString& sMaterialName, bool bMakeIfNotFound = true); - XmlNodeRef LoadXmlNode(const QString &fullSourcePath, const QString &relativeFilePath); - //! Loads a material, avoiding a call to CMaterialManager::MaterialToFilename if the full path is already known - CMaterial* LoadMaterialWithFullSourcePath(const QString& relativeFilePath, const QString& fullSourcePath, bool makeIfNotFound = true); - virtual CMaterial* LoadMaterial(const char* sMaterialName, bool bMakeIfNotFound = true); - virtual void OnRequestMaterial(_smart_ptr pMaterial); - // Creates a new material from a xml node. - CMaterial* CreateMaterial(const QString& sMaterialName, const XmlNodeRef& node = XmlNodeRef(), int nMtlFlags = 0, unsigned long nLoadingFlags = 0); - virtual CMaterial* CreateMaterial(const char* sMaterialName, const XmlNodeRef& node = XmlNodeRef(), int nMtlFlags = 0, unsigned long nLoadingFlags = 0); - - // Duplicate material and do nothing more. - CMaterial* DuplicateMaterial(const char* newName, CMaterial* pOriginal); - - // Delete specified material, erases material file, and unassigns from all objects. - virtual void DeleteMaterial(CMaterial* pMtl); - virtual void RemoveMaterialFromDisk(const char* fileName); - - - //! Export property manager to game. - void Export(XmlNodeRef& node); - int ExportLib(CMaterialLibrary* pLib, XmlNodeRef& libNode); - - virtual void SetSelectedItem(IDataBaseItem* pItem); - void SetCurrentMaterial(CMaterial* pMtl); - //! Get currently active material. - CMaterial* GetCurrentMaterial() const; - - void SetCurrentFolder(const QString& folder); - - // This material will be highlighted - void SetHighlightedMaterial(CMaterial* pMtl); - void GetHighlightColor(ColorF* color, float* intensity, int flags); - void HighlightedMaterialChanged(CMaterial* pMtl); - // highlightMask is a combination of EHighlightMode flags - void SetHighlightMask(int highlightMask); - int GetHighlightMask() const{ return m_highlightMask; } - void SetMarkedMaterials(const std::vector<_smart_ptr >& markedMaterials); - void OnLoadShader(CMaterial* pMaterial); - - //! Serialize property manager. - virtual void Serialize(XmlNodeRef& node, bool bLoading); - - virtual void SaveAllLibs(); - - ////////////////////////////////////////////////////////////////////////// - // IMaterialManagerListener implementation - ////////////////////////////////////////////////////////////////////////// - // Called when material manager tries to load a material. - virtual void OnCreateMaterial(_smart_ptr pMaterial); - virtual void OnDeleteMaterial(_smart_ptr pMaterial); - virtual bool IsCurrentMaterial(_smart_ptr pMaterial) const; - ////////////////////////////////////////////////////////////////////////// - - // Convert filename of material file into the name of the material. - QString FilenameToMaterial(const QString& filename); - - // Convert name of the material to the filename. - QString MaterialToFilename(const QString& sMaterialName); - - //! Get the full file path of the source material - const AZ::Data::AssetType& GetMaterialAssetType(); - - ////////////////////////////////////////////////////////////////////////// - // Convert 3DEngine IMaterial to Editor's CMaterial pointer. - CMaterial* FromIMaterial(_smart_ptr pMaterial); - - // Open File selection dialog to create a new material. - CMaterial* SelectNewMaterial(int nMtlFlags, const char* sStartPath = NULL); - - // Synchronize material between 3dsMax and editor. - void SyncMaterialEditor(); - - ////////////////////////////////////////////////////////////////////////// - void GotoMaterial(CMaterial* pMaterial); - void GotoMaterial(_smart_ptr pMaterial); - - // Gather resources from the game material. - static void GatherResources(_smart_ptr pMaterial, CUsedResources& resources); - - void Command_Create(); - void Command_CreateMulti(); - void Command_ConvertToMulti(); - void Command_Duplicate(); - void Command_Merge(); - void Command_Delete(); - void Command_AssignToSelection(); - void Command_ResetSelection(); - void Command_SelectAssignedObjects(); - void Command_SelectFromObject(); - -protected: - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // protected AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler - void AddSourceFileOpeners(const char* fullSourceFileName, const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) override; - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationsBus::Handler - void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry); - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // AssetCatalogEventBus Functions - void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override; - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // EditorEventsBus Functions - bool SkipEditorStartupUI() override; - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - void SaveDccMaterial(const AZStd::string& relativeDccMaterialPath); - bool DccMaterialRequiresSave(const AZStd::string& relativeDccMaterialPath, const AZStd::string& fullSourcePath); - void DccMaterialSourceControlCheck(const AZStd::string& relativeDccMaterialPath); - void AddDccMaterialPath(const AZStd::string relativeDccMaterialPath); - void TickSourceControl(); - void QueueSourceControlTick(); - - // Duplicate the source material and set it as a submaterial of the target material at subMaterialIndex. Returns true if successful. - bool DuplicateAsSubMaterialAtIndex(CMaterial* pSourceMaterial, CMaterial* pTargetMaterial, int subMaterialIndex); - // Generates a unique variant of the name of the source material to resolve name collisions with the names of the submaterials in the target material. - void GenerateUniqueSubmaterialName(const CMaterial* pSourceMaterial, const CMaterial* pTargetMaterial, QString& uniqueSubmaterialName) const; - - // Open save as dialog for saving materials. - bool SelectSaveMaterial(QString& itemName, QString& fullPath, const char* defaultStartPath); - - void OnEditorNotifyEvent(EEditorNotifyEvent event); - - virtual CBaseLibraryItem* MakeNewItem(); - virtual CBaseLibrary* MakeNewLibrary(); - //! Root node where this library will be saved. - virtual QString GetRootNodeName(); - //! Path to libraries in this manager. - virtual QString GetLibsPath(); - virtual void ReportDuplicateItem(CBaseLibraryItem* pItem, CBaseLibraryItem* pOldItem); - - void RegisterCommands(CRegistrationContext& regCtx); - - void UpdateHighlightedMaterials(); - void AddForHighlighting(CMaterial* pMaterial); - void RemoveFromHighlighting(CMaterial* pMaterial, int mask); - int GetHighlightFlags(CMaterial* pMaterial) const; - - // For material syncing with 3dsMax. - void PickPreviewMaterial(); - void InitMatSender(); - - //! Reloads any registered materials that have been modified by the runtime. - void ReloadDirtyMaterials(); - -protected: - QString m_libsPath; - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - // Currently selected (focused) material, in material browser. - _smart_ptr m_pCurrentMaterial; - // current selected folder - QString m_currentFolder; - // List of materials selected in material browser tree. - std::vector<_smart_ptr > m_markedMaterials; - // IMaterial is needed to not let 3Dengine release selected IMaterial - _smart_ptr m_pCurrentEngineMaterial; - - // Paths of .dccmtl that might require saving. They will be fed to - // DccMaterialSourceControlCheck() and if saving is required, they - // will be added to m_dccMaterialSaveBuffer - AZStd::vector m_sourceControlBuffer; - AZStd::mutex m_sourceControlBufferMutex; - AZStd::atomic_bool m_sourceControlFunctionQueued; - - // Paths of .dccmtl that require saving. These paths have - // gone through DccMaterialSourceControlCheck() and will - // be saved by the dcc material save thread - AZStd::vector m_dccMaterialSaveBuffer; - AZStd::mutex m_dccMaterialSaveMutex; - - // Material highlighting - _smart_ptr m_pHighlightMaterial; - CMaterialHighlighter* m_pHighlighter; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - int m_highlightMask; - - bool m_bHighlightingMaterial; - - // Only begin processing .dccmtl filepaths once editor is ready - // and we can display appropriate error messages - bool m_bEditorUiReady; - - // Only report source control error to the user once, - // no need to spam them for every material - bool m_bSourceControlErrorReported; - - class CMaterialSender* m_MatSender; - -private: - CMaterial* LoadMaterialInternal(const QString &materialNameClear, const QString &fullSourcePath, const QString &relativeFilePath, bool bMakeIfNotFound); - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - AZ::Data::AssetType m_materialAssetType; - AZ::Data::AssetType m_dccMaterialAssetType; - - void StartDccMaterialSaveThread(); - void DccMaterialSaveThreadFunc(); - AZStd::thread m_dccMaterialSaveThread; - AZStd::atomic_bool m_joinThreads; - AZStd::binary_semaphore m_dccMaterialSaveSemaphore; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALMANAGER_H diff --git a/Code/Sandbox/Editor/Material/MaterialPreviewModelView.cpp b/Code/Sandbox/Editor/Material/MaterialPreviewModelView.cpp deleted file mode 100644 index 3e1bc37c6a..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPreviewModelView.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "EditorDefs.h" - -#include "MaterialPreviewModelView.h" - - - -MaterialPreviewModelView::MaterialPreviewModelView(QWidget* parent, bool enableIdleUpdate) - : CPreviewModelView(parent) - , m_enableIdleUpdate(enableIdleUpdate) -{} - -MaterialPreviewModelView::~MaterialPreviewModelView() -{} - -void MaterialPreviewModelView::SetCameraLookAt(float fRadiusScale, const Vec3& fromDir) -{ - IStatObj* target = GetStaticModel(); - if (target) - { - Vec3 dir = fromDir.GetNormalized(); - - // Calculate the camera matrix - Matrix34 tm = Matrix33::CreateRotationVDir(dir, 0); - Vec3 translation = target->GetAABB().GetCenter() - dir * target->GetAABB().GetRadius() * fRadiusScale; - tm.SetTranslation(translation); - - // Convert it to a quaternion and move the viewport's camera - QuatT quat(tm); - CameraMoved(quat, true); - } -} - -void MaterialPreviewModelView::SetMaterial(_smart_ptr material) -{ - IStatObj* staticModel = GetStaticModel(); - if (staticModel) - { - staticModel->SetMaterial(material); - } -} - -void MaterialPreviewModelView::resizeEvent(QResizeEvent* event) -{ - if (m_enableIdleUpdate) - { - CPreviewModelView::resizeEvent(event); - } -} - -void MaterialPreviewModelView::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnIdleUpdate: - { - if (m_enableIdleUpdate) - { - Update(); - } - break; - } - default: - break; - } -} diff --git a/Code/Sandbox/Editor/Material/MaterialPreviewModelView.h b/Code/Sandbox/Editor/Material/MaterialPreviewModelView.h deleted file mode 100644 index 0df7c1767f..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPreviewModelView.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include "PreviewModelView.h" - -class MaterialPreviewModelView - : public CPreviewModelView -{ -public: - // set enableIdleUpdate to false if you don't want the view to update itself during - // application idle notification (and resize events). That makes sense when this view - // is only used to render into memory bitmaps. Note that the view has to been visible - // for that, but can be somewhere of-screen. - MaterialPreviewModelView(QWidget* parent, bool enableIdleUpdate = true); - virtual ~MaterialPreviewModelView(); - void SetCameraLookAt(float fRadiusScale, const Vec3& fromDir); - void SetMaterial(_smart_ptr material); - void OnEditorNotifyEvent(EEditorNotifyEvent event) override; - -protected: - void resizeEvent(QResizeEvent* event) override; - -private: - bool m_enableIdleUpdate; -}; diff --git a/Code/Sandbox/Editor/Material/MaterialPythonFuncs.cpp b/Code/Sandbox/Editor/Material/MaterialPythonFuncs.cpp deleted file mode 100644 index 5de75a7c39..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPythonFuncs.cpp +++ /dev/null @@ -1,2208 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Material support for Python - -#include "EditorDefs.h" - -#include "MaterialPythonFuncs.h" - -// Editor -#include "MaterialManager.h" -#include "ShaderEnum.h" - - -namespace -{ - void PyMaterialCreate() - { - GetIEditor()->GetMaterialManager()->Command_Create(); - } - - void PyMaterialCreateMulti() - { - GetIEditor()->GetMaterialManager()->Command_CreateMulti(); - } - - void PyMaterialConvertToMulti() - { - GetIEditor()->GetMaterialManager()->Command_ConvertToMulti(); - } - - void PyMaterialDuplicateCurrent() - { - GetIEditor()->GetMaterialManager()->Command_Duplicate(); - } - - void PyMaterialMergeSelection() - { - GetIEditor()->GetMaterialManager()->Command_Merge(); - } - - void PyMaterialDeleteCurrent() - { - GetIEditor()->GetMaterialManager()->Command_Delete(); - } - - void PyMaterialAssignCurrentToSelection() - { - CUndo undo("Assign Material To Selection"); - GetIEditor()->GetMaterialManager()->Command_AssignToSelection(); - } - - void PyMaterialResetSelection() - { - GetIEditor()->GetMaterialManager()->Command_ResetSelection(); - } - - void PyMaterialSelectObjectsWithCurrent() - { - CUndo undo("Select Objects With Current Material"); - GetIEditor()->GetMaterialManager()->Command_SelectAssignedObjects(); - } - - void PyMaterialSetCurrentFromObject() - { - GetIEditor()->GetMaterialManager()->Command_SelectFromObject(); - } - - AZStd::vector PyGetSubMaterial(const char* pMaterialPath) - { - QString materialPath = pMaterialPath; - CMaterial* pMaterial = GetIEditor()->GetMaterialManager()->LoadMaterial(pMaterialPath, false); - if (!pMaterial) - { - throw std::runtime_error("Invalid multi material."); - } - - AZStd::vector result; - for (int i = 0; i < pMaterial->GetSubMaterialCount(); i++) - { - if (pMaterial->GetSubMaterial(i)) - { - result.push_back((materialPath + "\\" + pMaterial->GetSubMaterial(i)->GetName()).toUtf8().data()); - } - } - return result; - } - - CMaterial* TryLoadingMaterial(const char* pPathAndMaterialName) - { - QString varMaterialPath = pPathAndMaterialName; - std::deque splittedMaterialPath; - for (auto token : varMaterialPath.split(QRegularExpression(R"([\\/])"), Qt::SkipEmptyParts)) - { - splittedMaterialPath.push_back(token); - } - - CMaterial* pMaterial = GetIEditor()->GetMaterialManager()->LoadMaterial(varMaterialPath, false); - if (!pMaterial) - { - QString subMaterialName = splittedMaterialPath.back(); - bool isSubMaterialExist(false); - - varMaterialPath.remove((varMaterialPath.length() - subMaterialName.length() - 1), varMaterialPath.length()); - QString test = varMaterialPath; - pMaterial = GetIEditor()->GetMaterialManager()->LoadMaterial(varMaterialPath, false); - - if (!pMaterial) - { - throw std::runtime_error("Invalid multi material."); - } - - for (int i = 0; i < pMaterial->GetSubMaterialCount(); i++) - { - if (pMaterial->GetSubMaterial(i)->GetName() == subMaterialName) - { - pMaterial = pMaterial->GetSubMaterial(i); - isSubMaterialExist = true; - } - } - - if (!pMaterial || !isSubMaterialExist) - { - throw std::runtime_error((QString("\"") + subMaterialName + "\" is an invalid sub material.").toUtf8().data()); - } - } - GetIEditor()->GetMaterialManager()->SetCurrentMaterial(pMaterial); - return pMaterial; - } - - std::deque PreparePropertyPath(const char* pPathAndPropertyName) - { - QString varPathProperty = pPathAndPropertyName; - std::deque splittedPropertyPath; - for (auto token : varPathProperty.split(QRegularExpression(R"([\\/])"), Qt::SkipEmptyParts)) - { - splittedPropertyPath.push_back(token); - } - - return splittedPropertyPath; - } - - ////////////////////////////////////////////////////////////////////////// - // Converter: Enum -> CString (human readable) - ////////////////////////////////////////////////////////////////////////// - - QString TryConvertingSEFResTextureToCString(SEfResTexture* pResTexture) - { - if (pResTexture) - { - return pResTexture->m_Name.c_str(); - } - return ""; - } - - QString TryConvertingETEX_TypeToCString(const uint8& texTypeName) - { - switch (texTypeName) - { - case eTT_2D: - return "2D"; - case eTT_Cube: - return "Cube-Map"; - case eTT_NearestCube: - return "Nearest Cube-Map probe for alpha blended"; - case eTT_Auto2D: - return "Auto 2D-Map"; - case eTT_Dyn2D: - return "Dynamic 2D-Map"; - case eTT_User: - return "From User Params"; - default: - throw std::runtime_error("Invalid tex type."); - } - } - - QString TryConvertingTexFilterToCString(const int& iFilterName) - { - switch (iFilterName) - { - case FILTER_NONE: - return "Default"; - case FILTER_POINT: - return "Point"; - case FILTER_LINEAR: - return "Linear"; - case FILTER_BILINEAR: - return "Bilinear"; - case FILTER_TRILINEAR: - return "Trilinear"; - case FILTER_ANISO2X: - return "Anisotropic 2x"; - case FILTER_ANISO4X: - return "Anisotropic 4x"; - case FILTER_ANISO8X: - return "Anisotropic 8x"; - case FILTER_ANISO16X: - return "Anisotropic 16x"; - default: - throw std::runtime_error("Invalid tex filter."); - } - } - - QString TryConvertingETexGenTypeToCString(const uint8& texGenType) - { - switch (texGenType) - { - case ETG_Stream: - return "Stream"; - case ETG_World: - return "World"; - case ETG_Camera: - return "Camera"; - default: - throw std::runtime_error("Invalid tex gen type."); - } - } - - QString TryConvertingETexModRotateTypeToCString(const uint8& rotateType) - { - switch (rotateType) - { - case ETMR_NoChange: - return "No Change"; - case ETMR_Fixed: - return "Fixed Rotation"; - case ETMR_Constant: - return "Constant Rotation"; - case ETMR_Oscillated: - return "Oscillated Rotation"; - default: - throw std::runtime_error("Invalid rotate type."); - } - } - - QString TryConvertingETexModMoveTypeToCString(const uint8& oscillatorType) - { - switch (oscillatorType) - { - case ETMM_NoChange: - return "No Change"; - case ETMM_Fixed: - return "Fixed Moving"; - case ETMM_Constant: - return "Constant Moving"; - case ETMM_Jitter: - return "Jitter Moving"; - case ETMM_Pan: - return "Pan Moving"; - case ETMM_Stretch: - return "Stretch Moving"; - case ETMM_StretchRepeat: - return "Stretch-Repeat Moving"; - default: - throw std::runtime_error("Invalid oscillator type."); - } - } - - QString TryConvertingEDeformTypeToCString(const EDeformType& deformType) - { - switch (deformType) - { - case eDT_Unknown: - return "None"; - case eDT_SinWave: - return "Sin Wave"; - case eDT_SinWaveUsingVtxColor: - return "Sin Wave using vertex color"; - case eDT_Bulge: - return "Bulge"; - case eDT_Squeeze: - return "Squeeze"; - case eDT_Perlin2D: - return "Perlin 2D"; - case eDT_Perlin3D: - return "Perlin 3D"; - case eDT_FromCenter: - return "From Center"; - case eDT_Bending: - return "Bending"; - case eDT_ProcFlare: - return "Proc. Flare"; - case eDT_AutoSprite: - return "Auto sprite"; - case eDT_Beam: - return "Beam"; - case eDT_FixedOffset: - return "FixedOffset"; - default: - throw std::runtime_error("Invalid deform type."); - } - } - - QString TryConvertingEWaveFormToCString(const EWaveForm& waveForm) - { - switch (waveForm) - { - case eWF_None: - return "None"; - case eWF_Sin: - return "Sin"; - case eWF_HalfSin: - return "Half Sin"; - case eWF_Square: - return "Square"; - case eWF_Triangle: - return "Triangle"; - case eWF_SawTooth: - return "Saw Tooth"; - case eWF_InvSawTooth: - return "Inverse Saw Tooth"; - case eWF_Hill: - return "Hill"; - case eWF_InvHill: - return "Inverse Hill"; - default: - throw std::runtime_error("Invalid wave form."); - } - } - - ////////////////////////////////////////////////////////////////////////// - // Converter: CString -> Enum - ////////////////////////////////////////////////////////////////////////// - - template - // [Shader System TO DO] remove once dynamic slots assingment is in place - EEfResTextures TryConvertingCStringToEEfResTextures(const STRING& resTextureName) - { - if (resTextureName == "Diffuse") - { - return EFTT_DIFFUSE; - } - else if (resTextureName == "Specular") - { - return EFTT_SPECULAR; - } - else if (resTextureName == "Bumpmap") - { - return EFTT_NORMALS; - } - else if (resTextureName == "Heightmap") - { - return EFTT_HEIGHT; - } - else if (resTextureName == "Environment") - { - return EFTT_ENV; - } - else if (resTextureName == "Detail") - { - return EFTT_DETAIL_OVERLAY; - } - else if (resTextureName == "Opacity") - { - return EFTT_OPACITY; - } - else if (resTextureName == "Decal") - { - return EFTT_DECAL_OVERLAY; - } - else if (resTextureName == "SubSurface") - { - return EFTT_SUBSURFACE; - } - else if (resTextureName == "Custom") - { - return EFTT_CUSTOM; - } - else if (resTextureName == "[1] Custom") - { - return EFTT_DIFFUSE; - } - else if (resTextureName == "Emittance") - { - return EFTT_EMITTANCE; - } - else if (resTextureName == "Occlusion") - { - return EFTT_OCCLUSION; - } - else if (resTextureName == "Specular2") - { - return EFTT_SPECULAR_2; - } - throw std::runtime_error("Invalid texture name."); - } - - template - ETEX_Type TryConvertingCStringToETEX_Type(const STRING& texTypeName) - { - if (texTypeName == "2D") - { - return eTT_2D; - } - else if (texTypeName == "Cube-Map") - { - return eTT_Cube; - } - else if (texTypeName == "Nearest Cube-Map probe for alpha blended") - { - return eTT_NearestCube; - } - else if (texTypeName == "Auto 2D-Map") - { - return eTT_Auto2D; - } - else if (texTypeName == "Dynamic 2D-Map") - { - return eTT_Dyn2D; - } - else if (texTypeName == "From User Params") - { - return eTT_User; - } - throw std::runtime_error("Invalid tex type name."); - } - - template - signed char TryConvertingCStringToTexFilter(const STRING& filterName) - { - if (filterName == "Default") - { - return FILTER_NONE; - } - else if (filterName == "Point") - { - return FILTER_POINT; - } - else if (filterName == "Linear") - { - return FILTER_LINEAR; - } - else if (filterName == "Bilinear") - { - return FILTER_BILINEAR; - } - else if (filterName == "Trilinear") - { - return FILTER_TRILINEAR; - } - else if (filterName == "Anisotropic 2x") - { - return FILTER_ANISO2X; - } - else if (filterName == "Anisotropic 4x") - { - return FILTER_ANISO4X; - } - else if (filterName == "Anisotropic 8x") - { - return FILTER_ANISO8X; - } - else if (filterName == "Anisotropic 16x") - { - return FILTER_ANISO16X; - } - throw std::runtime_error("Invalid filter name."); - } - - template - ETexGenType TryConvertingCStringToETexGenType(const STRING& texGenType) - { - if (texGenType == "Stream") - { - return ETG_Stream; - } - else if (texGenType == "World") - { - return ETG_World; - } - else if (texGenType == "Camera") - { - return ETG_Camera; - } - throw std::runtime_error("Invalid tex gen type name."); - } - - template - ETexModRotateType TryConvertingCStringToETexModRotateType(const STRING& rotateType) - { - if (rotateType == "No Change") - { - return ETMR_NoChange; - } - else if (rotateType == "Fixed Rotation") - { - return ETMR_Fixed; - } - else if (rotateType == "Constant Rotation") - { - return ETMR_Constant; - } - else if (rotateType == "Oscillated Rotation") - { - return ETMR_Oscillated; - } - throw std::runtime_error("Invalid rotate type name."); - } - - template - ETexModMoveType TryConvertingCStringToETexModMoveType(const STRING& oscillatorType) - { - if (oscillatorType == "No Change") - { - return ETMM_NoChange; - } - else if (oscillatorType == "Fixed Moving") - { - return ETMM_Fixed; - } - else if (oscillatorType == "Constant Moving") - { - return ETMM_Constant; - } - else if (oscillatorType == "Jitter Moving") - { - return ETMM_Jitter; - } - else if (oscillatorType == "Pan Moving") - { - return ETMM_Pan; - } - else if (oscillatorType == "Stretch Moving") - { - return ETMM_Stretch; - } - else if (oscillatorType == "Stretch-Repeat Moving") - { - return ETMM_StretchRepeat; - } - throw std::runtime_error("Invalid oscillator type."); - } - - template - EDeformType TryConvertingCStringToEDeformType(const STRING& deformType) - { - if (deformType == "None") - { - return eDT_Unknown; - } - else if (deformType == "Sin Wave") - { - return eDT_SinWave; - } - else if (deformType == "Sin Wave using vertex color") - { - return eDT_SinWaveUsingVtxColor; - } - else if (deformType == "Bulge") - { - return eDT_Bulge; - } - else if (deformType == "Squeeze") - { - return eDT_Squeeze; - } - else if (deformType == "Perlin 2D") - { - return eDT_Perlin2D; - } - else if (deformType == "Perlin 3D") - { - return eDT_Perlin3D; - } - else if (deformType == "From Center") - { - return eDT_FromCenter; - } - else if (deformType == "Bending") - { - return eDT_Bending; - } - else if (deformType == "Proc. Flare") - { - return eDT_ProcFlare; - } - else if (deformType == "Auto sprite") - { - return eDT_AutoSprite; - } - else if (deformType == "Beam") - { - return eDT_Beam; - } - else if (deformType == "FixedOffset") - { - return eDT_FixedOffset; - } - throw std::runtime_error("Invalid deform type."); - } - - template - EWaveForm TryConvertingCStringToEWaveForm(const STRING& waveForm) - { - if (waveForm == "None") - { - return eWF_None; - } - else if (waveForm == "Sin") - { - return eWF_Sin; - } - else if (waveForm == "Half Sin") - { - return eWF_HalfSin; - } - else if (waveForm == "Square") - { - return eWF_Square; - } - else if (waveForm == "Triangle") - { - return eWF_Triangle; - } - else if (waveForm == "Saw Tooth") - { - return eWF_SawTooth; - } - else if (waveForm == "Inverse Saw Tooth") - { - return eWF_InvSawTooth; - } - else if (waveForm == "Hill") - { - return eWF_Hill; - } - else if (waveForm == "Inverse Hill") - { - return eWF_InvHill; - } - throw std::runtime_error("Invalid wave form."); - } - - ////////////////////////////////////////////////////////////////////////// - // Script parser - ////////////////////////////////////////////////////////////////////////// - - QString ParseUINameFromPublicParamsScript(const char* sUIScript) - { - string uiscript = sUIScript; - string element[3]; - int p1 = 0; - string itemToken = uiscript.Tokenize(";", p1); - while (!itemToken.empty()) - { - int nElements = 0; - int p2 = 0; - string token = itemToken.Tokenize(" \t\r\n=", p2); - while (!token.empty()) - { - element[nElements++] = token; - if (nElements == 2) - { - element[nElements] = itemToken.substr(p2); - element[nElements].Trim(" =\t\""); - break; - } - token = itemToken.Tokenize(" \t\r\n=", p2); - } - - if (_stricmp(element[1], "UIName") == 0) - { - return element[2].c_str(); - } - itemToken = uiscript.Tokenize(";", p1); - } - return ""; - } - - std::map ParseValidRangeFromPublicParamsScript(const char* sUIScript) - { - string uiscript = sUIScript; - std::map result; - bool isUIMinExist(false); - bool isUIMaxExist(false); - string element[3]; - int p1 = 0; - string itemToken = uiscript.Tokenize(";", p1); - while (!itemToken.empty()) - { - int nElements = 0; - int p2 = 0; - string token = itemToken.Tokenize(" \t\r\n=", p2); - while (!token.empty()) - { - element[nElements++] = token; - if (nElements == 2) - { - element[nElements] = itemToken.substr(p2); - element[nElements].Trim(" =\t\""); - break; - } - token = itemToken.Tokenize(" \t\r\n=", p2); - } - - if (_stricmp(element[1], "UIMin") == 0) - { - result["UIMin"] = atof(element[2]); - isUIMinExist = true; - } - if (_stricmp(element[1], "UIMax") == 0) - { - result["UIMax"] = atof(element[2]); - isUIMaxExist = true; - } - itemToken = uiscript.Tokenize(";", p1); - } - if (!isUIMinExist || !isUIMaxExist) - { - throw std::runtime_error("Invalid range for shader param."); - } - return result; - } - - ////////////////////////////////////////////////////////////////////////// - // Set Flags - ////////////////////////////////////////////////////////////////////////// - - void SetMaterialFlag(CMaterial* pMaterial, const EMaterialFlags& eFlag, const bool& bFlag) - { - if (pMaterial->GetFlags() & eFlag && bFlag == false) - { - pMaterial->SetFlags(pMaterial->GetFlags() - eFlag); - } - else if (!(pMaterial->GetFlags() & eFlag) && bFlag == true) - { - pMaterial->SetFlags(pMaterial->GetFlags() | eFlag); - } - } - - void SetPropagationFlag(CMaterial* pMaterial, const eMTL_PROPAGATION& eFlag, const bool& bFlag) - { - if (pMaterial->GetPropagationFlags() & eFlag && bFlag == false) - { - pMaterial->SetPropagationFlags(pMaterial->GetPropagationFlags() - eFlag); - } - else if (!(pMaterial->GetPropagationFlags() & eFlag) && bFlag == true) - { - pMaterial->SetPropagationFlags(pMaterial->GetPropagationFlags() | eFlag); - } - } - - ////////////////////////////////////////////////////////////////////////// - template - bool IsAnyValidRange(const AZStd::any& value, const T& low, const T& high, const QString& invalidTypeMessage, const QString& invalidValueMessage) - { - static_assert(AZStd::is_arithmetic::value, "This function only works with numbers."); - - if (!value.is()) - { - throw std::runtime_error(invalidTypeMessage.toUtf8().data()); - } - - T valueData; - AZStd::any_numeric_cast(&value, valueData); - if (valueData < low || valueData > high) - { - throw std::runtime_error(invalidValueMessage.toUtf8().data()); - } - return true; - } - - template <> - bool IsAnyValidRange(const AZStd::any& value, const AZ::Color& low, const AZ::Color& high, const QString& invalidTypeMessage, const QString& invalidValueMessage) - { - if (!value.is()) - { - throw std::runtime_error(invalidTypeMessage.toUtf8().data()); - } - - const AZ::Color* valueData = AZStd::any_cast(&value); - if (!valueData) - { - throw std::runtime_error(invalidValueMessage.toUtf8().data()); - } - - if (valueData->IsLessThan(low) || valueData->IsGreaterThan(high)) - { - throw std::runtime_error(invalidValueMessage.toUtf8().data()); - } - return true; - } - - bool ValidateProperty(CMaterial* pMaterial, const std::deque& splittedPropertyPathParam, const AZStd::any& value) - { - std::deque splittedPropertyPath = splittedPropertyPathParam; - std::deque splittedPropertyPathSubCategory = splittedPropertyPathParam; - QString categoryName = splittedPropertyPath.front(); - QString subCategoryName = ""; - QString subSubCategoryName = ""; - QString currentPath = ""; - QString propertyName = splittedPropertyPath.back(); - - QString errorMsgInvalidValue = QString("Invalid value for property \"") + propertyName + "\""; - QString errorMsgInvalidDataType = QString("Invalid data type for property \"") + propertyName + "\""; - QString errorMsgInvalidPropertyPath = QString("Invalid property path"); - - const int iMinColorValue = 0; - const int iMaxColorValue = 255; - - if (splittedPropertyPathSubCategory.size() == 3) - { - splittedPropertyPathSubCategory.pop_back(); - subCategoryName = splittedPropertyPathSubCategory.back(); - currentPath = QString("") + categoryName + "/" + subCategoryName; - - if ( - subCategoryName != "TexType" && - subCategoryName != "Filter" && - subCategoryName != "IsProjectedTexGen" && - subCategoryName != "TexGenType" && - subCategoryName != "Wave X" && - subCategoryName != "Wave Y" && - subCategoryName != "Wave Z" && - subCategoryName != "Wave W" && - subCategoryName != "Shader1" && - subCategoryName != "Shader2" && - subCategoryName != "Shader3" && - subCategoryName != "Tiling" && - subCategoryName != "Rotator" && - subCategoryName != "Oscillator" && - subCategoryName != "Diffuse" && - subCategoryName != "Specular" && - subCategoryName != "Bumpmap" && - subCategoryName != "Heightmap" && - subCategoryName != "Environment" && - subCategoryName != "Detail" && - subCategoryName != "Opacity" && - subCategoryName != "Decal" && - subCategoryName != "SubSurface" && - subCategoryName != "Custom" && - subCategoryName != "[1] Custom" - ) - { - throw std::runtime_error((errorMsgInvalidPropertyPath + " (" + currentPath + ")").toUtf8().data()); - } - } - else if (splittedPropertyPathSubCategory.size() == 4) - { - splittedPropertyPathSubCategory.pop_back(); - subCategoryName = splittedPropertyPathSubCategory.back(); - splittedPropertyPathSubCategory.pop_back(); - subSubCategoryName = splittedPropertyPathSubCategory.back(); - currentPath = categoryName + "/" + subSubCategoryName + "/" + subCategoryName; - - if ( - subSubCategoryName != "Diffuse" && - subSubCategoryName != "Specular" && - subSubCategoryName != "Bumpmap" && - subSubCategoryName != "Heightmap" && - subSubCategoryName != "Environment" && - subSubCategoryName != "Detail" && - subSubCategoryName != "Opacity" && - subSubCategoryName != "Decal" && - subSubCategoryName != "SubSurface" && - subSubCategoryName != "Custom" && - subSubCategoryName != "[1] Custom" - ) - { - throw std::runtime_error((errorMsgInvalidPropertyPath + " (" + currentPath + ")").toUtf8().data()); - } - else if (subCategoryName != "Tiling" && subCategoryName != "Rotator" && subCategoryName != "Oscillator") - { - throw std::runtime_error((errorMsgInvalidPropertyPath + " (" + currentPath + ")").toUtf8().data()); - } - } - else - { - currentPath = categoryName; - } - - if ( - categoryName == "Material Settings" || - categoryName == "Opacity Settings" || - categoryName == "Lighting Settings" || - categoryName == "Advanced" || - categoryName == "Texture Maps" || - categoryName == "Vertex Deformation" || - categoryName == "Layer Presets") - { - if (propertyName == "Opacity" || propertyName == "AlphaTest" || propertyName == "Glow Amount") - { - // int: 0 < x < 100 - if (!value.is()) - { - throw std::runtime_error(errorMsgInvalidDataType.toUtf8().data()); - } - - AZ::s64 valueData; - AZStd::any_numeric_cast(&value, valueData); - if (valueData < 0 || valueData > 100) - { - throw std::runtime_error(errorMsgInvalidValue.toUtf8().data()); - } - return true; - } - else if (propertyName == "Smoothness" || propertyName == "Glossiness") - { - // int: 0 < x < 255 - return IsAnyValidRange(value, 0, 255, errorMsgInvalidDataType, errorMsgInvalidValue); - } - else if (propertyName == "Specular Level") - { - // float: 0.0 < x < 4.0 - return IsAnyValidRange(value, 0.0, 4.0, errorMsgInvalidDataType, errorMsgInvalidValue); - } - else if ( - propertyName == "TileU" || - propertyName == "TileV" || - propertyName == "OffsetU" || - propertyName == "OffsetV" || - propertyName == "RotateU" || - propertyName == "RotateV" || - propertyName == "RotateW" || - propertyName == "Rate" || - propertyName == "Phase" || - propertyName == "Amplitude" || - propertyName == "CenterU" || - propertyName == "CenterV" || - propertyName == "RateU" || - propertyName == "RateV" || - propertyName == "PhaseU" || - propertyName == "PhaseV" || - propertyName == "AmplitudeU" || - propertyName == "AmplitudeV" || - propertyName == "Wave Length X" || - propertyName == "Wave Length Y" || - propertyName == "Wave Length Z" || - propertyName == "Wave Length W" || - propertyName == "Level" || - propertyName == "Amplitude" || - propertyName == "Phase" || - propertyName == "Frequency") - { - // float: 0.0 < x < 100.0 - return IsAnyValidRange(value, 0.0, 100.0, errorMsgInvalidDataType, errorMsgInvalidValue); - } - else if (propertyName == "Voxel Coverage") - { - // float: 0.0 < x < 1.0 - return IsAnyValidRange(value, 0.0, 1.0, errorMsgInvalidDataType, errorMsgInvalidValue); - } - else if (propertyName == "Emissive Intensity") - { - // float: 0.0 < x < 200.0 - return IsAnyValidRange(value, 0.0, 200.0, errorMsgInvalidDataType, errorMsgInvalidValue); - } - else if (propertyName == "Diffuse Color" || propertyName == "Specular Color" || propertyName == "Emissive Color") - { - // intVector(RGB): 0 < x < 255 - return IsAnyValidRange(value, AZ::Color::CreateZero(), AZ::Color::CreateOne(), errorMsgInvalidDataType, errorMsgInvalidValue); - } - else if ( - propertyName == "Link to Material" || - propertyName == "Surface Type" || - propertyName == "Diffuse" || - propertyName == "Specular" || - propertyName == "Bumpmap" || - propertyName == "Heightmap" || - propertyName == "Environment" || - propertyName == "Detail" || - propertyName == "Opacity" || - propertyName == "Decal" || - propertyName == "SubSurface" || - propertyName == "Custom" || - propertyName == "[1] Custom" || - propertyName == "TexType" || - propertyName == "Filter" || - propertyName == "TexGenType" || - propertyName == "Type" || - propertyName == "TypeU" || - propertyName == "TypeV") - { - // string - if (!value.is()) - { - throw std::runtime_error(errorMsgInvalidDataType.toUtf8().data()); - } - return true; - } - else if ( - propertyName == "Additive" || - propertyName == "Allow layer activation" || - propertyName == "2 Sided" || - propertyName == "No Shadow" || - propertyName == "Use Scattering" || - propertyName == "Hide After Breaking" || - propertyName == "Fog Volume Shading Quality High" || - propertyName == "Blend Terrain Color" || - propertyName == "Propagate Material Settings" || - propertyName == "Propagate Opacity Settings" || - propertyName == "Propagate Lighting Settings" || - propertyName == "Propagate Advanced Settings" || - propertyName == "Propagate Texture Maps" || - propertyName == "Propagate Shader Params" || - propertyName == "Propagate Shader Generation" || - propertyName == "Propagate Vertex Deformation" || - propertyName == "Propagate Layer Presets" || - propertyName == "IsProjectedTexGen" || - propertyName == "IsTileU" || - propertyName == "IsTileV" || - propertyName == "No Draw") - { - // bool - if (!value.is()) - { - throw std::runtime_error(errorMsgInvalidDataType.toUtf8().data()); - } - return true; - } - else if (propertyName == "Shader" || propertyName == "Shader1" || propertyName == "Shader2" || propertyName == "Shader3") - { - // string && valid shader - if (!value.is()) - { - throw std::runtime_error(errorMsgInvalidDataType.toUtf8().data()); - } - - CShaderEnum* pShaderEnum = GetIEditor()->GetShaderEnum(); - if (!pShaderEnum) - { - throw std::runtime_error("Shader enumerator corrupted."); - } - pShaderEnum->EnumShaders(); - for (int i = 0; i < pShaderEnum->GetShaderCount(); i++) - { - if (pShaderEnum->GetShader(i) == AZStd::any_cast(value).data()) - { - return true; - } - } - } - else if (propertyName == "Noise Scale") - { - // FloatVec: undefined < x < undefined - if (!value.is()) - { - throw std::runtime_error(errorMsgInvalidDataType.toUtf8().data()); - } - return true; - } - } - else if (categoryName == "Shader Params") - { - auto& shaderParams = pMaterial->GetShaderResources().m_ShaderParams; - for (int i = 0; i < shaderParams.size(); i++) - { - if (propertyName == ParseUINameFromPublicParamsScript(shaderParams[i].m_Script.c_str())) - { - if (shaderParams[i].m_Type == eType_FLOAT) - { - // float: valid range (from script) - float floatValue; - if (!AZStd::any_numeric_cast(&value, floatValue)) - { - throw std::runtime_error(errorMsgInvalidDataType.toUtf8().data()); - } - std::map range = ParseValidRangeFromPublicParamsScript(shaderParams[i].m_Script.c_str()); - if (floatValue < range["UIMin"] || floatValue > range["UIMax"]) - { - QString errorMsg; - errorMsg = QStringLiteral("Invalid value for shader param \"%1\" (min: %2, max: %3)").arg(propertyName).arg(range["UIMin"]).arg(range["UIMax"]); - throw std::runtime_error(errorMsg.toUtf8().data()); - } - return true; - } - else if (shaderParams[i].m_Type == eType_FCOLOR) - { - return IsAnyValidRange(value, AZ::Color::CreateZero(), AZ::Color::CreateOne(), errorMsgInvalidDataType, errorMsgInvalidValue); - } - } - } - } - else if (categoryName == "Shader Generation Params") - { - for (int i = 0; i < pMaterial->GetShaderGenParamsVars()->GetNumVariables(); i++) - { - if (propertyName == pMaterial->GetShaderGenParamsVars()->GetVariable(i)->GetHumanName()) - { - if (!value.is()) - { - throw std::runtime_error(errorMsgInvalidDataType.toUtf8().data()); - } - return true; - } - } - } - else - { - throw std::runtime_error((errorMsgInvalidPropertyPath + " (" + currentPath + ")").toUtf8().data()); - } - return false; - } - - ////////////////////////////////////////////////////////////////////////// - template - T PyFetchNumericType(const AZStd::any& value) - { - T numericValue; - AZStd::any_numeric_cast(&value, numericValue); - return numericValue; - } - - AZStd::any PyGetProperty(const char* pPathAndMaterialName, const char* pPathAndPropertyName) - { - CMaterial* pMaterial = TryLoadingMaterial(pPathAndMaterialName); - std::deque splittedPropertyPath = PreparePropertyPath(pPathAndPropertyName); - std::deque splittedPropertyPathCategory = splittedPropertyPath; - QString categoryName = splittedPropertyPath.front(); - QString subCategoryName = "None"; - QString subSubCategoryName = "None"; - QString propertyName = splittedPropertyPath.back(); - QString errorMsgInvalidPropertyPath = "Invalid property path."; - - if (splittedPropertyPathCategory.size() == 3) - { - splittedPropertyPathCategory.pop_back(); - subCategoryName = splittedPropertyPathCategory.back(); - } - else if (splittedPropertyPathCategory.size() == 4) - { - splittedPropertyPathCategory.pop_back(); - subCategoryName = splittedPropertyPathCategory.back(); - splittedPropertyPathCategory.pop_back(); - subSubCategoryName = splittedPropertyPathCategory.back(); - } - - // ########## Material Settings ########## - if (categoryName == "Material Settings") - { - if (propertyName == "Shader") - { - return AZStd::make_any(pMaterial->GetShaderName().toUtf8().data()); - } - else if (propertyName == "Surface Type") - { - QString stringValue = pMaterial->GetSurfaceTypeName(); - if (stringValue.startsWith("mat_")) - { - stringValue.remove(0, 4); - } - return AZStd::make_any(stringValue.toLatin1().data()); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid material setting.").toUtf8().data()); - } - } - // ########## Opacity Settings ########## - else if (categoryName == "Opacity Settings") - { - if (propertyName == "Opacity") - { - AZ::s64 intValue = aznumeric_cast(pMaterial->GetShaderResources().m_LMaterial.m_Opacity * 100.0f); - return AZStd::make_any(intValue); - } - else if (propertyName == "AlphaTest") - { - AZ::s64 intValue = aznumeric_cast(pMaterial->GetShaderResources().m_AlphaRef * 100.0f); - return AZStd::make_any(intValue); - } - else if (propertyName == "Additive") - { - return AZStd::make_any(pMaterial->GetFlags() & MTL_FLAG_ADDITIVE); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid opacity setting.").toUtf8().data()); - } - } - // ########## Lighting Settings ########## - else if (categoryName == "Lighting Settings") - { - if (propertyName == "Diffuse Color") - { - QColor col = ColorLinearToGamma(ColorF( - pMaterial->GetShaderResources().m_LMaterial.m_Diffuse.r, - pMaterial->GetShaderResources().m_LMaterial.m_Diffuse.g, - pMaterial->GetShaderResources().m_LMaterial.m_Diffuse.b)); - return AZStd::make_any(col.red(), col.green(), col.blue(), 1.0f); - } - else if (propertyName == "Specular Color") - { - QColor col = ColorLinearToGamma(ColorF( - pMaterial->GetShaderResources().m_LMaterial.m_Specular.r / pMaterial->GetShaderResources().m_LMaterial.m_Specular.a, - pMaterial->GetShaderResources().m_LMaterial.m_Specular.g / pMaterial->GetShaderResources().m_LMaterial.m_Specular.a, - pMaterial->GetShaderResources().m_LMaterial.m_Specular.b / pMaterial->GetShaderResources().m_LMaterial.m_Specular.a)); - return AZStd::make_any(col.red(), col.green(), col.blue(), 1.0f); - } - else if (propertyName == "Glossiness") - { - return AZStd::make_any(pMaterial->GetShaderResources().m_LMaterial.m_Smoothness); - } - else if (propertyName == "Specular Level") - { - return AZStd::make_any(pMaterial->GetShaderResources().m_LMaterial.m_Specular.a); - } - else if (propertyName == "Emissive Color") - { - QColor col = ColorLinearToGamma(ColorF( - pMaterial->GetShaderResources().m_LMaterial.m_Emittance.r, - pMaterial->GetShaderResources().m_LMaterial.m_Emittance.g, - pMaterial->GetShaderResources().m_LMaterial.m_Emittance.b)); - return AZStd::make_any(col.red(), col.green(), col.blue(), 1.0f); - } - else if (propertyName == "Emissive Intensity") - { - return AZStd::make_any(pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid lighting setting.").toUtf8().data()); - } - } - // ########## Advanced ########## - else if (categoryName == "Advanced") - { - if (propertyName == "Allow layer activation") - { - return AZStd::make_any(pMaterial->LayerActivationAllowed()); - } - else if (propertyName == "2 Sided") - { - return AZStd::make_any(pMaterial->GetFlags() & MTL_FLAG_2SIDED); - } - else if (propertyName == "No Shadow") - { - return AZStd::make_any(pMaterial->GetFlags() & MTL_FLAG_NOSHADOW); - } - else if (propertyName == "Use Scattering") - { - return AZStd::make_any(pMaterial->GetFlags() & MTL_FLAG_SCATTER); - } - else if (propertyName == "Hide After Breaking") - { - return AZStd::make_any(pMaterial->GetFlags() & MTL_FLAG_HIDEONBREAK); - } - else if (propertyName == "Fog Volume Shading Quality High") - { - return AZStd::make_any(pMaterial->GetFlags() & MTL_FLAG_FOG_VOLUME_SHADING_QUALITY_HIGH); - } - else if (propertyName == "Blend Terrain Color") - { - return AZStd::make_any(pMaterial->GetFlags() & MTL_FLAG_BLEND_TERRAIN); - } - else if (propertyName == "Voxel Coverage") - { - return AZStd::make_any(aznumeric_cast(pMaterial->GetShaderResources().m_VoxelCoverage) / 255.0f); - } - else if (propertyName == "Link to Material") - { - return AZStd::make_any(pMaterial->GetMatInfo()->GetMaterialLinkName()); - } - else if (propertyName == "Propagate Material Settings") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_MATERIAL_SETTINGS); - } - else if (propertyName == "Propagate Opacity Settings") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_OPACITY); - } - else if (propertyName == "Propagate Lighting Settings") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_LIGHTING); - } - else if (propertyName == "Propagate Advanced Settings") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_ADVANCED); - } - else if (propertyName == "Propagate Texture Maps") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_TEXTURES); - } - else if (propertyName == "Propagate Shader Params") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_SHADER_PARAMS); - } - else if (propertyName == "Propagate Shader Generation") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_SHADER_GEN); - } - else if (propertyName == "Propagate Vertex Deformation") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_VERTEX_DEF); - } - else if (propertyName == "Propagate Layer Presets") - { - return AZStd::make_any(pMaterial->GetPropagationFlags() & MTL_PROPAGATE_LAYER_PRESETS); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid advanced setting.").toUtf8().data()); - } - } - // ########## Texture Maps ########## - else if (categoryName == "Texture Maps") - { - SInputShaderResources& shaderResources = pMaterial->GetShaderResources(); - // ########## Texture Maps / [name] ########## - if (splittedPropertyPath.size() == 2) - { - uint16 nSlot = aznumeric_cast(TryConvertingCStringToEEfResTextures(propertyName)); - SEfResTexture* pTextureRes = shaderResources.GetTextureResource(nSlot); - if (!pTextureRes || pTextureRes->m_Name.empty()) - { - AZ_Warning("ShadersSystem", false, "PyGetProperty - Error: empty texture slot [%d] (or missing name) for material %s", - nSlot, pMaterial->GetName().toStdString().c_str()); - return AZStd::any(); - } - else - { - return AZStd::make_any(pTextureRes->m_Name); - } - } - // ########## Texture Maps / [TexType | Filter | IsProjectedTexGen | TexGenType ] ########## - else if (splittedPropertyPath.size() == 3) - { - SEfResTexture* pTextureRes = shaderResources.GetTextureResource(TryConvertingCStringToEEfResTextures(subCategoryName)); - if (pTextureRes) - { - if (propertyName == "TexType") - { - return AZStd::make_any(TryConvertingETEX_TypeToCString(pTextureRes->m_Sampler.m_eTexType).toLatin1().data()); - } - else if (propertyName == "Filter") - { - return AZStd::make_any(TryConvertingTexFilterToCString(pTextureRes->m_Filter).toLatin1().data()); - } - else if (propertyName == "IsProjectedTexGen") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_bTexGenProjected); - } - else if (propertyName == "TexGenType") - { - return AZStd::make_any(TryConvertingETexGenTypeToCString(pTextureRes->AddModificator()->m_eTGType).toLatin1().data()); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid property.").toUtf8().data()); - } - } - else - { - AZ_Warning("ShadersSystem", false, "PyGetProperty - Error: empty 'subCategoryName' texture slot [%d] for material %s", - aznumeric_cast(TryConvertingCStringToEEfResTextures(subCategoryName)), - pMaterial->GetName().toStdString().c_str()); - } - } - // ########## Texture Maps / [Tiling | Rotator | Oscillator] ########## - else if (splittedPropertyPath.size() == 4) - { - SEfResTexture* pTextureRes = shaderResources.GetTextureResource(TryConvertingCStringToEEfResTextures(subSubCategoryName)); - if (pTextureRes) - { - if (subCategoryName == "Tiling") - { - if (propertyName == "IsTileU") - { - return AZStd::make_any(pTextureRes->m_bUTile); - } - else if (propertyName == "IsTileV") - { - return AZStd::make_any(pTextureRes->m_bVTile); - } - else if (propertyName == "TileU") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_Tiling[0]); - } - else if (propertyName == "TileV") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_Tiling[1]); - } - else if (propertyName == "OffsetU") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_Offs[0]); - } - else if (propertyName == "OffsetV") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_Offs[1]); - } - else if (propertyName == "RotateU") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_Rot[0]); - } - else if (propertyName == "RotateV") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_Rot[1]); - } - else if (propertyName == "RotateW") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_Rot[2]); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid property.").toUtf8().data()); - } - } - else if (subCategoryName == "Rotator") - { - if (propertyName == "Type") - { - return AZStd::make_any(TryConvertingETexModRotateTypeToCString(pTextureRes->AddModificator()->m_eRotType).toLatin1().data()); - } - else if (propertyName == "Rate") - { - return AZStd::make_any(Word2Degr(pTextureRes->AddModificator()->m_RotOscRate[2])); - } - else if (propertyName == "Phase") - { - return AZStd::make_any(Word2Degr(pTextureRes->AddModificator()->m_RotOscPhase[2])); - } - else if (propertyName == "Amplitude") - { - return AZStd::make_any(Word2Degr(pTextureRes->AddModificator()->m_RotOscAmplitude[2])); - } - else if (propertyName == "CenterU") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_RotOscCenter[0]); - } - else if (propertyName == "CenterV") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_RotOscCenter[1]); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid property.").toUtf8().data()); - } - } - else if (subCategoryName == "Oscillator") - { - if (propertyName == "TypeU") - { - return AZStd::make_any(TryConvertingETexModMoveTypeToCString(pTextureRes->AddModificator()->m_eMoveType[0]).toLatin1().data()); - } - else if (propertyName == "TypeV") - { - return AZStd::make_any(TryConvertingETexModMoveTypeToCString(pTextureRes->AddModificator()->m_eMoveType[1]).toLatin1().data()); - } - else if (propertyName == "RateU") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_OscRate[0]); - - } - else if (propertyName == "RateV") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_OscRate[1]); - } - else if (propertyName == "PhaseU") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_OscPhase[0]); - } - else if (propertyName == "PhaseV") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_OscPhase[1]); - } - else if (propertyName == "AmplitudeU") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_OscAmplitude[0]); - } - else if (propertyName == "AmplitudeV") - { - return AZStd::make_any(pTextureRes->AddModificator()->m_OscAmplitude[1]); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid property.").toUtf8().data()); - } - } - else - { - throw std::runtime_error((QString("\"") + subCategoryName + "\" is an invalid sub category.").toUtf8().data()); - } - } - else - { - AZ_Warning("ShadersSystem", false, "PyGetProperty - Error: empty 'subSubCategoryName' texture slot [%d] for material %s", - aznumeric_cast(TryConvertingCStringToEEfResTextures(subSubCategoryName)), - pMaterial->GetName().toStdString().c_str()); - } - } - else - { - throw std::runtime_error(errorMsgInvalidPropertyPath.toUtf8().data()); - } - } - // ########## Shader Params ########## - else if (categoryName == "Shader Params") - { - auto& shaderParams = pMaterial->GetShaderResources().m_ShaderParams; - - for (int i = 0; i < shaderParams.size(); i++) - { - if (propertyName == ParseUINameFromPublicParamsScript(shaderParams[i].m_Script.c_str())) - { - if (shaderParams[i].m_Type == eType_FLOAT) - { - return AZStd::make_any(shaderParams[i].m_Value.m_Float); - } - else if (shaderParams[i].m_Type == eType_FCOLOR) - { - QColor col = ColorLinearToGamma(ColorF( - shaderParams[i].m_Value.m_Vector[0], - shaderParams[i].m_Value.m_Vector[1], - shaderParams[i].m_Value.m_Vector[2])); - return AZStd::make_any(col.red(), col.green(), col.blue(), 1.0f); - } - } - } - - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid shader param.").toUtf8().data()); - } - // ########## Shader Generation Params ########## - else if (categoryName == "Shader Generation Params") - { - for (int i = 0; i < pMaterial->GetShaderGenParamsVars()->GetNumVariables(); i++) - { - if (propertyName == pMaterial->GetShaderGenParamsVars()->GetVariable(i)->GetHumanName()) - { - // get the current Boolean value for this shader variable and return so that the std::runtime_error() will not throw to indicate failure - bool boolValue = false; - pMaterial->GetShaderGenParamsVars()->GetVariable(i)->Get(boolValue); - return AZStd::make_any(boolValue); - } - } - - // not matching property was found, so throw a std::runtime_error() to indcate an error - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid shader generation param.").toUtf8().data()); - } - // ########## Vertex Deformation ########## - else if (categoryName == "Vertex Deformation") - { - // ########## Vertex Deformation / [ Type | Wave Length X | Wave Length Y | Wave Length Z | Wave Length W | Noise Scale ] ########## - if (splittedPropertyPath.size() == 2) - { - if (propertyName == "Type") - { - return AZStd::make_any(TryConvertingEDeformTypeToCString(pMaterial->GetShaderResources().m_DeformInfo.m_eType).toLatin1().data()); - } - else if (propertyName == "Wave Length X") - { - return AZStd::make_any(pMaterial->GetShaderResources().m_DeformInfo.m_fDividerX); - } - else if (propertyName == "Noise Scale") - { - return AZStd::make_any( - pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[0], - pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[1], - pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[2]); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid property.").toUtf8().data()); - } - } - // ########## Vertex Deformation / [ Wave X ] ########## - else if (splittedPropertyPath.size() == 3) - { - if (subCategoryName == "Wave X") - { - SWaveForm2 currentWaveForm; - if (subCategoryName == "Wave X") - { - currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveX; - } - - if (propertyName == "Type") - { - return AZStd::make_any(TryConvertingEWaveFormToCString(currentWaveForm.m_eWFType).toLatin1().data()); - } - else if (propertyName == "Level") - { - return AZStd::make_any(currentWaveForm.m_Level); - } - else if (propertyName == "Amplitude") - { - return AZStd::make_any(currentWaveForm.m_Amp); - } - else if (propertyName == "Phase") - { - return AZStd::make_any(currentWaveForm.m_Phase); - } - else if (propertyName == "Frequency") - { - return AZStd::make_any(currentWaveForm.m_Freq); - } - else - { - throw std::runtime_error((QString("\"") + propertyName + "\" is an invalid property.").toUtf8().data()); - } - } - else - { - throw std::runtime_error((QString("\"") + categoryName + "\" is an invalid category.").toUtf8().data()); - } - } - else - { - throw std::runtime_error(errorMsgInvalidPropertyPath.toUtf8().data()); - } - } - // ########## Layer Presets ########## - else if (categoryName == "Layer Presets") - { - // names are "Shader1", "Shader2" and "Shader3", because all have the name "Shader" in material editor - if (splittedPropertyPath.size() == 2) - { - int shaderNumber = -1; - if (propertyName == "Shader1") - { - shaderNumber = 0; - } - else if (propertyName == "Shader2") - { - shaderNumber = 1; - } - else if (propertyName == "Shader3") - { - shaderNumber = 2; - } - else - { - throw std::runtime_error("Invalid shader."); - } - - return AZStd::make_any(pMaterial->GetMtlLayerResources()[shaderNumber].m_shaderName.toLatin1().data()); - } - else if (splittedPropertyPath.size() == 3) - { - if (propertyName == "No Draw") - { - int shaderNumber = -1; - if (subCategoryName == "Shader1") - { - shaderNumber = 0; - } - else if (subCategoryName == "Shader2") - { - shaderNumber = 1; - } - else if (subCategoryName == "Shader3") - { - shaderNumber = 2; - } - else - { - throw std::runtime_error("Invalid shader."); - } - return AZStd::make_any(pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags & MTL_LAYER_USAGE_NODRAW); - } - } - } - - throw std::runtime_error(errorMsgInvalidPropertyPath.toUtf8().data()); - return AZStd::any(); - } - - void PySetProperty(const char* pPathAndMaterialName, const char* pPathAndPropertyName, const AZStd::any& value) - { - CMaterial* pMaterial = TryLoadingMaterial(pPathAndMaterialName); - std::deque splittedPropertyPath = PreparePropertyPath(pPathAndPropertyName); - std::deque splittedPropertyPathCategory = splittedPropertyPath; - QString categoryName = splittedPropertyPath.front(); - QString subCategoryName = "None"; - QString subSubCategoryName = "None"; - QString propertyName = splittedPropertyPath.back(); - QString errorMsgInvalidPropertyPath = "Invalid property path."; - - if (!ValidateProperty(pMaterial, splittedPropertyPath, value)) - { - throw std::runtime_error("Invalid property."); - } - - QString undoMsg = "Set Material Property"; - CUndo undo(undoMsg.toUtf8().data()); - pMaterial->RecordUndo(undoMsg.toUtf8().data(), true); - - if (splittedPropertyPathCategory.size() == 3) - { - splittedPropertyPathCategory.pop_back(); - subCategoryName = splittedPropertyPathCategory.back(); - } - else if (splittedPropertyPathCategory.size() == 4) - { - splittedPropertyPathCategory.pop_back(); - subCategoryName = splittedPropertyPathCategory.back(); - splittedPropertyPathCategory.pop_back(); - subSubCategoryName = splittedPropertyPathCategory.back(); - } - - // ########## Material Settings ########## - if (categoryName == "Material Settings") - { - if (propertyName == "Shader") - { - pMaterial->SetShaderName(AZStd::any_cast(value).data()); - } - else if (propertyName == "Surface Type") - { - bool isSurfaceExist(false); - QString realSurfacename = ""; - ISurfaceTypeEnumerator* pSurfaceTypeEnum = gEnv->p3DEngine->GetMaterialManager()->GetSurfaceTypeManager()->GetEnumerator(); - if (pSurfaceTypeEnum) - { - for (ISurfaceType* pSurfaceType = pSurfaceTypeEnum->GetFirst(); pSurfaceType; pSurfaceType = pSurfaceTypeEnum->GetNext()) - { - QString surfaceName = pSurfaceType->GetName(); - realSurfacename = surfaceName; - if (surfaceName.left(4) == "mat_") - { - surfaceName.remove(0, 4); - } - if (surfaceName == AZStd::any_cast(value).data()) - { - isSurfaceExist = true; - pMaterial->SetSurfaceTypeName(realSurfacename); - } - } - - if (!isSurfaceExist) - { - throw std::runtime_error("Invalid surface type name."); - } - } - else - { - throw std::runtime_error("Surface Type Enumerator corrupted."); - } - } - } - // ########## Opacity Settings ########## - else if (categoryName == "Opacity Settings") - { - if (propertyName == "Opacity") - { - pMaterial->GetShaderResources().m_LMaterial.m_Opacity = PyFetchNumericType(value) / 100.0f; - } - else if (propertyName == "AlphaTest") - { - pMaterial->GetShaderResources().m_AlphaRef = PyFetchNumericType(value) / 100.0f; - } - else if (propertyName == "Additive") - { - SetMaterialFlag(pMaterial, MTL_FLAG_ADDITIVE, PyFetchNumericType(value)); - } - } - // ########## Lighting Settings ########## - else if (categoryName == "Lighting Settings") - { - if (propertyName == "Diffuse Color") - { - const AZ::Color* color = AZStd::any_cast(&value); - pMaterial->GetShaderResources().m_LMaterial.m_Diffuse = ColorGammaToLinear(QColor(color->GetR8(), color->GetG8(), color->GetB8())); - } - else if (propertyName == "Specular Color") - { - const AZ::Color* color = AZStd::any_cast(&value); - ColorF colorFloat = ColorGammaToLinear(QColor(color->GetR8(), color->GetG8(), color->GetB8())); - colorFloat.a = pMaterial->GetShaderResources().m_LMaterial.m_Specular.a; - colorFloat.r *= colorFloat.a; - colorFloat.g *= colorFloat.a; - colorFloat.b *= colorFloat.a; - pMaterial->GetShaderResources().m_LMaterial.m_Specular = colorFloat; - } - else if (propertyName == "Glossiness" || propertyName == "Smoothness") - { - pMaterial->GetShaderResources().m_LMaterial.m_Smoothness = PyFetchNumericType(value); - } - else if (propertyName == "Specular Level") - { - const float localVariableAlpha = PyFetchNumericType(value); - ColorF colorFloat = pMaterial->GetShaderResources().m_LMaterial.m_Specular; - colorFloat.r *= localVariableAlpha; - colorFloat.g *= localVariableAlpha; - colorFloat.b *= localVariableAlpha; - colorFloat.a = 1.0f; - pMaterial->GetShaderResources().m_LMaterial.m_Specular = colorFloat; - } - else if (propertyName == "Emissive Color") - { - const AZ::Color* color = AZStd::any_cast(&value); - float emissiveIntensity = pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a; - pMaterial->GetShaderResources().m_LMaterial.m_Emittance = ColorGammaToLinear(QColor(color->GetR8(), color->GetG8(), color->GetB8())); - pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a = emissiveIntensity; - } - else if (propertyName == "Emissive Intensity") - { - pMaterial->GetShaderResources().m_LMaterial.m_Emittance.a = PyFetchNumericType(value); - } - } - // ########## Advanced ########## - else if (categoryName == "Advanced") - { - if (propertyName == "Allow layer activation") - { - pMaterial->SetLayerActivation(PyFetchNumericType(value)); - } - else if (propertyName == "2 Sided") - { - SetMaterialFlag(pMaterial, MTL_FLAG_2SIDED, PyFetchNumericType(value)); - } - else if (propertyName == "No Shadow") - { - SetMaterialFlag(pMaterial, MTL_FLAG_NOSHADOW, PyFetchNumericType(value)); - } - else if (propertyName == "Use Scattering") - { - SetMaterialFlag(pMaterial, MTL_FLAG_SCATTER, PyFetchNumericType(value)); - } - else if (propertyName == "Hide After Breaking") - { - SetMaterialFlag(pMaterial, MTL_FLAG_HIDEONBREAK, PyFetchNumericType(value)); - } - else if (propertyName == "Fog Volume Shading Quality High") - { - SetMaterialFlag(pMaterial, MTL_FLAG_FOG_VOLUME_SHADING_QUALITY_HIGH, PyFetchNumericType(value)); - } - else if (propertyName == "Blend Terrain Color") - { - SetMaterialFlag(pMaterial, MTL_FLAG_BLEND_TERRAIN, PyFetchNumericType(value)); - } - else if (propertyName == "Voxel Coverage") - { - pMaterial->GetShaderResources().m_VoxelCoverage = aznumeric_cast(PyFetchNumericType(value) * 255.0f); - } - else if (propertyName == "Link to Material") - { - pMaterial->GetMatInfo()->SetMaterialLinkName(AZStd::any_cast(value).data()); - } - else if (propertyName == "Propagate Material Settings") - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_MATERIAL_SETTINGS, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Opacity Settings") - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_OPACITY, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Lighting Settings") - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_LIGHTING, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Advanced Settings") - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_ADVANCED, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Texture Maps") - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_TEXTURES, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Shader Params") - { - if (PyFetchNumericType(value)) - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_MATERIAL_SETTINGS, true); - } - SetPropagationFlag(pMaterial, MTL_PROPAGATE_SHADER_PARAMS, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Shader Generation") - { - if (PyFetchNumericType(value)) - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_MATERIAL_SETTINGS, true); - } - SetPropagationFlag(pMaterial, MTL_PROPAGATE_SHADER_GEN, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Vertex Deformation") - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_VERTEX_DEF, PyFetchNumericType(value)); - } - else if (propertyName == "Propagate Layer Presets") - { - SetPropagationFlag(pMaterial, MTL_PROPAGATE_LAYER_PRESETS, PyFetchNumericType(value)); - } - } - // ########## Texture Maps ########## - else if (categoryName == "Texture Maps") - { - // ########## Texture Maps / [name] ########## - SInputShaderResources& shaderResources = pMaterial->GetShaderResources(); - if (splittedPropertyPath.size() == 2) - { - uint16 nSlot = aznumeric_cast(TryConvertingCStringToEEfResTextures(propertyName)); - auto stringValue = AZStd::any_cast(value); - if (stringValue.empty()) - { - AZ_Warning("ShadersSystem", false, "PySetProperty - Error: empty texture [%d] name for material %s", - nSlot, pMaterial->GetName().toStdString().c_str()); - } - // notice that the following is an insertion operation if the index did not exist in the map - shaderResources.m_TexturesResourcesMap[nSlot].m_Name = stringValue.data(); - } - // ########## Texture Maps / [TexType | Filter | IsProjectedTexGen | TexGenType ] ########## - else if (splittedPropertyPath.size() == 3) - { - uint16 nSlot = aznumeric_cast(TryConvertingCStringToEEfResTextures(subCategoryName)); - // notice that each of the following will add the texture slot if did not exist yet - if (propertyName == "TexType") - { - shaderResources.m_TexturesResourcesMap[nSlot].m_Sampler.m_eTexType = TryConvertingCStringToETEX_Type(AZStd::any_cast(value)); - } - else if (propertyName == "Filter") - { - shaderResources.m_TexturesResourcesMap[nSlot].m_Filter = TryConvertingCStringToTexFilter(AZStd::any_cast(value)); - } - else if (propertyName == "IsProjectedTexGen") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_bTexGenProjected = PyFetchNumericType(value); - } - else if (propertyName == "TexGenType") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_eTGType = TryConvertingCStringToETexGenType(AZStd::any_cast(value)); - } - } - // ########## Texture Maps / [Tiling | Rotator | Oscillator] ########## - else if (splittedPropertyPath.size() == 4) - { - uint16 nSlot = aznumeric_cast(TryConvertingCStringToEEfResTextures(subSubCategoryName)); - if (subCategoryName == "Tiling") - { - if (propertyName == "IsTileU") - { - shaderResources.m_TexturesResourcesMap[nSlot].m_bUTile = PyFetchNumericType(value); - } - else if (propertyName == "IsTileV") - { - shaderResources.m_TexturesResourcesMap[nSlot].m_bVTile = PyFetchNumericType(value); - } - else if (propertyName == "TileU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_Tiling[0] = PyFetchNumericType(value); - } - else if (propertyName == "TileV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_Tiling[1] = PyFetchNumericType(value); - } - else if (propertyName == "OffsetU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_Offs[0] = PyFetchNumericType(value); - } - else if (propertyName == "OffsetV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_Offs[1] = PyFetchNumericType(value); - } - else if (propertyName == "RotateU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_Rot[0] = Degr2Word(PyFetchNumericType(value)); - } - else if (propertyName == "RotateV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_Rot[1] = Degr2Word(PyFetchNumericType(value)); - } - else if (propertyName == "RotateW") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_Rot[2] = Degr2Word(PyFetchNumericType(value)); - } - } - else if (subCategoryName == "Rotator") - { - if (propertyName == "Type") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_eRotType = TryConvertingCStringToETexModRotateType(AZStd::any_cast(value)); - } - else if (propertyName == "Rate") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_RotOscRate[2] = Degr2Word(PyFetchNumericType(value)); - } - else if (propertyName == "Phase") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_RotOscPhase[2] = Degr2Word(PyFetchNumericType(value)); - } - else if (propertyName == "Amplitude") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_RotOscAmplitude[2] = Degr2Word(PyFetchNumericType(value)); - } - else if (propertyName == "CenterU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_RotOscCenter[0] = PyFetchNumericType(value); - } - else if (propertyName == "CenterV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_RotOscCenter[1] = PyFetchNumericType(value); - } - } - else if (subCategoryName == "Oscillator") - { - if (propertyName == "TypeU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_eMoveType[0] = TryConvertingCStringToETexModMoveType(AZStd::any_cast(value)); - } - else if (propertyName == "TypeV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_eMoveType[1] = TryConvertingCStringToETexModMoveType(AZStd::any_cast(value)); - } - else if (propertyName == "RateU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_OscRate[0] = PyFetchNumericType(value); - } - else if (propertyName == "RateV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_OscRate[1] = PyFetchNumericType(value); - } - else if (propertyName == "PhaseU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_OscPhase[0] = PyFetchNumericType(value); - } - else if (propertyName == "PhaseV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_OscPhase[1] = PyFetchNumericType(value); - } - else if (propertyName == "AmplitudeU") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_OscAmplitude[0] = PyFetchNumericType(value); - } - else if (propertyName == "AmplitudeV") - { - shaderResources.m_TexturesResourcesMap[nSlot].AddModificator()->m_OscAmplitude[1] = PyFetchNumericType(value); - } - } - } - } - // ########## Shader Params ########## - else if (categoryName == "Shader Params") - { - auto& shaderParams = pMaterial->GetShaderResources().m_ShaderParams; - - for (int i = 0; i < shaderParams.size(); i++) - { - if (propertyName == ParseUINameFromPublicParamsScript(shaderParams[i].m_Script.c_str())) - { - if (shaderParams[i].m_Type == eType_FLOAT) - { - shaderParams[i].m_Value.m_Float = PyFetchNumericType(value); - break; - } - else if (shaderParams[i].m_Type == eType_FCOLOR) - { - const AZ::Color* color = AZStd::any_cast(&value); - ColorF colorLinear = ColorGammaToLinear(QColor(color->GetR8(), color->GetG8(), color->GetB8())); - shaderParams[i].m_Value.m_Vector[0] = colorLinear.r; - shaderParams[i].m_Value.m_Vector[1] = colorLinear.g; - shaderParams[i].m_Value.m_Vector[2] = colorLinear.b; - break; - } - else - { - throw std::runtime_error("Invalid data type (Shader Params)"); - } - } - } - } - // ########## Shader Generation Params ########## - else if (categoryName == "Shader Generation Params") - { - for (int i = 0; i < pMaterial->GetShaderGenParamsVars()->GetNumVariables(); i++) - { - if (propertyName == pMaterial->GetShaderGenParamsVars()->GetVariable(i)->GetHumanName()) - { - CVarBlock* shaderGenBlock = pMaterial->GetShaderGenParamsVars(); - shaderGenBlock->GetVariable(i)->Set(PyFetchNumericType(value)); - pMaterial->SetShaderGenParamsVars(shaderGenBlock); - break; - } - } - } - // ########## Vertex Deformation ########## - else if (categoryName == "Vertex Deformation") - { - // ########## Vertex Deformation / [ Type | Wave Length X | Noise Scale ] ########## - if (splittedPropertyPath.size() == 2) - { - if (propertyName == "Type") - { - pMaterial->GetShaderResources().m_DeformInfo.m_eType = TryConvertingCStringToEDeformType(AZStd::any_cast(value)); - } - else if (propertyName == "Wave Length X") - { - pMaterial->GetShaderResources().m_DeformInfo.m_fDividerX = PyFetchNumericType(value); - } - else if (propertyName == "Noise Scale") - { - const AZ::Vector3* vecValue = AZStd::any_cast(&value); - pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[0] = vecValue->GetX(); - pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[1] = vecValue->GetY(); - pMaterial->GetShaderResources().m_DeformInfo.m_vNoiseScale[2] = vecValue->GetZ(); - } - } - // ########## Vertex Deformation / [ Wave X ] ########## - else if (splittedPropertyPath.size() == 3) - { - if (subCategoryName == "Wave X") - { - SWaveForm2& currentWaveForm = pMaterial->GetShaderResources().m_DeformInfo.m_WaveX; - - if (propertyName == "Type") - { - currentWaveForm.m_eWFType = TryConvertingCStringToEWaveForm(AZStd::any_cast(value)); - } - else if (propertyName == "Level") - { - currentWaveForm.m_Level = PyFetchNumericType(value); - } - else if (propertyName == "Amplitude") - { - currentWaveForm.m_Amp = PyFetchNumericType(value); - } - else if (propertyName == "Phase") - { - currentWaveForm.m_Phase = PyFetchNumericType(value); - } - else if (propertyName == "Frequency") - { - currentWaveForm.m_Freq = PyFetchNumericType(value); - } - } - } - } - // ########## Layer Presets ########## - else if (categoryName == "Layer Presets") - { - // names are "Shader1", "Shader2" and "Shader3", because all have the name "Shader" in material editor - if (splittedPropertyPath.size() == 2) - { - int shaderNumber = -1; - if (propertyName == "Shader1") - { - shaderNumber = 0; - } - else if (propertyName == "Shader2") - { - shaderNumber = 1; - } - else if (propertyName == "Shader3") - { - shaderNumber = 2; - } - - pMaterial->GetMtlLayerResources()[shaderNumber].m_shaderName = AZStd::any_cast(value).data(); - } - else if (splittedPropertyPath.size() == 3) - { - if (propertyName == "No Draw") - { - int shaderNumber = -1; - if (subCategoryName == "Shader1") - { - shaderNumber = 0; - } - else if (subCategoryName == "Shader2") - { - shaderNumber = 1; - } - else if (subCategoryName == "Shader3") - { - shaderNumber = 2; - } - - if (pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags & MTL_LAYER_USAGE_NODRAW && PyFetchNumericType(value) == false) - { - pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags = pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags - MTL_LAYER_USAGE_NODRAW; - } - else if (!(pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags & MTL_LAYER_USAGE_NODRAW) && PyFetchNumericType(value) == true) - { - pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags = pMaterial->GetMtlLayerResources()[shaderNumber].m_nFlags | MTL_LAYER_USAGE_NODRAW; - } - } - } - } - - pMaterial->Update(); - pMaterial->Save(); - GetIEditor()->GetMaterialManager()->OnUpdateProperties(pMaterial, true); - } -} - -namespace AzToolsFramework -{ - void MaterialPythonFuncsHandler::Reflect(AZ::ReflectContext* context) - { - if (auto behaviorContext = azrtti_cast(context)) - { - // this will put these methods into the 'azlmbr.legacy.material' module - auto addLegacyMaterial = [](AZ::BehaviorContext::GlobalMethodBuilder methodBuilder) - { - methodBuilder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) - ->Attribute(AZ::Script::Attributes::Category, "Legacy/Material") - ->Attribute(AZ::Script::Attributes::Module, "legacy.material"); - }; - addLegacyMaterial(behaviorContext->Method("create", PyMaterialCreate, nullptr, "Creates a material.")); - addLegacyMaterial(behaviorContext->Method("create_multi", PyMaterialCreateMulti, nullptr, "Creates a multi-material.")); - addLegacyMaterial(behaviorContext->Method("convert_to_multi", PyMaterialConvertToMulti, nullptr, "Converts the selected material to a multi-material.")); - addLegacyMaterial(behaviorContext->Method("duplicate_current", PyMaterialDuplicateCurrent, nullptr, "Duplicates the current material.")); - addLegacyMaterial(behaviorContext->Method("merge_selection", PyMaterialMergeSelection, nullptr, "Merges the selected materials.")); - addLegacyMaterial(behaviorContext->Method("delete_current", PyMaterialDeleteCurrent, nullptr, "Deletes the current material.")); - addLegacyMaterial(behaviorContext->Method("get_submaterial", PyGetSubMaterial, nullptr, "Gets sub materials of a material.")); - addLegacyMaterial(behaviorContext->Method("get_property", PyGetProperty, nullptr, "Gets a property of a material.")); - addLegacyMaterial(behaviorContext->Method("set_property", PySetProperty, nullptr, "Sets a property of a material.")); - } - } -} diff --git a/Code/Sandbox/Editor/Material/MaterialPythonFuncs.h b/Code/Sandbox/Editor/Material/MaterialPythonFuncs.h deleted file mode 100644 index f04542f466..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPythonFuncs.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include - -namespace AzToolsFramework -{ - //! A component to reflect scriptable commands for materials in the Editor - class MaterialPythonFuncsHandler - : public AZ::Component - { - public: - AZ_COMPONENT(MaterialPythonFuncsHandler, "{E437BCF2-DE71-43E1-A7EC-DD243EB41F0B}") - - SANDBOX_API static void Reflect(AZ::ReflectContext* context); - - // AZ::Component ... - void Activate() override {} - void Deactivate() override {} - }; - -} // namespace AzToolsFramework diff --git a/Code/Sandbox/Editor/Material/PreviewModelView.cpp b/Code/Sandbox/Editor/Material/PreviewModelView.cpp deleted file mode 100644 index 41a50436d1..0000000000 --- a/Code/Sandbox/Editor/Material/PreviewModelView.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "EditorDefs.h" - -//AZCore -#include - -//CRY -#include -#include - -//Editor -#include -#include -#include -#include -#include -#include -#include -#include - -//EditorCommon -#include - -//Local -#include "PreviewModelView.h" - -//QT -#include - - - -CPreviewModelView::CPreviewModelView(QWidget* parent) - : QViewport(parent, QViewport::StartupMode_Manual) // Manual since we need to set WA_DontCreateNativeAncestors before QViewport::Startup() creates the internal native window and propagates - , m_Flags(0) - , m_GridColor(150, 150, 150, 40) - , m_BackgroundColor(0.5f, 0.5f, 0.5f) - , m_TimeScale(1.0f) - , m_PlayState(PlayState::NONE) - , m_pStaticModel(nullptr) - , m_PostUpdateCallback(nullptr) - , m_ContextMenuCallback(nullptr) -{ -#ifdef Q_OS_MACOS - // Don't propagate the nativeness up, as dockwidgets on macOS don't like it - setAttribute(Qt::WA_DontCreateNativeAncestors); -#endif - Startup(); - - ////////////////////////////////////////////////////////// - //QViewport - AddConsumer(this); - ////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////// - //IEditorNotifyListener - GetIEditor()->RegisterNotifyListener(this); - ////////////////////////////////////////////////////////// - - FocusOnScreen();//update the camera ... - SetDefaultFlags(); - UpdateSettings(); -} - -CPreviewModelView::~CPreviewModelView() -{ - CRY_ASSERT(GetIEditor()); - - ////////////////////////////////////////////////////////// - //IEditorNotifyListener - GetIEditor()->UnregisterNotifyListener(this); - ////////////////////////////////////////////////////////// - - ReleaseModel(); -} - - -bool CPreviewModelView::IsFlagSet(PreviewModelViewFlag flag) const -{ - CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS); - return (m_Flags & (1 << static_cast(flag))); -} - -void CPreviewModelView::ToggleFlag(PreviewModelViewFlag flag) -{ - CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS); - if (IsFlagSet(flag)) - { - UnSetFlag(flag); - } - else - { - SetFlag(flag); - } -} - -void CPreviewModelView::SetFlag(PreviewModelViewFlag flag) -{ - CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS); - m_Flags |= (1 << static_cast(flag)); -} - -void CPreviewModelView::UnSetFlag(PreviewModelViewFlag flag) -{ - CRY_ASSERT(flag < PreviewModelViewFlag::END_POSSIBLE_ITEMS); - m_Flags &= ~(1 << static_cast(flag)); -} - -void CPreviewModelView::ResetPlaybackControls() -{ - UnSetFlag(CPreviewModelView::PreviewModelViewFlag::LOOPING_PLAY); - m_TimeScale = 1.0f; -} - -void CPreviewModelView::ResetBackgroundColor() -{ - SetBackgroundColor(ColorF(0.5f, 0.5f, 0.5f)); -} - -void CPreviewModelView::ResetGridColor() -{ - SetGridColor(ColorF(150, 150, 150, 40)); -} - -void CPreviewModelView::ResetCamera() -{ - FocusOnScreen(); -} - -void CPreviewModelView::ResetAll() -{ - ResetPlaybackControls(); - ResetGridColor(); - ResetBackgroundColor(); - ReleaseModel(); - SetDefaultFlags(); -} - -void CPreviewModelView::SetGridColor(ColorF color) -{ - m_GridColor = color; -} - -void CPreviewModelView::SetBackgroundColor(ColorF color) -{ - m_BackgroundColor = color; -} - -void CPreviewModelView::SetPlayState(PlayState state) -{ - m_PlayState = state; -} - -void CPreviewModelView::SetTimeScale(float scale) -{ - m_TimeScale = scale; -} - -CPreviewModelView::PlayState CPreviewModelView::GetPlayState() const -{ - return m_PlayState; -} - -float CPreviewModelView::GetTimeScale() const -{ - return m_TimeScale; -} - - -ColorF CPreviewModelView::GetGridColor() const -{ - return m_GridColor; -} - -ColorF CPreviewModelView::GetBackgroundColor() const -{ - return m_BackgroundColor; -} - -void CPreviewModelView::ImportModel() -{ - SResourceSelectorContext x; - x.typeName = Prop::GetPropertyTypeToResourceType(ePropertyModel); - - QString currPath = m_ModelFilename.toLower(); - QString selected = GetIEditor()->GetResourceSelectorHost()->SelectResource(x, currPath); - LoadModelFile(selected); -} - -void CPreviewModelView::SetPostUpdateCallback(PostUpdateCallback callback) -{ - m_PostUpdateCallback = callback; -} - -void CPreviewModelView::SetContextMenuCallback(ContextMenuCallback callback) -{ - m_ContextMenuCallback = callback; -} - -//////////////////////////////////////////////////////// -//QViewportConsumer -void CPreviewModelView::OnViewportRender(const SRenderContext& rc) -{ - ///UPDATE - UpdateSettings();//Some changes may take effect next frame ... - - //External updating ... - if (m_PostUpdateCallback) - { - m_PostUpdateCallback(); - } - - //RENDER - CRY_ASSERT(rc.renderParams); - CRY_ASSERT(rc.passInfo); - RenderModels(*rc.renderParams, *rc.passInfo); -} - -void CPreviewModelView::OnViewportKey([[maybe_unused]] const SKeyEvent& ev) -{ -} - -void CPreviewModelView::OnViewportMouse([[maybe_unused]] const SMouseEvent& ev) -{ -} -//////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////// -//IEditorNotifyListener -void CPreviewModelView::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnCloseScene: - { - ResetAll(); - break; - } - case eNotify_OnIdleUpdate: - { - Update(); - } - break; - default: - break; - } -} -/////////////////////////////////////////////////////// - - -void CPreviewModelView::UpdateSettings() -{ - //Update the settings - SViewportSettings allsettings; - - allsettings.background.topColor = m_BackgroundColor; - allsettings.background.useGradient = false; - - allsettings.grid.showGrid = IsFlagSet(PreviewModelViewFlag::SHOW_GRID); - allsettings.grid.middleColor = m_BackgroundColor; - allsettings.grid.mainColor = m_GridColor; - - allsettings.rendering.wireframe = IsFlagSet(PreviewModelViewFlag::DRAW_WIREFRAME); - allsettings.rendering.sunlight = IsFlagSet(PreviewModelViewFlag::ENABLE_TIME_OF_DAY); - allsettings.rendering.fps = false; - - - // Set zoom speed to 1.0f for better UI workflow, instead of the default 0.1f - allsettings.camera.zoomSpeed = 1.0f; - allsettings.camera.moveSpeed = GetIEditor()->GetEditorSettings()->cameraMoveSpeed; - allsettings.camera.fastMoveMultiplier = GetIEditor()->GetEditorSettings()->cameraFastMoveSpeed; - allsettings.camera.rotationSpeed = GetIEditor()->GetEditorSettings()->cameraRotateSpeed; - allsettings.camera.showViewportOrientation = IsFlagSet(PreviewModelViewFlag::SHOW_GRID_AXIS); - - //Set them ... - SetSettings(allsettings); -} - - - -void CPreviewModelView::RenderModels(SRendParams& rendParams, SRenderingPassInfo& passInfo) -{ - if (m_pStaticModel) - { - if (IsFlagSet(PreviewModelViewFlag::PRECACHE_MATERIAL)) - { - _smart_ptr pCurMat = m_pStaticModel->GetMaterial(); - if (pCurMat) - { - pCurMat->PrecacheMaterial(0.0f, nullptr, true, true); - } - } - m_pStaticModel->Render(rendParams, passInfo); - } -} - -void CPreviewModelView::ReleaseModel() -{ - m_ModelFilename = ""; - SAFE_RELEASE(m_pStaticModel); -} - -void CPreviewModelView::SetDefaultFlags() -{ - UnSetFlag(PreviewModelViewFlag::SHOW_OVERDRAW); - - m_Flags = 0; - - SetFlag(PreviewModelViewFlag::SHOW_GRID); - SetFlag(PreviewModelViewFlag::SHOW_GRID_AXIS); -} - -void CPreviewModelView::LoadModelFile(const QString& modelFile) -{ - //Something to load - if (!modelFile.isEmpty()) - { - //Make sure we are not loading the same thing ... - if (m_ModelFilename != modelFile) - { - ReleaseModel();//release any old mesh - - QString strFileExt = Path::GetExt(modelFile); - bool isCGF = (QString::compare(strFileExt, CRY_GEOMETRY_FILE_EXT, Qt::CaseInsensitive) == 0); - - // NOTE: have to create a local buffer and evaluate the full message here due to calling into another address space to evaluate va_args - // this prevents passing of random data to the log system ... any plugin that does not do it this way is rolling the dice each time. - char buffer[2046]; - CRY_ASSERT(GetIEditor()); - if (isCGF) - { - CRY_ASSERT(GetIEditor()->Get3DEngine()); - // Load object. - m_pStaticModel = GetIEditor()->Get3DEngine()->LoadStatObjUnsafeManualRef(modelFile.toUtf8().data(), nullptr, nullptr, false); - if (m_pStaticModel) - { - m_pStaticModel->AddRef(); - } - else - { - CRY_ASSERT(GetIEditor()->GetLogFile()); - azsprintf(buffer, "Loading of geometry object %s failed.", modelFile.toUtf8().data()); - GetIEditor()->GetLogFile()->Warning(buffer); - } - } - else - { - CRY_ASSERT(GetIEditor()->GetLogFile()); - azsprintf(buffer, "Unknown model file (%s) attempting to be loaded.", modelFile.toUtf8().data()); - GetIEditor()->GetLogFile()->Warning(buffer); - } - - //if something was loaded then we store off the model path for the future - if (m_pStaticModel) - { - m_ModelFilename = modelFile; - } - } - } -} - -IStatObj* CPreviewModelView::GetStaticModel() -{ - return m_pStaticModel; -} - -void CPreviewModelView::FocusOnScreen() -{ - CCamera* camera = Camera(); - if (camera) - { - AABB accumulated(2); - - if (m_pStaticModel) - { - AABB temp; - temp.min = m_pStaticModel->GetBoxMin(); - temp.max = m_pStaticModel->GetBoxMax(); - accumulated.Add(temp); - } - - Vec3 fromDir(1.0f, 1.0f, -0.5f); - Vec3 target = accumulated.GetCenter(); - float bbRadius = accumulated.GetRadius(); - - Vec3 dir = fromDir.GetNormalized(); - Matrix34 tm = Matrix33::CreateRotationVDir(dir, 0); - tm.SetTranslation(target - dir * bbRadius); - CameraMoved(QuatT(tm), true); - } -} - -float CPreviewModelView::GetSpeedScale() const -{ - CRY_ASSERT(GetIEditor()); - CRY_ASSERT(GetIEditor()->GetSystem()); - CRY_ASSERT(GetIEditor()->GetSystem()->GetITimer()); - //Taken from CRenderViewport to mirror controls from there ... - float speedScale = 60.0f * GetIEditor()->GetSystem()->GetITimer()->GetFrameTime(); - if (speedScale > 20.0f) - { - speedScale = 20.0f; - } - return speedScale; -} - diff --git a/Code/Sandbox/Editor/Material/PreviewModelView.h b/Code/Sandbox/Editor/Material/PreviewModelView.h deleted file mode 100644 index 3d27983be1..0000000000 --- a/Code/Sandbox/Editor/Material/PreviewModelView.h +++ /dev/null @@ -1,173 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -//Editor -#if !defined(Q_MOC_RUN) -#include "IEditor.h" -#include "../EditorCommon/QViewport.h" -#include "../EditorCommon/QViewportConsumer.h" - -#endif - -struct IStatObj; -struct SRenderingPassInfo; -struct SRendParams; -class CParticleItem; -class CAxisHelper; -struct HitContext; -struct IGizmoMouseDragHandler; -struct SLodInfo; - -namespace RotationDrawHelper -{ - class Axis; -} - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -class CPreviewModelView - : public QViewport - , public QViewportConsumer - , public IEditorNotifyListener -{ -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING -public: - enum class PlayState - { - NONE, - PLAY, - PAUSE, - STEP, - RESET - }; - enum class SplineMode - { - NONE, - LINE, - SINEWAVE, - COIL - }; - - //NOTE: these need to be limited to 32 as these are being used for bit wise operations. - enum class PreviewModelViewFlag - { - DRAW_WIREFRAME = 0, - - SHOW_BOUNDINGBOX, - SHOW_GIZMO, - SHOW_GRID, - SHOW_GRID_AXIS, - SHOW_EMITTER_SHAPE, - SHOW_OVERDRAW, - SHOW_FIRST_CONTAINER, - - LOOPING_PLAY, - - //Spline - SPLINE_LOOPING, - SPLINE_PINGPONG, - - PRECACHE_MATERIAL, - - ENABLE_TIME_OF_DAY, - - END_POSSIBLE_ITEMS = 32, - }; - - explicit CPreviewModelView(QWidget* parent); - virtual ~CPreviewModelView(); - - //Flags - bool IsFlagSet(PreviewModelViewFlag flag) const; - void ToggleFlag(PreviewModelViewFlag flag); - virtual void SetFlag(PreviewModelViewFlag flag); - virtual void UnSetFlag(PreviewModelViewFlag flag); - - //Resets - void ResetPlaybackControls(); - void ResetBackgroundColor(); - void ResetGridColor(); - virtual void ResetCamera(); - virtual void ResetAll(); - - void SetGridColor(ColorF color); - void SetBackgroundColor(ColorF color); - void SetPlayState(PlayState state); - void SetTimeScale(float scale); - - PlayState GetPlayState() const; - float GetTimeScale() const; - ColorF GetGridColor() const; - ColorF GetBackgroundColor() const; - - void ImportModel(); - - void LoadModelFile(const QString& modelFile); - IStatObj* GetStaticModel(); - - typedef std::function PostUpdateCallback; - void SetPostUpdateCallback(PostUpdateCallback callback); - - typedef std::function ContextMenuCallback; - void SetContextMenuCallback(ContextMenuCallback callback); - - //////////////////////////////////////////////////////// - //QViewportConsumer - virtual void OnViewportRender(const SRenderContext& rc) override; - virtual void OnViewportKey(const SKeyEvent& ev) override; - virtual void OnViewportMouse(const SMouseEvent& ev) override; - //////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////// - //IEditorNotifyListener - virtual void OnEditorNotifyEvent(EEditorNotifyEvent event) override; - //////////////////////////////////////////////////////// - -private: - - //Update - void UpdateSettings(); -protected: -private: - //Render - void RenderModels(SRendParams& rendParams, SRenderingPassInfo& passInfo); - - //Misc - void ReleaseModel(); - void SetDefaultFlags(); -protected: - void FocusOnScreen(); -private: - float GetSpeedScale() const; - -private: - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - ColorF m_GridColor; - ColorF m_BackgroundColor; - - QString m_ModelFilename; - - - IStatObj* m_pStaticModel; - -protected: - PostUpdateCallback m_PostUpdateCallback; - ContextMenuCallback m_ContextMenuCallback; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - -protected: - PlayState m_PlayState; - float m_TimeScale; -private: - unsigned int m_Flags; -}; diff --git a/Code/Sandbox/Editor/Material/images/filestatus_00.png b/Code/Sandbox/Editor/Material/images/filestatus_00.png deleted file mode 100644 index 414609f486..0000000000 --- a/Code/Sandbox/Editor/Material/images/filestatus_00.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3e5d226d043630028a1fe88af240b627a08966066b605294cc79ff8273588166 -size 194 diff --git a/Code/Sandbox/Editor/Material/images/filestatus_01.png b/Code/Sandbox/Editor/Material/images/filestatus_01.png deleted file mode 100644 index d644fcfe12..0000000000 --- a/Code/Sandbox/Editor/Material/images/filestatus_01.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f80544a0537398979dd423ffdc8e99c08e47dbe814cd4225646761cbe281eecc -size 206 diff --git a/Code/Sandbox/Editor/Material/images/filestatus_02.png b/Code/Sandbox/Editor/Material/images/filestatus_02.png deleted file mode 100644 index da155a1d2a..0000000000 --- a/Code/Sandbox/Editor/Material/images/filestatus_02.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bee8a3d1d5571e5afe0bd02edf0fc58d8297f96494a7c074fd2a37ecda7ae4dc -size 208 diff --git a/Code/Sandbox/Editor/Material/images/filestatus_03.png b/Code/Sandbox/Editor/Material/images/filestatus_03.png deleted file mode 100644 index a047cb4599..0000000000 --- a/Code/Sandbox/Editor/Material/images/filestatus_03.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d3d0fc234e3154c06abd4e3b8d3d7e52a75f80d527b1d05541f55221cba199d7 -size 183 diff --git a/Code/Sandbox/Editor/Material/images/filestatus_04.png b/Code/Sandbox/Editor/Material/images/filestatus_04.png deleted file mode 100644 index 519b68d500..0000000000 --- a/Code/Sandbox/Editor/Material/images/filestatus_04.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ffb3586ef4309d8bfa93a581c38fe970e8b0411f170955921054522b0bf52bd3 -size 182 diff --git a/Code/Sandbox/Editor/Material/images/filestatus_05.png b/Code/Sandbox/Editor/Material/images/filestatus_05.png deleted file mode 100644 index f4f548cdc9..0000000000 --- a/Code/Sandbox/Editor/Material/images/filestatus_05.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f258e9617a1d4c7be16fcab12533a4f0bfe4072151f2140ca41364ef1a3cea62 -size 196 diff --git a/Code/Sandbox/Editor/Material/images/filestatus_06.png b/Code/Sandbox/Editor/Material/images/filestatus_06.png deleted file mode 100644 index 7b7412b19d..0000000000 --- a/Code/Sandbox/Editor/Material/images/filestatus_06.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:68c609d7bde1796f281690148c19694afddcc2cf4ea306116b546327cb50aad2 -size 249 diff --git a/Code/Sandbox/Editor/Material/images/material_00.png b/Code/Sandbox/Editor/Material/images/material_00.png deleted file mode 100644 index a7f48148f1..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_00.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bd5106eebb6cf264fdac5f3568977fc8f944df4a4d4de6b0e9f35b3a001a3001 -size 206 diff --git a/Code/Sandbox/Editor/Material/images/material_01.png b/Code/Sandbox/Editor/Material/images/material_01.png deleted file mode 100644 index e6c26f748a..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_01.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2b08a8d94c64aed944901b76afcb921c3df2c122c9eac6d52140552c2eb4e5cc -size 227 diff --git a/Code/Sandbox/Editor/Material/images/material_02.png b/Code/Sandbox/Editor/Material/images/material_02.png deleted file mode 100644 index a116e84295..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_02.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:623a937f09f1de3ebb889d7ac9e042f91bf67bef34695801b3603f4517166c8e -size 223 diff --git a/Code/Sandbox/Editor/Material/images/material_03.png b/Code/Sandbox/Editor/Material/images/material_03.png deleted file mode 100644 index a116e84295..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_03.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:623a937f09f1de3ebb889d7ac9e042f91bf67bef34695801b3603f4517166c8e -size 223 diff --git a/Code/Sandbox/Editor/Material/images/material_04.png b/Code/Sandbox/Editor/Material/images/material_04.png deleted file mode 100644 index 1d83e3526a..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_04.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0ad56ab7be0a5a40b644045ac01c90fed6e70433a693e80c5b4b88d63801d75f -size 14604 diff --git a/Code/Sandbox/Editor/Material/images/material_05.png b/Code/Sandbox/Editor/Material/images/material_05.png deleted file mode 100644 index 8d953a6ae4..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_05.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9cc845c4eb0ed6fb772064d73f1c679e3b28288411a02f0cafaf248b83b44ca2 -size 221 diff --git a/Code/Sandbox/Editor/Material/images/material_06.png b/Code/Sandbox/Editor/Material/images/material_06.png deleted file mode 100644 index 7e5159a2fc..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_06.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:966fd5ef5c1e0fe6e920511952d7aea98ad0f165f9ce0197f000f9f48ccd338b -size 14628 diff --git a/Code/Sandbox/Editor/Material/images/material_07.png b/Code/Sandbox/Editor/Material/images/material_07.png deleted file mode 100644 index 7e5159a2fc..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_07.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:966fd5ef5c1e0fe6e920511952d7aea98ad0f165f9ce0197f000f9f48ccd338b -size 14628 diff --git a/Code/Sandbox/Editor/Material/images/material_browser_00.png b/Code/Sandbox/Editor/Material/images/material_browser_00.png deleted file mode 100644 index f1e7a2ffce..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_browser_00.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c4a8dc85c9928faacd184148aaf0f17ef7b68c185b04b0b5f16e942fb11c528e -size 209 diff --git a/Code/Sandbox/Editor/Material/images/material_browser_01.png b/Code/Sandbox/Editor/Material/images/material_browser_01.png deleted file mode 100644 index 1ff2ea213f..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_browser_01.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d9047378404e0893b79bafaad9e6b312d467033daab2191a8c8839e4ff494bd8 -size 321 diff --git a/Code/Sandbox/Editor/Material/images/material_browser_02.png b/Code/Sandbox/Editor/Material/images/material_browser_02.png deleted file mode 100644 index edd5148133..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_browser_02.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2e79122edef52c3f9a31fd662f9f5cfd08b06e44e861c7379d8869635fd1d245 -size 168 diff --git a/Code/Sandbox/Editor/Material/images/material_browser_03.png b/Code/Sandbox/Editor/Material/images/material_browser_03.png deleted file mode 100644 index bfbcc6ce98..0000000000 --- a/Code/Sandbox/Editor/Material/images/material_browser_03.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8cc16bbb4c4c0c1bea14c94d0609f4b11a7cd0ead4af3d236d329a404e8223a8 -size 200 diff --git a/Code/Sandbox/Editor/MaterialSender.cpp b/Code/Sandbox/Editor/MaterialSender.cpp deleted file mode 100644 index 2123eadb31..0000000000 --- a/Code/Sandbox/Editor/MaterialSender.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "EditorDefs.h" - -#include "MaterialSender.h" - -bool CMaterialSender::SendMessage(int msg, const XmlNodeRef& node) -{ - bool bRet = false; - -#if defined(AZ_PLATFORM_WINDOWS) - if (!CheckWindows()) - { - return false; - } - - m_h.msg = msg; - - int nDataSize = sizeof(SMaterialMapFileHeader) + strlen(node->getXML().c_str()) + 1; - - //hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nDataSize, "EditMatMappingObject"); - - HANDLE mapFileHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "EditMatMappingObject"); - if (mapFileHandle) - { - void* pMes = MapViewOfFile(mapFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, nDataSize); - if (pMes) - { - memcpy(pMes, &m_h, sizeof(SMaterialMapFileHeader)); - azstrcpy(((char*)pMes) + sizeof(SMaterialMapFileHeader), nDataSize - sizeof(SMaterialMapFileHeader), node->getXML().c_str()); - UnmapViewOfFile(pMes); - if (m_bIsMatEditor) - { - ::SendMessage(m_h.GetMaxHWND(), WM_MATEDITSEND, msg, 0); - } - else - { - ::SendMessage(m_h.GetEditorHWND(), WM_MATEDITSEND, msg, 0); - } - bRet = true; - } - CloseHandle(mapFileHandle); - } - else - { - CryLog("No File Map"); - } -#endif - - return bRet; -} diff --git a/Code/Sandbox/Editor/MaterialSender.h b/Code/Sandbox/Editor/MaterialSender.h deleted file mode 100644 index 0123223821..0000000000 --- a/Code/Sandbox/Editor/MaterialSender.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_MATERIALSENDER_H -#define CRYINCLUDE_EDITOR_MATERIALSENDER_H -#pragma once - -#ifndef WM_MATEDITSEND -// Value copied from Code/Tools/MaxCryExport/CryShader/MaterialSender.h -# define WM_MATEDITSEND (WM_USER + 315) -#endif - -enum EMaterialSenderMessage -{ - eMSM_Create = 1, - eMSM_GetSelectedMaterial = 2, - eMSM_Init = 3, -}; - -#if defined(AZ_PLATFORM_WINDOWS) -struct SMaterialMapFileHeader -{ - // max - void SetMaxHWND(HWND hWnd) - { - hwndMax = (int64)hWnd; - } - HWND GetMaxHWND() const - { - return (HWND)hwndMax; - } - // editor - void SetEditorHWND(HWND hWnd) - { - hwndMatEdit = (int64)hWnd; - } - HWND GetEditorHWND() const - { - return (HWND)hwndMatEdit; - } - int64 msg;// 64bits for both 32 and 64 - int64 Reserved;// 64bits for both 32 and 64 -protected: - uint64 hwndMax;// HWND for 32 and 64 is different - uint64 hwndMatEdit;// HWND for 32 and 64 is different -}; -#endif // AZ_PLATFORM_WINDOWS - - -class CMaterialSender -{ -public: - - CMaterialSender(bool bIsMatEditor) - : m_bIsMatEditor(bIsMatEditor) - { -#if defined(AZ_PLATFORM_WINDOWS) - m_h.SetEditorHWND(0); - m_h.SetMaxHWND(0); - m_h.msg = 0; - hMapFile = 0; -#endif - } - - ~CMaterialSender() - { -#if defined(AZ_PLATFORM_WINDOWS) - if (hMapFile) - { - CloseHandle(hMapFile); - } - hMapFile = 0; -#endif - } - - bool GetMessage() - { - LoadMapFile(); - return true; - } - - bool CheckWindows() - { -#if defined(AZ_PLATFORM_WINDOWS) - if (!m_h.GetMaxHWND() || !m_h.GetEditorHWND() || !::IsWindow(m_h.GetMaxHWND()) || !::IsWindow(m_h.GetEditorHWND())) - { - LoadMapFile(); - } - if (!m_h.GetMaxHWND() || !m_h.GetEditorHWND() || !::IsWindow(m_h.GetMaxHWND()) || !::IsWindow(m_h.GetEditorHWND())) - { - return false; - } -#endif - return true; - } - - bool Create() - { -#if defined(AZ_PLATFORM_WINDOWS) - hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024 * 1024, "EditMatMappingObject"); - if (hMapFile) - { - return true; - } - CryLog("Can't create File Map"); - - return false; -#else - return true; -#endif - } - - bool SendMessage(int msg, const XmlNodeRef& node); - - void SetupWindows(QWidget* hwndMax, QWidget* hwndMatEdit) - { -#if defined(AZ_PLATFORM_WINDOWS) - m_h.SetMaxHWND(reinterpret_cast(hwndMax->winId())); - m_h.SetEditorHWND(reinterpret_cast(hwndMatEdit->winId())); -#endif - } - -private: - - bool LoadMapFile() - { -#if defined(AZ_PLATFORM_WINDOWS) - bool bRet = false; - const HANDLE mapFileHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "EditMatMappingObject"); - if (mapFileHandle) - { - void* const pMes = MapViewOfFile(mapFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0); - - if (pMes) - { - memcpy(&m_h, pMes, sizeof(SMaterialMapFileHeader)); - const char* const pXml = ((const char*)pMes) + sizeof(SMaterialMapFileHeader); - m_node = XmlHelpers::LoadXmlFromBuffer(pXml, strlen(pXml)); - UnmapViewOfFile(pMes); - bRet = true; - } - - CloseHandle(mapFileHandle); - } - - return bRet; -#else - return false; -#endif - } - -public: -#if defined(AZ_PLATFORM_WINDOWS) - SMaterialMapFileHeader m_h; -#endif - XmlNodeRef m_node; -private: - bool m_bIsMatEditor; -#if defined(AZ_PLATFORM_WINDOWS) - HANDLE hMapFile; -#endif -}; - - -#endif // CRYINCLUDE_EDITOR_MATERIALSENDER_H diff --git a/Code/Sandbox/Editor/ModelViewport.cpp b/Code/Sandbox/Editor/ModelViewport.cpp index bf15f2fbaf..2e00adb4fc 100644 --- a/Code/Sandbox/Editor/ModelViewport.cpp +++ b/Code/Sandbox/Editor/ModelViewport.cpp @@ -29,7 +29,6 @@ // Editor #include "ThumbnailGenerator.h" // for CThumbnailGenerator #include "FileTypeUtils.h" // for IsPreviewableFileType -#include "Material/MaterialManager.h" // for CMaterialManager #include "ErrorRecorder.h" @@ -652,32 +651,6 @@ void CModelViewport::DrawInfo() const } } -////////////////////////////////////////////////////////////////////////// -void CModelViewport::SetCustomMaterial(CMaterial* pMaterial) -{ - m_pCurrentMaterial = pMaterial; -} - -////////////////////////////////////////////////////////////////////////// -CMaterial* CModelViewport::GetMaterial() -{ - if (m_pCurrentMaterial) - { - return m_pCurrentMaterial; - } - else - { - _smart_ptr pMtl = 0; - if (m_object) - { - pMtl = m_object->GetMaterial(); - } - - CMaterial* pCMaterial = GetIEditor()->GetMaterialManager()->FromIMaterial(pMtl); - return pCMaterial; - } -} - ////////////////////////////////////////////////////////////////////////// bool CModelViewport::CanDrop([[maybe_unused]] const QPoint& point, IDataBaseItem* pItem) { @@ -686,26 +659,12 @@ bool CModelViewport::CanDrop([[maybe_unused]] const QPoint& point, IDataBaseItem return false; } - if (pItem->GetType() == EDB_TYPE_MATERIAL) - { - SetCustomMaterial((CMaterial*)pItem); - } return true; } ////////////////////////////////////////////////////////////////////////// -void CModelViewport::Drop([[maybe_unused]] const QPoint& point, IDataBaseItem* pItem) +void CModelViewport::Drop([[maybe_unused]] const QPoint& point, [[maybe_unused]] IDataBaseItem* pItem) { - if (!pItem) - { - SetCustomMaterial(NULL); - return; - } - - if (pItem->GetType() == EDB_TYPE_MATERIAL) - { - SetCustomMaterial((CMaterial*)pItem); - } } ////////////////////////////////////////////////////////////////////////// @@ -788,10 +747,6 @@ void CModelViewport::DrawModel(const SRenderingPassInfo& passInfo) } rp.dwFObjFlags = 0; - if (m_pCurrentMaterial) - { - rp.pMaterial = m_pCurrentMaterial->GetMatInfo(); - } //----------------------------------------------------------------------------- //----- Render Static Object (handled by 3DEngine) ---- diff --git a/Code/Sandbox/Editor/ModelViewport.h b/Code/Sandbox/Editor/ModelViewport.h index d9b119c5d5..a5d1ac2a26 100644 --- a/Code/Sandbox/Editor/ModelViewport.h +++ b/Code/Sandbox/Editor/ModelViewport.h @@ -31,7 +31,6 @@ #if !defined(Q_MOC_RUN) #include "RenderViewport.h" -#include "Material/Material.h" #include "Util/Variable.h" #endif @@ -90,14 +89,6 @@ public: void UseWeaponIK([[maybe_unused]] bool val) { m_weaponIK = true; } - // Set current material to render object. - void SetCustomMaterial(CMaterial* pMaterial); - // Get custom material that object is rendered with. - CMaterial* GetCustomMaterial() { return m_pCurrentMaterial; }; - - // Get material the object is actually rendered with. - CMaterial* GetMaterial(); - void ReleaseObject(); void RePhysicalize(); @@ -182,7 +173,6 @@ protected: class CRESky* m_pRESky; struct ICVar* m_pSkyboxName; IShader* m_pSkyBoxShader; - _smart_ptr m_pCurrentMaterial; //--------------------------------------------------- //--- debug options --- diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.cpp b/Code/Sandbox/Editor/ModernViewportCameraController.cpp index 80bd9416f7..4725721f0e 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.cpp +++ b/Code/Sandbox/Editor/ModernViewportCameraController.cpp @@ -14,12 +14,35 @@ #include #include +#include #include +#include +#include #include #include +#include + +namespace AzFramework +{ + extern InputChannelId CameraFreeLookButton; + extern InputChannelId CameraFreePanButton; + extern InputChannelId CameraOrbitLookButton; + extern InputChannelId CameraOrbitDollyButton; + extern InputChannelId CameraOrbitPanButton; +} namespace SandboxEditor { + static void DrawPreviewAxis(AzFramework::DebugDisplayRequests& display, const AZ::Transform& transform, const float axisLength) + { + display.SetColor(AZ::Colors::Red); + display.DrawLine(transform.GetTranslation(), transform.GetTranslation() + transform.GetBasisX().GetNormalizedSafe() * axisLength); + display.SetColor(AZ::Colors::Green); + display.DrawLine(transform.GetTranslation(), transform.GetTranslation() + transform.GetBasisY().GetNormalizedSafe() * axisLength); + display.SetColor(AZ::Colors::Blue); + display.DrawLine(transform.GetTranslation(), transform.GetTranslation() + transform.GetBasisZ().GetNormalizedSafe() * axisLength); + } + static AZ::RPI::ViewportContextPtr RetrieveViewportContext(const AzFramework::ViewportId viewportId) { auto viewportContextManager = AZ::Interface::Get(); @@ -41,17 +64,21 @@ namespace SandboxEditor : MultiViewportControllerInstanceInterface(viewportId) { // LYN-2315 TODO - move setup out of constructor, pass cameras in - auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Right); - auto firstPersonPanCamera = AZStd::make_shared(AzFramework::LookPan); + auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton); + auto firstPersonPanCamera = + AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan); auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation); auto firstPersonWheelCamera = AZStd::make_shared(); auto orbitCamera = AZStd::make_shared(); - auto orbitRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Left); + auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton); auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation); auto orbitDollyWheelCamera = AZStd::make_shared(); - auto orbitDollyMoveCamera = AZStd::make_shared(); - auto orbitPanCamera = AZStd::make_shared(AzFramework::OrbitPan); + auto orbitDollyMoveCamera = + AZStd::make_shared(AzFramework::CameraOrbitDollyButton); + auto orbitPanCamera = + AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan); + orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera); @@ -64,15 +91,25 @@ namespace SandboxEditor m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera); m_cameraSystem.m_cameras.AddCamera(orbitCamera); - if (const auto viewportContext = RetrieveViewportContext(viewportId)) + if (auto viewportContext = RetrieveViewportContext(GetViewportId())) { - // set position but not orientation - m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation(); + auto handleCameraChange = [this](const AZ::Matrix4x4& matrix) { + UpdateCameraFromTransform( + m_targetCamera, + AZ::Transform::CreateFromMatrix3x3AndTranslation(AZ::Matrix3x3::CreateFromMatrix4x4(matrix), matrix.GetTranslation())); + }; - // LYN-2315 TODO https://www.geometrictools.com/Documentation/EulerAngles.pdf + m_cameraViewMatrixChangeHandler = AZ::RPI::ViewportContext::MatrixChangedEvent::Handler(handleCameraChange); - m_camera = m_targetCamera; + viewportContext->ConnectViewMatrixChangedHandler(m_cameraViewMatrixChangeHandler); } + + AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); + } + + ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance() + { + AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect(); } bool ModernViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) @@ -80,18 +117,78 @@ namespace SandboxEditor AzFramework::WindowSize windowSize; AzFramework::WindowRequestBus::EventResult( windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize); - m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); - return true; // consume event + + if (m_cameraMode == CameraMode::Control) + { + if (AzFramework::InputDeviceKeyboard::IsKeyboardDevice(event.m_inputChannel.GetInputDevice().GetInputDeviceId())) + { + if (event.m_inputChannel.GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::AlphanumericR) + { + m_transformEnd = m_camera.Transform(); + + return true; + } + else if (event.m_inputChannel.GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::AlphanumericP) + { + m_animationT = 0.0f; + m_cameraMode = CameraMode::Animation; + m_transformStart = m_camera.Transform(); + + return true; + } + } + } + + return m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize)); } void ModernViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) { if (auto viewportContext = RetrieveViewportContext(GetViewportId())) { - m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); - m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, m_smoothProps, event.m_deltaTime.count()); + if (m_cameraMode == CameraMode::Control) + { + m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count()); + m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, event.m_deltaTime.count()); - viewportContext->SetCameraTransform(m_camera.Transform()); + viewportContext->SetCameraTransform(m_camera.Transform()); + } + else if (m_cameraMode == CameraMode::Animation) + { + const auto smootherStepFn = [](const float t) { return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); }; + const float transitionT = smootherStepFn(m_animationT); + + const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation( + m_transformStart.GetRotation().Slerp(m_transformEnd.GetRotation(), transitionT), + m_transformStart.GetTranslation().Lerp(m_transformEnd.GetTranslation(), transitionT)); + + const AZ::Vector3 eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(current)); + m_camera.m_pitch = eulerAngles.GetX(); + m_camera.m_yaw = eulerAngles.GetZ(); + m_camera.m_lookAt = current.GetTranslation(); + m_targetCamera = m_camera; + + if (m_animationT >= 1.0f) + { + m_cameraMode = CameraMode::Control; + } + + m_animationT = AZ::GetClamp(m_animationT + event.m_deltaTime.count(), 0.0f, 1.0f); + + viewportContext->SetCameraTransform(current); + } } } + + void ModernViewportCameraControllerInstance::DisplayViewport( + [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) + { + if (const float alpha = AZStd::min(-m_camera.m_lookDist / 5.0f, 1.0f); alpha > AZ::Constants::FloatEpsilon) + { + debugDisplay.SetColor(1.0f, 1.0f, 1.0f, alpha); + debugDisplay.DrawWireSphere(m_camera.m_lookAt, 0.5f); + } + + DrawPreviewAxis(debugDisplay, m_transformEnd, 2.0f); + } } // namespace SandboxEditor diff --git a/Code/Sandbox/Editor/ModernViewportCameraController.h b/Code/Sandbox/Editor/ModernViewportCameraController.h index c65dbc8b8a..56345ad0da 100644 --- a/Code/Sandbox/Editor/ModernViewportCameraController.h +++ b/Code/Sandbox/Editor/ModernViewportCameraController.h @@ -12,25 +12,44 @@ #pragma once +#include +#include #include #include namespace SandboxEditor { - class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface + class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface, + private AzFramework::ViewportDebugDisplayEventBus::Handler { public: explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId); + ~ModernViewportCameraControllerInstance(); // MultiViewportControllerInstanceInterface overrides ... bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override; void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override; + // AzFramework::ViewportDebugDisplayEventBus overrides ... + void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + private: + enum class CameraMode + { + Control, + Animation + }; + AzFramework::Camera m_camera; AzFramework::Camera m_targetCamera; - AzFramework::SmoothProps m_smoothProps; AzFramework::CameraSystem m_cameraSystem; + + AZ::Transform m_transformStart = AZ::Transform::CreateIdentity(); + AZ::Transform m_transformEnd = AZ::Transform::CreateIdentity(); + float m_animationT = 0.0f; + CameraMode m_cameraMode = CameraMode::Control; + + AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler; }; using ModernViewportCameraController = AzFramework::MultiViewportController; diff --git a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp index 40970838c1..ef2b91685a 100644 --- a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp +++ b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp @@ -22,7 +22,6 @@ #include "ViewManager.h" #include "Settings.h" #include "RenderHelpers/AxisHelper.h" -#include "RenderHelpers/AxisHelperExtended.h" #include "IObjectManager.h" ////////////////////////////////////////////////////////////////////////// @@ -36,7 +35,6 @@ CAxisGizmo::CAxisGizmo(CBaseObject* object) assert(object != 0); m_object = object; m_pAxisHelper.reset(new CAxisHelper); - m_pAxisHelperExtended.reset(new CAxisHelperExtended); // Set selectable flag. SetFlags(EGIZMO_SELECTABLE | EGIZMO_TRANSFORM_MANIPULATOR); @@ -60,7 +58,6 @@ CAxisGizmo::CAxisGizmo() SetFlags(EGIZMO_SELECTABLE); m_axisGizmoCount++; m_pAxisHelper.reset(new CAxisHelper); - m_pAxisHelperExtended.reset(new CAxisHelperExtended); m_bDragging = false; m_bAlwaysUseLocal = false; m_coordSysBackUp = COORDS_VIEW; diff --git a/Code/Sandbox/Editor/Objects/AxisGizmo.h b/Code/Sandbox/Editor/Objects/AxisGizmo.h index 55506ed6b5..689b011972 100644 --- a/Code/Sandbox/Editor/Objects/AxisGizmo.h +++ b/Code/Sandbox/Editor/Objects/AxisGizmo.h @@ -22,7 +22,6 @@ // forward declarations. struct DisplayContext; class CAxisHelper; -class CAxisHelperExtended; /** Gizmo of Objects animation track. */ @@ -75,7 +74,6 @@ private: CBaseObjectPtr m_object; AABB m_bbox; std::unique_ptr m_pAxisHelper; - std::unique_ptr m_pAxisHelperExtended; bool m_bDragging; QPoint m_cMouseDownPos; diff --git a/Code/Sandbox/Editor/Objects/BaseObject.cpp b/Code/Sandbox/Editor/Objects/BaseObject.cpp index a579f303a9..109b28798f 100644 --- a/Code/Sandbox/Editor/Objects/BaseObject.cpp +++ b/Code/Sandbox/Editor/Objects/BaseObject.cpp @@ -30,8 +30,6 @@ #include "DisplaySettings.h" #include "Undo/Undo.h" #include "UsedResources.h" -#include "Material/Material.h" -#include "Material/MaterialManager.h" #include "GizmoManager.h" #include "Include/IIconManager.h" #include "Objects/SelectionGroup.h" @@ -398,7 +396,6 @@ CBaseObject::CBaseObject() , m_classDesc(nullptr) , m_numRefs(0) , m_parent(nullptr) - , m_pMaterial(nullptr) , m_bInSelectionBox(false) , m_pTransformDelegate(nullptr) , m_bMatrixInWorldSpace(false) @@ -438,7 +435,6 @@ bool CBaseObject::Init([[maybe_unused]] IEditor* ie, CBaseObject* prev, [[maybe_ SetArea(prev->GetArea()); SetColor(prev->GetColor()); m_nMaterialLayersMask = prev->m_nMaterialLayersMask; - SetMaterial(prev->GetMaterial()); SetMinSpec(prev->GetMinSpec(), false); // Copy all basic variables. @@ -485,12 +481,6 @@ void CBaseObject::Done() NotifyListeners(CBaseObject::ON_DELETE); m_eventListeners.clear(); - - if (m_pMaterial) - { - m_pMaterial->Release(); - m_pMaterial = NULL; - } } ////////////////////////////////////////////////////////////////////////// @@ -1838,11 +1828,6 @@ void CBaseObject::Serialize(CObjectArchive& ar) SetFrozen(bFrozen); SetHidden(bHidden); - ////////////////////////////////////////////////////////////////////////// - // Load material. - ////////////////////////////////////////////////////////////////////////// - SetMaterial(mtlName); - ar.SetResolveCallback(this, parentId, AZStd::bind(&CBaseObject::ResolveParent, this, AZStd::placeholders::_1 )); ar.SetResolveCallback(this, lookatId, AZStd::bind(&CBaseObject::SetLookAt, this, AZStd::placeholders::_1)); @@ -1912,11 +1897,6 @@ void CBaseObject::Serialize(CObjectArchive& ar) xmlNode->setAttr("Flags", flags); } - if (m_pMaterial) - { - xmlNode->setAttr("Material", GetMaterialName().toUtf8().data()); - } - if (m_nMinSpec != 0) { xmlNode->setAttr("MinSpec", (uint32)m_nMinSpec); @@ -1937,11 +1917,6 @@ XmlNodeRef CBaseObject::Export([[maybe_unused]] const QString& levelPath, XmlNod objNode->setAttr("Type", GetTypeName().toUtf8().data()); objNode->setAttr("Name", GetName().toUtf8().data()); - if (m_pMaterial) - { - objNode->setAttr("Material", m_pMaterial->GetName().toUtf8().data()); - } - Vec3 pos, scale; Quat rotate; if (m_parent) @@ -2926,7 +2901,6 @@ bool CBaseObject::ConvertFromObject(CBaseObject* object) { object->GetParent()->AttachChild(this); } - SetMaterial(object->GetMaterial()); return true; } @@ -2981,14 +2955,6 @@ void CBaseObject::Validate(IErrorReport* report) report->ReportError(err); } ////////////////////////////////////////////////////////////////////////// - - if (GetMaterial() != NULL && GetMaterial()->IsDummy()) - { - CErrorRecord err; - err.error = QStringLiteral("Material: %1 for object: %2 not found,").arg(GetMaterial()->GetName(), GetName()); - err.pObject = this; - report->ReportError(err); - } }; ////////////////////////////////////////////////////////////////////////// @@ -3055,10 +3021,6 @@ void CBaseObject::GatherUsedResources(CUsedResources& resources) { GetVarBlock()->GatherUsedResources(resources); } - if (m_pMaterial) - { - m_pMaterial->GatherUsedResources(resources); - } } ////////////////////////////////////////////////////////////////////////// @@ -3071,50 +3033,6 @@ bool CBaseObject::IsSimilarObject(CBaseObject* pObject) return false; } -////////////////////////////////////////////////////////////////////////// -void CBaseObject::SetMaterial(CMaterial* mtl) -{ - if (m_pMaterial == mtl) - { - return; - } - - StoreUndo("Assign Material"); - if (m_pMaterial) - { - m_pMaterial->Release(); - } - m_pMaterial = mtl; - if (m_pMaterial) - { - m_pMaterial->AddRef(); - } - - OnMaterialChanged(MATERIALCHANGE_ALL); -} - -////////////////////////////////////////////////////////////////////////// -QString CBaseObject::GetMaterialName() const -{ - if (m_pMaterial) - { - return m_pMaterial->GetName(); - } - return ""; -} - -////////////////////////////////////////////////////////////////////////// -void CBaseObject::SetMaterial(const QString& materialName) -{ - CMaterial* pMaterial = NULL; - CMaterialManager* pManager = GetIEditor()->GetMaterialManager(); - if (!materialName.isEmpty() && pManager != NULL) - { - pMaterial = pManager->LoadMaterial(materialName); - } - SetMaterial(pMaterial); -} - ////////////////////////////////////////////////////////////////////////// void CBaseObject::SetMinSpec(uint32 nSpec, bool bSetChildren) { diff --git a/Code/Sandbox/Editor/Objects/BaseObject.h b/Code/Sandbox/Editor/Objects/BaseObject.h index d62e0bed5f..44df1e5757 100644 --- a/Code/Sandbox/Editor/Objects/BaseObject.h +++ b/Code/Sandbox/Editor/Objects/BaseObject.h @@ -35,7 +35,6 @@ class CUndoBaseObject; class CObjectManager; class CGizmo; class CObjectArchive; -class CMaterial; class CEdGeometry; struct SSubObjSelectionModifyContext; struct SRayHitInfo; @@ -135,13 +134,6 @@ enum ObjectEditFlags OBJECT_COLLAPSE_OBJECTPANEL = 0x004 }; -/////////////////////////////////////////////////////////////////////////// -enum MaterialChangeFlags -{ - MATERIALCHANGE_SURFACETYPE = 0x001, - MATERIALCHANGE_ALL = 0xFFFFFFFF, -}; - ////////////////////////////////////////////////////////////////////////// //! Return values from CBaseObject::MouseCreateCallback method. enum MouseCreateResult @@ -554,22 +546,6 @@ public: //! Remove event listener callback. void RemoveEventListener(EventListener* listener); - ////////////////////////////////////////////////////////////////////////// - //! Material handling for this base object. - //! Override in derived classes. - ////////////////////////////////////////////////////////////////////////// - //! Assign new material to this object. - virtual void SetMaterial(CMaterial* mtl); - //! Assign new material to this object as a material name. - virtual void SetMaterial(const QString& materialName); - //! Get assigned material for this object. - virtual CMaterial* GetMaterial() const { return m_pMaterial; }; - // Get actual rendering material for this object. - virtual CMaterial* GetRenderMaterial() const { return m_pMaterial; }; - // Get the material name. Even though the material pointer is null, the material name can exist separately. - virtual QString GetMaterialName() const; - virtual void OnMaterialChanged([[maybe_unused]] MaterialChangeFlags change) {} - ////////////////////////////////////////////////////////////////////////// //! Analyze errors for this object. virtual void Validate(IErrorReport* report); @@ -861,9 +837,6 @@ private: //! Pointer to parent node. mutable CBaseObject* m_parent; - //! Material of this object. - CMaterial* m_pMaterial; - AABB m_worldBounds; // The transform delegate diff --git a/Code/Sandbox/Editor/Objects/EntityObject.cpp b/Code/Sandbox/Editor/Objects/EntityObject.cpp index 8beda36013..0b2627091c 100644 --- a/Code/Sandbox/Editor/Objects/EntityObject.cpp +++ b/Code/Sandbox/Editor/Objects/EntityObject.cpp @@ -25,22 +25,14 @@ #include "Settings.h" #include "Viewport.h" #include "LineGizmo.h" -#include "Material/MaterialManager.h" #include "Include/IObjectManager.h" #include "Objects/ObjectManager.h" #include "ViewManager.h" -#include "LensFlareEditor/LensFlareManager.h" -#include "LensFlareEditor/LensFlareUtil.h" -#include "LensFlareEditor/LensFlareLibrary.h" #include "AnimationContext.h" #include "HitContext.h" #include "Objects/SelectionGroup.h" -const char* CEntityObject::s_LensFlarePropertyName("flare_Flare"); -const char* CEntityObject::s_LensFlareMaterialName("EngineAssets/Materials/lens_optics"); - - ////////////////////////////////////////////////////////////////////////// //! Undo Entity Link class CUndoEntityLink @@ -1084,11 +1076,6 @@ XmlNodeRef CEntityObject::Export([[maybe_unused]] const QString& levelPath, XmlN objNode->setAttr("Name", GetName().toUtf8().data()); - if (GetMaterial()) - { - objNode->setAttr("Material", GetMaterial()->GetName().toUtf8().data()); - } - Vec3 pos = GetPos(), scale = GetScale(); Quat rotate = GetRotation(); @@ -1867,17 +1854,6 @@ void CEntityObject::OnLoadFailed() GetIEditor()->GetErrorReport()->ReportError(err); } -////////////////////////////////////////////////////////////////////////// -CMaterial* CEntityObject::GetRenderMaterial() const -{ - if (GetMaterial()) - { - return GetMaterial(); - } - - return NULL; -} - ////////////////////////////////////////////////////////////////////////// void CEntityObject::SetHelperScale(float scale) { @@ -1950,21 +1926,6 @@ void CEntityObject::OnContextMenu(QMenu* pMenu) CBaseObject::OnContextMenu(pMenu); } -////////////////////////////////////////////////////////////////////////// -void CEntityObject::OnMaterialChanged(MaterialChangeFlags change) -{ - if (change & MATERIALCHANGE_SURFACETYPE) - { - m_statObjValidator.Validate(0, GetRenderMaterial()); - } -} - -////////////////////////////////////////////////////////////////////////// -QString CEntityObject::GetTooltip() const -{ - return m_statObjValidator.GetDescription(); -} - ////////////////////////////////////////////////////////////////////////// IOpticsElementBasePtr CEntityObject::GetOpticsElement() { @@ -1976,60 +1937,6 @@ IOpticsElementBasePtr CEntityObject::GetOpticsElement() return pLight->GetLensOpticsElement(); } -////////////////////////////////////////////////////////////////////////// -void CEntityObject::SetOpticsElement(IOpticsElementBase* pOptics) -{ - CDLight* pLight = GetLightProperty(); - if (pLight == NULL) - { - return; - } - pLight->SetLensOpticsElement(pOptics); - if (GetEntityPropertyBool("bFlareEnable") && pOptics) - { - CBaseObject::SetMaterial(s_LensFlareMaterialName); - } - else - { - SetMaterial(NULL); - } -} - -////////////////////////////////////////////////////////////////////////// -void CEntityObject::ApplyOptics(const QString& opticsFullName, IOpticsElementBasePtr pOptics) -{ - if (pOptics == NULL) - { - CDLight* pLight = GetLightProperty(); - if (pLight) - { - pLight->SetLensOpticsElement(NULL); - } - SetFlareName(""); - SetMaterial(NULL); - } - else - { - int nOpticsIndex(0); - if (!gEnv->pOpticsManager->Load(opticsFullName.toUtf8().data(), nOpticsIndex)) - { - IOpticsElementBasePtr pNewOptics = gEnv->pOpticsManager->Create(eFT_Root); - if (!gEnv->pOpticsManager->AddOptics(pNewOptics, opticsFullName.toUtf8().data(), nOpticsIndex)) - { - CDLight* pLight = GetLightProperty(); - if (pLight) - { - pLight->SetLensOpticsElement(NULL); - SetMaterial(NULL); - } - return; - } - LensFlareUtil::CopyOptics(pOptics, pNewOptics); - } - SetFlareName(opticsFullName); - } -} - ////////////////////////////////////////////////////////////////////////// void CEntityObject::SetOpticsName(const QString& opticsFullName) { @@ -2040,18 +1947,6 @@ void CEntityObject::SetOpticsName(const QString& opticsFullName) { pLight->SetLensOpticsElement(NULL); } - SetFlareName(""); - SetMaterial(NULL); - } - else - { - if (GetOpticsElement()) - { - if (gEnv->pOpticsManager->Rename(GetOpticsElement()->GetName(), opticsFullName.toUtf8().data())) - { - SetFlareName(opticsFullName); - } - } } } @@ -2080,27 +1975,6 @@ CDLight* CEntityObject::GetLightProperty() const return NULL; } -////////////////////////////////////////////////////////////////////////// -bool CEntityObject::GetValidFlareName(QString& outFlareName) const -{ - IVariable* pFlareVar(m_pProperties->FindVariable(s_LensFlarePropertyName)); - if (!pFlareVar) - { - return false; - } - - QString flareName; - pFlareVar->Get(flareName); - if (flareName.isEmpty() || flareName == "@root") - { - return false; - } - - outFlareName = flareName; - - return true; -} - ////////////////////////////////////////////////////////////////////////// void CEntityObject::PreInitLightProperty() { @@ -2108,42 +1982,6 @@ void CEntityObject::PreInitLightProperty() { return; } - - QString flareFullName; - if (GetValidFlareName(flareFullName)) - { - bool bEnableOptics = GetEntityPropertyBool("bFlareEnable"); - if (bEnableOptics) - { - CLensFlareManager* pLensManager = GetIEditor()->GetLensFlareManager(); - CLensFlareLibrary* pLevelLib = (CLensFlareLibrary*)pLensManager->GetLevelLibrary(); - IOpticsElementBasePtr pLevelOptics = pLevelLib->GetOpticsOfItem(flareFullName.toUtf8().data()); - if (pLevelLib && pLevelOptics) - { - int nOpticsIndex(0); - IOpticsElementBasePtr pNewOptics = GetOpticsElement(); - if (pNewOptics == NULL) - { - pNewOptics = gEnv->pOpticsManager->Create(eFT_Root); - } - - if (gEnv->pOpticsManager->AddOptics(pNewOptics, flareFullName.toUtf8().data(), nOpticsIndex)) - { - LensFlareUtil::CopyOptics(pLevelOptics, pNewOptics); - SetOpticsElement(pNewOptics); - } - else - { - CDLight* pLight = GetLightProperty(); - if (pLight) - { - pLight->SetLensOpticsElement(NULL); - SetMaterial(NULL); - } - } - } - } - } } ////////////////////////////////////////////////////////////////////////// @@ -2153,26 +1991,6 @@ void CEntityObject::UpdateLightProperty() { return; } - - QString flareName; - if (GetValidFlareName(flareName)) - { - IOpticsElementBasePtr pOptics = GetOpticsElement(); - if (pOptics == NULL) - { - pOptics = gEnv->pOpticsManager->Create(eFT_Root); - } - bool bEnableOptics = GetEntityPropertyBool("bFlareEnable"); - if (bEnableOptics && GetIEditor()->GetLensFlareManager()->LoadFlareItemByName(flareName, pOptics)) - { - pOptics->SetName(flareName.toUtf8().data()); - SetOpticsElement(pOptics); - } - else - { - SetOpticsElement(NULL); - } - } } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Objects/EntityObject.h b/Code/Sandbox/Editor/Objects/EntityObject.h index 9964cbd72f..a287cd8828 100644 --- a/Code/Sandbox/Editor/Objects/EntityObject.h +++ b/Code/Sandbox/Editor/Objects/EntityObject.h @@ -21,7 +21,6 @@ #include "IMovieSystem.h" #include "IEntityObjectListener.h" -#include "StatObjValidator.h" #include "Gizmo.h" #include "CryListenerSet.h" #include "StatObjBus.h" @@ -108,8 +107,6 @@ public: void SetEntityPropertyFloat(const char* name, float value); void SetEntityPropertyString(const char* name, const QString& value); - virtual QString GetTooltip() const; - virtual int MouseCreateCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); virtual void OnContextMenu(QMenu* menu); @@ -134,9 +131,6 @@ public: virtual void SetTransformDelegate(ITransformDelegate* pTransformDelegate) override; - virtual CMaterial* GetRenderMaterial() const; - virtual void OnMaterialChanged(MaterialChangeFlags change); - // Set attach flags and target enum EAttachmentType { @@ -221,10 +215,7 @@ public: IVariable* GetLightVariable(const char* name) const; IOpticsElementBasePtr GetOpticsElement(); - void SetOpticsElement(IOpticsElementBase* pOptics); - void ApplyOptics(const QString& opticsFullName, IOpticsElementBasePtr pOptics); void SetOpticsName(const QString& opticsFullName); - bool GetValidFlareName(QString& outFlareName) const; void PreInitLightProperty(); void UpdateLightProperty(); @@ -236,9 +227,6 @@ public: static void StoreUndoEntityLink(CSelectionGroup* pGroup); - static const char* s_LensFlarePropertyName; - static const char* s_LensFlareMaterialName; - void RegisterListener(IEntityObjectListener* pListener); void UnregisterListener(IEntityObjectListener* pListener); @@ -322,11 +310,6 @@ protected: void AdjustLightProperties(CVarBlockPtr& properties, const char* pSubBlock); IVariable* FindVariableInSubBlock(CVarBlockPtr& properties, IVariable* pSubBlockVar, const char* pVarName); - void SetFlareName(const QString& name) - { - SetEntityPropertyString(s_LensFlarePropertyName, name); - } - unsigned int m_bLoadFailed : 1; unsigned int m_bCalcPhysics : 1; unsigned int m_bDisplayBBox : 1; @@ -416,8 +399,6 @@ protected: static float m_helperScale; - CStatObjValidator m_statObjValidator; - EAttachmentType m_attachmentType; bool m_bEnableReload; diff --git a/Code/Sandbox/Editor/Objects/ObjectLoader.cpp b/Code/Sandbox/Editor/Objects/ObjectLoader.cpp index 746b9e8c73..41f543a5a3 100644 --- a/Code/Sandbox/Editor/Objects/ObjectLoader.cpp +++ b/Code/Sandbox/Editor/Objects/ObjectLoader.cpp @@ -17,7 +17,6 @@ // Editor #include "Util/PakFile.h" -#include "Material/MaterialManager.h" #include "WaitProgress.h" #include "Include/IObjectManager.h" @@ -239,14 +238,6 @@ void CObjectArchive::ResolveObjects() obj.pObject->CreateGameObject(); - CMaterial* pMaterial = obj.pObject->GetRenderMaterial(); - CMaterialManager* pManager = GetIEditor()->GetMaterialManager(); - - if (pMaterial && pMaterial->GetMatInfo() && pManager) - { - pManager->OnRequestMaterial(pMaterial->GetMatInfo()); - } - // unset the current validator object because the wait Step // might generate unrelated errors m_pCurrentErrorReport->SetCurrentValidatorObject(nullptr); diff --git a/Code/Sandbox/Editor/Objects/SelectionGroup.cpp b/Code/Sandbox/Editor/Objects/SelectionGroup.cpp index b883b78e49..08abf8f763 100644 --- a/Code/Sandbox/Editor/Objects/SelectionGroup.cpp +++ b/Code/Sandbox/Editor/Objects/SelectionGroup.cpp @@ -20,7 +20,7 @@ // Editor #include "ViewManager.h" -#include "SurfaceInfoPicker.h" +#include "Include/IObjectManager.h" ////////////////////////////////////////////////////////////////////////// @@ -238,16 +238,6 @@ void CSelectionGroup::Move(const Vec3& offset, EMoveSelectionFlag moveFlag, [[ma } SRayHitInfo pickedInfo; - if (moveFlag == eMS_FollowGeometryPosNorm && bValidFollowGeometryMode) - { - CSurfaceInfoPicker::CExcludedObjects excludeObjects; - for (int i = 0; i < GetFilteredCount(); ++i) - { - excludeObjects.Add(GetFilteredObject(i)); - } - CSurfaceInfoPicker surfacePicker; - bValidFollowGeometryMode = surfacePicker.Pick(point, pickedInfo, &excludeObjects); - } if (moveFlag == eMS_FollowGeometryPosNorm) { diff --git a/Code/Sandbox/Editor/Objects/StatObjValidator.cpp b/Code/Sandbox/Editor/Objects/StatObjValidator.cpp deleted file mode 100644 index 85226fb236..0000000000 --- a/Code/Sandbox/Editor/Objects/StatObjValidator.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "StatObjValidator.h" - -// Editor -#include "Material/Material.h" - - -CStatObjValidator::CStatObjValidator() - : m_isValid(true) -{ -} - -template -bool HasPrefix(const char* name, const char (&prefix)[size]) -{ - return _strnicmp(name, prefix, size - 1) == 0; -} - -struct SMeshMaterialIssue -{ - AZStd::string nodeName; - AZStd::string description; - int subMaterialIndex; - - SMeshMaterialIssue() - : subMaterialIndex(-1) - { - } - - SMeshMaterialIssue(const AZStd::string& name, const AZStd::string& description) - : nodeName(name) - , description(description) - , subMaterialIndex(-1) - { - } -}; - -static void ValidateMeshMaterials(std::vector* issues, IStatObj* pStatObj, CMaterial* pMaterial) -{ - _smart_ptr pIMaterial = 0; - if (pMaterial) - { - if (pMaterial->GetParent()) - { - pIMaterial = pMaterial->GetParent()->GetMatInfo(); - } - else - { - pIMaterial = pMaterial->GetMatInfo(); - } - } - - IIndexedMesh* pIndexedMesh = pStatObj->GetIndexedMesh(true); - if (pIndexedMesh) - { - int breakableSubmeshes = 0; - int nonbreakableSubmeshes = 0; - - int subsetCount = pIndexedMesh->GetSubSetCount(); - for (int i = 0; i < subsetCount; ++i) - { - const SMeshSubset& subset = pIndexedMesh->GetSubSet(i); - if (subset.nNumVerts == 0) - { - continue; - } - - // Check to see if the material uses multiple uv sets and if the vertex format has the same number of texCoord attributes - SShaderItem shaderItem = pIMaterial->GetShaderItem(i); - if (shaderItem.m_pShader) - { - size_t materialUVs = shaderItem.m_pShader->GetNumberOfUVSets(); - size_t meshUVs = subset.vertexFormat.GetAttributeUsageCount(AZ::Vertex::AttributeUsage::TexCoord); - if (materialUVs != meshUVs) - { - const char* meshName = pStatObj->GetRenderMesh() ? pStatObj->GetRenderMesh()->GetSourceName() : "unknown"; - AZStd::string errorMessage; - errorMessage = AZStd::string::format("Material '%s' sub-material %d with %zu uv set(s) was assigned to mesh '%s' with %zu uv set(s). ", pIMaterial->GetName(), i + 1, materialUVs, meshName, meshUVs); - - AZStd::string recommendedAction; - if (materialUVs < meshUVs) - { - recommendedAction = AZStd::string::format("If you do not intend to use %zu uv sets, remove the extra uv set(s) from the source mesh during the import process. Otherwise, consider checking the desired 'Use uv set 2 for...' shader gen params in the material editor.", meshUVs); - } - else - { - recommendedAction = AZStd::string::format("If you intend to use %zu uv sets, include the additional uv set(s) in the source mesh during the import process. Otherwise, consider unchecking the 'Use uv set 2 for...' shader gen params in the material editor.", materialUVs); - } - errorMessage += recommendedAction; - AZ_Warning("Material Editor", false, errorMessage.c_str()); - SMeshMaterialIssue issue(meshName, errorMessage); - issues->push_back(issue); - } - } - - _smart_ptr pSubMaterial = pIMaterial->GetSubMtl(subset.nMatID); - if (!pSubMaterial) - { - continue; - } - - if (size_t(subset.nMatID) > size_t(pMaterial->GetSubMaterialCount())) - { - continue; - } - - if (pSubMaterial->GetSurfaceType()->GetBreakable2DParams()) - { - ++breakableSubmeshes; - } - else - { - ++nonbreakableSubmeshes; - } - } - } - - - int subobjectCount = pStatObj->GetSubObjectCount(); - for (int i = 0; i < subobjectCount; ++i) - { - const IStatObj::SSubObject* subobject = pStatObj->GetSubObject(i); - if (subobject->pStatObj) - { - ValidateMeshMaterials(issues, subobject->pStatObj, pMaterial); - } - } -} - -void CStatObjValidator::Validate(IStatObj* statObj, CMaterial* editorMaterial) -{ - m_description = QString(); - m_isValid = true; - - _smart_ptr pIMaterial = 0; - if (editorMaterial) - { - if (editorMaterial->GetParent()) - { - pIMaterial = editorMaterial->GetParent()->GetMatInfo(); - } - else - { - pIMaterial = editorMaterial->GetMatInfo(); - } - } - - if (statObj && editorMaterial) - { - std::vector issues; - ValidateMeshMaterials(&issues, statObj, editorMaterial); - - if (!issues.empty()) - { - m_isValid = false; - } - - for (size_t i = 0; i < issues.size(); ++i) - { - const SMeshMaterialIssue& issue = issues[i]; - if (!m_description.isEmpty()) - { - m_description += "\n"; - } - if (!issue.nodeName.empty()) - { - m_description += "Node "; - m_description += issue.nodeName.c_str(); - m_description += ":"; - } - if (issue.subMaterialIndex >= 0) - { - m_description += QStringLiteral("SubMaterial %1:").arg(issue.subMaterialIndex + 1); - } - if (!issue.nodeName.empty() || issue.subMaterialIndex >= 0) - { - m_description += "\n "; - } - if (!issue.description.empty()) - { - m_description += issue.description.c_str(); - } - } - } -} - diff --git a/Code/Sandbox/Editor/Objects/StatObjValidator.h b/Code/Sandbox/Editor/Objects/StatObjValidator.h deleted file mode 100644 index 40145e90c5..0000000000 --- a/Code/Sandbox/Editor/Objects/StatObjValidator.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// This class is supposed to validate CGF with assigned material. -// Some of the asset issues may be diagnosed only when SurfaceType is known. - -#pragma once - -class CRYEDIT_API CStatObjValidator -{ -public: - CStatObjValidator(); - - void Validate(IStatObj* statObj, CMaterial* editorMaterial); - bool IsValid() const { return m_isValid; } - - QString GetDescription() const { return m_description; } -private: - bool m_isValid; - QString m_description; -}; - diff --git a/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake b/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake index 484974745d..62523369e7 100644 --- a/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake +++ b/Code/Sandbox/Editor/Platform/Mac/editor_mac.cmake @@ -9,13 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_bundle_resources( - TARGET Editor - FILES - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/xmlfilter.txt - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/rc.ini -) - # Set resources directory for app icons target_sources(Editor PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Images.xcassets) set_target_properties(Editor PROPERTIES diff --git a/Code/Sandbox/Editor/RenderHelpers/AxisHelperExtended.cpp b/Code/Sandbox/Editor/RenderHelpers/AxisHelperExtended.cpp deleted file mode 100644 index cee7f0f716..0000000000 --- a/Code/Sandbox/Editor/RenderHelpers/AxisHelperExtended.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "AxisHelperExtended.h" - -#include "CryPhysicsDeprecation.h" - -// Editor -#include "Include/IDisplayViewport.h" -#include "SurfaceInfoPicker.h" -#include "Objects/DisplayContext.h" -#include "Objects/SelectionGroup.h" -#include "Util/fastlib.h" - - -////////////////////////////////////////////////////////////////////////// -// Helper Extended Axis object. -////////////////////////////////////////////////////////////////////////// -CAxisHelperExtended::CAxisHelperExtended() - : m_matrix(IDENTITY) - , m_vPos(ZERO) - , m_pCurObject(0) - , m_dwLastUpdateTime(0) - , m_fMaxDist(100.0f) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CAxisHelperExtended::DrawAxes(DisplayContext& dc, const Matrix34& matrix, bool bUsePhysicalProxy) -{ - const DWORD dwUpdateTime = 2000; // 2 sec - CSelectionGroup* pSel = GetIEditor()->GetSelection(); - int numSels = pSel->GetCount(); - - if (numSels == 0) - { - return; - } - - CBaseObject* pCurObject = pSel->GetObject(numSels - 1); // get just last object for simple check - - // Add current selection to the elements to be skipped - CRY_PHYSICS_REPLACEMENT_ASSERT(); - - Vec3 x = Vec3(1, 0, 0); - Vec3 y = Vec3(0, 1, 0); - Vec3 z = Vec3(0, 0, 1); - - Vec3 colR = Vec3(1, 0, 0); - Vec3 colG = Vec3(0, 1, 0); - Vec3 colB = Vec3(0, 0.8f, 1); - - m_vPos = matrix.GetTranslation(); - - Vec3 vDirX = (matrix * x - m_vPos); - Vec3 vDirY = (matrix * y - m_vPos); - Vec3 vDirZ = (matrix * z - m_vPos); - vDirX.Normalize(); - vDirY.Normalize(); - vDirZ.Normalize(); - - if ( - m_pCurObject != pCurObject || - GetTickCount() - m_dwLastUpdateTime > dwUpdateTime || - !Matrix34::IsEquivalent(m_matrix, matrix) - ) - { - Vec3 outTmp; - AABB aabb(m_vPos, m_fMaxDist); - m_objects.clear(); - CBaseObjectsArray allObjects; - GetIEditor()->GetObjectManager()->GetObjects(allObjects); - - for (size_t i = 0, n = allObjects.size(); i < n; ++i) - { - CBaseObject* pObject = allObjects[i]; - if (pObject->IsSelected() || !pObject->GetEngineNode()) - { - continue; - } - - AABB aabbObj; - pObject->GetBoundBox(aabbObj); - - if (!Intersect::Ray_AABB(m_vPos, vDirX, aabbObj, outTmp) - && !Intersect::Ray_AABB(m_vPos, vDirY, aabbObj, outTmp) - && !Intersect::Ray_AABB(m_vPos, vDirZ, aabbObj, outTmp) - && !Intersect::Ray_AABB(m_vPos, -vDirX, aabbObj, outTmp) - && !Intersect::Ray_AABB(m_vPos, -vDirY, aabbObj, outTmp) - && !Intersect::Ray_AABB(m_vPos, -vDirZ, aabbObj, outTmp)) - { - continue; - } - - if (aabb.IsIntersectBox(aabbObj)) - { - m_objects.push_back(pObject); - } - } - m_dwLastUpdateTime = GetTickCount(); - } - m_pCurObject = pCurObject; - m_matrix = matrix; - - DrawAxis(dc, vDirX, z, colR, bUsePhysicalProxy); - DrawAxis(dc, vDirY, z, colG, bUsePhysicalProxy); - DrawAxis(dc, vDirZ, x, colB, bUsePhysicalProxy); - DrawAxis(dc, -vDirX, z, colR, bUsePhysicalProxy); - DrawAxis(dc, -vDirY, z, colG, bUsePhysicalProxy); - DrawAxis(dc, -vDirZ, x, colB, bUsePhysicalProxy); -} - - -////////////////////////////////////////////////////////////////////////// -void CAxisHelperExtended::DrawAxis(DisplayContext& dc, const Vec3& vDir, const Vec3& vUpAxis, const Vec3& col, bool bUsePhysicalProxy) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - const float fBallSize = 0.005f; - const float fTextSize = 1.4f; - - float fDist = m_fMaxDist + 1.0f; - size_t objectsSize = m_objects.size(); - for (size_t i = 0; i < objectsSize; ++i) - { - CBaseObject* pObject = m_objects[i]; - if (pObject->CheckFlags(OBJFLAG_DELETED)) - { - continue; - } - - SRayHitInfo hitInfo; - if (pObject->IntersectRayMesh(m_vPos, vDir, hitInfo)) - { - Vec3 newP = pObject->GetWorldTM().TransformPoint(hitInfo.vHitPos); - float fNewDist = (newP - m_vPos).GetLength(); - if (fDist > fNewDist) - { - fDist = fNewDist; - } - } - } - - if (bUsePhysicalProxy) - { - CRY_PHYSICS_REPLACEMENT_ASSERT(); - } - else - { - CSurfaceInfoPicker picker; - m_objectsForPicker.assign(m_objects.begin(), m_objects.end()); - picker.SetObjects(&m_objectsForPicker); - SRayHitInfo hitInfo; - if (picker.Pick(m_vPos, fDist * vDir, hitInfo, NULL, CSurfaceInfoPicker::ePOG_All)) - { - fDist = hitInfo.fDistance; - } - picker.SetObjects(0); - } - - if (fDist < m_fMaxDist) - { - Vec3 p = m_vPos + vDir * fDist; - - dc.SetColor(col); - dc.DrawLine(m_vPos, p); - float fScreenScale = dc.view->GetScreenScaleFactor(p); - dc.DrawBall(p, fBallSize * fScreenScale); - QString label; - label = QString::number(fDist, 'f', 2); - dc.DrawTextOn2DBox((p + m_vPos) * 0.5f, label.toUtf8().data(), fTextSize, col, ColorF(0.0f, 0.0f, 0.0f, 0.7f)); - - Vec3 vUp = (m_matrix * vUpAxis - m_vPos); - vUp.Normalize(); - - Vec3 u = vUp; - Vec3 v = vDir ^ vUp; - float fPlaneSize = fDist / 4.0f; - float alphaMax = 1.0f, alphaMin = 0.0f; - ColorF colAlphaMin = ColorF(col.x, col.y, col.z, alphaMin); - - float fStepSize = dc.view->GetGridStep(); - const int MIN_STEP_COUNT = 5; - const int MAX_STEP_COUNT = 20; - int nSteps = std::min(std::max(FloatToIntRet(fPlaneSize / fStepSize), MIN_STEP_COUNT), MAX_STEP_COUNT); - float fGridSize = nSteps * fStepSize; - - for (int i = -nSteps; i <= nSteps; ++i) - { - Vec3 stepV = v * (fStepSize * i); - Vec3 stepU = u * (fStepSize * i); - ColorF colCurAlpha = ColorF(col.x, col.y, col.z, alphaMax - fabsf(float(i) / float(nSteps)) * (alphaMax - alphaMin)); - // Draw u lines. - dc.DrawLine(p + stepV, p + u * fGridSize + stepV, colCurAlpha, colAlphaMin); - dc.DrawLine(p + stepV, p - u * fGridSize + stepV, colCurAlpha, colAlphaMin); - // Draw v lines. - dc.DrawLine(p + stepU, p + v * fGridSize + stepU, colCurAlpha, colAlphaMin); - dc.DrawLine(p + stepU, p - v * fGridSize + stepU, colCurAlpha, colAlphaMin); - } - } -} diff --git a/Code/Sandbox/Editor/RenderHelpers/AxisHelperExtended.h b/Code/Sandbox/Editor/RenderHelpers/AxisHelperExtended.h deleted file mode 100644 index 42a1c66b9c..0000000000 --- a/Code/Sandbox/Editor/RenderHelpers/AxisHelperExtended.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_RENDERHELPERS_AXISHELPEREXTENDED_H -#define CRYINCLUDE_EDITOR_RENDERHELPERS_AXISHELPEREXTENDED_H -#pragma once - -#include "Objects/BaseObject.h" -#include "Include/IObjectManager.h" - -struct DisplayContext; -struct HitContext; - -class CAxisHelperExtended -{ -public: - CAxisHelperExtended(); - void DrawAxes(DisplayContext& dc, const Matrix34& matrix, bool bUsePhysicalProxy); - -private: - void DrawAxis(DisplayContext& dc, const Vec3& vDirAxis, const Vec3& vUpAxis, const Vec3& col, bool bUsePhysicalProxy); - -private: - Matrix34 m_matrix; - Vec3 m_vPos; - std::vector m_objects; - CBaseObjectsArray m_objectsForPicker; - CBaseObject* m_pCurObject; - DWORD m_dwLastUpdateTime; - - float m_fMaxDist; -}; - -#endif // CRYINCLUDE_EDITOR_RENDERHELPERS_AXISHELPEREXTENDED_H diff --git a/Code/Sandbox/Editor/RenderViewport.cpp b/Code/Sandbox/Editor/RenderViewport.cpp index cac1840b75..3e726f2468 100644 --- a/Code/Sandbox/Editor/RenderViewport.cpp +++ b/Code/Sandbox/Editor/RenderViewport.cpp @@ -42,7 +42,6 @@ # include #endif // defined(AZ_PLATFORM_WINDOWS) #include // for AzFramework::InputDeviceMouse -#include // AzQtComponents #include @@ -275,13 +274,10 @@ void CRenderViewport::resizeEvent(QResizeEvent* event) gEnv->pSystem->GetISystemEventDispatcher()->OnSystemEvent(ESYSTEM_EVENT_RESIZE, width(), height()); - if (AZ::Interface::Get()) - { - // We queue the window resize event because the render overlay may be hidden. - // If the render overlay is not visible, the native window that is backing it will - // also be hidden, and it will not resize until it becomes visible. - m_windowResizedEvent = true; - } + // We queue the window resize event because the render overlay may be hidden. + // If the render overlay is not visible, the native window that is backing it will + // also be hidden, and it will not resize until it becomes visible. + m_windowResizedEvent = true; } ////////////////////////////////////////////////////////////////////////// @@ -1553,14 +1549,6 @@ void CRenderViewport::OnRender() if (levelIsDisplayable) { m_renderer->SetViewport(0, 0, m_renderer->GetWidth(), m_renderer->GetHeight(), m_nCurViewportID); - - if (!AZ::Interface::Get()) - { - m_engine->Tick(); - m_engine->Update(); - - m_engine->RenderWorld(SHDF_ALLOW_AO | SHDF_ALLOWPOSTPROCESS | SHDF_ALLOW_WATER | SHDF_ALLOWHDR | SHDF_ZPASS, SRenderingPassInfo::CreateGeneralPassRenderingInfo(m_Camera), __FUNCTION__); - } } else { @@ -3659,11 +3647,8 @@ bool CRenderViewport::CreateRenderContext() { m_bRenderContextCreated = true; - if (AZ::Interface::Get()) - { - AzFramework::WindowRequestBus::Handler::BusConnect(renderOverlayHWND()); - AzFramework::WindowSystemNotificationBus::Broadcast(&AzFramework::WindowSystemNotificationBus::Handler::OnWindowCreated, renderOverlayHWND()); - } + AzFramework::WindowRequestBus::Handler::BusConnect(renderOverlayHWND()); + AzFramework::WindowSystemNotificationBus::Broadcast(&AzFramework::WindowSystemNotificationBus::Handler::OnWindowCreated, renderOverlayHWND()); WIN_HWND oldContext = m_renderer->GetCurrentContextHWND(); m_renderer->CreateContext(renderOverlayHWND()); diff --git a/Code/Sandbox/Editor/Resource.h b/Code/Sandbox/Editor/Resource.h index 78a9855d71..51f9b1f3e9 100644 --- a/Code/Sandbox/Editor/Resource.h +++ b/Code/Sandbox/Editor/Resource.h @@ -95,9 +95,6 @@ #define ID_CHANGEMOVESPEED_INCREASE 32928 #define ID_CHANGEMOVESPEED_DECREASE 32929 #define ID_CHANGEMOVESPEED_CHANGESTEP 32930 -#define ID_MATERIAL_ASSIGNCURRENT 32933 -#define ID_MATERIAL_RESETTODEFAULT 32934 -#define ID_MATERIAL_GETMATERIAL 32935 #define ID_PHYSICS_GETPHYSICSSTATE 32937 #define ID_PHYSICS_RESETPHYSICSSTATE 32938 #define ID_GAME_SYNCPLAYER 32941 diff --git a/Code/Sandbox/Editor/Style/resources.qrc b/Code/Sandbox/Editor/Style/resources.qrc index aa32f29555..aec7e2cf68 100644 --- a/Code/Sandbox/Editor/Style/resources.qrc +++ b/Code/Sandbox/Editor/Style/resources.qrc @@ -4,6 +4,5 @@ EditorPreferencesDialog.qss LayoutConfigDialog.qss GraphicsSettingsDialog.qss - LensFlareEditor.qss diff --git a/Code/Sandbox/Editor/SurfaceInfoPicker.cpp b/Code/Sandbox/Editor/SurfaceInfoPicker.cpp deleted file mode 100644 index f3d06e0017..0000000000 --- a/Code/Sandbox/Editor/SurfaceInfoPicker.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "SurfaceInfoPicker.h" - -// AzToolsFramework -#include - -// Editor -#include "Material/MaterialManager.h" -#include "Objects/EntityObject.h" -#include "Viewport.h" -#include "QtViewPane.h" - -// ComponentEntityEditorPlugin -#include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h" - -// LmbrCentral -#include -#include - - -static const float kEnoughFarDistance(5000.0f); - -CSurfaceInfoPicker::CSurfaceInfoPicker() - : m_pObjects(NULL) - , m_pSetObjects(NULL) - , m_PickOption(0) -{ - m_pActiveView = GetIEditor()->GetActiveView(); -} - -bool CSurfaceInfoPicker::PickByAABB(const QPoint& point, [[maybe_unused]] int nFlag, IDisplayViewport* pView, CExcludedObjects* pExcludedObjects, std::vector* pOutObjects) -{ - GetIEditor()->GetObjectManager()->GetObjects(m_objects); - - Vec3 vWorldRaySrc, vWorldRayDir; - m_pActiveView->ViewToWorldRay(point, vWorldRaySrc, vWorldRayDir); - vWorldRaySrc = vWorldRaySrc + vWorldRayDir * 0.1f; - vWorldRayDir = vWorldRayDir * kEnoughFarDistance; - - bool bPicked = false; - - for (int i = 0, iCount(m_objects.size()); i < iCount; ++i) - { - if (pExcludedObjects && pExcludedObjects->Contains(m_objects[i])) - { - continue; - } - - AABB worldObjAABB; - m_objects[i]->GetBoundBox(worldObjAABB); - - if (pView) - { - float fScreenFactor = pView->GetScreenScaleFactor(m_objects[i]->GetPos()); - worldObjAABB.Expand(0.01f * Vec3(fScreenFactor, fScreenFactor, fScreenFactor)); - } - - Vec3 vHitPos; - if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, worldObjAABB, vHitPos)) - { - if ((vHitPos - vWorldRaySrc).GetNormalized().Dot(vWorldRayDir) > 0 || worldObjAABB.IsContainPoint(vHitPos)) - { - if (pOutObjects) - { - pOutObjects->push_back(m_objects[i]); - } - bPicked = true; - } - } - } - - return bPicked; -} - -bool CSurfaceInfoPicker::PickImpl(const QPoint& point, - _smart_ptr* ppOutLastMaterial, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects, - int nFlag) -{ - Vec3 vWorldRaySrc; - Vec3 vWorldRayDir; - if (!m_pActiveView) - { - m_pActiveView = GetIEditor()->GetActiveView(); - } - m_pActiveView->ViewToWorldRay(point, vWorldRaySrc, vWorldRayDir); - vWorldRaySrc = vWorldRaySrc + vWorldRayDir * 0.1f; - vWorldRayDir = vWorldRayDir * kEnoughFarDistance; - - return PickImpl(vWorldRaySrc, vWorldRayDir, ppOutLastMaterial, outHitInfo, pExcludedObjects, nFlag); -} - -bool CSurfaceInfoPicker::PickImpl(const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, - _smart_ptr* ppOutLastMaterial, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects, - int nFlag) -{ - memset(&outHitInfo, 0, sizeof(outHitInfo)); - outHitInfo.fDistance = kEnoughFarDistance; - - if (m_pSetObjects) - { - m_pObjects = m_pSetObjects; - } - else - { - GetIEditor()->GetObjectManager()->GetObjects(m_objects); - m_pObjects = &m_objects; - } - - if (pExcludedObjects) - { - m_ExcludedObjects = *pExcludedObjects; - } - else - { - m_ExcludedObjects.Clear(); - } - - m_pPickedObject = NULL; - - if (nFlag & ePOG_Entity) - { - FindNearestInfoFromEntities(vWorldRaySrc, vWorldRayDir, ppOutLastMaterial, outHitInfo); - } - - if (!m_pSetObjects) - { - m_objects.clear(); - } - - m_ExcludedObjects.Clear(); - - return outHitInfo.fDistance < kEnoughFarDistance; -} - -void CSurfaceInfoPicker::FindNearestInfoFromEntities( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - _smart_ptr* pOutLastMaterial, - SRayHitInfo& outHitInfo) const -{ - for (size_t i = 0; i < m_pObjects->size(); ++i) - { - CBaseObject* object((*m_pObjects)[i]); - - if (object == nullptr - || !qobject_cast(object) - || object->IsHidden() - || IsFrozen(object) - || m_ExcludedObjects.Contains(object) - ) - { - continue; - } - - CEntityObject* entityObject = static_cast(object); - - // If a legacy entity doesn't have a material override, we'll get the default material for that statObj - _smart_ptr statObjDefaultMaterial = nullptr; - // And in some cases the material we want does comes from RayIntersection(), and we will skip AssignObjectMaterial(). - _smart_ptr pickedMaterial = nullptr; - - bool hit = false; - - // entityObject is a component entity... - if (entityObject->GetType() == OBJTYPE_AZENTITY) - { - AZ::EntityId id; - AzToolsFramework::ComponentEntityObjectRequestBus::EventResult(id, entityObject, &AzToolsFramework::ComponentEntityObjectRequestBus::Events::GetAssociatedEntityId); - - AZ::EBusAggregateResults statObjs; - LmbrCentral::LegacyMeshComponentRequestBus::EventResult(statObjs, id, &LmbrCentral::LegacyMeshComponentRequestBus::Events::GetStatObj); - - // If the entity has a MeshComponent, it will hit here - for (IStatObj* statObj : statObjs.values) - { - hit = RayIntersection(vWorldRaySrc, vWorldRayDir, nullptr, statObj, object->GetWorldTM(), outHitInfo, &statObjDefaultMaterial); - if (hit) - { - break; - } - } - - // If the entity has an ActorComponent or another component that overrides RenderNodeRequestBus, it will hit here - if (!hit) - { - // There might be multiple components with render nodes on the same entity - // This will get the highest priority one, as determined by RenderNodeRequests::GetRenderNodeRequestBusOrder - IRenderNode* renderNode = entityObject->GetEngineNode(); - - // If the renderNode exists and is physicalized, it will hit here - hit = RayIntersection_IRenderNode(vWorldRaySrc, vWorldRayDir, renderNode, &pickedMaterial, object->GetWorldTM(), outHitInfo); - if (!hit) - { - // If the renderNode is not physicalized, such as an actor component, but still exists and has a valid material we might want to pick - if (renderNode && renderNode->GetMaterial()) - { - // Do a hit test with anything in this entity that has overridden EditorComponentSelectionRequestsBus - CComponentEntityObject* componentEntityObject = static_cast(entityObject); - HitContext hc; - hc.raySrc = vWorldRaySrc; - hc.rayDir = vWorldRayDir; - bool intersects = componentEntityObject->HitTest(hc); - - if (intersects) - { - // If the distance is closer than the nearest distance so far - if (hc.dist < outHitInfo.fDistance) - { - hit = true; - outHitInfo.vHitPos = hc.raySrc + hc.rayDir * hc.dist; - outHitInfo.fDistance = hc.dist; - // We don't get material/sub-material information back from HitTest, so just use the material from the render node - pickedMaterial = renderNode->GetMaterial(); - outHitInfo.nHitMatID = 0; - // We don't get normal information back from HitTest, so just orient the selection disk towards the camera - outHitInfo.vHitNormal = vWorldRayDir.normalized(); - } - } - } - } - } - - // If the entity has a GeometryCacheComponent it will hit here - if (!hit) - { - IGeomCacheRenderNode* geomCacheRenderNode = nullptr; - LmbrCentral::GeometryCacheComponentRequestBus::EventResult(geomCacheRenderNode, id, &LmbrCentral::GeometryCacheComponentRequestBus::Events::GetGeomCacheRenderNode); - hit = RayIntersection_IGeomCacheRenderNode(vWorldRaySrc, vWorldRayDir, geomCacheRenderNode, &pickedMaterial, object->GetWorldTM(), outHitInfo); - } - } - - if (hit) - { - if(pickedMaterial) - { - AssignMaterial(pickedMaterial, outHitInfo, pOutLastMaterial); - } - else - { - if (object->GetMaterial()) - { - // If the entity has a material override, assign the object material - AssignObjectMaterial(object, outHitInfo, pOutLastMaterial); - } - else - { - // Otherwise assign the default material for that object - AssignMaterial(statObjDefaultMaterial, outHitInfo, pOutLastMaterial); - } - } - - m_pPickedObject = object; - } - } -} - -bool CSurfaceInfoPicker::RayIntersection_CBaseObject( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - CBaseObject* pBaseObject, - _smart_ptr* pOutLastMaterial, - SRayHitInfo& outHitInfo) -{ - if (pBaseObject == NULL) - { - return false; - } - IRenderNode* pRenderNode(pBaseObject->GetEngineNode()); - if (pRenderNode == NULL) - { - return false; - } - IStatObj* pStatObj(pRenderNode->GetEntityStatObj()); - if (pStatObj == NULL) - { - return false; - } - return RayIntersection(vWorldRaySrc, vWorldRayDir, pRenderNode, pStatObj, pBaseObject->GetWorldTM(), outHitInfo, pOutLastMaterial); -} - -bool CSurfaceInfoPicker::RayIntersection( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IRenderNode* pRenderNode, - IStatObj* pStatObj, - const Matrix34A& WorldTM, - SRayHitInfo& outHitInfo, - _smart_ptr* ppOutLastMaterial) -{ - SRayHitInfo hitInfo; - bool bRayIntersection = false; - _smart_ptr pMaterial(NULL); - - bRayIntersection = RayIntersection_IStatObj(vWorldRaySrc, vWorldRayDir, pStatObj, &pMaterial, WorldTM, hitInfo); - if (!bRayIntersection) - { - bRayIntersection = RayIntersection_IRenderNode(vWorldRaySrc, vWorldRayDir, pRenderNode, &pMaterial, WorldTM, hitInfo); - } - - if (bRayIntersection) - { - hitInfo.fDistance = vWorldRaySrc.GetDistance(hitInfo.vHitPos); - if (hitInfo.fDistance < outHitInfo.fDistance) - { - if (ppOutLastMaterial) - { - *ppOutLastMaterial = pMaterial; - } - memcpy(&outHitInfo, &hitInfo, sizeof(SRayHitInfo)); - outHitInfo.vHitNormal.Normalize(); - return true; - } - } - return false; -} - -bool CSurfaceInfoPicker::RayIntersection_IStatObj( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IStatObj* pStatObj, - _smart_ptr* ppOutLastMaterial, - const Matrix34A& worldTM, - SRayHitInfo& outHitInfo) -{ - if (pStatObj == NULL) - { - return false; - } - - Vec3 localRaySrc; - Vec3 localRayDir; - if (!RayWorldToLocal(worldTM, vWorldRaySrc, vWorldRayDir, localRaySrc, localRayDir)) - { - return false; - } - - // the outHitInfo contains information about the previous closest hit and should not be cleared / replaced unless you have a better hit! - // all of the intersection functions called (such as statobj's RayIntersection) only modify the hit info if it actually hits it closer than the current distance of the last hit. - - outHitInfo.inReferencePoint = localRaySrc; - outHitInfo.inRay = Ray(localRaySrc, localRayDir); - outHitInfo.bInFirstHit = false; - outHitInfo.bUseCache = false; - - _smart_ptr hitMaterial = nullptr; - - Vec3 hitPosOnAABB; - if (Intersect::Ray_AABB(outHitInfo.inRay, pStatObj->GetAABB(), hitPosOnAABB) == 0x00) - { - return false; - } - - if (pStatObj->RayIntersection(outHitInfo)) - { - if (outHitInfo.fDistance < 0) - { - return false; - } - outHitInfo.vHitPos = worldTM.TransformPoint(outHitInfo.vHitPos); - outHitInfo.vHitNormal = worldTM.GetTransposed().GetInverted().TransformVector(outHitInfo.vHitNormal); - - // we need to set nHitSurfaceID anyway - so we need to do this regardless of whether the caller - // has asked for detailed material info by passing in a non-null ppOutLastMaterial - hitMaterial = pStatObj->GetMaterial(); - - if (hitMaterial) - { - if (outHitInfo.nHitMatID >= 0) - { - if (hitMaterial->GetSubMtlCount() > 0 && outHitInfo.nHitMatID < hitMaterial->GetSubMtlCount()) - { - _smart_ptr subMaterial = hitMaterial->GetSubMtl(outHitInfo.nHitMatID); - if (subMaterial) - { - hitMaterial = subMaterial; - } - } - } - outHitInfo.nHitSurfaceID = hitMaterial->GetSurfaceTypeId(); - } - - if ((ppOutLastMaterial) && (hitMaterial)) - { - *ppOutLastMaterial = hitMaterial; - } - - return true; - } - - return outHitInfo.fDistance < kEnoughFarDistance; -} - -#if defined(USE_GEOM_CACHES) -bool CSurfaceInfoPicker::RayIntersection_IGeomCacheRenderNode( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IGeomCacheRenderNode* pGeomCacheRenderNode, - _smart_ptr* ppOutLastMaterial, - [[maybe_unused]] const Matrix34A& worldTM, - SRayHitInfo& outHitInfo) -{ - if (!pGeomCacheRenderNode) - { - return false; - } - - SRayHitInfo newHitInfo = outHitInfo; - newHitInfo.inReferencePoint = vWorldRaySrc; - newHitInfo.inRay = Ray(vWorldRaySrc, vWorldRayDir); - newHitInfo.bInFirstHit = false; - newHitInfo.bUseCache = false; - - if (pGeomCacheRenderNode->RayIntersection(newHitInfo)) - { - if (newHitInfo.fDistance < 0 || newHitInfo.fDistance > kEnoughFarDistance || (outHitInfo.fDistance != 0 && newHitInfo.fDistance > outHitInfo.fDistance)) - { - return false; - } - - // Only override outHitInfo if the new hit is closer than the original hit - outHitInfo = newHitInfo; - if (ppOutLastMaterial) - { - _smart_ptr pMaterial = pGeomCacheRenderNode->GetMaterial(); - if (pMaterial) - { - *ppOutLastMaterial = pMaterial; - if (outHitInfo.nHitMatID >= 0) - { - if (pMaterial->GetSubMtlCount() > 0 && outHitInfo.nHitMatID < pMaterial->GetSubMtlCount()) - { - *ppOutLastMaterial = pMaterial->GetSubMtl(outHitInfo.nHitMatID); - } - } - } - } - return true; - } - - return false; -} -#endif - -bool CSurfaceInfoPicker::RayIntersection_IRenderNode( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IRenderNode* pRenderNode, - _smart_ptr* pOutLastMaterial, - [[maybe_unused]] const Matrix34A& WorldTM, - SRayHitInfo& outHitInfo) -{ - if (pRenderNode == NULL) - { - return false; - } - - AZ_UNUSED(vWorldRaySrc) - AZ_UNUSED(vWorldRayDir) - AZ_UNUSED(pRenderNode) - AZ_UNUSED(pOutLastMaterial) - AZ_UNUSED(WorldTM) - AZ_UNUSED(outHitInfo) - return false; -} - -bool CSurfaceInfoPicker::RayWorldToLocal( - const Matrix34A& WorldTM, - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - Vec3& outRaySrc, - Vec3& outRayDir) -{ - if (!WorldTM.IsValid()) - { - return false; - } - Matrix34A invertedM(WorldTM.GetInverted()); - if (!invertedM.IsValid()) - { - return false; - } - outRaySrc = invertedM.TransformPoint(vWorldRaySrc); - outRayDir = invertedM.TransformVector(vWorldRayDir).GetNormalized(); - return true; -} - -bool CSurfaceInfoPicker::IsMaterialValid(CMaterial* pMaterial) -{ - if (pMaterial == NULL) - { - return false; - } - return !(pMaterial->GetMatInfo()->GetFlags() & MTL_FLAG_NODRAW); -} - -void CSurfaceInfoPicker::AssignObjectMaterial(CBaseObject* pObject, const SRayHitInfo& outHitInfo, _smart_ptr* pOutMaterial) -{ - CMaterial* material = pObject->GetMaterial(); - if (material) - { - if (material->GetMatInfo()) - { - if (pOutMaterial) - { - *pOutMaterial = material->GetMatInfo(); - if (*pOutMaterial) - { - if (outHitInfo.nHitMatID >= 0 && (*pOutMaterial)->GetSubMtlCount() > 0 && outHitInfo.nHitMatID < (*pOutMaterial)->GetSubMtlCount()) - { - *pOutMaterial = (*pOutMaterial)->GetSubMtl(outHitInfo.nHitMatID); - } - } - } - } - } -} - -void CSurfaceInfoPicker::AssignMaterial(_smart_ptr pMaterial, const SRayHitInfo& outHitInfo, _smart_ptr* pOutMaterial) -{ - if (pOutMaterial) - { - *pOutMaterial = pMaterial; - if (*pOutMaterial) - { - if (outHitInfo.nHitMatID >= 0 && (*pOutMaterial)->GetSubMtlCount() > 0 && outHitInfo.nHitMatID < (*pOutMaterial)->GetSubMtlCount()) - { - *pOutMaterial = (*pOutMaterial)->GetSubMtl(outHitInfo.nHitMatID); - } - } - } -} - -void CSurfaceInfoPicker::SetActiveView(IDisplayViewport* view) -{ - if (view) - { - m_pActiveView = view; - } - else - { - m_pActiveView = GetIEditor()->GetActiveView(); - } -} diff --git a/Code/Sandbox/Editor/SurfaceInfoPicker.h b/Code/Sandbox/Editor/SurfaceInfoPicker.h deleted file mode 100644 index 110408d558..0000000000 --- a/Code/Sandbox/Editor/SurfaceInfoPicker.h +++ /dev/null @@ -1,220 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_SURFACEINFOPICKER_H -#define CRYINCLUDE_EDITOR_SURFACEINFOPICKER_H - -#pragma once - -#include "Include/IObjectManager.h" -#include "Objects/BaseObject.h" - -class CKDTree; -struct IDisplayViewport; - -////////////////////////////////////////////////////////////////////////// -class SANDBOX_API CSurfaceInfoPicker -{ -public: - - CSurfaceInfoPicker(); - - class CExcludedObjects - { - public: - - CExcludedObjects(){} - ~CExcludedObjects(){} - CExcludedObjects(const CExcludedObjects& excluded) - { - objects = excluded.objects; - } - - void Add(CBaseObject* pObject) - { - objects.insert(pObject); - } - - void Clear() - { - objects.clear(); - } - - bool Contains(CBaseObject* pObject) const - { - return objects.find(pObject) != objects.end(); - } - - private: - std::set objects; - }; - - enum EPickedObjectGroup - { - ePOG_Entity = BIT(1), - ePOG_All = ePOG_Entity, - }; - - enum EPickOption - { - ePickOption_IncludeFrozenObject = BIT(0), - }; - - void SetPickOptionFlag(int nFlag) { m_PickOption = nFlag; } - -public: - - bool Pick(const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, - _smart_ptr& ppOutLastMaterial, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects = NULL, - int nFlag = ePOG_All) - { - return PickImpl(vWorldRaySrc, vWorldRayDir, &ppOutLastMaterial, outHitInfo, pExcludedObjects, nFlag); - } - - bool Pick(const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects = NULL, - int nFlag = ePOG_All) - { - return PickImpl(vWorldRaySrc, vWorldRayDir, NULL, outHitInfo, pExcludedObjects, nFlag); - } - - bool Pick(const QPoint& point, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects = NULL, - int nFlag = ePOG_All) - { - return PickImpl(point, NULL, outHitInfo, pExcludedObjects, nFlag); - } - - bool Pick(const QPoint& point, - _smart_ptr& ppOutLastMaterial, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects = NULL, - int nFlag = ePOG_All) - { - return PickImpl(point, &ppOutLastMaterial, outHitInfo, pExcludedObjects, nFlag); - } - - bool PickByAABB(const QPoint& point, int nFlag = ePOG_All, IDisplayViewport* pView = NULL, CExcludedObjects* pExcludedObjects = NULL, std::vector* pOutObjects = NULL); - - void SetObjects(CBaseObjectsArray* pSetObjects) { m_pSetObjects = pSetObjects; } - - CBaseObjectPtr GetPickedObject() - { - return m_pPickedObject; - } - - void SetActiveView(IDisplayViewport* view); - -public: - - static bool RayWorldToLocal( - const Matrix34A& WorldTM, - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - Vec3& outRaySrc, - Vec3& outRayDir); - -private: - - bool IsFrozen(CBaseObject* pBaseObject) const - { - return !(m_PickOption & ePickOption_IncludeFrozenObject) && pBaseObject->IsFrozen(); - } - - bool PickImpl(const QPoint& point, - _smart_ptr* ppOutLastMaterial, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects = NULL, - int nFlag = ePOG_All); - - bool PickImpl(const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, - _smart_ptr* ppOutLastMaterial, - SRayHitInfo& outHitInfo, - CExcludedObjects* pExcludedObjects = NULL, - int nFlag = ePOG_All); - - void FindNearestInfoFromEntities( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - _smart_ptr* ppOutLastMaterial, - SRayHitInfo& outHitInfo) const; - - /// Detect ray intersection with a IRenderNode or IStatObj. - /// But only if the intersection is closer than the one already in outHitInfo. - static bool RayIntersection( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IRenderNode* pRenderNode, - IStatObj* pStatObj, - const Matrix34A& WorldTM, - SRayHitInfo& outHitInfo, - _smart_ptr* ppOutLastMaterial); - - /// Detect ray intersection with a IStatObj - static bool RayIntersection_IStatObj( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IStatObj* pStatObj, - _smart_ptr* ppOutLastMaterial, - const Matrix34A& WorldTM, - SRayHitInfo& outHitInfo); - - /// Detect ray intersection with a IGeomCacheRenderNode - static bool RayIntersection_IGeomCacheRenderNode( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IGeomCacheRenderNode* pGeomCacheRenderNode, - _smart_ptr* ppOutLastMaterial, - const Matrix34A& worldTM, - SRayHitInfo& outHitInfo); - - /// Detect ray intersection with a IRenderNode - static bool RayIntersection_IRenderNode( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - IRenderNode* pRenderNode, - _smart_ptr* ppOutLastMaterial, - const Matrix34A& WorldTM, - SRayHitInfo& outHitInfo); - - /// Detect ray intersection with a CBaseObject - static bool RayIntersection_CBaseObject( - const Vec3& vWorldRaySrc, - const Vec3& vWorldRayDir, - CBaseObject* pBaseObject, - _smart_ptr* ppOutLastMaterial, - SRayHitInfo& outHitInfo); - - static void AssignObjectMaterial(CBaseObject* pObject, const SRayHitInfo& outHitInfo, _smart_ptr* pOutMaterial); - static void AssignMaterial(_smart_ptr pObject, const SRayHitInfo& outHitInfo, _smart_ptr* pOutMaterial); - static bool IsMaterialValid(CMaterial* pMaterial); - -private: - - int m_PickOption; - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - CBaseObjectsArray* m_pObjects; - CBaseObjectsArray* m_pSetObjects; - CBaseObjectsArray m_objects; - IDisplayViewport* m_pActiveView; - CExcludedObjects m_ExcludedObjects; - mutable CBaseObjectPtr m_pPickedObject; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -#endif // CRYINCLUDE_EDITOR_SURFACEINFOPICKER_H diff --git a/Code/Sandbox/Editor/SurfaceTypeValidator.cpp b/Code/Sandbox/Editor/SurfaceTypeValidator.cpp index 68bbdcf3bb..9aec070912 100644 --- a/Code/Sandbox/Editor/SurfaceTypeValidator.cpp +++ b/Code/Sandbox/Editor/SurfaceTypeValidator.cpp @@ -16,7 +16,6 @@ #include "SurfaceTypeValidator.h" // Editor -#include "Material/Material.h" #include "Include/IObjectManager.h" #include "Objects/BaseObject.h" #include "ErrorReport.h" diff --git a/Code/Sandbox/Editor/ToolbarManager.cpp b/Code/Sandbox/Editor/ToolbarManager.cpp index 01bd7be82b..bbb3ef6790 100644 --- a/Code/Sandbox/Editor/ToolbarManager.cpp +++ b/Code/Sandbox/Editor/ToolbarManager.cpp @@ -16,7 +16,6 @@ // AzCore #include -#include #include // Qt diff --git a/Code/Sandbox/Editor/TrackView/TrackViewSequenceManager.cpp b/Code/Sandbox/Editor/TrackView/TrackViewSequenceManager.cpp index 12f38c920a..0ba7c5b325 100644 --- a/Code/Sandbox/Editor/TrackView/TrackViewSequenceManager.cpp +++ b/Code/Sandbox/Editor/TrackView/TrackViewSequenceManager.cpp @@ -27,7 +27,6 @@ #include "AnimationContext.h" #include "GameEngine.h" #include "Include/IObjectManager.h" -#include "Material/MaterialManager.h" #include "Objects/ObjectManager.h" @@ -35,7 +34,6 @@ CTrackViewSequenceManager::CTrackViewSequenceManager() { GetIEditor()->RegisterNotifyListener(this); - GetIEditor()->GetMaterialManager()->AddListener(this); AZ::EntitySystemBus::Handler::BusConnect(); } @@ -45,7 +43,6 @@ CTrackViewSequenceManager::~CTrackViewSequenceManager() { AZ::EntitySystemBus::Handler::BusDisconnect(); - GetIEditor()->GetMaterialManager()->RemoveListener(this); GetIEditor()->UnregisterNotifyListener(this); } diff --git a/Code/Sandbox/Editor/Util/Variable.h b/Code/Sandbox/Editor/Util/Variable.h index ab43d24e94..d00ef6103a 100644 --- a/Code/Sandbox/Editor/Util/Variable.h +++ b/Code/Sandbox/Editor/Util/Variable.h @@ -152,7 +152,7 @@ struct IVariable DT_LOCAL_STRING, DT_EQUIP, DT_REVERBPRESET, - DT_MATERIAL, + DT_DEPRECATED0, // formerly DT_MATERIAL DT_MATERIALLOOKUP, DT_EXTARRAY, // Extendable Array DT_SEQUENCE, // Movie Sequence (DEPRECATED, use DT_SEQUENCE_ID, instead.) @@ -163,7 +163,7 @@ struct IVariable DT_LIGHT_ANIMATION, // Light Animation Node in the global Light Animation Set DT_PARTICLE_EFFECT, DT_GEOM_CACHE, // Geometry cache - DT_FLARE, + DT_DEPRECATED, // formerly DT_FLARE DT_AUDIO_TRIGGER, DT_AUDIO_SWITCH, DT_AUDIO_SWITCH_STATE, diff --git a/Code/Sandbox/Editor/Util/VariablePropertyType.cpp b/Code/Sandbox/Editor/Util/VariablePropertyType.cpp index 5a3029807b..c7fd3d9de2 100644 --- a/Code/Sandbox/Editor/Util/VariablePropertyType.cpp +++ b/Code/Sandbox/Editor/Util/VariablePropertyType.cpp @@ -49,7 +49,7 @@ namespace Prop { IVariable::DT_SIMPLE, "Selection", ePropertySelection, -1 }, { IVariable::DT_SIMPLE, "List", ePropertyList, -1 }, { IVariable::DT_SHADER, "Shader", ePropertyShader, 9 }, - { IVariable::DT_MATERIAL, "Material", ePropertyMaterial, 14 }, + { IVariable::DT_DEPRECATED0, "DEPRECATED", ePropertyDeprecated2, -1 }, { IVariable::DT_EQUIP, "Equip", ePropertyEquip, 11 }, { IVariable::DT_REVERBPRESET, "ReverbPreset", ePropertyReverbPreset, 11 }, { IVariable::DT_LOCAL_STRING, "LocalString", ePropertyLocalString, 3 }, @@ -58,7 +58,6 @@ namespace Prop { IVariable::DT_USERITEMCB, "User", ePropertyUser, -1 }, { IVariable::DT_SEQUENCE_ID, "SequenceId", ePropertySequenceId, -1 }, { IVariable::DT_LIGHT_ANIMATION, "LightAnimation", ePropertyLightAnimation, -1 }, - { IVariable::DT_FLARE, "Flare", ePropertyFlare, 7 }, { IVariable::DT_PARTICLE_EFFECT, "ParticleEffect", ePropertyParticleName, 3 }, { IVariable::DT_GEOM_CACHE, "Geometry Cache", ePropertyGeomCache, 5 }, { IVariable::DT_AUDIO_TRIGGER, "Audio Trigger", ePropertyAudioTrigger, 6 }, diff --git a/Code/Sandbox/Editor/Util/VariablePropertyType.h b/Code/Sandbox/Editor/Util/VariablePropertyType.h index 86fc8e9c0f..130148c903 100644 --- a/Code/Sandbox/Editor/Util/VariablePropertyType.h +++ b/Code/Sandbox/Editor/Util/VariablePropertyType.h @@ -39,7 +39,7 @@ enum PropertyType ePropertySelection, ePropertyList, ePropertyShader, - ePropertyMaterial, + ePropertyDeprecated2, // formerly ePropertyMaterial ePropertyEquip, ePropertyReverbPreset, ePropertyLocalString, @@ -50,7 +50,7 @@ enum PropertyType ePropertyUser, ePropertySequenceId, ePropertyLightAnimation, - ePropertyFlare, + ePropertyDeprecated1, // formerly ePropertyFlare ePropertyParticleName, ePropertyGeomCache, ePropertyAudioTrigger, diff --git a/Code/Sandbox/Editor/Util/VariableTypeInfo.cpp b/Code/Sandbox/Editor/Util/VariableTypeInfo.cpp index 61cdac53c6..206131e5a9 100644 --- a/Code/Sandbox/Editor/Util/VariableTypeInfo.cpp +++ b/Code/Sandbox/Editor/Util/VariableTypeInfo.cpp @@ -112,10 +112,6 @@ void CVariableTypeInfo::SetTypes(CTypeInfo const& TypeInfo, EType eType) { SetDataType(DT_TEXTURE); } - else if (m_name == "Material") - { - SetDataType(DT_MATERIAL); - } else if (m_name == "Geometry") { SetDataType(DT_OBJECT); diff --git a/Code/Sandbox/Editor/ViewManager.cpp b/Code/Sandbox/Editor/ViewManager.cpp index 7dd0f3e033..334e78a826 100644 --- a/Code/Sandbox/Editor/ViewManager.cpp +++ b/Code/Sandbox/Editor/ViewManager.cpp @@ -34,7 +34,6 @@ #include "EditorViewportWidget.h" #include "CryEditDoc.h" -#include #include AZ_CVAR(bool, ed_useAtomNativeViewport, true, nullptr, AZ::ConsoleFunctorFlags::Null, "Use the new Atom-native Editor viewport (experimental, not yet stable"); @@ -42,7 +41,7 @@ AZ_CVAR(bool, ed_useAtomNativeViewport, true, nullptr, AZ::ConsoleFunctorFlags:: bool CViewManager::IsMultiViewportEnabled() { // Enable multi-viewport for legacy renderer, or if we're using the new fully Atom-native viewport - return !AZ::Interface::Get() || ed_useAtomNativeViewport; + return ed_useAtomNativeViewport; } ////////////////////////////////////////////////////////////////////// @@ -81,7 +80,7 @@ CViewManager::CViewManager() RegisterQtViewPane(GetIEditor(), "Left", LyViewPane::CategoryViewport, viewportOptions); viewportOptions.viewportType = ET_ViewportCamera; - if (ed_useAtomNativeViewport && AZ::Interface::Get()) + if (ed_useAtomNativeViewport) { RegisterQtViewPaneWithName(GetIEditor(), "Perspective", LyViewPane::CategoryViewport, viewportOptions); } diff --git a/Code/Sandbox/Editor/ViewPane.cpp b/Code/Sandbox/Editor/ViewPane.cpp index 43e4330113..480e39bedf 100644 --- a/Code/Sandbox/Editor/ViewPane.cpp +++ b/Code/Sandbox/Editor/ViewPane.cpp @@ -33,7 +33,6 @@ // AzFramework #include -#include #include // Editor diff --git a/Code/Sandbox/Editor/editor_files.cmake b/Code/Sandbox/Editor/editor_files.cmake index 50521d23aa..9acfb2aaf8 100644 --- a/Code/Sandbox/Editor/editor_files.cmake +++ b/Code/Sandbox/Editor/editor_files.cmake @@ -13,6 +13,5 @@ set(FILES main.cpp Style/Editor.qss Style/resources.qrc - Style/LensFlareEditor.qss EditorCryEdit.rc ) diff --git a/Code/Sandbox/Editor/editor_lib_files.cmake b/Code/Sandbox/Editor/editor_lib_files.cmake index 80ec582d19..a0c22c9a14 100644 --- a/Code/Sandbox/Editor/editor_lib_files.cmake +++ b/Code/Sandbox/Editor/editor_lib_files.cmake @@ -309,15 +309,6 @@ set(FILES Util/AffineParts.cpp Objects/BaseObject.cpp Objects/BaseObject.h - Material/Material.cpp - Material/Material.h - Material/MaterialHelpers.cpp - Material/MaterialHelpers.h - Material/MaterialDialog.qrc - Material/MaterialPreviewModelView.cpp - Material/MaterialPreviewModelView.h - Material/PreviewModelView.cpp - Material/PreviewModelView.h Alembic/AlembicCompileDialog.cpp Alembic/AlembicCompileDialog.h Alembic/AlembicCompileDialog.ui @@ -545,9 +536,6 @@ set(FILES Geometry/TriMesh.h AboutDialog.h AboutDialog.ui - DatabaseFrameWnd.h - DatabaseFrameWnd.ui - DatabaseFrameWnd.qrc DocMultiArchive.h EditMode/DeepSelection.h FBXExporterDialog.h @@ -556,7 +544,6 @@ set(FILES IObservable.h IPostRenderer.h LightmapCompiler/SimpleTriangleRasterizer.h - SurfaceInfoPicker.h ToolBox.h TrackViewNewSequenceDialog.h UndoConfigSpec.h @@ -571,52 +558,8 @@ set(FILES WipFeaturesDlg.qrc LevelIndependentFileMan.cpp LevelIndependentFileMan.h - LensFlareEditor/ILensFlareListener.h - LensFlareEditor/LensFlareAtomicList.cpp - LensFlareEditor/LensFlareAtomicList.h - LensFlareEditor/LensFlareEditor.cpp - LensFlareEditor/LensFlareEditor.h - LensFlareEditor/LensFlareElement.cpp - LensFlareEditor/LensFlareElement.h - LensFlareEditor/LensFlareElementTree.cpp - LensFlareEditor/LensFlareElementTree.h - LensFlareEditor/LensFlareItem.cpp - LensFlareEditor/LensFlareItem.h - LensFlareEditor/LensFlareItemTree.cpp - LensFlareEditor/LensFlareItemTree.h - LensFlareEditor/LensFlareLibrary.cpp - LensFlareEditor/LensFlareLibrary.h - LensFlareEditor/LensFlareLightEntityTree.cpp - LensFlareEditor/LensFlareLightEntityTree.h - LensFlareEditor/LensFlareManager.cpp - LensFlareEditor/LensFlareManager.h - LensFlareEditor/LensFlareUndo.cpp - LensFlareEditor/LensFlareUndo.h - LensFlareEditor/LensFlareUtil.cpp - LensFlareEditor/LensFlareUtil.h - LensFlareEditor/LensFlareView.cpp - LensFlareEditor/LensFlareView.h LogFileImpl.cpp LogFileImpl.h - MatEditPreviewDlg.cpp - MatEditPreviewDlg.h - Material/MaterialBrowser.cpp - Material/MaterialBrowser.h - Material/MaterialBrowser.ui - Material/MaterialBrowserSearchFilters.cpp - Material/MaterialBrowserSearchFilters.h - Material/MaterialBrowserFilterModel.cpp - Material/MaterialBrowserFilterModel.h - Material/MaterialImageListCtrl.cpp - Material/MaterialImageListCtrl.h - Material/MaterialLibrary.cpp - Material/MaterialLibrary.h - Material/MaterialManager.cpp - Material/MaterialManager.h - MaterialSender.h - MaterialSender.cpp - Material/MaterialPythonFuncs.h - Material/MaterialPythonFuncs.cpp Mission.cpp Mission.h Objects/ClassDesc.cpp @@ -624,8 +567,6 @@ set(FILES Objects/IEntityObjectListener.h Objects/SelectionGroup.cpp Objects/SelectionGroup.h - Objects/StatObjValidator.cpp - Objects/StatObjValidator.h Objects/SubObjSelection.cpp Objects/SubObjSelection.h Objects/ObjectLoader.cpp @@ -659,9 +600,7 @@ set(FILES QtUI/WaitCursor.h QtUI/WaitCursor.cpp RenderHelpers/AxisHelper.cpp - RenderHelpers/AxisHelperExtended.cpp RenderHelpers/AxisHelper.h - RenderHelpers/AxisHelperExtended.h Serialization.h Serialization/VariableOArchive.cpp Serialization/VariableOArchive.h @@ -706,7 +645,6 @@ set(FILES GraphicsSettingsDialog.cpp graphicssettingsdialog.ui AboutDialog.cpp - DatabaseFrameWnd.cpp ErrorReportTableModel.h ErrorReportTableModel.cpp EditMode/DeepSelection.cpp @@ -716,7 +654,6 @@ set(FILES LightmapCompiler/SimpleTriangleRasterizer.cpp ResourceSelectorHost.cpp ResourceSelectorHost.h - SurfaceInfoPicker.cpp ThumbnailGenerator.cpp ThumbnailGenerator.h ToolBox.cpp diff --git a/Code/Sandbox/Editor/editor_lib_test_files.cmake b/Code/Sandbox/Editor/editor_lib_test_files.cmake index f537169136..9eca3c56ae 100644 --- a/Code/Sandbox/Editor/editor_lib_test_files.cmake +++ b/Code/Sandbox/Editor/editor_lib_test_files.cmake @@ -18,7 +18,6 @@ set(FILES Lib/Tests/test_EditorUtils.cpp Lib/Tests/test_Main.cpp Lib/Tests/test_MainWindowPythonBindings.cpp - Lib/Tests/test_MaterialPythonFuncs.cpp Lib/Tests/test_ObjectManagerPythonBindings.cpp Lib/Tests/test_TrackViewPythonBindings.cpp Lib/Tests/test_ViewPanePythonBindings.cpp diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp index 60574ee48c..692bb92bf7 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp @@ -43,13 +43,10 @@ #include #include #include -#include #include #include -#include #include -#include #include #include #include @@ -112,7 +109,6 @@ void CComponentEntityObject::AssignEntity(AZ::Entity* entity, bool destroyOld) { AZ::TransformNotificationBus::Handler::BusDisconnect(); LmbrCentral::RenderBoundsNotificationBus::Handler::BusDisconnect(); - LmbrCentral::MeshComponentNotificationBus::Handler::BusDisconnect(); AzToolsFramework::ComponentEntityEditorRequestBus::Handler::BusDisconnect(); AZ::EntityBus::Handler::BusDisconnect(); AzToolsFramework::ComponentEntityObjectRequestBus::Handler::BusDisconnect(); @@ -158,7 +154,6 @@ void CComponentEntityObject::AssignEntity(AZ::Entity* entity, bool destroyOld) AZ::TransformNotificationBus::Handler::BusConnect(m_entityId); LmbrCentral::RenderBoundsNotificationBus::Handler::BusConnect(m_entityId); - LmbrCentral::MeshComponentNotificationBus::Handler::BusConnect(m_entityId); AzToolsFramework::ComponentEntityEditorRequestBus::Handler::BusConnect(m_entityId); AZ::EntityBus::Handler::BusConnect(m_entityId); AzToolsFramework::ComponentEntityObjectRequestBus::Handler::BusConnect(this); @@ -399,15 +394,6 @@ void CComponentEntityObject::OnParentChanged([[maybe_unused]] AZ::EntityId oldPa { } -void CComponentEntityObject::OnMeshCreated(const AZ::Data::Asset& asset) -{ - (void)asset; - - // Need to recalculate bounds when the mesh changes. - OnRenderBoundsReset(); - ValidateMeshStatObject(); -} - void CComponentEntityObject::OnRenderBoundsReset() { CEntityObject::InvalidateTM(0); @@ -950,9 +936,7 @@ void CComponentEntityObject::DrawDefault(DisplayContext& dc, const QColor& label IStatObj* CComponentEntityObject::GetIStatObj() { - IStatObj* statObj = nullptr; - LmbrCentral::LegacyMeshComponentRequestBus::EventResult(statObj, m_entityId, &LmbrCentral::LegacyMeshComponentRequests::GetStatObj); - return statObj; + return nullptr; } bool CComponentEntityObject::IsIsolated() const @@ -1110,56 +1094,3 @@ void CComponentEntityObject::DrawAccent(DisplayContext& dc) dc.DrawWireBox(box.min, box.max); } } - -void CComponentEntityObject::SetMaterial(CMaterial* material) -{ - AZ::Entity* entity = nullptr; - EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, m_entityId); - if (entity) - { - if (material) - { - EBUS_EVENT_ID(m_entityId, LmbrCentral::MaterialOwnerRequestBus, SetMaterial, material->GetMatInfo()); - } - else - { - EBUS_EVENT_ID(m_entityId, LmbrCentral::MaterialOwnerRequestBus, SetMaterial, nullptr); - } - } - - ValidateMeshStatObject(); -} - -CMaterial* CComponentEntityObject::GetMaterial() const -{ - _smart_ptr material = nullptr; - EBUS_EVENT_ID_RESULT(material, m_entityId, LmbrCentral::MaterialOwnerRequestBus, GetMaterial); - return GetIEditor()->GetMaterialManager()->FromIMaterial(material); -} - -CMaterial* CComponentEntityObject::GetRenderMaterial() const -{ - AZ::Entity* entity = nullptr; - EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, m_entityId); - if (entity) - { - _smart_ptr material = nullptr; - EBUS_EVENT_ID_RESULT(material, m_entityId, LmbrCentral::MaterialOwnerRequestBus, GetMaterial); - - if (material) - { - return GetIEditor()->GetMaterialManager()->LoadMaterial(material->GetName(), false); - } - } - - return nullptr; -} - -void CComponentEntityObject::ValidateMeshStatObject() -{ - IStatObj* statObj = GetIStatObj(); - CMaterial* editorMaterial = GetMaterial(); - CStatObjValidator statValidator; - statValidator.Validate(statObj, editorMaterial); -} - diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h index 208ade7cd7..b64bd6b3e1 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h @@ -27,7 +27,6 @@ #include #include "../Editor/Objects/EntityObject.h" -#include #include #endif @@ -43,7 +42,6 @@ class CComponentEntityObject , private AzToolsFramework::EditorEntityIconComponentNotificationBus::Handler , private AZ::TransformNotificationBus::Handler , private LmbrCentral::RenderBoundsNotificationBus::Handler - , private LmbrCentral::MeshComponentNotificationBus::Handler , private AzToolsFramework::ComponentEntityEditorRequestBus::Handler , private AzToolsFramework::ComponentEntityObjectRequestBus::Handler , private AZ::EntityBus::Handler @@ -81,9 +79,6 @@ public: CBaseObject* GetLinkParent() const override; XmlNodeRef Export(const QString& levelPath, XmlNodeRef& xmlNode) override; void DeleteEntity() override; - void SetMaterial(CMaterial* mtl) override; - CMaterial* GetMaterial() const override; - CMaterial* GetRenderMaterial() const override; void DrawDefault(DisplayContext& dc, const QColor& labelColor = QColor(255, 255, 255)) override; IStatObj* GetIStatObj() override; bool IsIsolated() const override; @@ -131,11 +126,6 @@ public: void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId newParent) override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - //! MeshComponentNotificationBus - void OnMeshCreated(const AZ::Data::Asset& asset) override; - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// //! RenderBoundsNotificationBus void OnRenderBoundsReset() override; @@ -191,8 +181,6 @@ protected: void DrawAccent(DisplayContext& dc); - void ValidateMeshStatObject(); - class EditorActionGuard { public: diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index ecfb155d79..c7c501c70a 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -162,13 +161,6 @@ void SandboxIntegrationManager::Setup() AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect(); - // turn on the this debug display request bus implementation if no other implementation is active - if( !(AZ::Interface::Get() && AzFramework::DebugDisplayRequestBus::HasHandlers())) - { - m_debugDisplayBusImplementationActive = true; - AzFramework::DebugDisplayRequestBus::Handler::BusConnect( - AzToolsFramework::ViewportInteraction::g_mainViewportEntityDebugDisplayId); - } AzFramework::DisplayContextRequestBus::Handler::BusConnect(); SetupFileExtensionMap(); @@ -302,12 +294,15 @@ void SandboxIntegrationManager::OnCatalogAssetAdded(const AZ::Data::AssetId& ass // operation writing to shared resource is queued on main thread. void SandboxIntegrationManager::OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) { + bool isPrefabSystemEnabled = false; + AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled); + // Check to see if the removed slice asset has any instance in the level, then check if // those dangling instances are directly under the root slice (not sub-slices). If yes, // detach them and save necessary information so they can be restored when their slice asset // comes back. - if (assetInfo.m_assetType == AZ::AzTypeInfo::Uuid()) + if (!isPrefabSystemEnabled && assetInfo.m_assetType == AZ::AzTypeInfo::Uuid()) { AZ::SliceComponent* rootSlice = nullptr; AzToolsFramework::SliceEditorEntityOwnershipServiceRequestBus::BroadcastResult(rootSlice, diff --git a/Code/Sandbox/Plugins/EditorCommon/QViewport.cpp b/Code/Sandbox/Plugins/EditorCommon/QViewport.cpp index 5ca6cf5ac6..362452a67e 100644 --- a/Code/Sandbox/Plugins/EditorCommon/QViewport.cpp +++ b/Code/Sandbox/Plugins/EditorCommon/QViewport.cpp @@ -37,8 +37,6 @@ #include #include -#include - #include // Class to implement the WindowRequestBus::Handler instead of the QViewport class. @@ -365,7 +363,7 @@ bool QViewport::CreateRenderContext() HWND windowHandle = reinterpret_cast(QWidget::winId()); - if( AZ::Interface::Get() && m_renderContextCreated && windowHandle == m_lastHwnd) + if( m_renderContextCreated && windowHandle == m_lastHwnd) { // the hwnd has not changed, no need to destroy and recreate context (and swap chain etc) return false; @@ -377,13 +375,10 @@ bool QViewport::CreateRenderContext() { m_renderContextCreated = true; - if (AZ::Interface::Get()) - { - m_viewportRequests.get()->BusConnect(windowHandle); - AzFramework::WindowSystemNotificationBus::Broadcast(&AzFramework::WindowSystemNotificationBus::Handler::OnWindowCreated, windowHandle); + m_viewportRequests.get()->BusConnect(windowHandle); + AzFramework::WindowSystemNotificationBus::Broadcast(&AzFramework::WindowSystemNotificationBus::Handler::OnWindowCreated, windowHandle); - m_lastHwnd = windowHandle; - } + m_lastHwnd = windowHandle; StorePreviousContext(); GetIEditor()->GetEnv()->pRenderer->CreateContext(windowHandle); diff --git a/Code/Sandbox/Plugins/PerforcePlugin/PerforceSourceControl.h b/Code/Sandbox/Plugins/PerforcePlugin/PerforceSourceControl.h index 16489d99fc..1efbbc912c 100644 --- a/Code/Sandbox/Plugins/PerforcePlugin/PerforceSourceControl.h +++ b/Code/Sandbox/Plugins/PerforcePlugin/PerforceSourceControl.h @@ -26,7 +26,7 @@ class CPerforceSourceControl public: // constructor CPerforceSourceControl() = default; - ~CPerforceSourceControl() = default; + virtual ~CPerforceSourceControl() = default; void Init(); diff --git a/Code/Tools/AssetBundler/CMakeLists.txt b/Code/Tools/AssetBundler/CMakeLists.txt index 41b95fd2ae..c99ffaef6b 100644 --- a/Code/Tools/AssetBundler/CMakeLists.txt +++ b/Code/Tools/AssetBundler/CMakeLists.txt @@ -13,9 +13,13 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() +include(${CMAKE_CURRENT_SOURCE_DIR}/Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) + +# AssetBundlerBatch - CLI Application ly_add_target( - NAME AssetBundler.Static STATIC + NAME AssetBundlerBatch.Static STATIC NAMESPACE AZ + AUTOMOC FILES_CMAKE assetbundlerbatch_files.cmake INCLUDE_DIRECTORIES @@ -23,6 +27,9 @@ ly_add_target( . BUILD_DEPENDENCIES PUBLIC + 3rdParty::Qt::Core + 3rdParty::Qt::Gui + 3rdParty::Qt::Widgets AZ::AzToolsFramework ${additional_dependencies} ) @@ -32,12 +39,41 @@ ly_add_target( NAMESPACE AZ FILES_CMAKE assetbundlerbatch_exe_files.cmake + COMPILE_DEFINITIONS + PRIVATE + AB_BATCH_MODE INCLUDE_DIRECTORIES PRIVATE . BUILD_DEPENDENCIES PRIVATE - AZ::AssetBundler.Static + AZ::AssetBundlerBatch.Static +) + +# AssetBundler - Qt GUI Application +ly_add_target( + NAME AssetBundler ${PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE} + NAMESPACE AZ + AUTOMOC + AUTOUIC + AUTORCC + FILES_CMAKE + assetbundlergui_files.cmake + assetbundler_exe_files.cmake + Platform/${PAL_PLATFORM_NAME}/assetbundlergui_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + INCLUDE_DIRECTORIES + PUBLIC + Platform/${PAL_PLATFORM_NAME} + PRIVATE + . + BUILD_DEPENDENCIES + PUBLIC + 3rdParty::Qt::Core + 3rdParty::Qt::Gui + 3rdParty::Qt::Widgets + AZ::AzToolsFramework + AZ::AssetBundlerBatch.Static + ${additional_dependencies} ) if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) @@ -53,7 +89,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) BUILD_DEPENDENCIES PRIVATE AZ::AzTest - AZ::AssetBundler.Static + AZ::AssetBundlerBatch.Static AZ::AzFrameworkTestShared ) diff --git a/cmake/3rdParty/Platform/Linux/dyad_linux.cmake b/Code/Tools/AssetBundler/Platform/Linux/PAL_linux.cmake similarity index 86% rename from cmake/3rdParty/Platform/Linux/dyad_linux.cmake rename to Code/Tools/AssetBundler/Platform/Linux/PAL_linux.cmake index ae9e3d99d7..d0d27a99ac 100644 --- a/cmake/3rdParty/Platform/Linux/dyad_linux.cmake +++ b/Code/Tools/AssetBundler/Platform/Linux/PAL_linux.cmake @@ -9,4 +9,5 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(DYAD_LIBS ${BASE_PATH}/lib/linux_$,debug,release>/libdyad.a) \ No newline at end of file +set (PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE APPLICATION) + diff --git a/cmake/3rdParty/Platform/Windows/dyad_windows.cmake b/Code/Tools/AssetBundler/Platform/Linux/assetbundlergui_linux_files.cmake similarity index 85% rename from cmake/3rdParty/Platform/Windows/dyad_windows.cmake rename to Code/Tools/AssetBundler/Platform/Linux/assetbundlergui_linux_files.cmake index 8f008ba54e..23bbefccdc 100644 --- a/cmake/3rdParty/Platform/Windows/dyad_windows.cmake +++ b/Code/Tools/AssetBundler/Platform/Linux/assetbundlergui_linux_files.cmake @@ -9,4 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(DYAD_LIBS ${BASE_PATH}/lib/x64_v140_$,Debug,Release>/libdyad.lib) +set(FILES + source/utils/GUIApplicationManager_Linux.cpp +) \ No newline at end of file diff --git a/Gems/Visibility/Code/Source/VisibilityGem.h b/Code/Tools/AssetBundler/Platform/Linux/source/utils/GUIApplicationManager_Linux.cpp similarity index 67% rename from Gems/Visibility/Code/Source/VisibilityGem.h rename to Code/Tools/AssetBundler/Platform/Linux/source/utils/GUIApplicationManager_Linux.cpp index 1abc1b8901..7af09214cb 100644 --- a/Gems/Visibility/Code/Source/VisibilityGem.h +++ b/Code/Tools/AssetBundler/Platform/Linux/source/utils/GUIApplicationManager_Linux.cpp @@ -10,18 +10,12 @@ * */ -#pragma once +#include -#include - -#include - - -class VisibilityGem - : public AZ::Module +namespace Platform { -public: - AZ_RTTI(VisibilityGem, "{5138F2B6-EDFB-490E-AB3E-B82E43263A20}"); - - VisibilityGem(); -}; + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption() + { + return AzQtComponents::WindowDecorationWrapper::OptionDisabled; + } +} \ No newline at end of file diff --git a/Code/Tools/AssetBundler/Platform/Mac/PAL_mac.cmake b/Code/Tools/AssetBundler/Platform/Mac/PAL_mac.cmake new file mode 100644 index 0000000000..d0d27a99ac --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Mac/PAL_mac.cmake @@ -0,0 +1,13 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set (PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE APPLICATION) + diff --git a/Code/Tools/AssetBundler/Platform/Mac/assetbundlergui_mac_files.cmake b/Code/Tools/AssetBundler/Platform/Mac/assetbundlergui_mac_files.cmake new file mode 100644 index 0000000000..a8a116ac79 --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Mac/assetbundlergui_mac_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + source/utils/GUIApplicationManager_OSX.cpp +) \ No newline at end of file diff --git a/Code/Sandbox/Editor/Style/LensFlareEditor.qss b/Code/Tools/AssetBundler/Platform/Mac/source/utils/GUIApplicationManager_OSX.cpp similarity index 67% rename from Code/Sandbox/Editor/Style/LensFlareEditor.qss rename to Code/Tools/AssetBundler/Platform/Mac/source/utils/GUIApplicationManager_OSX.cpp index 58d99c9f92..7af09214cb 100644 --- a/Code/Sandbox/Editor/Style/LensFlareEditor.qss +++ b/Code/Tools/AssetBundler/Platform/Mac/source/utils/GUIApplicationManager_OSX.cpp @@ -10,8 +10,12 @@ * */ -#DatabaseFrameWnd QToolBar -{ - border-bottom: 2px solid #111111; -} +#include +namespace Platform +{ + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption() + { + return AzQtComponents::WindowDecorationWrapper::OptionDisabled; + } +} \ No newline at end of file diff --git a/Code/Tools/AssetBundler/Platform/Windows/PAL_windows.cmake b/Code/Tools/AssetBundler/Platform/Windows/PAL_windows.cmake new file mode 100644 index 0000000000..d0d27a99ac --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Windows/PAL_windows.cmake @@ -0,0 +1,13 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set (PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE APPLICATION) + diff --git a/Code/Tools/AssetBundler/Platform/Windows/assetbundlergui_windows_files.cmake b/Code/Tools/AssetBundler/Platform/Windows/assetbundlergui_windows_files.cmake new file mode 100644 index 0000000000..f9e1ffda8d --- /dev/null +++ b/Code/Tools/AssetBundler/Platform/Windows/assetbundlergui_windows_files.cmake @@ -0,0 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + source/utils/GUIApplicationManager_Win.cpp +) \ No newline at end of file diff --git a/Gems/Visibility/Code/Source/Visibility_precompiled.h b/Code/Tools/AssetBundler/Platform/Windows/source/utils/GUIApplicationManager_Win.cpp similarity index 67% rename from Gems/Visibility/Code/Source/Visibility_precompiled.h rename to Code/Tools/AssetBundler/Platform/Windows/source/utils/GUIApplicationManager_Win.cpp index 2a1bc2e083..99e254a774 100644 --- a/Gems/Visibility/Code/Source/Visibility_precompiled.h +++ b/Code/Tools/AssetBundler/Platform/Windows/source/utils/GUIApplicationManager_Win.cpp @@ -10,10 +10,12 @@ * */ -#pragma once +#include -#include -#include -#include -#include -#include +namespace Platform +{ + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption() + { + return AzQtComponents::WindowDecorationWrapper::OptionAutoAttach; + } +} \ No newline at end of file diff --git a/Gems/Visibility/Code/visibility_shared_files.cmake b/Code/Tools/AssetBundler/assetbundler_exe_files.cmake similarity index 90% rename from Gems/Visibility/Code/visibility_shared_files.cmake rename to Code/Tools/AssetBundler/assetbundler_exe_files.cmake index a37350ade6..976405c4f7 100644 --- a/Gems/Visibility/Code/visibility_shared_files.cmake +++ b/Code/Tools/AssetBundler/assetbundler_exe_files.cmake @@ -10,6 +10,6 @@ # set(FILES - Source/VisibilityGem.h - Source/VisibilityGem.cpp + source/main.cpp + source/AssetBundler.rc ) diff --git a/Code/Tools/AssetBundler/assetbundlergui_files.cmake b/Code/Tools/AssetBundler/assetbundlergui_files.cmake new file mode 100644 index 0000000000..7ac5d34eb3 --- /dev/null +++ b/Code/Tools/AssetBundler/assetbundlergui_files.cmake @@ -0,0 +1,70 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + source/models/AssetBundlerAbstractFileTableModel.h + source/models/AssetBundlerAbstractFileTableModel.cpp + source/models/AssetBundlerFileTableFilterModel.h + source/models/AssetBundlerFileTableFilterModel.cpp + source/models/AssetListFileTableModel.h + source/models/AssetListFileTableModel.cpp + source/models/AssetListTableModel.cpp + source/models/AssetListTableModel.h + source/models/BundleFileListModel.h + source/models/BundleFileListModel.cpp + source/models/RulesFileTableModel.h + source/models/RulesFileTableModel.cpp + source/models/SeedListFileTableModel.h + source/models/SeedListFileTableModel.cpp + source/models/SeedListTableModel.h + source/models/SeedListTableModel.cpp + source/ui/style/AssetBundler.qrc + source/ui/style/AssetBundler.qss + source/ui/style/AssetBundlerConfig.ini + source/ui/style/AssetBundler-Icon-256x256@x2.ico + source/ui/AddSeedDialog.h + source/ui/AddSeedDialog.cpp + source/ui/AddSeedDialog.ui + source/ui/AssetBundlerTabWidget.h + source/ui/AssetBundlerTabWidget.cpp + source/ui/AssetListTabWidget.h + source/ui/AssetListTabWidget.cpp + source/ui/AssetListTabWidget.ui + source/ui/BundleListTabWidget.h + source/ui/BundleListTabWidget.cpp + source/ui/BundleListTabWidget.ui + source/ui/ComparisonDataWidget.h + source/ui/ComparisonDataWidget.cpp + source/ui/ComparisonDataWidget.ui + source/ui/EditSeedDialog.h + source/ui/EditSeedDialog.cpp + source/ui/EditSeedDialog.ui + source/ui/GenerateBundlesModal.h + source/ui/GenerateBundlesModal.cpp + source/ui/GenerateBundlesModal.ui + source/ui/MainWindow.h + source/ui/MainWindow.cpp + source/ui/MainWindow.ui + source/ui/NewFileDialog.h + source/ui/NewFileDialog.cpp + source/ui/NewFileDialog.ui + source/ui/PlatformSelectionWidget.h + source/ui/PlatformSelectionWidget.cpp + source/ui/PlatformSelectionWidget.ui + source/ui/RulesTabWidget.h + source/ui/RulesTabWidget.cpp + source/ui/RulesTabWidget.ui + source/ui/SeedTabWidget.h + source/ui/SeedTabWidget.cpp + source/ui/SeedTabWidget.ui + source/utils/GUIApplicationManager.h + source/utils/GUIApplicationManager.cpp +) diff --git a/Code/Tools/AssetBundler/source/AssetBundler.rc b/Code/Tools/AssetBundler/source/AssetBundler.rc new file mode 100644 index 0000000000..a3116a384f --- /dev/null +++ b/Code/Tools/AssetBundler/source/AssetBundler.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "ui\\style\\AssetBundler-Icon-256x256@x2.ico" diff --git a/Code/Tools/AssetBundler/source/main.cpp b/Code/Tools/AssetBundler/source/main.cpp index f1b782ff44..be152d6bf3 100644 --- a/Code/Tools/AssetBundler/source/main.cpp +++ b/Code/Tools/AssetBundler/source/main.cpp @@ -10,17 +10,48 @@ * */ +#if defined(AB_BATCH_MODE) #include +#else +#include +#include +#endif + +#if defined(AZ_TESTS_ENABLED) +#include +DECLARE_AZ_UNIT_TEST_MAIN(); +#endif int main(int argc, char* argv[]) { +#if defined(AZ_TESTS_ENABLED) + INVOKE_AZ_UNIT_TEST_MAIN(); +#endif + AZ::AllocatorInstance::Create(); int runSuccess = 0; + { - AssetBundler::ApplicationManager applicationManger(&argc, &argv); - applicationManger.Init(); - runSuccess = applicationManger.Run() ? 0 : 1; + //This nested scope is necessary as the applicationManager needs to have its destructor called BEFORE you destroy the allocators + +#if defined(AB_BATCH_MODE) + AssetBundler::ApplicationManager applicationManager(&argc, &argv); +#else + // Must be called before using any Qt, or the app won't be able to locate Qt libs + AzQtComponents::PrepareQtPaths(); + AssetBundler::GUIApplicationManager applicationManager(&argc, &argv); +#endif + if (!applicationManager.Init()) + { + AZ_Error("AssetBundler", false, "AssetBundler initialization failed"); + runSuccess = 1; + } + else + { + runSuccess = applicationManager.Run() ? 0 : 1; + } } + AZ::AllocatorInstance::Destroy(); return runSuccess; } diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp new file mode 100644 index 0000000000..c2aac4e943 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.cpp @@ -0,0 +1,233 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + const char* DateTimeFormat = "hh:mm:ss MMM dd, yyyy"; + + AssetBundlerAbstractFileTableModel::AssetBundlerAbstractFileTableModel(QObject* parent) + : QAbstractTableModel(parent) + { + } + + void AssetBundlerAbstractFileTableModel::Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles, const AZStd::unordered_map& pathToProjectNameMap) + { + AZStd::vector keysToRemove = m_fileListKeys; + + // Reload all the files in the watched folders + QString filter = QString("*.%1").arg(fileExtension); + + QSetIterator itr(watchedFolders); + while (itr.hasNext()) + { + QDir filesDir(itr.next()); + filesDir.setNameFilters({ filter }); + for (const QString& fileNameAndExtension : filesDir.entryList(QDir::Files)) + { + AZStd::string absolutePath = filesDir.absoluteFilePath(fileNameAndExtension).toUtf8().data(); + AZStd::string projectName; + if (pathToProjectNameMap.contains(absolutePath)) + { + projectName = pathToProjectNameMap.at(absolutePath); + } + + // If a project name is already specified, then the associated file is a default file + LoadFile(absolutePath, projectName, !projectName.empty()); + keysToRemove.erase(AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)), keysToRemove.end()); + } + } + + // Reload all the watched files + for (const QString& filePath : watchedFiles) + { + AZStd::string absolutePath = filePath.toUtf8().data(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath.c_str())) + { + AZStd::string projectName = pathToProjectNameMap.at(absolutePath); + + // If a project name is already specified, then the associated file is a default file + LoadFile(absolutePath, projectName, !projectName.empty()); + keysToRemove.erase(AZStd::remove(keysToRemove.begin(), keysToRemove.end(), AssetBundler::GenerateKeyFromAbsolutePath(absolutePath)), keysToRemove.end()); + } + } + + //Remove nonexistant files from the model + for (const AZStd::string& key : keysToRemove) + { + DeleteFileByKey(key); + } + } + + void AssetBundlerAbstractFileTableModel::ReloadFiles(const AZStd::vector& absoluteFilePathList, AZStd::unordered_map pathToProjectNameMap) + { + for (const AZStd::string& absoluteFilePath : absoluteFilePathList) + { + if (!AZ::IO::FileIOBase::GetInstance()->Exists(absoluteFilePath.c_str())) + { + // File is not present on-disk, make sure to remove it from the model + DeleteFileByKey(AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath)); + continue; + } + + // If a project name is already specified, then the associated file is a default file + AZStd::string projectName = pathToProjectNameMap[absoluteFilePath]; + LoadFile(absoluteFilePath, projectName, !projectName.empty()); + } + } + + bool AssetBundlerAbstractFileTableModel::Save(const QModelIndex& selectedIndex) + { + if (!selectedIndex.isValid() || m_keysWithUnsavedChanges.empty()) + { + // There is nothing to save + return true; + } + + AZStd::string key = GetFileKey(selectedIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + // Save the file + if (!WriteToDisk(key)) + { + return false; + } + + // Update the display + m_keysWithUnsavedChanges.erase(key); + QModelIndex topLeftIndex = index(selectedIndex.row(), 0); + QModelIndex bottomRightIndex = index(selectedIndex.row(), columnCount() - 1); + emit dataChanged(topLeftIndex, bottomRightIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool AssetBundlerAbstractFileTableModel::SaveAll() + { + if (!HasUnsavedChanges()) + { + // No need to update all of the elements if we are not changing anything + return true; + } + + bool hasSaveErrors = false; + + // Save every file with unsaved changes + AZStd::unordered_set keysWithErrors; + for (const AZStd::string& key : m_keysWithUnsavedChanges) + { + if (!WriteToDisk(key)) + { + // Error has already been thrown + hasSaveErrors = true; + keysWithErrors.emplace(key); + } + } + + m_keysWithUnsavedChanges = keysWithErrors; + + // Update the display of all elements + QModelIndex firstIndex = index(0, 0); + QModelIndex lastIndex = index(rowCount() - 1, columnCount() - 1); + emit dataChanged(firstIndex, lastIndex, { Qt::DisplayRole, Qt::FontRole }); + + return !hasSaveErrors; + } + + bool AssetBundlerAbstractFileTableModel::HasUnsavedChanges() const + { + return !m_keysWithUnsavedChanges.empty(); + } + + int AssetBundlerAbstractFileTableModel::rowCount(const QModelIndex& /*parent*/) const + { + return static_cast(m_fileListKeys.size()); + } + + AZStd::string AssetBundlerAbstractFileTableModel::GetFileKey(const QModelIndex& index) const + { + int row = index.row(); + int col = index.column(); + if (row >= rowCount() || row < 0 || col >= columnCount() || col < 0) + { + AZ_Error("AssetBundler", false, "Selected index (%i, %i) is out of range.", row, col); + return {}; + } + + return m_fileListKeys.at(row); + } + + const AZStd::vector& AssetBundlerAbstractFileTableModel::GetAllFileKeys() const + { + return m_fileListKeys; + } + + int AssetBundlerAbstractFileTableModel::GetIndexRowByKey(const AZStd::string& key) const + { + auto it = AZStd::find(m_fileListKeys.begin(), m_fileListKeys.end(), key); + return it == m_fileListKeys.end() ? -1 : static_cast(AZStd::distance(m_fileListKeys.begin(), it)); + } + + void AssetBundlerAbstractFileTableModel::AddFileKey(const AZStd::string& key) + { + if (AZStd::find(m_fileListKeys.begin(), m_fileListKeys.end(), key) != m_fileListKeys.end()) + { + // Key already exists. This could happen when we update existing entires. + return; + } + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_fileListKeys.push_back(key); + endInsertRows(); + } + + bool AssetBundlerAbstractFileTableModel::RemoveFileKey(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + int row = index.row(); + beginRemoveRows(QModelIndex(), row, row); + + m_fileListKeys.erase(m_fileListKeys.begin() + row); + m_keysWithUnsavedChanges.erase(key); + + endRemoveRows(); + + return true; + } + + bool AssetBundlerAbstractFileTableModel::DeleteFileByKey(const AZStd::string& key) + { + int indexRow = GetIndexRowByKey(key); + if (indexRow >= 0) + { + return DeleteFile(index(indexRow, 0)); + } + + return false; + } +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.h b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.h new file mode 100644 index 0000000000..cfe3e3f241 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerAbstractFileTableModel.h @@ -0,0 +1,111 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +namespace AssetBundler +{ + + extern const char* DateTimeFormat; + + //! Provides an abstract model that can be subclassed to create table models used to store information about files found on-disk. + class AssetBundlerAbstractFileTableModel + : public QAbstractTableModel + { + public: + + enum DataRoles + { + SortRole = Qt::UserRole + 1, + }; + + explicit AssetBundlerAbstractFileTableModel(QObject* parent = nullptr); + virtual ~AssetBundlerAbstractFileTableModel() {} + + ////////////////////////////////////////////////////////////////////////// + // Pure virtual functions + virtual AZStd::vector CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms, const QString& project = QString()) = 0; + virtual bool DeleteFile(const QModelIndex& index) = 0; + virtual void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) = 0; + virtual bool WriteToDisk(const AZStd::string& key) = 0; + + //! Returns the absolute path of the file at the given index on success, returns an empty string on failure. + virtual AZStd::string GetFileAbsolutePath(const QModelIndex& index) const = 0; + + virtual int GetFileNameColumnIndex() const = 0; + virtual int GetTimeStampColumnIndex() const = 0; + ////////////////////////////////////////////////////////////////////////// + + //! Reload all the data based on the watched folders and files + virtual void Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles = QSet(), const AZStd::unordered_map& pathToProjectNameMap = AZStd::unordered_map()); + + virtual void ReloadFiles(const AZStd::vector& absoluteFilePathList, AZStd::unordered_map pathToProjectNameMap = AZStd::unordered_map()); + + bool Save(const QModelIndex& selectedIndex); + + bool SaveAll(); + + bool HasUnsavedChanges() const; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractTableModel overrides + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + ////////////////////////////////////////////////////////////////////////// + + protected: + //! Verifies input index is in range and returns the associated key. + //! Throws an error and returns an empty string if the input index is out of range. + AZStd::string GetFileKey(const QModelIndex& index) const; + + //! Returns an ordered list of every file key in the model. + //! If a proxy model is not used, the order of this list will also be the display order. + const AZStd::vector& GetAllFileKeys() const; + + //! Get the index row if the file info is stored in the model + //! Returns -1 if the file key doesn't exist. + int GetIndexRowByKey(const AZStd::string& key) const; + + //! Adds input key to the end of the list of all keys and notifies the view that a row has been added. + //! When subclassing, instantiate all data associated with this key so the view can update properly. + void AddFileKey(const AZStd::string& key); + + //! Verifies input index, signals to the view that rows will be removed, and removes the key found at the input index. + //! When subclassing, be sure to remove all data associated with the key at this index before calling this function. + //! Returns true if the index is successfully removed, and false on failure + bool RemoveFileKey(const QModelIndex& index); + + //! Delete a file from the disk and remove it from the model by its key + bool DeleteFileByKey(const AZStd::string& key); + + AZStd::unordered_set m_keysWithUnsavedChanges; + + private: + //! When subclassing: store file information in a map, and add the keys to this vector. + //! Provides a 1:1 mapping between a QModelIndex::row value and a key. + AZStd::vector m_fileListKeys; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.cpp b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.cpp new file mode 100644 index 0000000000..f9a24392a2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.cpp @@ -0,0 +1,62 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include "AssetBundlerFileTableFilterModel.h" + +#include + +#include + +namespace AssetBundler +{ + AssetBundlerFileTableFilterModel::AssetBundlerFileTableFilterModel(QObject* parent, int displayNameCol, int dateTimeCol) + : QSortFilterProxyModel(parent) + , m_displayNameCol(displayNameCol) + , m_dateTimeCol(dateTimeCol) + { + } + + void AssetBundlerFileTableFilterModel::FilterChanged(const QString& newFilter) + { + setFilterRegExp(newFilter.toLower()); + invalidateFilter(); + } + + bool AssetBundlerFileTableFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const + { + // Override the default implemention since we want to define custom rules here + QModelIndex index = sourceModel()->index(sourceRow, m_displayNameCol, sourceParent); + QRegExp filter(filterRegExp()); + + return sourceModel()->data(index).toString().toLower().contains(filter); + } + + bool AssetBundlerFileTableFilterModel::lessThan(const QModelIndex& left, const QModelIndex& right) const + { + // Any column displaying a DateTime string needs to be compared as a DateTime object to ensure + // proper sorting + if (left.column() != m_dateTimeCol || right.column() != m_dateTimeCol) + { + return QSortFilterProxyModel::lessThan(left, right); + } + + QVariant leftTime = sourceModel()->data(left, AssetBundlerAbstractFileTableModel::SortRole); + QVariant rightTime = sourceModel()->data(right, AssetBundlerAbstractFileTableModel::SortRole); + + if (leftTime.type() != QVariant::DateTime || rightTime.type() != QVariant::DateTime) + { + return QSortFilterProxyModel::lessThan(left, right); + } + + return leftTime.toDateTime() < rightTime.toDateTime(); + } +} diff --git a/Gems/LmbrCentral/Code/Source/Rendering/StereoRendererComponent.h b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.h similarity index 50% rename from Gems/LmbrCentral/Code/Source/Rendering/StereoRendererComponent.h rename to Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.h index 262c3cc5da..89f33c065a 100644 --- a/Gems/LmbrCentral/Code/Source/Rendering/StereoRendererComponent.h +++ b/Code/Tools/AssetBundler/source/models/AssetBundlerFileTableFilterModel.h @@ -12,26 +12,23 @@ #pragma once -#include +#include -/* -This class exposes functionality from the renderer to lua -*/ - -namespace LmbrCentral +namespace AssetBundler { - class StereoRendererComponent : - public AZ::Component + class AssetBundlerFileTableFilterModel + : public QSortFilterProxyModel { public: - AZ_COMPONENT(StereoRendererComponent, "{BBFE0965-5564-4739-8219-AFE8209A5E57}"); + AssetBundlerFileTableFilterModel(QObject* parent, int displayNameCol, int dateTimeCol = -1); - StereoRendererComponent() {}; - ~StereoRendererComponent() override {}; + void FilterChanged(const QString& newFilter); - void Activate() override {}; - void Deactivate() override {}; + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override; - static void Reflect(AZ::ReflectContext* context); + int m_displayNameCol = 0; + int m_dateTimeCol = -1; }; } diff --git a/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.cpp new file mode 100644 index 0000000000..e4bb7b6ca2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.cpp @@ -0,0 +1,251 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace AssetBundler +{ + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AssetListFileInfo + ////////////////////////////////////////////////////////////////////////////////////////////////// + AssetListFileInfo::AssetListFileInfo(const AZStd::string& absolutePath, const QString& fileName, const AZStd::string& platform) + : m_absolutePath(absolutePath) + , m_fileName(fileName) + , m_platform(QString(platform.c_str())) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + + // Modification time will either give us the time the file was last overwritten + // (or the time it was created if it has never been overwritten) + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileCreationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + + // Load the contents of the asset list file into memory + m_assetListModel.reset(new AssetListTableModel(nullptr, absolutePath, platform)); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AssetListFileTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + AssetListFileTableModel::AssetListFileTableModel() + : AssetBundlerAbstractFileTableModel() + { + } + + QSharedPointer AssetListFileTableModel::GetAssetListFileContents(const QModelIndex& index) + { + auto assetListFileInfoOutcome = GetAssetFileInfo(index); + if (!assetListFileInfoOutcome.IsSuccess()) + { + return QSharedPointer(); + } + + return assetListFileInfoOutcome.GetValue()->m_assetListModel; + } + + bool AssetListFileTableModel::DeleteFile(const QModelIndex& index) + { + auto assetFileInfoOutcome = GetAssetFileInfo(index); + if (!assetFileInfoOutcome.IsSuccess()) + { + return false; + } + + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(assetFileInfoOutcome.GetValue()->m_absolutePath); + if (m_assetListFileInfoMap.find(key) == m_assetListFileInfoMap.end()) + { + return false; + } + + AssetListFileInfoPtr assetFileInfo = m_assetListFileInfoMap[key]; + + // Remove file from disk + const char* absolutePath = assetFileInfo->m_absolutePath.c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath)) + { + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath)) + { + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath); + if (!deleteResult) + { + return false; + } + } + + // Remove file from model + m_assetListFileInfoMap.erase(key); + RemoveFileKey(index); + + return true; + } + + void AssetListFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/) + { + AZStd::string fullFileName; + AzFramework::StringFunc::Path::GetFullFileName(absoluteFilePath.c_str(), fullFileName); + + // Get the file name without the platform for display purposes + AZStd::string baseFileName; + AZStd::string platformIdentifier; + AzToolsFramework::SplitFilename(fullFileName, baseFileName, platformIdentifier); + + // Read the AssetListFile into memory and store it + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + m_assetListFileInfoMap[key].reset(new AssetListFileInfo(absoluteFilePath, QString(baseFileName.c_str()), platformIdentifier)); + AddFileKey(key); + } + + bool AssetListFileTableModel::WriteToDisk(const AZStd::string& /*key*/) + { + return true; + } + + AZStd::string AssetListFileTableModel::GetFileAbsolutePath(const QModelIndex& index) const + { + auto assetFileInfoOutcome = GetAssetFileInfo(index); + if (!assetFileInfoOutcome.IsSuccess()) + { + // Error has already been thrown + return AZStd::string(); + } + return assetFileInfoOutcome.GetValue()->m_absolutePath; + } + + int AssetListFileTableModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int AssetListFileTableModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileCreationTime; + } + + int AssetListFileTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant AssetListFileTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Asset List File")); + case Column::ColumnPlatform: + return QString(tr("Platform")); + case Column::ColumnFileCreationTime: + return QString(tr("Creation Time")); + default: + break; + } + } + + return QVariant(); + } + + QVariant AssetListFileTableModel::data(const QModelIndex& index, int role) const + { + auto assetListFileInfoOutcome = GetAssetFileInfo(index); + if (!assetListFileInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + int col = index.column(); + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + return assetListFileInfoOutcome.GetValue()->m_fileName; + } + else if (col == Column::ColumnPlatform) + { + return assetListFileInfoOutcome.GetValue()->m_platform; + } + else if (col == Column::ColumnFileCreationTime) + { + if (role == SortRole) + { + return assetListFileInfoOutcome.GetValue()->m_fileCreationTime; + } + else + { + return assetListFileInfoOutcome.GetValue()->m_fileCreationTime.toString(DateTimeFormat); + } + } + else + { + // Returning an empty QString will ensure the checkboxes do not have any text displayed next to them + return QString(); + } + } + case Qt::FontRole: + { + if (col == Column::ColumnFileName) + { + QFont boldFont; + boldFont.setBold(true); + return boldFont; + } + } + default: + break; + } + + return QVariant(); + } + + AZ::Outcome AssetListFileTableModel::GetAssetFileInfo(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return AZ::Failure(); + } + + if (m_assetListFileInfoMap.find(key) != m_assetListFileInfoMap.end()) + { + return AZ::Success(m_assetListFileInfoMap.at(key)); + } + else + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot find Asset List File Info"); + return AZ::Failure(); + } + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.h b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.h new file mode 100644 index 0000000000..61f1455130 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListFileTableModel.h @@ -0,0 +1,88 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#include +#include + +namespace AssetBundler +{ + class AssetListTableModel; + + struct AssetListFileInfo + { + /** + * Stores information about an Asset List File on disk. + * + * @param absolutePath The absolute path of the Asset List File + * @param fileName The name of the Asset List File. This does not include the platform ID + * @param platform The platform for the Asset List File + */ + AssetListFileInfo(const AZStd::string& absolutePath, const QString& fileName, const AZStd::string& platform); + + AZStd::string m_absolutePath; + QDateTime m_fileCreationTime; + /// Use QString for display purpose. This can help to avoid losts of string conversion + QString m_fileName; + QString m_platform; + + QSharedPointer m_assetListModel; + }; + + using AssetListFileInfoPtr = AZStd::shared_ptr; + /// Stores AssetListFileInfo, using the absolute path (without the drive letter) of the Asset List file as the key + using AssetListFileInfoMap = AZStd::unordered_map; + + class AssetListFileTableModel + : public AssetBundlerAbstractFileTableModel + { + public: + explicit AssetListFileTableModel(); + virtual ~AssetListFileTableModel() {} + + QSharedPointer GetAssetListFileContents(const QModelIndex& index); + + ////////////////////////////////////////////////////////////////////////// + // AssetBundlerAbstractFileTableModel overrides + AZStd::vector CreateNewFiles(const AZStd::string& /*absoluteFilePath*/, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) override { return {}; } + bool DeleteFile(const QModelIndex& index) override; + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + bool WriteToDisk(const AZStd::string& key) override; + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + int GetFileNameColumnIndex() const override; + int GetTimeStampColumnIndex() const override; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnFileName, + ColumnPlatform, + ColumnFileCreationTime, + Max + }; + + private: + AZ::Outcome GetAssetFileInfo(const QModelIndex& index) const; + + AssetListFileInfoMap m_assetListFileInfoMap; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/AssetListTableModel.cpp b/Code/Tools/AssetBundler/source/models/AssetListTableModel.cpp new file mode 100644 index 0000000000..cec057d38b --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListTableModel.cpp @@ -0,0 +1,129 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include + +#include + +namespace AssetBundler +{ + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AssetListTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + AssetListTableModel::AssetListTableModel(QObject* parent, const AZStd::string& absolutePath, const AZStd::string& platform) + : QAbstractTableModel(parent) + { + m_seedListManager.reset(new AzToolsFramework::AssetSeedManager()); + + if (absolutePath.empty() || platform.empty()) + { + return; + } + + AZ::Outcome outcome = m_seedListManager->LoadAssetFileInfo(absolutePath); + if (!outcome.IsSuccess()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Failed to load the asset file info for %s", absolutePath.c_str()); + return; + } + + m_assetFileInfoList = outcome.TakeValue(); + m_platformId = static_cast(AzFramework::PlatformHelper::GetPlatformIndexFromName(platform.c_str())); + } + + int AssetListTableModel::rowCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : static_cast(m_assetFileInfoList.m_fileInfoList.size()); + } + + int AssetListTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant AssetListTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnAssetName: + return QString("Asset Name"); + case Column::ColumnRelativePath: + return QString("Relative Path"); + case Column::ColumnAssetId: + return QString("Asset ID"); + default: + break; + } + } + + return QVariant(); + } + + QVariant AssetListTableModel::data(const QModelIndex& index, int role) const + { + auto assetFileInfoOutcome = GetAssetFileInfo(index); + if (!assetFileInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + switch (role) + { + case Qt::DisplayRole: + { + switch (index.column()) + { + case Column::ColumnAssetName: + { + AZStd::string fileName = assetFileInfoOutcome.GetValue().m_assetRelativePath; + AzFramework::StringFunc::Path::GetFullFileName(fileName.c_str(), fileName); + + return fileName.c_str(); + } + case Column::ColumnRelativePath: + { + return assetFileInfoOutcome.GetValue().m_assetRelativePath.c_str(); + } + case Column::ColumnAssetId: + { + AZStd::string assetIdStr; + assetFileInfoOutcome.GetValue().m_assetId.ToString(assetIdStr); + + return assetIdStr.c_str(); + } + default: + break; + } + } + default: + break; + } + + return QVariant(); + } + + AZ::Outcome AssetListTableModel::GetAssetFileInfo(const QModelIndex& index) const + { + int row = index.row(); + int col = index.column(); + if (row >= rowCount() || row < 0 || col >= columnCount() || col < 0) + { + return AZ::Failure(AZStd::string::format("Selected index (%i, %i) is out of range", row, col)); + } + + return AZ::Success(m_assetFileInfoList.m_fileInfoList.at(row)); + } +} diff --git a/Code/Tools/AssetBundler/source/models/AssetListTableModel.h b/Code/Tools/AssetBundler/source/models/AssetListTableModel.h new file mode 100644 index 0000000000..94500f520f --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/AssetListTableModel.h @@ -0,0 +1,54 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +#include + +namespace AssetBundler +{ + class AssetListTableModel + : public QAbstractTableModel + { + public: + explicit AssetListTableModel(QObject* parent = nullptr, const AZStd::string& absolutePath = AZStd::string(), const AZStd::string& platform = ""); + virtual ~AssetListTableModel() {} + + AZStd::shared_ptr GetSeedListManager() { return m_seedListManager; } + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnAssetName, + ColumnRelativePath, + ColumnAssetId, + Max + }; + + private: + AZ::Outcome GetAssetFileInfo(const QModelIndex& index) const; + + AZStd::shared_ptr m_seedListManager; + AzToolsFramework::AssetFileInfoList m_assetFileInfoList; + AzFramework::PlatformId m_platformId; + }; +} diff --git a/Code/Tools/AssetBundler/source/models/BundleFileListModel.cpp b/Code/Tools/AssetBundler/source/models/BundleFileListModel.cpp new file mode 100644 index 0000000000..d7c0e93279 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/BundleFileListModel.cpp @@ -0,0 +1,236 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include + +#include + +#include + + +namespace AssetBundler +{ + BundleFileInfo::BundleFileInfo(const AZStd::string& absolutePath) + : m_absolutePath(absolutePath) + , m_compressedSize(0u) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + + AZStd::string fileNameStr; + if (AzFramework::StringFunc::Path::GetFileName(m_absolutePath.c_str(), fileNameStr)) + { + m_fileName = QString(fileNameStr.c_str()); + } + else + { + AZ_Error("AssetBundler", false, "Failed to get file name from %s", m_absolutePath.c_str()); + } + + // Modification time will either give us the time the file was last overwritten + // (or the time it was created if it has never been overwritten) + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileCreationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + } + + BundleFileListModel::BundleFileListModel() + : AssetBundlerAbstractFileTableModel() + { + } + + bool BundleFileListModel::DeleteFile(const QModelIndex& index) + { + AZStd::string fileKey = GetFileKey(index); + if (fileKey.empty()) + { + // Error has already been thrown + return false; + } + + auto bundleFileInfoIt = m_bundleFileInfoMap.find(fileKey); + if (bundleFileInfoIt == m_bundleFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Bundle Info with key ( %s )", fileKey.c_str()); + return false; + } + + BundleFileInfoPtr bundleFileInfo = bundleFileInfoIt->second; + + // Remove file from disk + const char* absolutePath = bundleFileInfo->m_absolutePath.c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath)) + { + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath)) + { + AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", absolutePath); + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath); + if (!deleteResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", absolutePath); + return false; + } + } + + // Remove file from Model + m_bundleFileInfoMap.erase(fileKey); + RemoveFileKey(index); + + return true; + } + + int BundleFileListModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant BundleFileListModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Name")); + case Column::ColumnFileCreationTime: + return QString(tr("Creation Time")); + default: + break; + } + } + return QVariant(); + } + + QVariant BundleFileListModel::data(const QModelIndex& index, int role) const + { + auto bundleInfoOutcome = GetBundleInfo(index); + if (!bundleInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + int col = index.column(); + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + return bundleInfoOutcome.GetValue()->m_fileName; + } + else if (col == Column::ColumnFileCreationTime) + { + if (role == SortRole) + { + return bundleInfoOutcome.GetValue()->m_fileCreationTime; + } + else + { + return bundleInfoOutcome.GetValue()->m_fileCreationTime.toString(DateTimeFormat); + } + } + } + default: + break; + } + + return QVariant(); + } + + AZStd::string BundleFileListModel::GetFileAbsolutePath(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return key; + } + + return m_bundleFileInfoMap.at(key)->m_absolutePath; + } + + int BundleFileListModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int BundleFileListModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileCreationTime; + } + + void BundleFileListModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/) + { + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + + BundleFileInfo* newInfo = new BundleFileInfo(absoluteFilePath); + + QFile bundleFile(absoluteFilePath.c_str()); + if (bundleFile.open(QIODevice::ReadOnly)) + { + newInfo->m_compressedSize = bundleFile.size(); + bundleFile.close(); + } + else + { + AZ_Error("AssetBundler", false, "Failed to open file at %s", absoluteFilePath.c_str()); + } + + auto manifest = AzToolsFramework::AssetBundleComponent::GetManifestFromBundle(absoluteFilePath); + if (manifest != nullptr) + { + for (auto& bundleName : manifest->GetDependentBundleNames()) + { + newInfo->m_relatedBundles.push_back(bundleName.c_str()); + } + } + else + { + AZ_Error("AssetBundler", false, "Failed to get manifest from bundle at %s", absoluteFilePath.c_str()); + } + + m_bundleFileInfoMap[key].reset(newInfo); + // Add it to the list that gets displayed by AssetBundlerAbstractFileTableModel. Make sure that + // AddFileKey is called after m_bundleFileInfoMap is reset since the filterAcceptsRow funtion + // of the filter model will be called when a new row is inserted and it could cause a crash + // without valid data being set + AddFileKey(key); + } + + AZ::Outcome BundleFileListModel::GetBundleInfo(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return AZ::Failure(); + } + + if (m_bundleFileInfoMap.find(key) != m_bundleFileInfoMap.end()) + { + return AZ::Success(m_bundleFileInfoMap.at(key)); + } + else + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot find Bundle File Info"); + return AZ::Failure(); + } + } + +} diff --git a/Code/Tools/AssetBundler/source/models/BundleFileListModel.h b/Code/Tools/AssetBundler/source/models/BundleFileListModel.h new file mode 100644 index 0000000000..13e5838c57 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/BundleFileListModel.h @@ -0,0 +1,74 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + + struct BundleFileInfo + { + AZStd::string m_absolutePath; + QString m_fileName; + QDateTime m_fileCreationTime; + AZ::u64 m_compressedSize; + QStringList m_relatedBundles; + + BundleFileInfo(const AZStd::string& absolutePath); + }; + + using BundleFileInfoPtr = AZStd::shared_ptr; + using BundleFileInfoMap = AZStd::unordered_map; + + class BundleFileListModel + : public AssetBundlerAbstractFileTableModel + { + public: + explicit BundleFileListModel(); + virtual ~BundleFileListModel() {} + + AZStd::vector CreateNewFiles(const AZStd::string& /*absoluteFilePath*/, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) override { return {}; } + bool DeleteFile(const QModelIndex& index) override; + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + bool WriteToDisk(const AZStd::string& /*key*/) override { return true; } + + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + int GetFileNameColumnIndex() const override; + int GetTimeStampColumnIndex() const override; + + AZ::Outcome GetBundleInfo(const QModelIndex& index) const; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractTableModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnFileName, + ColumnFileCreationTime, + Max + }; + + private: + BundleFileInfoMap m_bundleFileInfoMap; + }; +} diff --git a/Code/Tools/AssetBundler/source/models/RulesFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.cpp new file mode 100644 index 0000000000..c7ae384d6e --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.cpp @@ -0,0 +1,305 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include +#include +#include + +#include +#include + +namespace AssetBundler +{ + RulesFileInfo::RulesFileInfo(const AZStd::string& absolutePath, const QString& fileName, bool loadFromFile) + : m_absolutePath(absolutePath) + , m_fileName(fileName) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + m_comparisonSteps = AZStd::make_shared(); + + if (loadFromFile) + { + auto outcome = AzToolsFramework::AssetFileInfoListComparison::Load(m_absolutePath); + if (!outcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, outcome.GetError().c_str()); + return; + } + m_comparisonSteps = AZStd::make_unique(outcome.TakeValue()); + + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileModificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + } + else + { + m_fileModificationTime = QDateTime::currentDateTime(); + } + } + + bool RulesFileInfo::SaveRulesFile() + { + if (!m_comparisonSteps->Save(m_absolutePath)) + { + return false; + } + + m_hasUnsavedChanges = false; + m_fileModificationTime = QDateTime::currentDateTime(); + return true; + } + + + + RulesFileTableModel::RulesFileTableModel() + : AssetBundlerAbstractFileTableModel() + { + } + + AZStd::vector RulesFileTableModel::CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& /*platforms*/, const QString& /*project*/) + { + if (absoluteFilePath.empty()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Input file path is empty"); + return {}; + } + + // Create a platform-specific file path + if (AZ::IO::FileIOBase::GetInstance()->Exists(absoluteFilePath.c_str())) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot Create New File: (%s) already exists", absoluteFilePath.c_str()); + return {}; + } + + // Get the file name without the extension for display purposes + AZStd::string fileName = absoluteFilePath; + AzToolsFramework::RemovePlatformIdentifier(fileName); + AzFramework::StringFunc::Path::GetFileName(fileName.c_str(), fileName); + + // Create a Rules File and save it to disk + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + RulesFileInfoPtr newRulesFile = AZStd::make_shared(absoluteFilePath, QString(fileName.c_str()), false); + + if (!newRulesFile->SaveRulesFile()) + { + return {}; + } + + // Add the new file to the model + m_rulesFileInfoMap[key] = newRulesFile; + AddFileKey(key); + return { absoluteFilePath }; + } + + bool RulesFileTableModel::DeleteFile(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + RulesFileInfoPtr rulesFileInfo = m_rulesFileInfoMap[key]; + + // Remove file from disk + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(rulesFileInfo->m_absolutePath.c_str())) + { + AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", rulesFileInfo->m_absolutePath.c_str()); + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(rulesFileInfo->m_absolutePath.c_str()); + if (!deleteResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", rulesFileInfo->m_absolutePath.c_str()); + return false; + } + + // Remove file from model + m_rulesFileInfoMap.erase(key); + RemoveFileKey(index); + + return true; + } + + void RulesFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& /*projectName*/, bool /*isDefaultFile*/) + { + // Get the file name without the extension for display purposes + AZStd::string fileName(absoluteFilePath); + AzFramework::StringFunc::Path::GetFileName(fileName.c_str(), fileName); + + // Read the Rules file into memory and store it + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + auto fileInfoIt = m_rulesFileInfoMap.find(key); + if (fileInfoIt != m_rulesFileInfoMap.end() && fileInfoIt->second->m_hasUnsavedChanges) + { + AZ_Warning(AssetBundler::AppWindowName, false, "Rules File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str()); + return; + } + + m_rulesFileInfoMap[key] = AZStd::make_shared(absoluteFilePath, QString(fileName.c_str()), true); + AddFileKey(key); + } + + bool RulesFileTableModel::WriteToDisk(const AZStd::string& key) + { + auto rulesFileIt = m_rulesFileInfoMap.find(key); + return rulesFileIt != m_rulesFileInfoMap.end() && rulesFileIt->second->SaveRulesFile(); + } + + AZStd::string RulesFileTableModel::GetFileAbsolutePath(const QModelIndex& index) const + { + RulesFileInfoPtr rulesFileInfo = GetRulesFileInfoPtr(index); + if (!rulesFileInfo) + { + return AZStd::string(); + } + + return rulesFileInfo->m_absolutePath; + } + + int RulesFileTableModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int RulesFileTableModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileModificationTime; + } + + AZStd::shared_ptr RulesFileTableModel::GetComparisonSteps(const QModelIndex& index) const + { + RulesFileInfoPtr rulesFileInfo = GetRulesFileInfoPtr(index); + if (!rulesFileInfo) + { + return nullptr; + } + + return rulesFileInfo->m_comparisonSteps; + } + + bool RulesFileTableModel::MarkFileChanged(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + m_rulesFileInfoMap[key]->m_hasUnsavedChanges = true; + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.emplace(key); + QModelIndex changedIndex = QAbstractTableModel::index(index.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + int RulesFileTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant RulesFileTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Name")); + case Column::ColumnFileModificationTime: + return QString(tr("Modification Time")); + default: + break; + } + } + + return QVariant(); + } + + QVariant RulesFileTableModel::data(const QModelIndex& index, int role) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + return QVariant(); + } + + RulesFileInfoPtr rulesFileInfo = m_rulesFileInfoMap.at(key); + + int col = index.column(); + bool hasUnsavedChanges = rulesFileInfo->m_hasUnsavedChanges; + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + QString displayName = rulesFileInfo->m_fileName; + if (hasUnsavedChanges) + { + displayName.append("*"); + } + return displayName; + } + else if (col == Column::ColumnFileModificationTime) + { + if (role == SortRole) + { + return rulesFileInfo->m_fileModificationTime; + } + else + { + return rulesFileInfo->m_fileModificationTime.toString(DateTimeFormat); + } + } + break; + } + case Qt::FontRole: + { + if (col == Column::ColumnFileName && hasUnsavedChanges) + { + QFont boldFont; + boldFont.setBold(true); + return boldFont; + } + break; + } + default: + break; + } + + return QVariant(); + } + + RulesFileInfoPtr RulesFileTableModel::GetRulesFileInfoPtr(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + return nullptr; + } + + return m_rulesFileInfoMap.at(key); + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/RulesFileTableModel.h b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.h new file mode 100644 index 0000000000..a9931a9819 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/RulesFileTableModel.h @@ -0,0 +1,88 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + + //! Stores information about a Rules file on disk. + struct RulesFileInfo + { + RulesFileInfo(const AZStd::string& absolutePath, const QString& fileName, bool loadFromFile); + + bool SaveRulesFile(); + + AZStd::string m_absolutePath; + QString m_fileName; + QDateTime m_fileModificationTime; + bool m_hasUnsavedChanges = false; + + AZStd::shared_ptr m_comparisonSteps; + }; + + using RulesFileInfoPtr = AZStd::shared_ptr; + using RulesFileInfoMap = AZStd::unordered_map; + + + class RulesFileTableModel + : public AssetBundlerAbstractFileTableModel + { + public: + RulesFileTableModel(); + virtual ~RulesFileTableModel() {} + + AZStd::vector CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE, const QString& project = QString()) override; + + bool DeleteFile(const QModelIndex& index) override; + + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + + bool WriteToDisk(const AZStd::string& key) override; + + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + + int GetFileNameColumnIndex() const override; + + int GetTimeStampColumnIndex() const override; + + AZStd::shared_ptr GetComparisonSteps(const QModelIndex& index) const; + + bool MarkFileChanged(const QModelIndex& index); + + ////////////////////////////////////////////////////////////////////////// + // QAbstractTableModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnFileName, + ColumnFileModificationTime, + Max + }; + + private: + RulesFileInfoMap m_rulesFileInfoMap; + + RulesFileInfoPtr GetRulesFileInfoPtr(const QModelIndex& index) const; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.cpp b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.cpp new file mode 100644 index 0000000000..1e7ec36bac --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.cpp @@ -0,0 +1,601 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace AssetBundler +{ + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // SeedListFileInfo + ////////////////////////////////////////////////////////////////////////////////////////////////// + SeedListFileInfo::SeedListFileInfo( + const AZStd::string& absolutePath, + const QString& fileName, + const QString& project, + bool loadFromFile, + bool isDefaultSeedList, + const AZStd::vector& defaultSeeds, + const AzFramework::PlatformFlags& platforms) + : m_absolutePath(absolutePath) + , m_fileName(fileName) + , m_project(project) + , m_isDefaultSeedList(isDefaultSeedList) + { + AzFramework::StringFunc::Path::Normalize(m_absolutePath); + + // Load the contents of the seed file into memory + if (loadFromFile) + { + m_seedListModel.reset(new SeedListTableModel(nullptr, absolutePath)); + QFileInfo fileInfo(m_absolutePath.c_str()); + m_fileModificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime); + } + else + { + m_seedListModel.reset(new SeedListTableModel(nullptr, "", defaultSeeds, platforms)); + m_fileModificationTime = QDateTime::currentDateTime(); + } + } + + bool SeedListFileInfo::SaveSeedFile() + { + if (m_seedListModel->Save(m_absolutePath)) + { + m_fileModificationTime = QDateTime::currentDateTime(); + return true; + } + return false; + } + + bool SeedListFileInfo::HasUnsavedChanges() + { + return m_seedListModel->HasUnsavedChanges(); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // SeedListFileTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + + SeedListFileTableModel::SeedListFileTableModel(SeedTabWidget* parentSeedTabWidget) + : AssetBundlerAbstractFileTableModel() + , m_seedTabWidget(parentSeedTabWidget) + { + m_inMemoryDefaultSeedList.reset(new SeedListFileInfo("", "", "", false)); + } + + SeedListFileTableModel::~SeedListFileTableModel() + { + m_seedTabWidget = nullptr; + } + + void SeedListFileTableModel::AddDefaultSeedsToInMemoryList(const AZStd::vector& defaultSeeds, const char* projectName, const AzFramework::PlatformFlags& platforms) + { + m_inMemoryDefaultSeedList.reset(new SeedListFileInfo(m_inMemoryDefaultSeedListKey, tr("DefaultSeeds"), QString(projectName), false, true, defaultSeeds, platforms)); + } + + AZStd::vector SeedListFileTableModel::CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& /*platforms*/, const QString& project) + { + if (absoluteFilePath.empty()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Input file path is empty."); + return {}; + } + + // Get the file name without the extension for display purposes + AZStd::string fileName; + AzFramework::StringFunc::Path::GetFileName(absoluteFilePath.c_str(), fileName); + + // Create a Seed List File and save it to disk + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + + AZStd::shared_ptr newSeedListFile = AZStd::make_shared(absoluteFilePath, QString(fileName.c_str()), project, false); + newSeedListFile->m_seedListModel->SetHasUnsavedChanges(true); + bool saveResult = newSeedListFile->SaveSeedFile(); + if (!saveResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to create Seed List File: %s", absoluteFilePath.c_str()); + return {}; + } + + // Add new file to the model + m_seedListFileInfoMap[key] = newSeedListFile; + AddFileKey(key); + + AZStd::vector createdFiles = { absoluteFilePath }; + return createdFiles; + } + + bool SeedListFileTableModel::DeleteFile(const QModelIndex& index) + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + + // Remove file from disk + const char* absolutePath = seedFileInfo->m_absolutePath.c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(absolutePath)) + { + if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(absolutePath)) + { + AZ_Error(AssetBundler::AppWindowName, false, "File (%s) is Read-Only. Please check your version control and try again.", absolutePath); + return false; + } + + auto deleteResult = AZ::IO::FileIOBase::GetInstance()->Remove(absolutePath); + if (!deleteResult) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to delete: %s", absolutePath); + return false; + } + } + + // Remove file from model + m_seedListFileInfoMap.erase(key); + RemoveFileKey(index); + + return true; + } + + void SeedListFileTableModel::Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles, const AZStd::unordered_map& pathToProjectNameMap) + { + // Load in the Seed List files from disk + AssetBundlerAbstractFileTableModel::Reload(fileExtension, watchedFolders, watchedFiles, pathToProjectNameMap); + + // Add the in-memory Default Seed List to the model + m_seedListFileInfoMap[m_inMemoryDefaultSeedListKey] = m_inMemoryDefaultSeedList; + AddFileKey(m_inMemoryDefaultSeedListKey); + } + + void SeedListFileTableModel::LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName, bool isDefaultFile) + { + // Get the file name without the extension for display purposes + AZStd::string fileName; + AzFramework::StringFunc::Path::GetFileName(absoluteFilePath.c_str(), fileName); + + // Read the SeedListFile into memory and store it + AZStd::string key = AssetBundler::GenerateKeyFromAbsolutePath(absoluteFilePath); + auto fileInfoIt = m_seedListFileInfoMap.find(key); + if (fileInfoIt != m_seedListFileInfoMap.end() && fileInfoIt->second->HasUnsavedChanges()) + { + AZ_Warning(AssetBundler::AppWindowName, false, "Seed List File %s has unsaved changes and couldn't be reloaded", absoluteFilePath.c_str()); + return; + } + + AZStd::string projectNameOnDisplay = projectName; + if (projectName.empty()) + { + auto outcome = AssetBundler::GetCurrentProjectName(); + if (!outcome.IsSuccess()) + { + AZ_Error(AssetBundler::AppWindowName, false, outcome.TakeError().c_str()); + return; + } + + projectNameOnDisplay = outcome.TakeValue(); + } + + m_seedListFileInfoMap[key].reset(new SeedListFileInfo(absoluteFilePath, QString(fileName.c_str()), QString(projectNameOnDisplay.c_str()), true, isDefaultFile)); + AddFileKey(key); + } + + void SeedListFileTableModel::SelectDefaultSeedLists(bool setSelected) + { + for (const AZStd::string& key : GetAllFileKeys()) + { + auto seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_isDefaultSeedList) + { + continue; + } + + seedFileInfo->m_isChecked = setSelected; + if(setSelected) + { + m_checkedSeedListFiles.insert(key); + } + else + { + m_checkedSeedListFiles.erase(key); + } + } + + m_seedTabWidget->SetGenerateAssetListsButtonEnabled(!m_checkedSeedListFiles.empty()); + + // Update the Check State display of all elements + QModelIndex firstIndex = index(0, 0); + QModelIndex lastIndex = index(rowCount() - 1, columnCount() - 1); + emit dataChanged(firstIndex, lastIndex, { Qt::CheckStateRole }); + } + + AZStd::vector SeedListFileTableModel::GenerateAssetLists(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms) + { + if (!m_checkedSeedListFiles.size()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot Generate Asset List File(s): No Seed List Files are selected"); + return {}; + } + + if (absoluteFilePath.empty()) + { + AZ_Error(AssetBundler::AppWindowName, false, "File path cannot be empty"); + return {}; + } + + if(platforms == AzFramework::PlatformFlags::Platform_NONE) + { + AZ_Error(AssetBundler::AppWindowName, false, "Input platform cannot be empty"); + return {}; + } + + // Get all of the Seeds into one AssetSeedManager + AzToolsFramework::AssetSeedManager assetSeedManager; + + if (m_checkedSeedListFiles.find(m_inMemoryDefaultSeedListKey) != m_checkedSeedListFiles.end()) + { + // The In-Memory Default Seed List can't be loaded from a file on disk, it is a special case + assetSeedManager = *m_inMemoryDefaultSeedList->m_seedListModel->GetSeedListManager().get(); + m_checkedSeedListFiles.erase(m_inMemoryDefaultSeedListKey); + } + + for (const auto& checkedSeedFileKey : m_checkedSeedListFiles) + { + assetSeedManager.Load(m_seedListFileInfoMap[checkedSeedFileKey]->m_absolutePath); + } + + // Generate an AssetList for every input platform + AZStd::vector createdFiles; + for (const auto& platformIndex : AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(platforms)) + { + AZStd::string platformSpecificCachePath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(platformIndex); + AzFramework::StringFunc::Path::StripFullName(platformSpecificCachePath); + + FilePath platformSpecificPath(absoluteFilePath, AZStd::string(AzFramework::PlatformHelper::GetPlatformName(platformIndex))); + if (assetSeedManager.SaveAssetFileInfo(platformSpecificPath.AbsolutePath(), AzFramework::PlatformHelper::GetPlatformFlagFromPlatformIndex(platformIndex))) + { + createdFiles.emplace_back(platformSpecificPath.AbsolutePath()); + } + } + + return createdFiles; + } + + QSharedPointer SeedListFileTableModel::GetSeedListFileContents(const QModelIndex& index) + { + auto seedFileInfoOutcome = GetSeedFileInfo(index); + if (!seedFileInfoOutcome.IsSuccess()) + { + return QSharedPointer(); + } + + return seedFileInfoOutcome.GetValue()->m_seedListModel; + } + + bool SeedListFileTableModel::SetSeedPlatforms(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex, const AzFramework::PlatformFlags& platforms) + { + AZStd::string key = GetFileKey(seedFileIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_seedListModel->SetSeedPlatforms(seedIndex, platforms)) + { + // Error has already been thrown + return false; + } + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.insert(key); + QModelIndex changedIndex = QAbstractTableModel::index(seedFileIndex.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool SeedListFileTableModel::AddSeed(const QModelIndex& seedFileIndex, const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms) + { + AZStd::string key = GetFileKey(seedFileIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_seedListModel->AddSeed(seedRelativePath, platforms)) + { + // Error has already been thrown + return false; + } + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.insert(key); + QModelIndex changedIndex = QAbstractTableModel::index(seedFileIndex.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool SeedListFileTableModel::RemoveSeed(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex) + { + AZStd::string key = GetFileKey(seedFileIndex); + if (key.empty()) + { + // Error has already been thrown + return false; + } + + if (m_seedListFileInfoMap.find(key) == m_seedListFileInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find Seed File Info with key ( %s )", key.c_str()); + return false; + } + + SeedListFileInfoPtr seedFileInfo = m_seedListFileInfoMap[key]; + if (!seedFileInfo->m_seedListModel->RemoveSeed(seedIndex)) + { + // Error has already been thrown + return false; + } + + // Update display so the user knows there are unsaved changes + m_keysWithUnsavedChanges.insert(key); + QModelIndex changedIndex = QAbstractTableModel::index(seedFileIndex.row(), Column::ColumnFileName); + emit dataChanged(changedIndex, changedIndex, { Qt::DisplayRole, Qt::FontRole }); + + return true; + } + + bool SeedListFileTableModel::WriteToDisk(const AZStd::string& key) + { + if (key == m_inMemoryDefaultSeedListKey) + { + return true; + } + + auto seedListFileIt = m_seedListFileInfoMap.find(key); + return seedListFileIt != m_seedListFileInfoMap.end() && seedListFileIt->second->SaveSeedFile(); + } + + AZStd::string SeedListFileTableModel::GetFileAbsolutePath(const QModelIndex& index) const + { + auto seedFileInfoOutcome = GetSeedFileInfo(index); + if (!seedFileInfoOutcome.IsSuccess() || seedFileInfoOutcome.GetValue()->m_absolutePath == m_inMemoryDefaultSeedListKey) + { + // Error has already been thrown + return AZStd::string(); + } + return seedFileInfoOutcome.GetValue()->m_absolutePath; + } + + int SeedListFileTableModel::GetFileNameColumnIndex() const + { + return Column::ColumnFileName; + } + + int SeedListFileTableModel::GetTimeStampColumnIndex() const + { + return Column::ColumnFileModificationTime; + } + + int SeedListFileTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant SeedListFileTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnFileName: + return QString(tr("Seed List File")); + case Column::ColumnProject: + return QString(tr("Project Source")); + case Column::ColumnFileModificationTime: + return QString(tr("Modification Time")); + default: + break; + } + } + + return QVariant(); + } + + QVariant SeedListFileTableModel::data(const QModelIndex& index, int role) const + { + auto seedFileInfoOutcome = GetSeedFileInfo(index); + if (!seedFileInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + int col = index.column(); + bool hasUnsavedChanges = seedFileInfoOutcome.GetValue()->m_seedListModel->HasUnsavedChanges(); + + switch (role) + { + case Qt::DisplayRole: + [[fallthrough]]; + case SortRole: + { + if (col == Column::ColumnFileName) + { + QString displayName = seedFileInfoOutcome.GetValue()->m_fileName; + if (hasUnsavedChanges) + { + displayName.append("*"); + } + return displayName; + } + else if (col == Column::ColumnProject) + { + return seedFileInfoOutcome.GetValue()->m_project; + } + else if (col == Column::ColumnFileModificationTime) + { + if (role == SortRole) + { + return seedFileInfoOutcome.GetValue()->m_fileModificationTime; + } + else + { + return seedFileInfoOutcome.GetValue()->m_fileModificationTime.toString(DateTimeFormat); + } + } + else + { + // Returning an empty QString will ensure the checkboxes do not have any text displayed next to them + return QString(); + } + } + case Qt::FontRole: + { + if (col == Column::ColumnFileName && hasUnsavedChanges) + { + QFont boldFont; + boldFont.setBold(true); + return boldFont; + } + } + case Qt::CheckStateRole: + { + if (col == Column::ColumnCheckBox) + { + if (seedFileInfoOutcome.GetValue()->m_isChecked) + { + return Qt::Checked; + } + else + { + return Qt::Unchecked; + } + } + } + default: + break; + } + + return QVariant(); + } + + bool SeedListFileTableModel::setData(const QModelIndex& index, const QVariant& value, int role) + { + if (role != Qt::CheckStateRole || index.column() != Column::ColumnCheckBox) + { + return false; + } + + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + return false; + } + + auto seedFileInfo = m_seedListFileInfoMap.find(key); + if (seedFileInfo == m_seedListFileInfoMap.end()) + { + return false; + } + + if (value == Qt::CheckState::Unchecked) + { + seedFileInfo->second->m_isChecked = false; + m_checkedSeedListFiles.erase(key); + + if (seedFileInfo->second->m_isDefaultSeedList) + { + m_seedTabWidget->UncheckSelectDefaultSeedListsCheckBox(); + } + } + else + { + seedFileInfo->second->m_isChecked = true; + m_checkedSeedListFiles.insert(key); + } + + m_seedTabWidget->SetGenerateAssetListsButtonEnabled(!m_checkedSeedListFiles.empty()); + + return true; + } + + Qt::ItemFlags SeedListFileTableModel::flags(const QModelIndex& index) const + { + if (index.column() == Column::ColumnCheckBox) + { + return Qt::ItemIsUserCheckable | QAbstractTableModel::flags(index); + } + + return QAbstractTableModel::flags(index); + } + + AZ::Outcome SeedListFileTableModel::GetSeedFileInfo(const QModelIndex& index) const + { + AZStd::string key = GetFileKey(index); + if (key.empty()) + { + // Error has already been thrown + return AZ::Failure(); + } + + if (m_seedListFileInfoMap.find(key) != m_seedListFileInfoMap.end()) + { + return AZ::Success(m_seedListFileInfoMap.at(key)); + } + else + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot find Seed File Info"); + return AZ::Failure(); + } + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.h b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.h new file mode 100644 index 0000000000..3bd8fbd600 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListFileTableModel.h @@ -0,0 +1,134 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#include +#include + +#include +#include + +namespace AssetBundler +{ + class SeedListTableModel; + + class SeedTabWidget; + + struct SeedListFileInfo + { + /** + * Stores information about a Seed List File on disk. + * + * @param absolutePath The absolute path of the Seed List File + * @param fileName The name of the Seed List File. This does not include the ".seed" file extension + * @param project The area of the codebase the Seed List File is from (ex: ProjectName, Engine, Gem) + * @param loadFromFile Set to True if you wish to load an existing Seed List File into memory. Set to False if you are creating a new Seed List File. + */ + SeedListFileInfo( + const AZStd::string& absolutePath, + const QString& fileName, + const QString& project, + bool loadFromFile, + bool isDefaultSeedList = false, + const AZStd::vector& defaultSeeds = AZStd::vector(), + const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE); + + bool SaveSeedFile(); + + bool HasUnsavedChanges(); + + AZStd::string m_absolutePath; + bool m_isChecked = false; + bool m_isDefaultSeedList = false; + QString m_fileName; + QString m_project; + QDateTime m_fileModificationTime; + + QSharedPointer m_seedListModel; + }; + + using SeedListFileInfoPtr = AZStd::shared_ptr; + /// Stores SeedListFileInfo, using the absolute path (without the drive letter) of the Seed List file as the key + using SeedListFileInfoMap = AZStd::unordered_map; + + class SeedListFileTableModel + : public AssetBundlerAbstractFileTableModel + { + + public: + explicit SeedListFileTableModel(SeedTabWidget* parentSeedTabWidget); + virtual ~SeedListFileTableModel(); + + void AddDefaultSeedsToInMemoryList(const AZStd::vector& defaultSeeds, const char* projectName, const AzFramework::PlatformFlags& platforms); + + AZStd::vector CreateNewFiles(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms, const QString& project) override; + + bool DeleteFile(const QModelIndex& index) override; + + void Reload(const char* fileExtension, const QSet& watchedFolders, const QSet& watchedFiles = QSet(), const AZStd::unordered_map& pathToProjectNameMap = AZStd::unordered_map()) override; + + void LoadFile(const AZStd::string& absoluteFilePath, const AZStd::string& projectName = "", bool isDefaultFile = false) override; + + void SelectDefaultSeedLists(bool setSelected); + + AZStd::vector GenerateAssetLists(const AZStd::string& absoluteFilePath, const AzFramework::PlatformFlags& platforms); + + QSharedPointer GetSeedListFileContents(const QModelIndex& index); + + bool SetSeedPlatforms(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex, const AzFramework::PlatformFlags& platforms); + + bool AddSeed(const QModelIndex& seedFileIndex, const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms); + + bool RemoveSeed(const QModelIndex& seedFileIndex, const QModelIndex& seedIndex); + + bool WriteToDisk(const AZStd::string& key) override; + + AZStd::string GetFileAbsolutePath(const QModelIndex& index) const override; + + int GetFileNameColumnIndex() const override; + + int GetTimeStampColumnIndex() const override; + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::CheckStateRole) override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnCheckBox, + ColumnFileName, + ColumnProject, + ColumnFileModificationTime, + Max + }; + + private: + AZ::Outcome GetSeedFileInfo(const QModelIndex& index) const; + + SeedListFileInfoMap m_seedListFileInfoMap; + AZStd::unordered_set m_checkedSeedListFiles; + + AZStd::string m_inMemoryDefaultSeedListKey = "InMemoryDefaultKey"; + SeedListFileInfoPtr m_inMemoryDefaultSeedList; + + SeedTabWidget* m_seedTabWidget = nullptr; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp b/Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp new file mode 100644 index 0000000000..fc04686436 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListTableModel.cpp @@ -0,0 +1,270 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +namespace AssetBundler +{ + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // AdditionalSeedInfo + ////////////////////////////////////////////////////////////////////////////////////////////////// + AdditionalSeedInfo::AdditionalSeedInfo(const QString& relativePath, const QString& platformList) + : m_relativePath(relativePath) + , m_platformList(platformList) + { + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // SeedListTableModel + ////////////////////////////////////////////////////////////////////////////////////////////////// + SeedListTableModel::SeedListTableModel(QObject* parent, const AZStd::string& absolutePath, const AZStd::vector& defaultSeeds, const AzFramework::PlatformFlags& platforms) + : QAbstractTableModel(parent) + { + m_seedListManager.reset(new AzToolsFramework::AssetSeedManager()); + + if (absolutePath.empty() && defaultSeeds.empty()) + { + return; + } + + if (!defaultSeeds.empty()) + { + for (const AZStd::string& seed : defaultSeeds) + { + m_seedListManager->AddSeedAssetForValidPlatforms(seed, platforms); + } + + m_isFileOnDisk = false; + } + else + { + m_seedListManager->Load(absolutePath); + } + + AZ::Data::AssetInfo assetInfo; + QString platformList; + for (const auto& seed : m_seedListManager->GetAssetSeedList()) + { + assetInfo = AzToolsFramework::AssetSeedManager::GetAssetInfoById(seed.m_assetId, AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(seed.m_platformFlags)[0], absolutePath); + platformList = QString(m_seedListManager->GetReadablePlatformList(seed).c_str()); + + m_additionalSeedInfoMap[seed.m_assetId].reset(new AdditionalSeedInfo(assetInfo.m_relativePath.c_str(), platformList)); + } + } + + AZ::Outcome SeedListTableModel::GetSeedPlatforms(const QModelIndex& index) const + { + auto seedOutcome = GetSeedInfo(index); + if (!seedOutcome.IsSuccess()) + { + // Error has already been thrown + return AZ::Failure(); + } + + return AZ::Success(seedOutcome.GetValue().m_platformFlags); + } + + bool SeedListTableModel::Save(const AZStd::string& absolutePath) + { + if (!HasUnsavedChanges()) + { + // There are no changes, so there is nothing to save + return true; + } + + SetHasUnsavedChanges(!m_seedListManager->Save(absolutePath)); + return !HasUnsavedChanges(); + } + + bool SeedListTableModel::SetSeedPlatforms(const QModelIndex& index, const AzFramework::PlatformFlags& platforms) + { + auto seedOutcome = GetSeedInfo(index); + if (!seedOutcome.IsSuccess()) + { + // Error has already been thrown + return false; + } + + if (platforms == AzFramework::PlatformFlags::Platform_NONE) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot Edit Platforms: No platforms were selected"); + return false; + } + + auto setPlatformOutcome = m_seedListManager->SetSeedPlatformFlags(index.row(), platforms); + if (!setPlatformOutcome.IsSuccess()) + { + AZ_Error(AssetBundler::AppWindowName, false, setPlatformOutcome.GetError().c_str()); + return false; + } + + // Update the cached display info + auto additionalSeedInfo = m_additionalSeedInfoMap.find(seedOutcome.GetValue().m_assetId); + if (additionalSeedInfo == m_additionalSeedInfoMap.end()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Unable to find additional Seed info"); + return false; + } + additionalSeedInfo->second->m_platformList = QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platforms).c_str()); + + SetHasUnsavedChanges(true); + + // Update the display + QModelIndex firstChangedIndex = QAbstractTableModel::index(index.row(), Column::ColumnRelativePath); + QModelIndex lastChangedIndex = QAbstractTableModel::index(index.row(), Column::Max - 1); + emit dataChanged(firstChangedIndex, lastChangedIndex, { Qt::DisplayRole }); + + return true; + } + + bool SeedListTableModel::AddSeed(const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms) + { + AZStd::pair addSeedsResult = m_seedListManager->AddSeedAssetForValidPlatforms(seedRelativePath, platforms); + + if (!addSeedsResult.first.IsValid() || addSeedsResult.second == AzFramework::PlatformFlags::Platform_NONE) + { + // Error has already been thrown + return false; + } + + QString platformList = QString(AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(addSeedsResult.second).c_str()); + + int lastRowIndex = AZStd::max(rowCount() - 1, 0); + beginInsertRows(QModelIndex(), lastRowIndex, lastRowIndex); + + m_additionalSeedInfoMap[addSeedsResult.first].reset(new AdditionalSeedInfo(QString(seedRelativePath.c_str()), platformList)); + + endInsertRows(); + + SetHasUnsavedChanges(true); + return true; + } + + bool SeedListTableModel::RemoveSeed(const QModelIndex& seedIndex) + { + auto seedOutcome = GetSeedInfo(seedIndex); + if (!seedOutcome.IsSuccess()) + { + // Error has already been thrown + return false; + } + + int row = seedIndex.row(); + beginRemoveRows(QModelIndex(), row, row); + m_seedListManager->RemoveSeedAsset(seedOutcome.GetValue().m_assetId, seedOutcome.GetValue().m_platformFlags); + m_additionalSeedInfoMap.erase(seedOutcome.GetValue().m_assetId); + endRemoveRows(); + + SetHasUnsavedChanges(true); + return true; + } + + int SeedListTableModel::rowCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : static_cast(m_additionalSeedInfoMap.size()); + } + + int SeedListTableModel::columnCount(const QModelIndex& parent) const + { + return parent.isValid() ? 0 : Column::Max; + } + + QVariant SeedListTableModel::headerData(int section, Qt::Orientation orientation, int role) const + { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) + { + switch (section) + { + case Column::ColumnRelativePath: + return QString("Seed"); + case Column::ColumnPlatformList: + return QString("Platforms"); + default: + break; + } + } + + return QVariant(); + } + + QVariant SeedListTableModel::data(const QModelIndex& index, int role) const + { + auto additionalSeedInfoOutcome = GetAdditionalSeedInfo(index); + if (!additionalSeedInfoOutcome.IsSuccess()) + { + return QVariant(); + } + + switch (role) + { + case Qt::DisplayRole: + { + if (index.column() == Column::ColumnRelativePath) + { + return additionalSeedInfoOutcome.GetValue()->m_relativePath; + } + else if (index.column() == Column::ColumnPlatformList) + { + return additionalSeedInfoOutcome.GetValue()->m_platformList; + } + } + default: + break; + } + + return QVariant(); + } + + AZ::Outcome SeedListTableModel::GetSeedInfo(const QModelIndex& index) const + { + int row = index.row(); + int col = index.column(); + if (row >= rowCount() || row < 0 || col >= columnCount() || col < 0) + { + AZ_Error(AssetBundler::AppWindowName, false, "Selected index (%i, %i) is out of range", row, col); + return AZ::Failure(); + } + + return AZ::Success(m_seedListManager->GetAssetSeedList().at(row)); + } + + AZ::Outcome SeedListTableModel::GetAdditionalSeedInfo(const QModelIndex& index) const + { + auto seedInfoOutcome = GetSeedInfo(index); + if (!seedInfoOutcome.IsSuccess()) + { + // Error has already been thrown + return AZ::Failure(); + } + + auto additionalSeedInfoIt = m_additionalSeedInfoMap.find(seedInfoOutcome.GetValue().m_assetId); + if (additionalSeedInfoIt == m_additionalSeedInfoMap.end()) + { + return AZ::Failure(); + } + + return AZ::Success(additionalSeedInfoIt->second); + } + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/models/SeedListTableModel.h b/Code/Tools/AssetBundler/source/models/SeedListTableModel.h new file mode 100644 index 0000000000..b8cbe95201 --- /dev/null +++ b/Code/Tools/AssetBundler/source/models/SeedListTableModel.h @@ -0,0 +1,84 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#include +#include + +#include + +namespace AssetBundler +{ + struct AdditionalSeedInfo + { + AdditionalSeedInfo(const QString& relativePath, const QString& platformList); + + QString m_relativePath; + QString m_platformList; + }; + + using AdditionalSeedInfoPtr = AZStd::shared_ptr; + using AdditionalSeedInfoMap = AZStd::unordered_map; + + class SeedListTableModel + : public QAbstractTableModel + { + public: + explicit SeedListTableModel(QObject* parent = nullptr, const AZStd::string& absolutePath = AZStd::string(), const AZStd::vector& defaultSeeds = AZStd::vector(), const AzFramework::PlatformFlags& platforms = AzFramework::PlatformFlags::Platform_NONE); + virtual ~SeedListTableModel() {} + + AZStd::shared_ptr GetSeedListManager() { return m_seedListManager; } + + bool HasUnsavedChanges() { return m_hasUnsavedChanges && m_isFileOnDisk; } + + void SetHasUnsavedChanges(bool hasUnsavedChanges) { m_hasUnsavedChanges = hasUnsavedChanges; } + + bool Save(const AZStd::string& absolutePath); + + AZ::Outcome GetSeedPlatforms(const QModelIndex& index) const; + + bool SetSeedPlatforms(const QModelIndex& index, const AzFramework::PlatformFlags& platforms); + + bool AddSeed(const AZStd::string& seedRelativePath, const AzFramework::PlatformFlags& platforms); + + bool RemoveSeed(const QModelIndex& seedIndex); + + ////////////////////////////////////////////////////////////////////////// + // QAbstractListModel overrides + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + QVariant data(const QModelIndex& index, int role) const override; + ////////////////////////////////////////////////////////////////////////// + + enum Column + { + ColumnRelativePath, + ColumnPlatformList, + Max + }; + + private: + AZ::Outcome GetSeedInfo(const QModelIndex& index) const; + + AZ::Outcome GetAdditionalSeedInfo(const QModelIndex& index) const; + + AZStd::shared_ptr m_seedListManager; + AdditionalSeedInfoMap m_additionalSeedInfoMap; + + bool m_hasUnsavedChanges = false; + bool m_isFileOnDisk = true; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AddSeedDialog.cpp b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.cpp new file mode 100644 index 0000000000..be156efde2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.cpp @@ -0,0 +1,96 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include +#include + +const char QtRelativePathPrefix[] = "../"; + +namespace AssetBundler +{ + AddSeedDialog::AddSeedDialog(QWidget* parent, const AzFramework::PlatformFlags& enabledPlatforms, const AZStd::string& platformSpecificCachePath) + : QDialog(parent) + , m_platformSpecificCachePath(platformSpecificCachePath.c_str()) + { + m_ui.reset(new Ui::AddSeedDialog); + m_ui->setupUi(this); + + // Set up Browse File button + m_ui->fileNameLineEdit->setReadOnly(true); + connect(m_ui->browseFileButton, &QPushButton::clicked, this, &AddSeedDialog::OnBrowseFileButtonPressed); + + // Set up Platform selection + m_ui->platformSelectionWidget->Init(enabledPlatforms); + connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &AddSeedDialog::OnPlatformSelectionChanged); + + // Set up Cancel and Create New File buttons + m_ui->addSeedButton->setEnabled(false); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(m_ui->addSeedButton, &QPushButton::clicked, this, &QDialog::accept); + } + + AZStd::string AddSeedDialog::GetFileName() + { + return m_fileName; + } + + AzFramework::PlatformFlags AddSeedDialog::GetPlatformFlags() + { + return m_ui->platformSelectionWidget->GetSelectedPlatforms(); + } + + void AddSeedDialog::OnBrowseFileButtonPressed() + { + QString seedAbsolutePath = QFileDialog::getOpenFileName(this, tr("Add New Seed"), m_platformSpecificCachePath); + m_fileNameIsValid = !seedAbsolutePath.isEmpty(); + if (!m_fileNameIsValid) + { + // The user canceled out of the window, do not update anything + return; + } + + // Make sure the path is relative to the platform-specific cache + QDir platformSpecificCacheDir(m_platformSpecificCachePath); + QString seedRelativePath = platformSpecificCacheDir.relativeFilePath(seedAbsolutePath); + + // trim off the "../" from the relative path + FormatRelativePathString(seedRelativePath); + m_fileName = seedRelativePath.toUtf8().data(); + + // Update the ui + m_ui->fileNameLineEdit->setText(seedRelativePath); + m_ui->addSeedButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void AddSeedDialog::OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms) + { + // Hide the "Create File" button if no platforms are selected + m_platformIsValid = selectedPlatforms != AzFramework::PlatformFlags::Platform_NONE; + m_ui->addSeedButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void AddSeedDialog::FormatRelativePathString(QString& relativePath) + { + if (relativePath.startsWith(QtRelativePathPrefix)) + { + relativePath.remove(0, static_cast(strlen(QtRelativePathPrefix))); + } + } + +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/AddSeedDialog.h b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.h new file mode 100644 index 0000000000..fed6b031d1 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.h @@ -0,0 +1,58 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#endif + +namespace Ui +{ + class AddSeedDialog; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class AddSeedDialog + : public QDialog + { + Q_OBJECT + + public: + explicit AddSeedDialog(QWidget* parent, const AzFramework::PlatformFlags& enabledPlatforms, const AZStd::string& platformSpecificCachePath); + virtual ~AddSeedDialog() {} + + AZStd::string GetFileName(); + AzFramework::PlatformFlags GetPlatformFlags(); + + private: + void OnBrowseFileButtonPressed(); + void OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms); + + void FormatRelativePathString(QString& relativePath); + + QSharedPointer m_ui; + QString m_platformSpecificCachePath; + bool m_isAddSeedDialog = false; + + AZStd::string m_fileName; + + bool m_fileNameIsValid = false; + bool m_platformIsValid = false; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AddSeedDialog.ui b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.ui new file mode 100644 index 0000000000..e3c0f471aa --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AddSeedDialog.ui @@ -0,0 +1,185 @@ + + + AddSeedDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 450 + 108 + + + + + 0 + 0 + + + + + 450 + 0 + + + + Add Seed Asset + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Select Seed Asset: + + + + + + + + + true + + + + + + + Browse... + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + + + + + + + + + + + + + 10 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + false + + + + + + + Add Seed + + + true + + + + + + + + + + AssetBundler::PlatformSelectionWidget + QWidget +
source/ui/PlatformSelectionWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.cpp new file mode 100644 index 0000000000..9dcfd34c35 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.cpp @@ -0,0 +1,366 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AssetBundler +{ + const char AssetBundlerCommonSettingsFile[] = "AssetBundlerCommonSettings.json"; + const char AssetBundlerUserSettingsFile[] = "AssetBundlerUserSettings.json"; + + const char ScanPathsKey[] = "ScanPaths"; + + const QString AssetBundlingFileTypes[] = + { + "SeedLists", + "AssetLists", + "BundleSettings", + "Bundles", + "Rules" + }; + + const int MarginSize = 10; + + AssetBundlerTabWidget::AssetBundlerTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : QWidget(parent) + , m_guiApplicationManager(guiApplicationManager) + { + connect(m_guiApplicationManager, &GUIApplicationManager::UpdateTab, this, &AssetBundlerTabWidget::OnUpdateTab); + connect(m_guiApplicationManager, &GUIApplicationManager::UpdateFiles, this, &AssetBundlerTabWidget::OnUpdateFiles); + + QAction* deleteFileAction = new QAction(tr("Delete"), this); + addAction(deleteFileAction); + deleteFileAction->setShortcut(QKeySequence::Delete); + connect(deleteFileAction, &QAction::triggered, this, &AssetBundlerTabWidget::OnDeleteSelectedFileRequested); + } + + AssetBundlerTabWidget::~AssetBundlerTabWidget() + { + m_guiApplicationManager = nullptr; + } + + void AssetBundlerTabWidget::Activate() + { + SetActiveProjectLabel(tr("Active Project: %1").arg(m_guiApplicationManager->GetCurrentProjectName().c_str())); + + SetupContextMenu(); + Reload(); + + connect(GetFileTableView()->header(), &QHeaderView::sortIndicatorChanged, m_fileTableFilterModel.get(), &AssetBundlerFileTableFilterModel::sort); + GetFileTableView()->header()->setSortIndicatorShown(true); + // Setting this in descending order will ensure the most recent files are at the top + GetFileTableView()->header()->setSortIndicator(GetFileTableModel()->GetTimeStampColumnIndex(), Qt::DescendingOrder); + GetFileTableView()->setSortingEnabled(true); + } + + void AssetBundlerTabWidget::InitAssetBundlerSettings(const char* currentProjectFolderPath) + { + AZStd::string commonSettingsPath = GetAssetBundlerCommonSettingsFile(currentProjectFolderPath); + if (!AZ::IO::FileIOBase::GetInstance()->Exists(commonSettingsPath.c_str())) + { + CreateEmptyAssetBundlerSettings(commonSettingsPath); + } + + AZStd::string userSettingsPath = GetAssetBundlerUserSettingsFile(currentProjectFolderPath); + if (!AZ::IO::FileIOBase::GetInstance()->Exists(userSettingsPath.c_str())) + { + CreateEmptyAssetBundlerSettings(userSettingsPath); + } + } + + void AssetBundlerTabWidget::OnFileTableContextMenuRequested(const QPoint& pos) + { + AZStd::string selectedFileAbsolutePath(GetFileTableModel()->GetFileAbsolutePath(GetSelectedFileTableIndex())); + + QMenu* contextMenu = new QMenu(this); + contextMenu->setToolTipsVisible(true); + + bool arePathOperationsEnabled = !selectedFileAbsolutePath.empty(); + QString emptyPathToolTip(tr("This file is not present on-disk.")); + + QAction* action = contextMenu->addAction(AzQtComponents::fileBrowserActionName(), [=]() + { + AzQtComponents::ShowFileOnDesktop(selectedFileAbsolutePath.c_str()); + }); + if (arePathOperationsEnabled) + { + action->setToolTip(tr("Shows the location of this file on your computer")); + } + else + { + action->setToolTip(emptyPathToolTip); + action->setEnabled(false); + } + + action = contextMenu->addAction(tr("Copy Path to Clipboard"), [=]() + { + QApplication::clipboard()->setText(QString(selectedFileAbsolutePath.c_str())); + }); + if (arePathOperationsEnabled) + { + action->setToolTip(tr("Copies the absolute path of this file to your Clipboard")); + } + else + { + action->setToolTip(emptyPathToolTip); + action->setEnabled(false); + } + + contextMenu->addSeparator(); + + // We can't use the same Delete action as the constructor because we need to modify a lot of values + action = new QAction(tr("Delete"), this); + action->setShortcutContext(Qt::WidgetWithChildrenShortcut); + action->setShortcut(QKeySequence::Delete); + connect(action, &QAction::triggered, this, &AssetBundlerTabWidget::OnDeleteSelectedFileRequested); + if (arePathOperationsEnabled) + { + action->setToolTip(tr("Deletes the selected file from disk.")); + } + else + { + action->setToolTip(emptyPathToolTip); + action->setEnabled(false); + } + contextMenu->addAction(action); + + contextMenu->exec(GetFileTableView()->mapToGlobal(pos)); + delete contextMenu; + } + + void AssetBundlerTabWidget::OnDeleteSelectedFileRequested() + { + AZStd::string selectedFileAbsolutePath(GetFileTableModel()->GetFileAbsolutePath(GetSelectedFileTableIndex())); + if (selectedFileAbsolutePath.empty()) + { + return; + } + + QString messageBoxText = QString(tr("Are you sure you would like to delete %1? \n\nThis will permanently delete the file.")).arg(QString(selectedFileAbsolutePath.c_str())); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Delete %1")).arg(GetFileTypeDisplayName()), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the confirmation dialog + return; + } + + if (GetFileTableModel()->DeleteFile(GetSelectedFileTableIndex())) + { + RemoveScanPathFromAssetBundlerSettings(GetFileType(), selectedFileAbsolutePath.c_str()); + } + } + + void AssetBundlerTabWidget::ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType fileType) + { + AZStd::string currentProjectFolderPath = m_guiApplicationManager->GetCurrentProjectFolder(); + ReadAssetBundlerSettings(GetAssetBundlerUserSettingsFile(currentProjectFolderPath.c_str()), fileType); + ReadAssetBundlerSettings(GetAssetBundlerCommonSettingsFile(currentProjectFolderPath.c_str()), fileType); + } + + void AssetBundlerTabWidget::AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, AZStd::string filePath) + { + AZStd::string defaultFolderPath; + switch (fileType) + { + case AssetBundlingFileType::SeedListFileType: + defaultFolderPath = m_guiApplicationManager->GetSeedListsFolder(); + break; + case AssetBundlingFileType::AssetListFileType: + defaultFolderPath = m_guiApplicationManager->GetAssetListsFolder(); + break; + case AssetBundlingFileType::RulesFileType: + defaultFolderPath = m_guiApplicationManager->GetRulesFolder(); + break; + case AssetBundlingFileType::BundleSettingsFileType: + defaultFolderPath = m_guiApplicationManager->GetBundleSettingsFolder(); + break; + case AssetBundlingFileType::BundleFileType: + defaultFolderPath = m_guiApplicationManager->GetBundlesFolder(); + break; + default: + AZ_Warning(AssetBundler::AppWindowName, false, "No default folder is defined for AssetBundlingFileType ( %i ).", static_cast(fileType)); + break; + } + + AzFramework::StringFunc::Path::Normalize(filePath); + AzFramework::StringFunc::Path::Normalize(defaultFolderPath); + + if (AzFramework::StringFunc::StartsWith(filePath, defaultFolderPath)) + { + // file is already in a watched folder, no need to add it to the settings file + return; + } + + AddScanPathToAssetBundlerSettings(fileType, QString(filePath.c_str())); + } + + void AssetBundlerTabWidget::AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath) + { + AZStd::string assetBundlerSettingsFileAbsolutePath = GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str()); + QJsonObject assetBundlerSettings = AssetBundler::ReadJson(assetBundlerSettingsFileAbsolutePath); + QJsonObject scanPathsSettings = assetBundlerSettings[ScanPathsKey].toObject(); + QJsonArray scanPaths = scanPathsSettings[AssetBundlingFileTypes[fileType]].toArray(); + + QFileInfo inputFileInfo(filePath); + + for (const QJsonValue scanPath : m_watchedFiles + m_watchedFolders) + { + auto scanFilePathStr = (AZ::IO::Path(AZStd::string_view{ AZ::Utils::GetEnginePath() }) + / scanPath.toString().toUtf8().data()).LexicallyNormal(); + + // Check whether the file has already been watched + // Get absolute file paths via QFileInfo to keep consistency in the letter case + if (inputFileInfo.absoluteFilePath().startsWith( + QFileInfo(scanFilePathStr.c_str()).absoluteFilePath())) + { + return; + } + } + + scanPaths.push_back(filePath); + scanPathsSettings[AssetBundlingFileTypes[fileType]] = scanPaths; + assetBundlerSettings[ScanPathsKey] = scanPathsSettings; + AssetBundler::SaveJson(assetBundlerSettingsFileAbsolutePath, assetBundlerSettings); + + m_watchedFiles.insert(filePath); + m_guiApplicationManager->AddWatchedPath(filePath); + } + + void AssetBundlerTabWidget::RemoveScanPathFromAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath) + { + AZStd::string assetBundlerSettingsFileAbsolutePath = GetAssetBundlerUserSettingsFile(m_guiApplicationManager->GetCurrentProjectFolder().c_str()); + QJsonObject assetBundlerSettings = AssetBundler::ReadJson(assetBundlerSettingsFileAbsolutePath); + QJsonObject scanPathsSettings = assetBundlerSettings[ScanPathsKey].toObject(); + QJsonArray scanPaths = scanPathsSettings[AssetBundlingFileTypes[fileType]].toArray(); + + for (auto itr = scanPaths.begin(); itr != scanPaths.end(); ++itr) + { + QJsonValueRef scanPathValueRef = *itr; + auto scanPath = (AZ::IO::Path(AZStd::string_view{ AZ::Utils::GetEnginePath() }) + / scanPathValueRef.toString().toUtf8().data()).LexicallyNormal(); + + // Check whether the file is being watched + // Get absolute file paths via QFileInfo to keep consistency in the letter case + if (QFileInfo(filePath).absoluteFilePath() == QFileInfo(scanPath.c_str()).absoluteFilePath()) + { + itr = scanPaths.erase(itr); + break; + } + } + + scanPathsSettings[AssetBundlingFileTypes[fileType]] = scanPaths; + assetBundlerSettings[ScanPathsKey] = scanPathsSettings; + AssetBundler::SaveJson(assetBundlerSettingsFileAbsolutePath, assetBundlerSettings); + + m_guiApplicationManager->RemoveWatchedPath(filePath); + } + + void AssetBundlerTabWidget::OnUpdateTab(const AZStd::string& path) + { + if (m_watchedFolders.contains(path.c_str()) || + m_watchedFiles.contains(path.c_str())) + { + Reload(); + } + } + + void AssetBundlerTabWidget::OnUpdateFiles(AssetBundlingFileType fileType, const AZStd::vector& absoluteFilePaths) + { + if (fileType == GetFileType()) + { + GetFileTableModel()->ReloadFiles(absoluteFilePaths, m_filePathToGemNameMap); + m_fileTableFilterModel->sort(m_fileTableFilterModel->sortColumn(), m_fileTableFilterModel->sortOrder()); + FileSelectionChanged(); + } + } + + void AssetBundlerTabWidget::SetupContextMenu() + { + GetFileTableView()->setContextMenuPolicy(Qt::CustomContextMenu); + connect(GetFileTableView(), &QTreeView::customContextMenuRequested, this, &AssetBundlerTabWidget::OnFileTableContextMenuRequested); + } + + void AssetBundlerTabWidget::ReadAssetBundlerSettings(const AZStd::string& filePath, AssetBundlingFileType fileType) + { + // Read the config file which contains the customized scan paths information + AZStd::vector assetBundlerSettingsFileList; + QJsonObject assetBundlerSettings = AssetBundler::ReadJson(filePath); + QJsonObject scanPaths = assetBundlerSettings.find(ScanPathsKey).value().toObject(); + + for (const QJsonValue scanPath : scanPaths[AssetBundlingFileTypes[fileType]].toArray()) + { + auto absoluteScanPath = (AZ::IO::Path(AZStd::string_view{ AZ::Utils::GetEnginePath() }) + / scanPath.toString().toUtf8().data()).LexicallyNormal(); + + if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(absoluteScanPath.c_str())) + { + // The path specified in the config file is a directory + m_watchedFolders.insert(absoluteScanPath.c_str()); + } + else if (AZ::IO::FileIOBase::GetInstance()->Exists(absoluteScanPath.c_str())) + { + // The path specified in the config file is a file + m_watchedFiles.insert(absoluteScanPath.c_str()); + } + } + } + + AZStd::string AssetBundlerTabWidget::GetAssetBundlerUserSettingsFile(const char* currentProjectFolderPath) + { + AZStd::string absoluteFilePath; + AzFramework::StringFunc::Path::ConstructFull(currentProjectFolderPath, AssetBundlerUserSettingsFile, absoluteFilePath); + return absoluteFilePath; + } + + AZStd::string AssetBundlerTabWidget::GetAssetBundlerCommonSettingsFile(const char* currentProjectFolderPath) + { + AZStd::string absoluteFilePath; + AzFramework::StringFunc::Path::ConstructFull(currentProjectFolderPath, AssetBundlerCommonSettingsFile, absoluteFilePath); + return absoluteFilePath; + } + + void AssetBundlerTabWidget::CreateEmptyAssetBundlerSettings(const AZStd::string& filePath) + { + QJsonObject assetBundlerSettings; + QJsonObject scanPathSettings; + + for (const auto& fileType : AssetBundlingFileTypes) + { + scanPathSettings.insert(fileType, QJsonArray()); + } + + assetBundlerSettings.insert(ScanPathsKey, scanPathSettings); + + AssetBundler::SaveJson(filePath, assetBundlerSettings); + } + +} // namespace AssetBundler +#include diff --git a/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.h b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.h new file mode 100644 index 0000000000..edef5c0437 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetBundlerTabWidget.h @@ -0,0 +1,118 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#endif + +namespace AssetBundler +{ + // Keys for the corresponding scan path lists in the asset bundling settings file + extern const QString AssetBundlingFileTypes[]; + + extern const int MarginSize; + + class AssetBundlerTabWidget + : public QWidget + { + Q_OBJECT + + public: + explicit AssetBundlerTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~AssetBundlerTabWidget(); + + void Activate(); + + virtual QString GetTabTitle() = 0; + + virtual QString GetFileTypeDisplayName() = 0; + + virtual AssetBundlingFileType GetFileType() = 0; + + virtual bool HasUnsavedChanges() = 0; + + //! Reload all the files on display. + virtual void Reload() = 0; + + //! Saves the selected file to disk. + //! @return true on successful save, or throws an error message and returns false on a failed save. + virtual bool SaveCurrentSelection() = 0; + + //! Saves all modified files to disk. + //! @return true on successful save, or throws an error message and returns false on a failed save. + virtual bool SaveAll() = 0; + + //! Set watched folders and files for the model + virtual void SetModelDataSource() = 0; + + virtual AzQtComponents::TableView* GetFileTableView() = 0; + + virtual QModelIndex GetSelectedFileTableIndex() = 0; + + virtual AssetBundlerAbstractFileTableModel* GetFileTableModel() = 0; + + virtual void SetActiveProjectLabel(const QString& labelText) = 0; + + virtual void ApplyConfig() = 0; + + virtual void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) = 0; + + static void InitAssetBundlerSettings(const char* currentProjectFolderPath); + + void AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, AZStd::string filePath); + + GUIApplicationManager* GetGUIApplicationManager() { return m_guiApplicationManager; } + + protected: + void OnFileTableContextMenuRequested(const QPoint& pos); + //! Asks the user to confirm they wish to permanently delete the selected file, then removes it from disk and memory. + void OnDeleteSelectedFileRequested(); + bool ConfirmFileDeleteDialog(const QString& absoluteFilePath); + void ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType fileType); + void RemoveScanPathFromAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath); + + GUIApplicationManager* m_guiApplicationManager = nullptr; + QScopedPointer m_fileTableFilterModel; + + QSet m_watchedFolders; + QSet m_watchedFiles; + AZStd::unordered_map m_filePathToGemNameMap; + + private slots: + void OnUpdateTab(const AZStd::string& path); + void OnUpdateFiles(AssetBundlingFileType fileType, const AZStd::vector& absoluteFilePaths); + + private: + void SetupContextMenu(); + void AddScanPathToAssetBundlerSettings(AssetBundlingFileType fileType, const QString& filePath); + void ReadAssetBundlerSettings(const AZStd::string& filePath, AssetBundlingFileType fileType); + + static AZStd::string GetAssetBundlerUserSettingsFile(const char* currentProjectFolderPath); + static AZStd::string GetAssetBundlerCommonSettingsFile(const char* currentProjectFolderPath); + static void CreateEmptyAssetBundlerSettings(const AZStd::string& filePath); + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.cpp new file mode 100644 index 0000000000..339dc080fa --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.cpp @@ -0,0 +1,182 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace AssetBundler +{ + AssetListTabWidget::AssetListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : AssetBundlerTabWidget(parent, guiApplicationManager) + , m_fileTableModel(new AssetListFileTableModel()) + , m_assetListContentsModel(new AssetListTableModel()) + { + m_ui.reset(new Ui::AssetListTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(10, 10, 10, 10); + + // File view of all Asset List Files + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->assetListsTable->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->assetListsTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &AssetListTabWidget::FileSelectionChanged); + + m_ui->fileTableHeaderLayout->setContentsMargins(0, 0, 0, 0); + m_ui->fileTableVerticalLayout->setContentsMargins(0, 0, 0, 0); + m_ui->assetListsTable->setIndentation(0); + + // Generate Bundle Button + m_ui->generateBundleButton->setDefault(true); + m_ui->generateBundleButton->setEnabled(false); + connect(m_ui->generateBundleButton, &QPushButton::clicked, this, &AssetListTabWidget::OnGenerateBundleButtonPressed); + + // Absolute path of selected Asset List file + m_ui->assetListFileAbsolutePathLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); + + // Table that displays the contents of an Asset List File + m_assetListContentsFilterModel.reset(new AssetBundlerFileTableFilterModel(this, AssetListTableModel::Column::ColumnAssetName)); + + m_assetListContentsFilterModel->setSourceModel(m_assetListContentsModel.data()); + m_ui->assetListContentsTable->setModel(m_assetListContentsFilterModel.data()); + connect(m_ui->assetListContentsFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_assetListContentsFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + + m_ui->fileContentsHeaderLayout->setContentsMargins(0, 0, 0, 0); + m_ui->fileContentsVerticalLayout->setContentsMargins(0, 0, 0, 0); + m_ui->assetListContentsTable->setIndentation(0); + + SetModelDataSource(); + } + + void AssetListTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folder for the model + m_watchedFolders.clear(); + m_watchedFiles.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetAssetListsFolder().c_str()); + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::AssetListFileType); + + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* AssetListTabWidget::GetFileTableView() + { + return m_ui->assetListsTable; + } + + QModelIndex AssetListTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* AssetListTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void AssetListTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void AssetListTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + + m_ui->assetListsTable->header()->resizeSection(AssetListFileTableModel::Column::ColumnFileName, config.assetListFileNameColumnWidth); + m_ui->assetListsTable->header()->resizeSection(AssetListFileTableModel::Column::ColumnPlatform, config.assetListPlatformColumnWidth); + + m_ui->assetListContentsFilteredSearchWidget->setFixedWidth(config.fileTableWidth); + + m_ui->assetListContentsTable->header()->resizeSection(AssetListTableModel::Column::ColumnAssetName, config.productAssetNameColumnWidth); + m_ui->assetListContentsTable->header()->resizeSection(AssetListTableModel::Column::ColumnRelativePath, config.productAssetRelativePathColumnWidth); + } + + + void AssetListTabWidget::Reload() + { + // Reload all the asset list files + m_fileTableModel->Reload(AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), m_watchedFolders, m_watchedFiles); + + // Update the selected row + FileSelectionChanged(); + } + + void AssetListTabWidget::FileSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) + { + AZ_UNUSED(selected); + AZ_UNUSED(deselected); + + if (m_ui->assetListsTable->selectionModel()->selectedRows().size() == 0) + { + // Set selected index to an invalid value + m_selectedFileTableIndex = QModelIndex(); + m_ui->assetListFileAbsolutePathLabel->setText(""); + m_assetListContentsModel.reset(new AssetListTableModel()); + m_assetListContentsFilterModel->setSourceModel(m_assetListContentsModel.data()); + m_ui->generateBundleButton->setEnabled(false); + + return; + } + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->assetListsTable->selectionModel()->currentIndex()); + + m_ui->assetListFileAbsolutePathLabel->setText(QString(m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex).c_str())); + + m_assetListContentsModel = m_fileTableModel->GetAssetListFileContents(m_selectedFileTableIndex); + m_assetListContentsFilterModel->setSourceModel(m_assetListContentsModel.data()); + + m_ui->generateBundleButton->setEnabled(true); + } + + void AssetListTabWidget::OnGenerateBundleButtonPressed() + { + GenerateBundlesModal generateBundlesModal( + this, + m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex), + m_guiApplicationManager->GetBundlesFolder(), + m_guiApplicationManager->GetBundleSettingsFolder(), + this); + generateBundlesModal.exec(); + } +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.h b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.h new file mode 100644 index 0000000000..890f45a0c9 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.h @@ -0,0 +1,82 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class AssetListTabWidget; +} + +class QFileSystemModel; +class QStringListModel; + +namespace AssetBundler +{ + class GUIApplicationManager; + + class AssetListFileTableModel; + class AssetListTableModel; + + class AssetListTabWidget + : public AssetBundlerTabWidget + { + Q_OBJECT + + public: + explicit AssetListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~AssetListTabWidget() {} + + ////////////////////////////////////////////////////////////////////////// + // AssetBundlerTabWidget overrides + QString GetTabTitle() override { return tr("Asset Lists"); } + QString GetFileTypeDisplayName() override { return tr("Asset List file"); } + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::AssetListFileType; } + bool HasUnsavedChanges() override { return false; }; + void Reload() override; + bool SaveCurrentSelection() override { return true; }; + bool SaveAll() override { return true; }; + void SetModelDataSource() override; + AzQtComponents::TableView* GetFileTableView() override; + QModelIndex GetSelectedFileTableIndex() override; + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + void SetActiveProjectLabel(const QString& labelText) override; + void ApplyConfig() override; + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + ////////////////////////////////////////////////////////////////////////// + + private: + void OnGenerateBundleButtonPressed(); + + QSharedPointer m_ui; + + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + + QSharedPointer m_assetListContentsFilterModel; + QSharedPointer m_assetListContentsModel; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.ui b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.ui new file mode 100644 index 0000000000..a5bdea227b --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/AssetListTabWidget.ui @@ -0,0 +1,168 @@ + + + AssetListTabWidget + + + + 0 + 0 + 813 + 673 + + + + Asset List Tab Widget + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Generate Bundle + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Asset List Files + + + + + + + + + + Filter by file name + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Asset List + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Filter by file name + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.cpp new file mode 100644 index 0000000000..b670fd0ebd --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.cpp @@ -0,0 +1,159 @@ +/* +* All or portions of this file Copyright(c) Amazon.com, Inc. or its affiliates or +*its licensors. +* +* For complete copyrightand license terms please see the LICENSE at the root of this +* distribution(the "License").All use of this software is governed by the License, +* or , if provided, by the license below or the license accompanying this file.Do not +*remove or modify any license notices.This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#include +#include + +#include +#include + +#include + +#include +#include + +const double BytesToMegabytes = 1024.0 * 1024.0; + +namespace AssetBundler +{ + + BundleListTabWidget::BundleListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : AssetBundlerTabWidget(parent, guiApplicationManager) + { + m_ui.reset(new Ui::BundleListTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + m_fileTableModel.reset(new BundleFileListModel); + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->fileTableView->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &BundleListTabWidget::FileSelectionChanged); + + m_ui->fileTableView->setIndentation(0); + + m_relatedBundlesListModel.reset(new QStringListModel); + m_ui->relatedBundlesListView->setModel(m_relatedBundlesListModel.data()); + + m_ui->bundleFileContentsVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + SetModelDataSource(); + } + + void BundleListTabWidget::Reload() + { + // The act of cracking open paks kicks off a DirectoryChanged event. We need to temporarily remove the Bundles + // directory from our watched paths to prevent an infinite loop of events. + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders); + + // Reload all the bundle files + m_fileTableModel->Reload(AzToolsFramework::AssetBundleSettings::GetBundleFileExtension(), m_watchedFolders, m_watchedFiles); + + // Update the selected row + FileSelectionChanged(); + + // Start recieving DirectoryChanged events for these folders again + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders); + } + + void BundleListTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folder for the model + m_watchedFolders.clear(); + m_watchedFiles.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetBundlesFolder().c_str()); + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::BundleFileType); + + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* BundleListTabWidget::GetFileTableView() + { + return m_ui->fileTableView; + } + + QModelIndex BundleListTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* BundleListTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void BundleListTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void BundleListTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + m_ui->fileTableView->header()->resizeSection(BundleFileListModel::Column::ColumnFileName, config.fileNameColumnWidth); + } + + + void BundleListTabWidget::FileSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/) + { + if (m_ui->fileTableView->selectionModel()->selectedRows().size() == 0) + { + m_selectedFileTableIndex = QModelIndex(); + ClearDisplayedBundleValues(); + return; + } + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->fileTableView->selectionModel()->selectedRows()[0]); + AZ::Outcome< BundleFileInfoPtr, void> fileInfoOutcome = m_fileTableModel->GetBundleInfo(m_selectedFileTableIndex); + + if (!fileInfoOutcome.IsSuccess()) + { + ClearDisplayedBundleValues(); + return; + } + + BundleFileInfoPtr fileInfoPtr = fileInfoOutcome.GetValue(); + + m_ui->absolutePathLabel->setText(fileInfoPtr->m_absolutePath.c_str()); + + QString sizeFormat("%1 MB"); + double compressedSize = (double)fileInfoPtr->m_compressedSize / BytesToMegabytes; + m_ui->compressedSizeValueLabel->setText(sizeFormat.arg(compressedSize, 6, 'f', 3)); + + bool hasRelatedBundles = !fileInfoPtr->m_relatedBundles.isEmpty(); + if (hasRelatedBundles) + { + m_relatedBundlesListModel->setStringList(fileInfoPtr->m_relatedBundles); + } + m_ui->relatedBundlesLabel->setVisible(hasRelatedBundles); + m_ui->relatedBundlesListView->setVisible(hasRelatedBundles); + } + + void BundleListTabWidget::ClearDisplayedBundleValues() + { + m_ui->absolutePathLabel->clear(); + m_ui->compressedSizeValueLabel->clear(); + m_ui->relatedBundlesLabel->setVisible(false); + m_ui->relatedBundlesListView->setVisible(false); + m_relatedBundlesListModel->setStringList({}); + } +} + +#include diff --git a/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.h b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.h new file mode 100644 index 0000000000..c05e1078fa --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.h @@ -0,0 +1,67 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class BundleListTabWidget; +} + +namespace AssetBundler +{ + class BundleFileListModel; + + class BundleListTabWidget + : public AssetBundlerTabWidget + { + Q_OBJECT + public: + explicit BundleListTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~BundleListTabWidget() {} + + QString GetTabTitle() override { return tr("Completed Bundles"); } + QString GetFileTypeDisplayName() override { return tr("Bundle"); } + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::BundleFileType; } + bool HasUnsavedChanges() override { return false; } + void Reload() override; + bool SaveCurrentSelection() override { return true; } + bool SaveAll() override { return true; } + void SetModelDataSource() override; + AzQtComponents::TableView* GetFileTableView() override; + QModelIndex GetSelectedFileTableIndex() override; + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + void SetActiveProjectLabel(const QString& labelText) override; + void ApplyConfig() override; + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + + private: + void ClearDisplayedBundleValues(); + + QSharedPointer m_ui; + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + QSharedPointer m_relatedBundlesListModel; + }; + +} diff --git a/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.ui b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.ui new file mode 100644 index 0000000000..9880640f09 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/BundleListTabWidget.ui @@ -0,0 +1,253 @@ + + + BundleListTabWidget + + + + 0 + 0 + 888 + 562 + + + + Bundle List Tab Widget + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Bundles + + + + + + + + + + Filter by file name + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Bundle Info + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Compressed Size + + + + + + + TextLabel + + + + + + + Related Bundles + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.cpp b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.cpp new file mode 100644 index 0000000000..b5c2d78030 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.cpp @@ -0,0 +1,451 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include +#include + +namespace AssetBundler +{ + ////////////////////////////////////////////////////////////////////////////////////////////////// + // ComparisonDataWidget + ////////////////////////////////////////////////////////////////////////////////////////////////// + + const QStringList ComparisonTypeStringList = { "Default", "Delta", "Union", "Intersection", "Complement", "Wildcard", "Regex" }; + + ComparisonDataWidget::ComparisonDataWidget( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent) + : QWidget(parent) + , m_comparisonDataIndex(comparisonDataIndex) + , m_defaultAssetListFileDirectory(defaultAssetListFileDirectory) + { + m_ui.reset(new Ui::ComparisonDataWidget); + m_ui->setupUi(this); + + m_comparisonList = comparisonList; + + if (!IsComparisonDataIndexValid()) + { + AZ_Error("AssetBundler", false, "ComparisonData index ( %u ) is out of bounds. ComparisonData cannot be displayed.", m_comparisonDataIndex); + return; + } + + // Due to initialization order, we need to hard-code this or else the value will be overwritten once this + // ComparisonDataWidget is added to the ComparisonDataCard, and the Card.qss file is applied + QString lineEditStyle("background-color: #CCCCCC;"); + m_ui->nameLineEdit->setStyleSheet(lineEditStyle); + m_ui->firstInputLineEdit->setStyleSheet(lineEditStyle); + m_ui->secondInputLineEdit->setStyleSheet(lineEditStyle); + m_ui->filePatternLineEdit->setStyleSheet(lineEditStyle); + + m_ui->firstInputLineEdit->setReadOnly(true); + m_ui->secondInputLineEdit->setReadOnly(true); + + SetAllDisplayValues(m_comparisonList->GetComparisonList()[m_comparisonDataIndex]); + + MouseWheelEventFilter* mouseWheelEventFilter = new MouseWheelEventFilter(this); + + connect(m_ui->nameLineEdit, &QLineEdit::textEdited, this, &ComparisonDataWidget::OnNameLineEditChanged); + + m_ui->comparisonTypeComboBox->installEventFilter(mouseWheelEventFilter); + connect(m_ui->comparisonTypeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnComparisonTypeComboBoxChanged); + + m_ui->firstInputComboBox->installEventFilter(mouseWheelEventFilter); + connect(m_ui->firstInputComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnFirstInputComboBoxChanged); + connect(m_ui->firstInputBrowseButton, &QPushButton::pressed, this, &ComparisonDataWidget::OnFirstInputBrowseButtonPressed); + + m_ui->secondInputComboBox->installEventFilter(mouseWheelEventFilter); + connect(m_ui->secondInputComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &ComparisonDataWidget::OnSecondInputComboBoxChanged); + connect(m_ui->secondInputBrowseButton, &QPushButton::pressed, this, &ComparisonDataWidget::OnSecondInputBrowseButtonPressed); + + connect(m_ui->filePatternLineEdit, &QLineEdit::textEdited, this, &ComparisonDataWidget::OnFilePatternLineEditChanged); + } + + void ComparisonDataWidget::UpdateListOfTokenNames() + { + using namespace AzToolsFramework; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + m_inputTokenNameList.clear(); + m_ui->firstInputComboBox->clear(); + m_ui->secondInputComboBox->clear(); + + // Store info about the current FirstInput and SecondInput values so we may auto-select them later + auto allComparisonDataSteps = m_comparisonList->GetComparisonList(); + AZStd::string selectedFirstInput = allComparisonDataSteps.at(m_comparisonDataIndex).m_firstInput; + int selectedFirstInputIndex = 0; + AZStd::string selectedSecondInput = allComparisonDataSteps.at(m_comparisonDataIndex).m_secondInput; + int selectedSecondInputIndex = 0; + + // Build list of all Token Names that have come before the current Comparison Step + m_inputTokenNameList.append(tr("Choose Asset List...")); + int currentComboBoxIndex = 1; + + AZStd::string tokenName; + for (size_t i = 0; i < m_comparisonDataIndex; ++i) + { + tokenName = allComparisonDataSteps.at(i).m_output; + if (!AssetFileInfoListComparison::IsTokenFile(tokenName)) + { + continue; + } + + if (tokenName == selectedFirstInput) + { + selectedFirstInputIndex = currentComboBoxIndex; + } + if (tokenName == selectedSecondInput) + { + selectedSecondInputIndex = currentComboBoxIndex; + } + + m_inputTokenNameList.append(RemoveTokenCharFromString(tokenName)); + ++currentComboBoxIndex; + } + + // Update display with list of Token Names, and select current Token Name in both input combo boxes + m_ui->firstInputComboBox->insertItems(0, m_inputTokenNameList); + m_ui->firstInputComboBox->setCurrentIndex(selectedFirstInputIndex); + m_isFirstInputFileNameVisible = selectedFirstInputIndex == 0; + SetFirstInputFileVisibility(m_isFirstInputFileNameVisible); + + m_ui->secondInputComboBox->insertItems(0, m_inputTokenNameList); + m_ui->secondInputComboBox->setCurrentIndex(selectedSecondInputIndex); + m_isSecondInputFileNameVisible = selectedSecondInputIndex == 0; + SetSecondInputFileVisibility(m_isSecondInputFileNameVisible); + } + + void ComparisonDataWidget::SetAllDisplayValues(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData) + { + using namespace AzToolsFramework; + + // Name (Token value) + m_ui->nameLineEdit->setText(RemoveTokenCharFromString(comparisonData.m_output)); + + // Comparison Type + InitComparisonTypeComboBox(comparisonData); + + // Inputs + UpdateListOfTokenNames(); + m_ui->firstInputLineEdit->setText(QString(comparisonData.m_cachedFirstInputPath.c_str())); + m_ui->secondInputLineEdit->setText(QString(comparisonData.m_cachedSecondInputPath.c_str())); + + // Update fields that are not always visible + UpdateOnComparisonTypeChanged(comparisonData.m_filePatternType != AssetFileInfoListComparison::FilePatternType::Default); + } + + void ComparisonDataWidget::OnNameLineEditChanged() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + AZStd::string tokenName = m_ui->nameLineEdit->text().toUtf8().data(); + AzToolsFramework::AssetFileInfoListComparison::FormatOutputToken(tokenName); + m_comparisonList->SetOutput(m_comparisonDataIndex, tokenName); + emit comparisonDataChanged(); + emit comparisonDataTokenNameChanged(m_comparisonDataIndex); + } + + void ComparisonDataWidget::UpdateOnComparisonTypeChanged(bool isFilePatternOperation) + { + using namespace AzToolsFramework; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + AssetFileInfoListComparison::ComparisonData comparisonData = m_comparisonList->GetComparisonList()[m_comparisonDataIndex]; + m_ui->inputBLabel->setVisible(!isFilePatternOperation); + m_ui->secondInputComboBox->setVisible(!isFilePatternOperation); + SetSecondInputFileVisibility(!isFilePatternOperation && m_isSecondInputFileNameVisible); + + m_ui->filePatternLabel->setVisible(isFilePatternOperation); + m_ui->filePatternLineEdit->setVisible(isFilePatternOperation); + m_ui->filePatternLineEdit->setText(comparisonData.m_filePattern.c_str()); + } + + void ComparisonDataWidget::InitComparisonTypeComboBox(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData) + { + using namespace AzToolsFramework; + + m_ui->comparisonTypeComboBox->insertItems(0, ComparisonTypeStringList); + int initialSelectionIndex = ComparisonTypeIndex::Default; + + if (comparisonData.m_filePatternType != AssetFileInfoListComparison::FilePatternType::Default + && comparisonData.m_comparisonType == AssetFileInfoListComparison::ComparisonType::FilePattern) + { + if (comparisonData.m_filePatternType == AssetFileInfoListComparison::FilePatternType::Wildcard) + { + initialSelectionIndex = ComparisonTypeIndex::Wildcard; + } + else + { + initialSelectionIndex = ComparisonTypeIndex::Regex; + } + } + else + { + switch (comparisonData.m_comparisonType) + { + case AssetFileInfoListComparison::ComparisonType::Default: + break; + case AssetFileInfoListComparison::ComparisonType::Delta: + initialSelectionIndex = ComparisonTypeIndex::Delta; + break; + case AssetFileInfoListComparison::ComparisonType::Union: + initialSelectionIndex = ComparisonTypeIndex::Union; + break; + case AssetFileInfoListComparison::ComparisonType::Intersection: + initialSelectionIndex = ComparisonTypeIndex::Intersection; + break; + case AssetFileInfoListComparison::ComparisonType::Complement: + initialSelectionIndex = ComparisonTypeIndex::Complement; + break; + default: + AZ_Warning("AssetBundler", false, "ComparisonType ( %u ) is not supported in the Asset Bundler", comparisonData.m_comparisonType); + } + } + + m_ui->comparisonTypeComboBox->setCurrentIndex(initialSelectionIndex); + } + + void ComparisonDataWidget::OnComparisonTypeComboBoxChanged(int index) + { + using namespace AzToolsFramework; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + bool isFilePattern = false; + + switch (index) + { + case ComparisonTypeIndex::Default: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Default); + break; + case ComparisonTypeIndex::Delta: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Delta); + break; + case ComparisonTypeIndex::Union: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Union); + break; + case ComparisonTypeIndex::Intersection: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Intersection); + break; + case ComparisonTypeIndex::Complement: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::Complement); + break; + case ComparisonTypeIndex::Wildcard: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::FilePattern); + m_comparisonList->SetFilePatternType(m_comparisonDataIndex, AssetFileInfoListComparison::FilePatternType::Wildcard); + isFilePattern = true; + break; + case ComparisonTypeIndex::Regex: + m_comparisonList->SetComparisonType(m_comparisonDataIndex, AssetFileInfoListComparison::ComparisonType::FilePattern); + m_comparisonList->SetFilePatternType(m_comparisonDataIndex, AssetFileInfoListComparison::FilePatternType::Regex); + isFilePattern = true; + break; + } + + UpdateOnComparisonTypeChanged(isFilePattern); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::OnFilePatternLineEditChanged() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + m_comparisonList->SetFilePattern(m_comparisonDataIndex, m_ui->filePatternLineEdit->text().toUtf8().data()); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::OnFirstInputComboBoxChanged(int index) + { + AZStd::string firstInputValue; + + if (!IsComparisonDataIndexValid()) + { + return; + } + + m_isFirstInputFileNameVisible = index == 0; + + if (!m_isFirstInputFileNameVisible) + { + // The 0th index is the default value, which translates to an empty token string. + firstInputValue = m_ui->firstInputComboBox->currentText().toUtf8().data(); + AzToolsFramework::AssetFileInfoListComparison::FormatOutputToken(firstInputValue); + } + + SetFirstInputFileVisibility(m_isFirstInputFileNameVisible); + + m_comparisonList->SetFirstInput(m_comparisonDataIndex, firstInputValue); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::SetFirstInputFileVisibility(bool isVisible) + { + m_ui->firstInputLineEdit->setVisible(isVisible); + m_ui->firstInputBrowseButton->setVisible(isVisible); + } + + void ComparisonDataWidget::OnFirstInputBrowseButtonPressed() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + QString absoluteFilePath = BrowseButtonPressed(); + if (absoluteFilePath.isEmpty()) + { + // User canceled out of the dialog + return; + } + + m_ui->firstInputLineEdit->setText(absoluteFilePath); + m_comparisonList->SetCachedFirstInputPath(m_comparisonDataIndex, absoluteFilePath.toUtf8().data()); + } + + void ComparisonDataWidget::OnSecondInputComboBoxChanged(int index) + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + AZStd::string secondInputValue; + + m_isSecondInputFileNameVisible = index == 0; + + if (!m_isSecondInputFileNameVisible) + { + // The 0th index is the default value, which translates to an empty token string. + secondInputValue = m_ui->secondInputComboBox->currentText().toUtf8().data(); + AzToolsFramework::AssetFileInfoListComparison::FormatOutputToken(secondInputValue); + } + + SetSecondInputFileVisibility(m_isSecondInputFileNameVisible); + + m_comparisonList->SetSecondInput(m_comparisonDataIndex, secondInputValue); + emit comparisonDataChanged(); + } + + void ComparisonDataWidget::SetSecondInputFileVisibility(bool isVisible) + { + m_ui->secondInputLineEdit->setVisible(isVisible); + m_ui->secondInputBrowseButton->setVisible(isVisible); + } + + void ComparisonDataWidget::OnSecondInputBrowseButtonPressed() + { + if (!IsComparisonDataIndexValid()) + { + return; + } + + QString absoluteFilePath = BrowseButtonPressed(); + if (absoluteFilePath.isEmpty()) + { + // User canceled out of the dialog + return; + } + + m_ui->secondInputLineEdit->setText(absoluteFilePath); + m_comparisonList->SetCachedSecondInputPath(m_comparisonDataIndex, absoluteFilePath.toUtf8().data()); + } + + QString ComparisonDataWidget::BrowseButtonPressed() + { + AZStd::string selectedPath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), + "Asset List", + m_defaultAssetListFileDirectory); + AzToolsFramework::RemovePlatformIdentifier(selectedPath); + return selectedPath.c_str(); + } + + bool ComparisonDataWidget::IsComparisonDataIndexValid() + { + return m_comparisonList->GetComparisonList().size() > m_comparisonDataIndex; + } + + QString ComparisonDataWidget::RemoveTokenCharFromString(const AZStd::string& tokenName) + { + QString displayName = tokenName.c_str(); + if (displayName.startsWith(AzToolsFramework::AssetFileInfoListComparison::GetTokenIdentifier())) + { + displayName.remove(0, 1); + } + + return displayName; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // MouseWheelEventFilter + ////////////////////////////////////////////////////////////////////////////////////////////////// + + bool MouseWheelEventFilter::eventFilter(QObject* obj, QEvent* ev) + { + if (ev->type() == QEvent::Wheel) + { + return true; + } + + return QObject::eventFilter(obj, ev); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // ComparisonDataCard + ////////////////////////////////////////////////////////////////////////////////////////////////// + + ComparisonDataCard::ComparisonDataCard( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent) + : AzQtComponents::Card(parent) + { + m_comparisonDataWidget = new ComparisonDataWidget(comparisonList, comparisonDataIndex, defaultAssetListFileDirectory, this); + setContentWidget(m_comparisonDataWidget); + + connect(this, &AzQtComponents::Card::contextMenuRequested, this, &ComparisonDataCard::OnContextMenuRequested); + } + + void ComparisonDataCard::OnContextMenuRequested(const QPoint& position) + { + emit comparisonDataCardContextMenuRequested(m_comparisonDataWidget->GetComparisonDataIndex(), position); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.h b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.h new file mode 100644 index 0000000000..9728d281a7 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.h @@ -0,0 +1,151 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include +#include +#include + +#include +#endif + +namespace Ui +{ + class ComparisonDataWidget; +} + +namespace AssetBundler +{ + //! Widget for displaying and editing a single Comparison Step inside a Comparison Rules file. + class ComparisonDataWidget + : public QWidget + { + Q_OBJECT + + public: + explicit ComparisonDataWidget( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent = nullptr); + virtual ~ComparisonDataWidget() {} + + enum ComparisonTypeIndex : int + { + Default = 0, + Delta, + Union, + Intersection, + Complement, + Wildcard, + Regex, + MAX + }; + + size_t GetComparisonDataIndex() { return m_comparisonDataIndex; } + + void UpdateListOfTokenNames(); + + Q_SIGNALS: + void comparisonDataChanged(); + + void comparisonDataTokenNameChanged(size_t comparisonDataIndex); + + private: + void SetAllDisplayValues(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData); + + void OnNameLineEditChanged(); + + void UpdateOnComparisonTypeChanged(bool isFilePatternOperation); + + void InitComparisonTypeComboBox(const AzToolsFramework::AssetFileInfoListComparison::ComparisonData& comparisonData); + + void OnComparisonTypeComboBoxChanged(int index); + + void OnFilePatternLineEditChanged(); + + void OnFirstInputComboBoxChanged(int index); + + void SetFirstInputFileVisibility(bool isVisible); + + void OnFirstInputBrowseButtonPressed(); + + void OnSecondInputComboBoxChanged(int index); + + void SetSecondInputFileVisibility(bool isVisible); + + void OnSecondInputBrowseButtonPressed(); + + QString BrowseButtonPressed(); + + bool IsComparisonDataIndexValid(); + + QString RemoveTokenCharFromString(const AZStd::string& tokenName); + + QSharedPointer m_ui; + + AZStd::shared_ptr m_comparisonList; + size_t m_comparisonDataIndex; + + AZStd::string m_defaultAssetListFileDirectory; + + QStringList m_inputTokenNameList; + QString m_outputAssetListFileAbsolutePath; + + bool m_isFirstInputFileNameVisible = false; + bool m_isSecondInputFileNameVisible = false; + }; + + class MouseWheelEventFilter + : public QObject + { + Q_OBJECT + + public: + explicit MouseWheelEventFilter(QObject* parent) : QObject(parent) {} + + protected: + bool eventFilter(QObject* obj, QEvent* ev) override; + }; + + + //! Wrapper widget that controls the expansion state and signals that trigger a context menu of a ComparisonDataWidget. + class ComparisonDataCard + : public AzQtComponents::Card + { + Q_OBJECT + + public: + explicit ComparisonDataCard( + AZStd::shared_ptr comparisonList, + size_t comparisonDataIndex, + const AZStd::string& defaultAssetListFileDirectory, + QWidget* parent = nullptr); + virtual ~ComparisonDataCard() {} + + ComparisonDataWidget* GetComparisonDataWidget() { return m_comparisonDataWidget; } + + Q_SIGNALS: + void comparisonDataCardContextMenuRequested(size_t comparisonDataIndex, const QPoint& position); + + private: + ComparisonDataWidget* m_comparisonDataWidget = nullptr; + + private slots: + void OnContextMenuRequested(const QPoint& position); + }; + + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.ui b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.ui new file mode 100644 index 0000000000..4e148e21bb --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/ComparisonDataWidget.ui @@ -0,0 +1,150 @@ + + + ComparisonDataWidget + + + + 0 + 0 + 400 + 300 + + + + + 0 + 0 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + QLayout::SetDefaultConstraint + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Name + + + + + + + + + + Comparison Type + + + + + + + + + + Input A + + + + + + + + + + 10 + + + + + + + + Browse... + + + + + + + + + Input B + + + + + + + + + + 10 + + + + + + + + Browse... + + + + + + + + + File Pattern + + + + + + + + + + + + + + diff --git a/Code/Tools/AssetBundler/source/ui/EditSeedDialog.cpp b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.cpp new file mode 100644 index 0000000000..a42e0cd0f0 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.cpp @@ -0,0 +1,62 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +#include + +namespace AssetBundler +{ + + EditSeedDialog::EditSeedDialog( + QWidget* parent, + const AzFramework::PlatformFlags& enabledPlatforms, + const AzFramework::PlatformFlags& selectedPlatforms, + const AzFramework::PlatformFlags& partiallySelectedPlatforms) + : QDialog(parent) + { + m_ui.reset(new Ui::EditSeedDialog); + m_ui->setupUi(this); + + m_ui->platformSelectionWidget->Init(enabledPlatforms); + m_ui->platformSelectionWidget->SetSelectedPlatforms(selectedPlatforms, partiallySelectedPlatforms); + connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &EditSeedDialog::OnPlatformSelectionChanged); + + // Set up confirm and cancel buttons + connect(m_ui->applyChangesButton, &QPushButton::clicked, this, &QDialog::accept); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + } + + AzFramework::PlatformFlags EditSeedDialog::GetPlatformFlags() + { + return m_ui->platformSelectionWidget->GetSelectedPlatforms(); + } + + AzFramework::PlatformFlags EditSeedDialog::GetPartiallySelectedPlatformFlags() + { + return m_ui->platformSelectionWidget->GetPartiallySelectedPlatforms(); + } + + void EditSeedDialog::OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms) + { + // Disable the "Apply Changes" button if no platforms are selected + bool areAnyPlatformsSelected = selectedPlatforms != AzFramework::PlatformFlags::Platform_NONE || + partiallySelectedPlatforms != AzFramework::PlatformFlags::Platform_NONE; + m_ui->applyChangesButton->setEnabled(areAnyPlatformsSelected); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/EditSeedDialog.h b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.h new file mode 100644 index 0000000000..751c1eae3d --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.h @@ -0,0 +1,52 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#endif + +namespace Ui +{ + class EditSeedDialog; +} + +namespace AssetBundler +{ + class EditSeedDialog + : public QDialog + { + Q_OBJECT + + public: + explicit EditSeedDialog( + QWidget* parent, + const AzFramework::PlatformFlags& enabledPlatforms, + const AzFramework::PlatformFlags& selectedPlatforms, + const AzFramework::PlatformFlags& partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE); + virtual ~EditSeedDialog() {} + + AzFramework::PlatformFlags GetPlatformFlags(); + AzFramework::PlatformFlags GetPartiallySelectedPlatformFlags(); + + private: + void OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms); + + QSharedPointer m_ui; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/EditSeedDialog.ui b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.ui new file mode 100644 index 0000000000..7d42d2d252 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/EditSeedDialog.ui @@ -0,0 +1,117 @@ + + + EditSeedDialog + + + + 0 + 0 + 400 + 92 + + + + + 300 + 0 + + + + Edit Selected Platforms + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + 10 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + Apply Changes + + + true + + + + + + + + + + AssetBundler::PlatformSelectionWidget + QWidget +
source/ui/PlatformSelectionWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.cpp b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.cpp new file mode 100644 index 0000000000..3724bc8753 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.cpp @@ -0,0 +1,276 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +const char CustomBundleSettingsText[] = "Custom"; + +namespace AssetBundler +{ + GenerateBundlesModal::GenerateBundlesModal( + QWidget* parent, + const AZStd::string& assetListFileAbsolutePath, + const AZStd::string& defaultBundleDirectory, + const AZStd::string& defaultBundleSettingsDirectory, + AssetListTabWidget* assetListTabWidget) + : QDialog(parent) + , m_assetListFileAbsolutePath(assetListFileAbsolutePath) + , m_defaultBundleDirectory(defaultBundleDirectory) + , m_defaultBundleSettingsDirectory(defaultBundleSettingsDirectory) + , m_assetListTabWidget(assetListTabWidget) + { + m_ui.reset(new Ui::GenerateBundlesModal); + m_ui->setupUi(this); + + m_platformName = AzToolsFramework::GetPlatformIdentifier(m_assetListFileAbsolutePath); + + // Selected Asset List + m_ui->selectedAssetListPathLabel->setText(QString(m_assetListFileAbsolutePath.c_str())); + + // Platform + m_ui->platformNameLabel->setText(QString(m_platformName.c_str())); + + // Bundle Output + m_ui->outputBundlePathLineEdit->setReadOnly(true); + connect(m_ui->outputBundlePathBrowseButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnOutputBundleLocationBrowseButtonPressed); + + // Bundle Settings files + m_ui->bundleSettingsFileLineEdit->setReadOnly(true); + m_ui->bundleSettingsFileLineEdit->setText(tr(CustomBundleSettingsText)); + connect(m_ui->bundleSettingsFileBrowseButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnBundleSettingsBrowseButtonPressed); + connect(m_ui->bundleSettingsFileSaveButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnBundleSettingsSaveButtonPressed); + + // Max Bundle Size + m_ui->maxBundleSizeSpinBox->setRange(1, AzToolsFramework::MaxBundleSizeInMB); + m_ui->maxBundleSizeSpinBox->setValue(AzToolsFramework::MaxBundleSizeInMB); + m_ui->maxBundleSizeSpinBox->setButtonSymbols(QAbstractSpinBox::ButtonSymbols::NoButtons); + m_ui->maxBundleSizeSpinBox->setSuffix(" MB"); + connect(m_ui->maxBundleSizeSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &GenerateBundlesModal::OnMaxBundleSizeChanged); + + // Bundle Version + m_ui->bundleVersionSpinBox->setRange(1, AzFramework::AssetBundleManifest::CurrentBundleVersion); + m_ui->bundleVersionSpinBox->setValue(AzFramework::AssetBundleManifest::CurrentBundleVersion); + m_ui->bundleVersionSpinBox->setButtonSymbols(QAbstractSpinBox::ButtonSymbols::NoButtons); + connect(m_ui->bundleVersionSpinBox, QOverload::of(&QSpinBox::valueChanged), this, &GenerateBundlesModal::OnBundleVersionChanged); + + // Cancel and Generate Bundles buttons + m_ui->generateBundlesButton->setEnabled(false); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(m_ui->generateBundlesButton, &QPushButton::clicked, this, &GenerateBundlesModal::OnGenerateBundlesButtonPressed); + + // In-memory Bundle Settings + m_bundleSettings.m_assetFileInfoListPath = m_assetListFileAbsolutePath; + m_bundleSettings.m_platform = m_platformName; + m_bundleSettings.m_maxBundleSizeInMB = static_cast(m_ui->maxBundleSizeSpinBox->value()); + m_bundleSettings.m_bundleVersion = m_ui->bundleVersionSpinBox->value(); + } + + GenerateBundlesModal::~GenerateBundlesModal() + { + m_assetListTabWidget = nullptr; + } + + void GenerateBundlesModal::OnOutputBundleLocationBrowseButtonPressed() + { + AZStd::string outputBundleAbsolutePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetBundleSettings::GetBundleFileExtension(), + "Bundle", + m_defaultBundleDirectory); + + if (outputBundleAbsolutePath.empty()) + { + // User canceled out of the dialog + return; + } + + AzToolsFramework::RemovePlatformIdentifier(outputBundleAbsolutePath); + AddPlatformIdentifier(outputBundleAbsolutePath, m_platformName); + + m_bundleSettings.m_bundleFilePath = outputBundleAbsolutePath; + + m_ui->outputBundlePathLineEdit->setText(outputBundleAbsolutePath.c_str()); + m_ui->generateBundlesButton->setEnabled(true); + } + + void GenerateBundlesModal::OnBundleSettingsBrowseButtonPressed() + { + AZStd::string bundleSettingsAbsolutePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetBundleSettings::GetBundleSettingsFileExtension(), + "Bundle Settings", + m_defaultBundleSettingsDirectory); + + if (bundleSettingsAbsolutePath.empty()) + { + // User canceled out of the dialog + return; + } + + // Read in the values from the Bundle Settings file + bool loadResult = LoadBundleSettingsValues(bundleSettingsAbsolutePath); + if (!loadResult) + { + return; + } + + // Update the display name for our settings + UpdateBundleSettingsDisplayName(bundleSettingsAbsolutePath); + } + + bool GenerateBundlesModal::LoadBundleSettingsValues(const AZStd::string& absoluteBundleSettingsFilePath) + { + using namespace AzToolsFramework; + + auto outcome = AssetBundleSettings::Load(absoluteBundleSettingsFilePath); + if (!outcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, outcome.GetError().c_str()); + return false; + } + + // We don't want to overwrite all of the in-memory bundle settings, so we will just update a few + AssetBundleSettings loadedSettings = outcome.TakeValue(); + + m_bundleSettings.m_maxBundleSizeInMB = loadedSettings.m_maxBundleSizeInMB; + m_ui->maxBundleSizeSpinBox->setValue(static_cast(m_bundleSettings.m_maxBundleSizeInMB)); + + m_bundleSettings.m_bundleVersion = loadedSettings.m_bundleVersion; + m_ui->bundleVersionSpinBox->setValue(m_bundleSettings.m_bundleVersion); + + return true; + } + + void GenerateBundlesModal::UpdateBundleSettingsDisplayName(const AZStd::string& absoluteBundleSettingsFilePath) + { + if (absoluteBundleSettingsFilePath.empty()) + { + m_ui->bundleSettingsFileLineEdit->setText(tr(CustomBundleSettingsText)); + return; + } + + AZStd::string bundleSettingsFileName = absoluteBundleSettingsFilePath; + AzToolsFramework::RemovePlatformIdentifier(bundleSettingsFileName); + AzFramework::StringFunc::Path::GetFileName(bundleSettingsFileName.c_str(), bundleSettingsFileName); + m_ui->bundleSettingsFileLineEdit->setText(bundleSettingsFileName.c_str()); + } + + void GenerateBundlesModal::OnBundleSettingsSaveButtonPressed() + { + using namespace AzToolsFramework; + + // Ask the user where they want to save the Bundle Settings file + AZStd::string bundleSettingsAbsolutePath = NewFileDialog::OSNewFileDialog( + this, + AssetBundleSettings::GetBundleSettingsFileExtension(), + "Bundle Settings", + m_defaultBundleSettingsDirectory); + + if (bundleSettingsAbsolutePath.empty()) + { + // User canceled out of the operation + return; + } + + AzToolsFramework::RemovePlatformIdentifier(bundleSettingsAbsolutePath); + AddPlatformIdentifier(bundleSettingsAbsolutePath, m_platformName); + + if (AZ::IO::FileIOBase::GetInstance()->Exists(bundleSettingsAbsolutePath.c_str())) + { + QString messageBoxText = QString(tr("Bundle Settings ( %1 ) already exists on-disk. Saving the current settings will override the existing settings. \n\nDo you wish to continue?")).arg(bundleSettingsAbsolutePath.c_str()); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Settings")), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the operation + return; + } + } + + bool saveResult = AssetBundleSettings::Save(m_bundleSettings, bundleSettingsAbsolutePath); + if (!saveResult) + { + // Error has already been thrown + return; + } + + m_assetListTabWidget->AddScanPathToAssetBundlerSettings(AssetBundlingFileType::BundleSettingsFileType, bundleSettingsAbsolutePath); + + UpdateBundleSettingsDisplayName(bundleSettingsAbsolutePath); + } + + void GenerateBundlesModal::OnMaxBundleSizeChanged() + { + m_bundleSettings.m_maxBundleSizeInMB = static_cast(m_ui->maxBundleSizeSpinBox->value()); + UpdateBundleSettingsDisplayName(""); + } + + void GenerateBundlesModal::OnBundleVersionChanged() + { + m_bundleSettings.m_bundleVersion = m_ui->bundleVersionSpinBox->value(); + UpdateBundleSettingsDisplayName(""); + } + + void GenerateBundlesModal::OnGenerateBundlesButtonPressed() + { + using namespace AzToolsFramework; + + if (AZ::IO::FileIOBase::GetInstance()->Exists(m_bundleSettings.m_bundleFilePath.c_str())) + { + QString messageBoxText = QString(tr("Asset Bundle ( %1 ) already exists on-disk. Generating a new Bundle will override the existing Bundle. \n\nDo you wish to permanently delete the existing Bundle?")).arg(m_bundleSettings.m_bundleFilePath.c_str()); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Bundle")), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the operation + return; + } + } + + bool result = false; + AssetBundleCommandsBus::BroadcastResult(result, &AssetBundleCommandsBus::Events::CreateAssetBundle, m_bundleSettings); + + // This operation will take long enough that the OS will throw up its own wait cursor, + // but there is a slight delay where the UI is unresponsive but the cursor hasn't changed. + // We are changing the cursor manually to avoid that. + setCursor(Qt::WaitCursor); + + emit QDialog::accept(); + + if (result) + { + m_assetListTabWidget->AddScanPathToAssetBundlerSettings(AssetBundlingFileType::BundleFileType, m_bundleSettings.m_bundleFilePath); + + // The watched files list was updated after the files were created, so we need to force-reload them + m_assetListTabWidget->GetGUIApplicationManager()->UpdateFiles(AssetBundlingFileType::BundleFileType, { m_bundleSettings.m_bundleFilePath }); + } + + AZStd::vector generatedFilePaths = { m_bundleSettings.m_bundleFilePath }; + NewFileDialog::FileGenerationResultMessageBox(this, generatedFilePaths, !result); + + unsetCursor(); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.h b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.h new file mode 100644 index 0000000000..b4edaedb9b --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.h @@ -0,0 +1,75 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#endif + +namespace Ui +{ + class GenerateBundlesModal; +} + +namespace AssetBundler +{ + class AssetListTabWidget; + + class GenerateBundlesModal + : public QDialog + { + Q_OBJECT + + public: + explicit GenerateBundlesModal( + QWidget* parent, + const AZStd::string& assetListFileAbsolutePath, + const AZStd::string& defaultBundleDirectory, + const AZStd::string& defaultBundleSettingsDirectory, + AssetListTabWidget* assetListTabWidget); + virtual ~GenerateBundlesModal(); + + private: + void OnOutputBundleLocationBrowseButtonPressed(); + + void OnBundleSettingsBrowseButtonPressed(); + + bool LoadBundleSettingsValues(const AZStd::string& absoluteBundleSettingsFilePath); + + void UpdateBundleSettingsDisplayName(const AZStd::string& absoluteBundleSettingsFilePath); + + void OnBundleSettingsSaveButtonPressed(); + + void OnMaxBundleSizeChanged(); + + void OnBundleVersionChanged(); + + void OnGenerateBundlesButtonPressed(); + + QSharedPointer m_ui; + + AssetListTabWidget* m_assetListTabWidget = nullptr; + + AZStd::string m_assetListFileAbsolutePath; + AZStd::string m_defaultBundleDirectory; + AZStd::string m_defaultBundleSettingsDirectory; + AZStd::string m_platformName; + + AzToolsFramework::AssetBundleSettings m_bundleSettings; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.ui b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.ui new file mode 100644 index 0000000000..df7ac0f0be --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/GenerateBundlesModal.ui @@ -0,0 +1,292 @@ + + + GenerateBundlesModal + + + Qt::ApplicationModal + + + + 0 + 0 + 800 + 300 + + + + + 0 + 0 + + + + + 750 + 0 + + + + Generate Bundles + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 5 + + + 0 + + + 5 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Asset List + + + + + + + TextLabel + + + + + + + Platform + + + + + + + TextLabel + + + + + + + Output Bundle Name + + + + + + + + + + + + Browse... + + + + + + + + + + + + Qt::Horizontal + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Settings + + + + + + + + + + + + Browse... + + + + + + + Save + + + + + + + + + Max Bundle Size + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Bundle Version + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + + + + + Generate Bundles + + + true + + + + + + + + + + diff --git a/Code/Tools/AssetBundler/source/ui/MainWindow.cpp b/Code/Tools/AssetBundler/source/ui/MainWindow.cpp new file mode 100644 index 0000000000..c0e30c01f2 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/MainWindow.cpp @@ -0,0 +1,249 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace AssetBundler +{ + + MainWindow::MainWindow(AssetBundler::GUIApplicationManager* guiApplicationManager, QWidget* parent) + : QMainWindow(parent) + , m_guiApplicationManager(guiApplicationManager) + { + m_ui.reset(new Ui::MainWindow); + m_ui->setupUi(this); + + m_ui->verticalLayout->setContentsMargins(0, 0, 0, 0); + + // Set up Log + m_logModel.reset(new AzToolsFramework::Logging::LogTableModel(this)); + m_ui->logTableView->setModel(m_logModel.data()); + m_ui->logTableView->setIndentation(0); + + m_ui->logTableView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_ui->logTableView, &QWidget::customContextMenuRequested, this, &MainWindow::ShowLogContextMenu); + + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + // Create the Unsaved Changes Popup + m_unsavedChangesMsgBox.reset(new QMessageBox(this)); + m_unsavedChangesMsgBox->setText(tr("There are unsaved changes.")); + m_unsavedChangesMsgBox->setInformativeText(tr("Would you like to save all changes before quitting?")); + m_unsavedChangesMsgBox->setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + m_unsavedChangesMsgBox->setDefaultButton(QMessageBox::Save); + + // Set up Quit functionality + m_ui->actionClose->setShortcut(Qt::Key_Q | Qt::CTRL); + m_ui->actionClose->setMenuRole(QAction::QuitRole); + connect(m_ui->actionClose, SIGNAL(triggered()), this, SLOT(close())); + this->addAction(m_ui->actionClose); + + // Set up Tabs + AssetBundlerTabWidget::InitAssetBundlerSettings(m_guiApplicationManager->GetCurrentProjectFolder().c_str()); + + m_seedListTab.reset(new SeedTabWidget(this, m_guiApplicationManager, QString(m_guiApplicationManager->GetAssetBundlingFolder().c_str()))); + m_ui->tabWidget->addTab(m_seedListTab.data(), m_seedListTab->GetTabTitle()); + + m_assetListTab.reset(new AssetListTabWidget(this, m_guiApplicationManager)); + m_ui->tabWidget->addTab(m_assetListTab.data(), m_assetListTab->GetTabTitle()); + + m_rulesTab.reset(new RulesTabWidget(this, m_guiApplicationManager)); + m_ui->tabWidget->addTab(m_rulesTab.data(), m_rulesTab->GetTabTitle()); + + m_bundleListTab.reset(new BundleListTabWidget(this, m_guiApplicationManager)); + m_ui->tabWidget->addTab(m_bundleListTab.data(), m_bundleListTab->GetTabTitle()); + + // Set up link to documentation + QAction* supportAction = new QAction(QIcon(":/stylesheet/img/help.svg"), "", this); + connect(supportAction, &QAction::triggered, this, &MainWindow::OnSupportClicked); + connect(m_ui->actionDocumentation, &QAction::triggered, this, &MainWindow::OnSupportClicked); + m_ui->tabWidget->setActionToolBarVisible(); + m_ui->tabWidget->addAction(supportAction); + + // Set up Save functionality + m_ui->actionSave->setShortcut(Qt::Key_S | Qt::CTRL); + connect(m_ui->actionSave, &QAction::triggered, this, &MainWindow::SaveCurrentSelection); + + m_ui->actionSaveAll->setShortcut(Qt::Key_S | Qt::CTRL | Qt::SHIFT); + connect(m_ui->actionSaveAll, &QAction::triggered, this, &MainWindow::SaveAll); + } + + MainWindow::~MainWindow() + { + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + m_guiApplicationManager = nullptr; + } + + void MainWindow::Activate() + { + m_seedListTab->Activate(); + m_rulesTab->Activate(); + m_assetListTab->Activate(); + m_bundleListTab->Activate(); + } + + void MainWindow::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + // Event Log Details + m_ui->logTableView->header()->resizeSection(AzToolsFramework::Logging::LogTableModel::ColumnType, config.logTypeColumnWidth); + m_ui->logTableView->header()->resizeSection(AzToolsFramework::Logging::LogTableModel::ColumnWindow, config.logSourceColumnWidth); + + m_seedListTab->ApplyConfig(); + m_assetListTab->ApplyConfig(); + m_rulesTab->ApplyConfig(); + m_bundleListTab->ApplyConfig(); + } + + void MainWindow::WriteToLog(const AZStd::string& message, AzToolsFramework::Logging::LogLine::LogType logType) + { + WriteToLog(message.c_str(), logType); + } + + void MainWindow::WriteToLog(const QString& message, AzToolsFramework::Logging::LogLine::LogType logType) + { + WriteToLog(message.toUtf8().data(), logType); + } + + void MainWindow::WriteToLog(const char* message, AzToolsFramework::Logging::LogLine::LogType logType) + { + WriteToLog(message, "AssetBundler", logType); + } + + void MainWindow::WriteToLog(const char* message, const char* window, AzToolsFramework::Logging::LogLine::LogType logType) + { + m_logModel->AppendLine( + AzToolsFramework::Logging::LogLine( + message, + window, + logType, + QDateTime::currentMSecsSinceEpoch())); + m_ui->logTableView->scrollToBottom(); + } + + bool MainWindow::OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + WriteToLog(message, window, AzToolsFramework::Logging::LogLine::LogType::TYPE_ERROR); + return true; + } + + bool MainWindow::OnPreWarning(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + WriteToLog(message, window, AzToolsFramework::Logging::LogLine::LogType::TYPE_WARNING); + return true; + } + + bool MainWindow::OnPrintf(const char* /*window*/, const char* /*message*/) + { + return true; + } + + void MainWindow::ShowWindow() + { + AzQtComponents::bringWindowToTop(this); + } + + void MainWindow::closeEvent(QCloseEvent* event) + { + if (!HasUnsavedChanges()) + { + // No need to ask the user if they want to quit when there are no unsaved changes + event->accept(); + return; + } + + int unsavedChangesResult = m_unsavedChangesMsgBox->exec(); + + switch (unsavedChangesResult) + { + case QMessageBox::Save: + // Save All was clicked + SaveAll(); + event->accept(); + break; + case QMessageBox::Discard: + // Don't Save was clicked + event->accept(); + break; + case QMessageBox::Cancel: + // Cancel was clicked + event->ignore(); + break; + default: + // should never be reached + AZ_Assert(false, "No result was returned by the Unsaved Changes Message Box!"); + break; + } + } + + void MainWindow::OnSupportClicked() + { + QDesktopServices::openUrl( + QStringLiteral("https://docs.aws.amazon.com/lumberyard/latest/userguide/asset-bundler-overview.html")); + } + + void MainWindow::ShowLogContextMenu(const QPoint& pos) + { + QModelIndex index = m_ui->logTableView->indexAt(pos); + + QMenu menu; + + QAction* action = menu.addAction(tr("Copy line"), this, [&]() + { + QApplication::clipboard()->setText(index.data(AzToolsFramework::Logging::LogTableModel::LogLineTextRole).toString()); + }); + action->setEnabled(index.isValid()); + + menu.exec(m_ui->logTableView->mapToGlobal(pos)); + } + + bool MainWindow::HasUnsavedChanges() + { + return m_seedListTab->HasUnsavedChanges() || m_rulesTab->HasUnsavedChanges(); + } + + void MainWindow::SaveCurrentSelection() + { + switch (m_ui->tabWidget->currentIndex()) + { + case TabIndex::Seeds: + m_seedListTab->SaveCurrentSelection(); + break; + case TabIndex::Rules: + m_rulesTab->SaveCurrentSelection(); + break; + default: + break; + } + } + + void MainWindow::SaveAll() + { + m_seedListTab->SaveAll(); + m_rulesTab->SaveAll(); + } +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/MainWindow.h b/Code/Tools/AssetBundler/source/ui/MainWindow.h new file mode 100644 index 0000000000..e8c5570649 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/MainWindow.h @@ -0,0 +1,105 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#endif + +namespace Ui +{ + class MainWindow; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class MainWindow + : public QMainWindow + , public AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + + explicit MainWindow(AssetBundler::GUIApplicationManager* guiApplicationManager, QWidget* parent = 0); + virtual ~MainWindow(); + + void Activate(); + + void ApplyConfig(); + + void WriteToLog(const AZStd::string& message, AzToolsFramework::Logging::LogLine::LogType logType); + void WriteToLog(const QString& message, AzToolsFramework::Logging::LogLine::LogType logType); + void WriteToLog(const char* message, AzToolsFramework::Logging::LogLine::LogType logType); + void WriteToLog(const char* message, const char* window, AzToolsFramework::Logging::LogLine::LogType logType); + + ///////////////////////////////////////////////////////// + // TraceMessageBus overrides + bool OnPreError(const char* window, const char* fileName, int line, const char* func, const char* message) override; + bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override; + bool OnPrintf(const char* window, const char* message) override; + ///////////////////////////////////////////////////////// + + public Q_SLOTS: + void ShowWindow(); + + protected: + void closeEvent(QCloseEvent* event) override; + + private: + QSharedPointer m_ui; + + // Tabs + QSharedPointer m_assetListTab; + QSharedPointer m_seedListTab; + QSharedPointer m_rulesTab; + QSharedPointer m_bundleListTab; + + enum TabIndex + { + Seeds, + AssetLists, + Rules, + Bundles, + MAX + }; + + void OnSupportClicked(); + + // Log + QSharedPointer m_logModel; + + void ShowLogContextMenu(const QPoint& pos); + + // Detecting Unsaved Changes + QSharedPointer m_unsavedChangesMsgBox; + + bool HasUnsavedChanges(); + void SaveCurrentSelection(); + void SaveAll(); + + AssetBundler::GUIApplicationManager* m_guiApplicationManager = nullptr; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/MainWindow.ui b/Code/Tools/AssetBundler/source/ui/MainWindow.ui new file mode 100644 index 0000000000..902652459f --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/MainWindow.ui @@ -0,0 +1,112 @@ + + + MainWindow + + + + 0 + 0 + 1200 + 1000 + + + + + 200 + 200 + + + + Asset Bundler + + + + + + + -1 + + + + + + + + 0 + 0 + + + + + + + + + + 0 + 0 + 1200 + 21 + + + + + File + + + + + + + + + Help + + + + + + + + + Save + + + + + Close + + + + + Documentation + + + + + About Asset Bundler + + + + + Save All + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::TabWidget + QTabWidget +
AzQtComponents/Components/Widgets/TabWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/NewFileDialog.cpp b/Code/Tools/AssetBundler/source/ui/NewFileDialog.cpp new file mode 100644 index 0000000000..170da4a659 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/NewFileDialog.cpp @@ -0,0 +1,224 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace AssetBundler +{ + NewFileDialog::NewFileDialog( + QWidget* parent, + const QString& dialogTitle, + const QString& startingPath, + const char* fileExtension, + const QString& fileNameFilter, + const AzFramework::PlatformFlags& enabledPlatforms, + bool isRunningRule) + : QDialog(parent) + , m_startingPath(startingPath) + , m_fileExtension(fileExtension) + { + m_ui.reset(new Ui::NewFileDialog); + m_ui->setupUi(this); + + setWindowTitle(dialogTitle); + + // Set up File Name section + m_ui->fileNameLineEdit->setEnabled(false); + connect(m_ui->browseButton, &QPushButton::clicked, this, &NewFileDialog::OnBrowseButtonPressed); + + m_newFileDialog.setFileMode(QFileDialog::AnyFile); + m_newFileDialog.setNameFilter(fileNameFilter); + m_newFileDialog.setViewMode(QFileDialog::Detail); + m_newFileDialog.setDirectory(m_startingPath); + // We are not creating a new file when Qt thinks we are, so we need to block signals or else the file watcher will be triggered too soon + m_newFileDialog.blockSignals(true); + + // Set up Platform selection + QString disabledPatformMessageOverride; + if (isRunningRule) + { + disabledPatformMessageOverride = tr("This platform is not valid for all input Asset Lists."); + } + m_ui->platformSelectionWidget->Init(enabledPlatforms, disabledPatformMessageOverride); + connect(m_ui->platformSelectionWidget, &PlatformSelectionWidget::PlatformsSelected, this, &NewFileDialog::OnPlatformSelectionChanged); + + // Set up Cancel and Create New File buttons + m_ui->createFileButton->setEnabled(false); + connect(m_ui->cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(m_ui->createFileButton, &QPushButton::clicked, this, &NewFileDialog::OnCreateFileButtonPressed); + } + + AZStd::string NewFileDialog::GetAbsoluteFilePath() + { + return m_absoluteFilePath; + } + + AzFramework::PlatformFlags NewFileDialog::GetPlatformFlags() + { + return m_ui->platformSelectionWidget->GetSelectedPlatforms(); + } + + void NewFileDialog::OnBrowseButtonPressed() + { + int result = m_newFileDialog.exec(); + if (result == QDialog::DialogCode::Accepted) + { + m_absoluteFilePath = m_newFileDialog.selectedFiles()[0].toUtf8().data(); + AzToolsFramework::RemovePlatformIdentifier(m_absoluteFilePath); + + if (m_fileExtension && !AzFramework::StringFunc::Path::HasExtension(m_absoluteFilePath.c_str())) + { + m_absoluteFilePath.append("."); + m_absoluteFilePath.append(m_fileExtension); + } + + m_ui->fileNameLineEdit->setEnabled(true); + m_ui->fileNameLineEdit->setText(m_absoluteFilePath.c_str()); + } + + m_fileNameIsValid = !m_absoluteFilePath.empty(); + m_ui->createFileButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void NewFileDialog::OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms) + { + // Hide the "Create File" button if no platforms are selected + m_platformIsValid = selectedPlatforms != AzFramework::PlatformFlags::Platform_NONE; + m_ui->createFileButton->setEnabled(m_platformIsValid && m_fileNameIsValid); + } + + void NewFileDialog::OnCreateFileButtonPressed() + { + // Check to see if any of the selected platform-specific files already exist on-disk + QString overwriteExistingFilesList; + AZStd::fixed_vector selectedPlatformNames = AzFramework::PlatformHelper::GetPlatforms(GetPlatformFlags()); + for (const AZStd::string& platformName : selectedPlatformNames) + { + FilePath platformSpecificFilePath(GetAbsoluteFilePath(), platformName); + const char* platformSpecificFileAbsolutePath = platformSpecificFilePath.AbsolutePath().c_str(); + if (AZ::IO::FileIOBase::GetInstance()->Exists(platformSpecificFileAbsolutePath)) + { + overwriteExistingFilesList.append(QString("%1\n").arg(platformSpecificFileAbsolutePath)); + } + } + + // Ask the user if they are sure they want to overwrite existing files + if (!overwriteExistingFilesList.isEmpty()) + { + QString messageBoxText = QString(tr("The following files already exist on-disk. Generating new files will overwrite the existing ones.\n\n%1\n\nDo you wish to permanently delete the existing files?")).arg(overwriteExistingFilesList); + + QMessageBox::StandardButton confirmDeleteFileResult = QMessageBox::question(this, QString(tr("Replace Existing Files")), messageBoxText); + if (confirmDeleteFileResult != QMessageBox::StandardButton::Yes) + { + // User canceled out of the operation + return; + } + } + + emit QDialog::accept(); + } + + AZStd::string NewFileDialog::OSNewFileDialog(QWidget* parent, const char* fileExtension, const char* fileTypeDisplayName, const AZStd::string& startingDirectory) + { + QFileDialog filePathDialog(parent); + filePathDialog.setFileMode(QFileDialog::AnyFile); + filePathDialog.setNameFilter(QString(tr("%1 (*.%2)")).arg(fileTypeDisplayName).arg(fileExtension)); + filePathDialog.setViewMode(QFileDialog::Detail); + filePathDialog.setDirectory(startingDirectory.c_str()); + + // Since we handle file creation instead of the OS, we have to block signals or else the model will be reloaded, + // and our in-memory changes will be lost. + filePathDialog.blockSignals(true); + int result = filePathDialog.exec(); + if (result == QDialog::DialogCode::Rejected || filePathDialog.selectedFiles().empty()) + { + // User canceled out of the file dialog, cancel operation + return ""; + } + + AZStd::string absoluteFilePath(filePathDialog.selectedFiles()[0].toUtf8().data()); + if (!AzFramework::StringFunc::Path::HasExtension(absoluteFilePath.c_str())) + { + absoluteFilePath = AZStd::string::format("%s%c%s", absoluteFilePath.c_str(), AZ_FILESYSTEM_EXTENSION_SEPARATOR, fileExtension); + } + + return absoluteFilePath; + } + + int NewFileDialog::FileGenerationResultMessageBox(QWidget* parent, const AZStd::vector& generatedFiles, bool generatedWithErrors) + { + QMessageBox messageBox(parent); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.setDefaultButton(QMessageBox::Ok); + + if (generatedFiles.empty()) + { + messageBox.setText(QString("No files were generated. Please refer to the console for more information.")); + messageBox.setIcon(QMessageBox::Critical); + return messageBox.exec(); + } + + QString messageText; + if (generatedWithErrors) + { + messageText = QString("The following files were generated with errors. Please refer to the console for more information.\n\n"); + messageBox.setIcon(QMessageBox::Warning); + } + else + { + messageText = QString("You have successfully generated:\n\n"); + messageBox.setIcon(QMessageBox::NoIcon); + } + + AZStd::string fileName; + for (const AZStd::string& filePath : generatedFiles) + { + AzFramework::StringFunc::Path::GetFullFileName(filePath.c_str(), fileName); + messageText.append(QString("%1\n").arg(fileName.c_str())); + } + + AZStd::string extension; + AzFramework::StringFunc::Path::GetExtension(fileName.c_str(), extension, false); + if (extension == AzToolsFramework::AssetSeedManager::GetAssetListFileExtension()) + { + messageText.append("\nVisit the Asset Lists tab to see the lists."); + } + else if (extension == AzToolsFramework::AssetBundleSettings::GetBundleFileExtension()) + { + messageText.append("\nVisit the Completed Bundles tab to see the bundles."); + } + + messageBox.setText(messageText); + + // QMessageBoxes try to shrink to the smallest size possible, so we need to make a spacer + QSpacerItem* horizontalSpacer = new QSpacerItem(550, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); + QGridLayout* layout = static_cast(messageBox.layout()); + layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount()); + + return messageBox.exec(); + } + +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/NewFileDialog.h b/Code/Tools/AssetBundler/source/ui/NewFileDialog.h new file mode 100644 index 0000000000..5974d3da6a --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/NewFileDialog.h @@ -0,0 +1,73 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#include +#endif + +namespace Ui +{ + class NewFileDialog; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class NewFileDialog + : public QDialog + { + Q_OBJECT + + public: + explicit NewFileDialog( + QWidget* parent, + const QString& dialogTitle, + const QString& startingPath, + const char* fileExtension, + const QString& fileNameFilter, + const AzFramework::PlatformFlags& enabledPlatforms, + bool isRunningRule = false); + virtual ~NewFileDialog() {} + + AZStd::string GetAbsoluteFilePath(); + AzFramework::PlatformFlags GetPlatformFlags(); + + //! A standard OS-specific New File Dialog, but blocks all Qt signals from the dialog and does NOT create a new file. + //! Use in place of the static QFileDialog functions to avoid unexpected file watcher updates. + //! Returns the absolute path of the file the user either selected or attempted to create, or an empty string if the user canceled out of the dialog. + static AZStd::string OSNewFileDialog(QWidget* parent, const char* fileExtension, const char* fileTypeDisplayName, const AZStd::string& startingDirectory); + + static int FileGenerationResultMessageBox(QWidget* parent, const AZStd::vector& generatedFiles, bool generatedWithErrors); + + private: + void OnBrowseButtonPressed(); + void OnPlatformSelectionChanged(const AzFramework::PlatformFlags& selectedPlatforms); + void OnCreateFileButtonPressed(); + + QSharedPointer m_ui; + QString m_startingPath; + const char* m_fileExtension; + QFileDialog m_newFileDialog; + + AZStd::string m_absoluteFilePath; + + bool m_fileNameIsValid = false; + bool m_platformIsValid = false; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/NewFileDialog.ui b/Code/Tools/AssetBundler/source/ui/NewFileDialog.ui new file mode 100644 index 0000000000..17d439549c --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/NewFileDialog.ui @@ -0,0 +1,154 @@ + + + NewFileDialog + + + Qt::ApplicationModal + + + + 0 + 0 + 450 + 90 + + + + + 0 + 0 + + + + + 450 + 0 + + + + Dialog + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Save As: + + + + + + + true + + + + + + + Browse... + + + + + + + + + + + + + + + 10 + + + 10 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Cancel + + + false + + + + + + + Create New File + + + true + + + + + + + + + + AssetBundler::PlatformSelectionWidget + QWidget +
source/ui/PlatformSelectionWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.cpp b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.cpp new file mode 100644 index 0000000000..80b4590c3c --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.cpp @@ -0,0 +1,126 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include + +namespace AssetBundler +{ + + PlatformSelectionWidget::PlatformSelectionWidget(QWidget* parent) + : QWidget(parent) + { + m_ui.reset(new Ui::PlatformSelectionWidget); + m_ui->setupUi(this); + + m_platformHelper.reset(new AzFramework::PlatformHelper); + + m_selectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + m_partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + } + + void PlatformSelectionWidget::Init(const AzFramework::PlatformFlags& enabledPlatforms, const QString& disabledPatformMessageOverride) + { + using namespace AzFramework; + + // Set up Platform Checkboxes + for (const AZStd::string_view& platformString : m_platformHelper->GetPlatforms(PlatformFlags::AllNamedPlatforms)) + { + // Create the CheckBox and store what platform it maps to + QSharedPointer platformCheckBox(new QCheckBox(QString::fromUtf8(platformString.data(), platformString.size()))); + m_platformCheckBoxes.push_back(platformCheckBox); + PlatformFlags currentPlatformFlag = m_platformHelper->GetPlatformFlag(platformString); + m_platformList.push_back(currentPlatformFlag); + + // Add the CheckBox to the view + m_ui->platformCheckBoxLayout->addWidget(platformCheckBox.data()); + + // If the platform is not enabled for the current project, disable it and tell the user + if ((enabledPlatforms & currentPlatformFlag) == PlatformFlags::Platform_NONE) + { + platformCheckBox->setEnabled(false); + if (disabledPatformMessageOverride.isEmpty()) + { + platformCheckBox->setToolTip(tr("This platform is not enabled for the current project.")); + } + else + { + platformCheckBox->setToolTip(disabledPatformMessageOverride); + } + } + else + { + connect(platformCheckBox.data(), &QCheckBox::stateChanged, this, &PlatformSelectionWidget::OnPlatformSelectionChanged); + } + } + } + + void PlatformSelectionWidget::SetSelectedPlatforms(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms) + { + m_selectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + m_partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + for (int checkBoxIndex = 0; checkBoxIndex < m_platformCheckBoxes.size(); ++checkBoxIndex) + { + AzFramework::PlatformFlags checkBoxPlatform = m_platformList[checkBoxIndex]; + bool isSelected = (checkBoxPlatform & selectedPlatforms) != AzFramework::PlatformFlags::Platform_NONE; + m_platformCheckBoxes[checkBoxIndex]->setChecked(isSelected); + if (isSelected) + { + m_selectedPlatforms |= checkBoxPlatform; + } + + // Set the check status to Qt::PartiallyChecked when some of the selected items support the current platform + bool isPartiallySelected = (checkBoxPlatform & partiallySelectedPlatforms) != AzFramework::PlatformFlags::Platform_NONE; + if (isPartiallySelected) + { + m_platformCheckBoxes[checkBoxIndex]->setCheckState(Qt::PartiallyChecked); + m_partiallySelectedPlatforms |= checkBoxPlatform; + } + } + + emit PlatformsSelected(m_selectedPlatforms, m_partiallySelectedPlatforms); + } + + AzFramework::PlatformFlags PlatformSelectionWidget::GetSelectedPlatforms() + { + return m_selectedPlatforms; + } + + AzFramework::PlatformFlags PlatformSelectionWidget::GetPartiallySelectedPlatforms() + { + return m_partiallySelectedPlatforms; + } + + void PlatformSelectionWidget::OnPlatformSelectionChanged() + { + m_selectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + m_partiallySelectedPlatforms = AzFramework::PlatformFlags::Platform_NONE; + for (int checkBoxIndex = 0; checkBoxIndex < m_platformCheckBoxes.size(); ++checkBoxIndex) + { + if (m_platformCheckBoxes[checkBoxIndex]->checkState() == Qt::Checked) + { + m_selectedPlatforms |= m_platformList[checkBoxIndex]; + } + else if (m_platformCheckBoxes[checkBoxIndex]->checkState() == Qt::PartiallyChecked) + { + m_partiallySelectedPlatforms |= m_platformList[checkBoxIndex]; + } + } + + emit PlatformsSelected(m_selectedPlatforms, m_partiallySelectedPlatforms); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.h b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.h new file mode 100644 index 0000000000..223044478f --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.h @@ -0,0 +1,62 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include + +#include +#include +#include +#endif + +namespace Ui +{ + class PlatformSelectionWidget; +} + +namespace AssetBundler +{ + class PlatformSelectionWidget + : public QWidget + { + Q_OBJECT + + public: + explicit PlatformSelectionWidget(QWidget* parent); + virtual ~PlatformSelectionWidget() {} + + void Init(const AzFramework::PlatformFlags& enabledPlatforms, const QString& disabledPatformMessageOverride = ""); + + void SetSelectedPlatforms(const AzFramework::PlatformFlags& selectedPlatforms, const AzFramework::PlatformFlags& partiallySelectedPlatforms); + + AzFramework::PlatformFlags GetSelectedPlatforms(); + AzFramework::PlatformFlags GetPartiallySelectedPlatforms(); + + Q_SIGNALS: + void PlatformsSelected(AzFramework::PlatformFlags selectedPlatforms, AzFramework::PlatformFlags partiallySelectedPlatforms); + + private: + void OnPlatformSelectionChanged(); + + QSharedPointer m_ui; + AZStd::unique_ptr m_platformHelper; + + QVector> m_platformCheckBoxes; + AZStd::vector m_platformList; + + AzFramework::PlatformFlags m_selectedPlatforms; + AzFramework::PlatformFlags m_partiallySelectedPlatforms; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.ui b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.ui new file mode 100644 index 0000000000..d2ecb61e64 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/PlatformSelectionWidget.ui @@ -0,0 +1,49 @@ + + + PlatformSelectionWidget + + + + 0 + 0 + 400 + 300 + + + + Form + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Platforms: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + diff --git a/Code/Tools/AssetBundler/source/ui/RulesTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.cpp new file mode 100644 index 0000000000..56447f4a57 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.cpp @@ -0,0 +1,432 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +namespace AssetBundler +{ + RulesTabWidget::RulesTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager) + : AssetBundlerTabWidget(parent, guiApplicationManager) + { + m_ui.reset(new Ui::RulesTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + m_fileTableModel.reset(new RulesFileTableModel); + m_ui->fileTableView->setModel(m_fileTableModel.data()); + + // Table View of all Rules files + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->fileTableView->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RulesTabWidget::FileSelectionChanged); + + m_ui->fileTableView->setIndentation(0); + + // New File Button + connect(m_ui->createNewFileButton, &QPushButton::clicked, this, &RulesTabWidget::OnNewFileButtonPressed); + + // Run Rule Button + m_ui->runRuleButton->setEnabled(false); + connect(m_ui->runRuleButton, &QPushButton::clicked, this, &RulesTabWidget::OnRunRuleButtonPressed); + + // Add Comparison Step button + connect(m_ui->addComparisonStepButton, &QPushButton::clicked, this, &RulesTabWidget::AddNewComparisonStep); + + SetModelDataSource(); + } + + bool RulesTabWidget::HasUnsavedChanges() + { + return m_fileTableModel->HasUnsavedChanges(); + } + + void RulesTabWidget::Reload() + { + m_fileTableModel->Reload(AzToolsFramework::AssetFileInfoListComparison::GetComparisonRulesFileExtension(), m_watchedFolders, m_watchedFiles); + FileSelectionChanged(); + } + + bool RulesTabWidget::SaveCurrentSelection() + { + return m_fileTableModel->Save(m_selectedFileTableIndex); + } + + bool RulesTabWidget::SaveAll() + { + return m_fileTableModel->SaveAll(); + } + + void RulesTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folder for the model + m_watchedFolders.clear(); + m_watchedFiles.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetRulesFolder().c_str()); + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::RulesFileType); + + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* RulesTabWidget::GetFileTableView() + { + return m_ui->fileTableView; + } + + QModelIndex RulesTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* RulesTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void RulesTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void RulesTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + m_ui->fileTableView->header()->resizeSection(RulesFileTableModel::Column::ColumnFileName, config.fileNameColumnWidth); + } + + + void RulesTabWidget::FileSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/) + { + if (m_ui->fileTableView->selectionModel()->selectedRows().size() == 0) + { + m_selectedFileTableIndex = QModelIndex(); + m_selectedComparisonRules = nullptr; + m_ui->runRuleButton->setEnabled(false); + m_ui->addComparisonStepButton->setEnabled(false); + m_ui->rulesFileAbsolutePathLabel->clear(); + RemoveAllComparisonDataCards(); + + return; + } + + m_ui->runRuleButton->setEnabled(true); + m_ui->addComparisonStepButton->setEnabled(true); + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->fileTableView->selectionModel()->selectedRows()[0]); + m_selectedComparisonRules = m_fileTableModel->GetComparisonSteps(m_selectedFileTableIndex); + + m_ui->rulesFileAbsolutePathLabel->setText(m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex).c_str()); + + RebuildComparisonDataCardList(); + } + + void RulesTabWidget::OnNewFileButtonPressed() + { + AZStd::string absoluteFilePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetFileInfoListComparison::GetComparisonRulesFileExtension(), + "Comparison Rules", + m_guiApplicationManager->GetRulesFolder()); + + if (absoluteFilePath.empty()) + { + // User canceled out of the dialog + return; + } + + AZStd::vector createdFile = m_fileTableModel->CreateNewFiles(absoluteFilePath); + if (!createdFile.empty()) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::RulesFileType, createdFile.at(0)); + } + } + + void RulesTabWidget::OnRunRuleButtonPressed() + { + using namespace AzToolsFramework; + + // Determine which platforms all of the input Asset List files have in common + AzFramework::PlatformFlags commonPlatforms = AzFramework::PlatformFlags::AllNamedPlatforms; + for (const AssetFileInfoListComparison::ComparisonData& comparisonStep : m_selectedComparisonRules->GetComparisonList()) + { + if (!comparisonStep.m_cachedFirstInputPath.empty()) + { + commonPlatforms = commonPlatforms & GetPlatformsOnDiskForPlatformSpecificFile(comparisonStep.m_cachedFirstInputPath); + } + + if (!comparisonStep.m_cachedSecondInputPath.empty()) + { + commonPlatforms = commonPlatforms & GetPlatformsOnDiskForPlatformSpecificFile(comparisonStep.m_cachedSecondInputPath); + } + } + + if (commonPlatforms == AzFramework::PlatformFlags::Platform_NONE) + { + AZ_Error("AssetBundler", false, "Unable to run Rule: Input Asset List files have no platforms in common."); + return; + } + + // Prompt the user to select an output path and the platforms to run the rule on + NewFileDialog runRuleDialog = NewFileDialog( + this, + "Run Rule", + QString(m_guiApplicationManager->GetAssetListsFolder().c_str()), + AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), + QString(tr("Asset List (*.%1)")).arg(AzToolsFramework::AssetSeedManager::GetAssetListFileExtension()), + commonPlatforms, + true); + + auto dialogResponse = runRuleDialog.exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + AZStd::vector outputFilePaths; + bool hasFileGenerationErrors = false; + + AZStd::fixed_vector selectedPlatformNames = AzFramework::PlatformHelper::GetPlatforms(runRuleDialog.GetPlatformFlags()); + for (const AZStd::string& platformName : selectedPlatformNames) + { + // We do not want to modify the original Rules file, as we do not save Asset List file paths to disk + AssetFileInfoListComparison currentFileCopy = *m_selectedComparisonRules.get(); + + //Update the first and second input values with any non-token Asset List file paths that have been set, + size_t numComparisonSteps = currentFileCopy.GetNumComparisonSteps(); + for (size_t comparisonStepIndex = 0; comparisonStepIndex < numComparisonSteps; ++comparisonStepIndex) + { + AssetFileInfoListComparison::ComparisonData comparisonStep = currentFileCopy.GetComparisonList()[comparisonStepIndex]; + if (comparisonStep.m_firstInput.empty()) + { + if (comparisonStep.m_cachedFirstInputPath.empty()) + { + AZ_Error("AssetBundler", false, "Unable to run Rule: Comparison Step #%u has no specified first input.", comparisonStepIndex); + return; + } + + FilePath firstInput = FilePath(comparisonStep.m_cachedFirstInputPath, platformName); + currentFileCopy.SetFirstInput(comparisonStepIndex, firstInput.AbsolutePath()); + } + + if (comparisonStep.m_comparisonType != AssetFileInfoListComparison::ComparisonType::FilePattern + && comparisonStep.m_secondInput.empty()) + { + if (comparisonStep.m_cachedSecondInputPath.empty()) + { + AZ_Error("AssetBundler", false, "Unable to run Rule: Comparison Step #%u has no specified second input.", comparisonStepIndex); + return; + } + + FilePath secondInput = FilePath(comparisonStep.m_cachedSecondInputPath, platformName); + currentFileCopy.SetSecondInput(comparisonStepIndex, secondInput.AbsolutePath()); + } + } + + // Set the output location of the Asset List file that will be generated + FilePath finalOutputPath = FilePath(runRuleDialog.GetAbsoluteFilePath(), platformName); + currentFileCopy.SetOutput(numComparisonSteps - 1, finalOutputPath.AbsolutePath()); + + //Run the Rule + auto compareOutcome = currentFileCopy.CompareAndSaveResults(); + if (compareOutcome.IsSuccess()) + { + outputFilePaths.emplace_back(finalOutputPath.AbsolutePath()); + } + else + { + hasFileGenerationErrors = true; + AZ_Error("AssetBundler", false, compareOutcome.GetError().c_str()); + } + } + + // Add created files to the file watcher + for (const AZStd::string& absolutePath : outputFilePaths) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::AssetListFileType, absolutePath); + } + + // The watched files list was updated after the files were created, so we need to force-reload them + m_guiApplicationManager->UpdateFiles(AssetBundlingFileType::AssetListFileType, outputFilePaths); + + NewFileDialog::FileGenerationResultMessageBox(this, outputFilePaths, hasFileGenerationErrors); + } + + void RulesTabWidget::MarkFileChanged() + { + m_fileTableModel->MarkFileChanged(m_selectedFileTableIndex); + } + + void RulesTabWidget::RebuildComparisonDataCardList() + { + RemoveAllComparisonDataCards(); + PopulateComparisonDataCardList(); + } + + void RulesTabWidget::PopulateComparisonDataCardList() + { + if (!m_selectedComparisonRules) + { + return; + } + + for (int index = 0; index < m_selectedComparisonRules->GetComparisonList().size(); ++index) + { + CreateComparisonDataCard(m_selectedComparisonRules, static_cast(index)); + } + } + + void RulesTabWidget::CreateComparisonDataCard(AZStd::shared_ptr comparisonList, size_t comparisonDataIndex) + { + ComparisonDataCard* comparisonDataCard = new ComparisonDataCard(comparisonList, comparisonDataIndex, m_guiApplicationManager->GetAssetListsFolder()); + comparisonDataCard->setTitle(tr("Step %1").arg(static_cast(comparisonDataIndex) + 1)); + m_ui->comparisonDataListLayout->addWidget(comparisonDataCard); + m_comparisonDataCardList.push_back(comparisonDataCard); + + ComparisonDataWidget* comparisonDataWidget = comparisonDataCard->GetComparisonDataWidget(); + connect(comparisonDataCard, &ComparisonDataCard::comparisonDataCardContextMenuRequested, this, &RulesTabWidget::OnComparisonDataCardContextMenuRequested); + connect(comparisonDataWidget, &ComparisonDataWidget::comparisonDataChanged, this, &RulesTabWidget::MarkFileChanged); + connect(comparisonDataWidget, &ComparisonDataWidget::comparisonDataTokenNameChanged, this, &RulesTabWidget::OnAnyTokenNameChanged); + + comparisonDataCard->show(); + } + + void RulesTabWidget::RemoveAllComparisonDataCards() + { + m_comparisonDataCardList.clear(); + + while (!m_ui->comparisonDataListLayout->isEmpty()) + { + QLayoutItem* item = m_ui->comparisonDataListLayout->takeAt(0); + item->widget()->hide(); + delete item; + } + } + + void RulesTabWidget::AddNewComparisonStep() + { + if (!m_selectedComparisonRules) + { + return; + } + + if (!m_selectedComparisonRules->AddComparisonStep(AzToolsFramework::AssetFileInfoListComparison::ComparisonData())) + { + return; + } + + CreateComparisonDataCard(m_selectedComparisonRules, m_selectedComparisonRules->GetComparisonList().size() - 1); + MarkFileChanged(); + } + + void RulesTabWidget::RemoveComparisonStep(size_t comparisonDataIndex) + { + if (!m_selectedComparisonRules) + { + return; + } + + if (m_selectedComparisonRules->RemoveComparisonStep(comparisonDataIndex)) + { + MarkFileChanged(); + RebuildComparisonDataCardList(); + } + } + + void RulesTabWidget::MoveComparisonStep(size_t startingIndex, size_t destinationIndex) + { + if (!m_selectedComparisonRules) + { + return; + } + + if (m_selectedComparisonRules->MoveComparisonStep(startingIndex, destinationIndex)) + { + MarkFileChanged(); + RebuildComparisonDataCardList(); + } + } + + void RulesTabWidget::OnAnyTokenNameChanged(size_t comparisonDataIndex) + { + if (comparisonDataIndex >= m_comparisonDataCardList.size() - 1) + { + return; + } + + for (size_t i = comparisonDataIndex + 1; i < m_comparisonDataCardList.size(); ++i) + { + m_comparisonDataCardList[i]->GetComparisonDataWidget()->UpdateListOfTokenNames(); + } + } + + void RulesTabWidget::OnComparisonDataCardContextMenuRequested(size_t comparisonDataIndex, const QPoint& position) + { + if (!m_selectedComparisonRules) + { + return; + } + + QMenu menu; + + QAction* moveUpAction = new QAction(tr("Move Up"), this); + moveUpAction->setEnabled(comparisonDataIndex > 0); + connect(moveUpAction, &QAction::triggered, this, [=]() { MoveComparisonStep(comparisonDataIndex, comparisonDataIndex - 1); }); + menu.addAction(moveUpAction); + + QAction* moveDownAction = new QAction(tr("Move Down"), this); + moveDownAction->setEnabled(comparisonDataIndex < m_selectedComparisonRules->GetNumComparisonSteps() - 1); + connect(moveDownAction, &QAction::triggered, this, [=]() { MoveComparisonStep(comparisonDataIndex, comparisonDataIndex + 2); }); + menu.addAction(moveDownAction); + + QAction* separator = new QAction(this); + separator->setSeparator(true); + menu.addAction(separator); + + QAction* deleteAction = new QAction(tr("Remove Comparison Step"), this); + connect(deleteAction, &QAction::triggered, this, [=]() { RemoveComparisonStep(comparisonDataIndex); }); + menu.addAction(deleteAction); + + menu.exec(position); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/RulesTabWidget.h b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.h new file mode 100644 index 0000000000..7dedce3efe --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.h @@ -0,0 +1,120 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include + +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class RulesTabWidget; +} + +class QItemSelection; + +namespace AzToolsFramework +{ + class AssetFileInfoListComparison; +} + +namespace AssetBundler +{ + class GUIApplicationManager; + + class RulesFileTableModel; + + class ComparisonDataCard; + + class ComparisonDataWidget; + + class RulesTabWidget + : public AssetBundlerTabWidget + { + Q_OBJECT + + public: + explicit RulesTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager); + virtual ~RulesTabWidget() {} + + QString GetTabTitle() override { return tr("Rules"); } + + QString GetFileTypeDisplayName() override { return tr("Rules file"); } + + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::RulesFileType; } + + bool HasUnsavedChanges() override; + + void Reload() override; + + bool SaveCurrentSelection() override; + + bool SaveAll() override; + + void SetModelDataSource() override; + + AzQtComponents::TableView* GetFileTableView() override; + + QModelIndex GetSelectedFileTableIndex() override; + + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + + void SetActiveProjectLabel(const QString& labelText) override; + + void ApplyConfig() override; + + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + + private: + void OnNewFileButtonPressed(); + + void OnRunRuleButtonPressed(); + + void MarkFileChanged(); + + void RebuildComparisonDataCardList(); + + void PopulateComparisonDataCardList(); + + void CreateComparisonDataCard(AZStd::shared_ptr comparisonList, size_t comparisonDataIndex); + + void RemoveAllComparisonDataCards(); + + void AddNewComparisonStep(); + + void RemoveComparisonStep(size_t comparisonDataIndex); + + void MoveComparisonStep(size_t startingIndex, size_t destinationIndex); + + void OnAnyTokenNameChanged(size_t comparisonDataIndex); + + QSharedPointer m_ui; + + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + AZStd::shared_ptr m_selectedComparisonRules; + + AZStd::vector m_comparisonDataCardList; + + private slots: + void OnComparisonDataCardContextMenuRequested(size_t comparisonDataIndex, const QPoint& position); + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/RulesTabWidget.ui b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.ui new file mode 100644 index 0000000000..f7eec0a796 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/RulesTabWidget.ui @@ -0,0 +1,312 @@ + + + RulesTabWidget + + + + 0 + 0 + 1180 + 728 + + + + Rules Tab Widget + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Run Selected Rule + + + true + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Rules + + + + + + + + + + Filter by file name + + + + + + + 5 + + + 5 + + + + + + Create new Rules file + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Comparison Steps + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 5 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Add Step + + + + + + + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + 0 + 0 + 573 + 614 + + + + + 0 + 0 + + + + + 12 + + + 10 + + + 10 + + + 10 + + + 0 + + + + + + + + Qt::Vertical + + + + 40 + 20 + + + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/SeedTabWidget.cpp b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.cpp new file mode 100644 index 0000000000..60b4104c5a --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.cpp @@ -0,0 +1,453 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +const char GenerateAssetListFilesDialogName[] = "Generate Asset List Files"; + +const int CheckBoxTableIndentationSize = 2; // when the indentation is 0, the checkboxes are too close to the edge + +namespace AssetBundler +{ + SeedTabWidget::SeedTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager, const QString& assetBundlingDirectory) + : AssetBundlerTabWidget(parent, guiApplicationManager) + , m_fileTableModel(new SeedListFileTableModel(this)) + , m_seedListContentsModel(new SeedListTableModel()) + { + AZ_UNUSED(assetBundlingDirectory); + + m_ui.reset(new Ui::SeedTabWidget); + m_ui->setupUi(this); + + m_ui->mainVerticalLayout->setContentsMargins(MarginSize, MarginSize, MarginSize, MarginSize); + + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + + // File view of all Seed List Files + m_fileTableFilterModel.reset(new AssetBundlerFileTableFilterModel(this, m_fileTableModel->GetFileNameColumnIndex(), m_fileTableModel->GetTimeStampColumnIndex())); + + m_fileTableFilterModel->setSourceModel(m_fileTableModel.data()); + m_ui->fileTableView->setModel(m_fileTableFilterModel.data()); + connect(m_ui->fileFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_fileTableFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + connect(m_ui->fileTableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SeedTabWidget::FileSelectionChanged); + + m_ui->fileTableView->setIndentation(CheckBoxTableIndentationSize); + + // New File Button + connect(m_ui->createNewSeedListButton, &QPushButton::clicked, this, &SeedTabWidget::OnNewFileButtonPressed); + + // Select Default Seed Lists + connect(m_ui->selectDefaultSeedListsCheckBox, &QCheckBox::clicked, this, &SeedTabWidget::OnSelectDefaultSeedListsCheckBoxChanged); + + // Generate Asset Lists Button + SetGenerateAssetListsButtonEnabled(false); + connect(m_ui->generateAssetListsButton, &QPushButton::clicked, this, &SeedTabWidget::OnGenerateAssetListsButtonPressed); + + // Table that displays the contents of a Seed List File + m_seedListContentsFilterModel.reset(new AssetBundlerFileTableFilterModel(this, SeedListTableModel::Column::ColumnRelativePath)); + + m_seedListContentsFilterModel->setSourceModel(m_seedListContentsModel.data()); + m_ui->seedFileContentsTable->setModel(m_seedListContentsFilterModel.data()); + connect(m_ui->seedListContentsFilteredSearchWidget, &AzQtComponents::FilteredSearchWidget::TextFilterChanged, + m_seedListContentsFilterModel.data(), static_cast(&AssetBundlerFileTableFilterModel::FilterChanged)); + + m_ui->seedFileContentsTable->setContextMenuPolicy(Qt::CustomContextMenu); + connect(m_ui->seedFileContentsTable, &QTreeView::customContextMenuRequested, this, &SeedTabWidget::OnSeedListContentsTableContextMenuRequested); + + m_ui->seedFileContentsTable->setIndentation(0); + + // Edit All Platforms + connect(m_ui->editAllSeedsButton, &QPushButton::clicked, this, &SeedTabWidget::OnEditAllButtonPressed); + + // Add Seed + connect(m_ui->addSeedButton, &QPushButton::clicked, this, &SeedTabWidget::OnAddSeedButtonPressed); + + SetModelDataSource(); + } + + SeedTabWidget::~SeedTabWidget() + { + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + bool SeedTabWidget::HasUnsavedChanges() + { + return m_fileTableModel->HasUnsavedChanges(); + } + + void SeedTabWidget::Reload() + { + // Reload all the seed list files + m_fileTableModel->Reload(AzToolsFramework::AssetSeedManager::GetSeedFileExtension(), m_watchedFolders, m_watchedFiles, m_filePathToGemNameMap); + + // Update the selected row + FileSelectionChanged(); + } + + bool SeedTabWidget::SaveCurrentSelection() + { + return m_fileTableModel->Save(m_selectedFileTableIndex); + } + + bool SeedTabWidget::SaveAll() + { + return m_fileTableModel->SaveAll(); + } + + void SeedTabWidget::SetModelDataSource() + { + // Remove the current watched folders and files + m_guiApplicationManager->RemoveWatchedPaths(m_watchedFolders + m_watchedFiles); + + // Set the new watched folders for the model + m_watchedFolders.clear(); + m_watchedFolders.insert(m_guiApplicationManager->GetSeedListsFolder().c_str()); + + // Get the list of default Seed List files + m_filePathToGemNameMap = AssetBundler::GetDefaultSeedListFiles(AZStd::string_view{ AZ::Utils::GetEnginePath() }, m_guiApplicationManager->GetCurrentProjectName(), + m_guiApplicationManager->GetGemInfoList(), m_guiApplicationManager->GetEnabledPlatforms()); + + // Get the list of default Seeds that are not stored in a Seed List file on-disk + AZStd::vector defaultSeeds = GetDefaultSeeds(AZ::Utils::GetProjectPath(), m_guiApplicationManager->GetCurrentProjectName()); + m_fileTableModel->AddDefaultSeedsToInMemoryList(defaultSeeds, m_guiApplicationManager->GetCurrentProjectName().c_str(), m_guiApplicationManager->GetEnabledPlatforms()); + + // Set the new watched filess for the model + m_watchedFiles.clear(); + for (const auto& it : m_filePathToGemNameMap) + { + m_watchedFiles.insert(it.first.c_str()); + } + + ReadScanPathsFromAssetBundlerSettings(AssetBundlingFileType::SeedListFileType); + m_guiApplicationManager->AddWatchedPaths(m_watchedFolders + m_watchedFiles); + } + + AzQtComponents::TableView* SeedTabWidget::GetFileTableView() + { + return m_ui->fileTableView; + } + + QModelIndex SeedTabWidget::GetSelectedFileTableIndex() + { + return m_selectedFileTableIndex; + } + + AssetBundlerAbstractFileTableModel* SeedTabWidget::GetFileTableModel() + { + return m_fileTableModel.get(); + } + + void SeedTabWidget::SetActiveProjectLabel(const QString& labelText) + { + m_ui->activeProjectLabel->setText(labelText); + } + + void SeedTabWidget::ApplyConfig() + { + const GUIApplicationManager::Config& config = m_guiApplicationManager->GetConfig(); + + m_ui->fileTableFrame->setFixedWidth(config.fileTableWidth); + m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnFileName, config.seedListFileNameColumnWidth); + m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnCheckBox, config.checkBoxColumnWidth); + m_ui->fileTableView->header()->resizeSection(SeedListFileTableModel::Column::ColumnProject, config.projectNameColumnWidth); + + m_ui->seedFileContentsTable->header()->resizeSection(SeedListTableModel::Column::ColumnRelativePath, config.seedListContentsNameColumnWidth); + } + + void SeedTabWidget::UncheckSelectDefaultSeedListsCheckBox() + { + m_ui->selectDefaultSeedListsCheckBox->setChecked(false); + } + + void SeedTabWidget::SetGenerateAssetListsButtonEnabled(bool isEnabled) + { + m_ui->generateAssetListsButton->setEnabled(isEnabled); + } + + bool SeedTabWidget::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + { + m_hasWarnings = true; + return false; + } + + bool SeedTabWidget::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + { + m_hasWarnings = true; + return false; + } + + void SeedTabWidget::FileSelectionChanged(const QItemSelection& /*selected*/, const QItemSelection& /*deselected*/) + { + if (m_ui->fileTableView->selectionModel()->selectedRows().size() == 0) + { + // Set selected index to an invalid value + m_selectedFileTableIndex = QModelIndex(); + m_ui->seedListFileAbsolutePathLabel->clear(); + return; + } + + m_selectedFileTableIndex = m_fileTableFilterModel->mapToSource(m_ui->fileTableView->selectionModel()->currentIndex()); + + m_seedListContentsModel = m_fileTableModel->GetSeedListFileContents(m_selectedFileTableIndex); + m_seedListContentsFilterModel->setSourceModel(m_seedListContentsModel.data()); + + m_ui->seedListFileAbsolutePathLabel->setText(m_fileTableModel->GetFileAbsolutePath(m_selectedFileTableIndex).c_str()); + } + + void SeedTabWidget::OnNewFileButtonPressed() + { + AZStd::string absoluteFilePath = NewFileDialog::OSNewFileDialog( + this, + AzToolsFramework::AssetSeedManager::GetSeedFileExtension(), + "Seed List", + m_guiApplicationManager->GetSeedListsFolder()); + + if (absoluteFilePath.empty()) + { + // User canceled out of the file dialog + return; + } + + AZStd::vector createdFiles = m_fileTableModel->CreateNewFiles( + absoluteFilePath, + AzFramework::PlatformFlags::Platform_NONE, + QString(m_guiApplicationManager->GetCurrentProjectName().c_str())); + + if (!createdFiles.empty()) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::SeedListFileType, createdFiles.at(0)); + } + } + + void SeedTabWidget::OnSelectDefaultSeedListsCheckBoxChanged() + { + m_fileTableModel->SelectDefaultSeedLists(m_ui->selectDefaultSeedListsCheckBox->isChecked()); + } + + void SeedTabWidget::OnGenerateAssetListsButtonPressed() + { + m_generateAssetListsDialog.reset( + new NewFileDialog( + this, + GenerateAssetListFilesDialogName, + QString(m_guiApplicationManager->GetAssetListsFolder().c_str()), + AzToolsFramework::AssetSeedManager::GetAssetListFileExtension(), + QString(tr("Asset List (*.%1)")).arg(AzToolsFramework::AssetSeedManager::GetAssetListFileExtension()), + m_guiApplicationManager->GetEnabledPlatforms())); + auto dialogResponse = m_generateAssetListsDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + m_hasWarnings = false; + auto createdFiles = m_fileTableModel->GenerateAssetLists(m_generateAssetListsDialog->GetAbsoluteFilePath(), m_generateAssetListsDialog->GetPlatformFlags()); + + // Warnings will not prevent the generation of Asset List files, we must track them separately + NewFileDialog::FileGenerationResultMessageBox(this, createdFiles, m_hasWarnings); + + if (createdFiles.empty()) + { + // Error has already been thrown + return; + } + + // Add created files to the file watcher + for (const AZStd::string& absolutePath : createdFiles) + { + AddScanPathToAssetBundlerSettings(AssetBundlingFileType::AssetListFileType, absolutePath); + } + + // The watched files list was updated after the files were created, so we need to force-reload them + m_guiApplicationManager->UpdateFiles(AssetBundlingFileType::AssetListFileType, createdFiles); + } + + void SeedTabWidget::OnEditSeedButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Edit Seed operation: No Seed List File is selected"); + return; + } + + // Get the current platforms of the selected Seed so we can display them as already checked + QModelIndex currentSeedIndex = m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex()); + auto getPlatformOutcome = m_seedListContentsModel->GetSeedPlatforms(currentSeedIndex); + if (!getPlatformOutcome.IsSuccess()) + { + // Error has already been thrown + return; + } + + // Create and display the Edit Seed dialog + m_editSeedDialog.reset(new EditSeedDialog(this, m_guiApplicationManager->GetEnabledPlatforms(), getPlatformOutcome.GetValue())); + auto dialogResponse = m_editSeedDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + // Set the data in the model + m_fileTableModel->SetSeedPlatforms(m_selectedFileTableIndex, currentSeedIndex, m_editSeedDialog->GetPlatformFlags()); + } + + void SeedTabWidget::OnEditAllButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Edit All operation: No Seed List File is selected"); + return; + } + + // Get the platforms of all the seeds so we can display them as already checked or partially checked + AzFramework::PlatformFlags selectedPlatformFlags = AzFramework::PlatformFlags::AllNamedPlatforms; + AzFramework::PlatformFlags partiallySelectedPlatformFlags = AzFramework::PlatformFlags::Platform_NONE; + QMap indexToPlatformFlagsMap; + for (int row = 0; row < m_seedListContentsModel->rowCount(); ++row) + { + QModelIndex currentSeedIndex = m_seedListContentsModel->index(row, 0); + auto getPlatformOutcome = m_seedListContentsModel->GetSeedPlatforms(currentSeedIndex); + if (!getPlatformOutcome.IsSuccess()) + { + // Error has already been thrown + return; + } + + indexToPlatformFlagsMap[currentSeedIndex] = getPlatformOutcome.TakeValue(); + selectedPlatformFlags &= indexToPlatformFlagsMap[currentSeedIndex]; + partiallySelectedPlatformFlags |= selectedPlatformFlags ^ indexToPlatformFlagsMap[currentSeedIndex]; + } + + // Create and display the Edit Seed dialog + m_editSeedDialog.reset(new EditSeedDialog( + this, + m_guiApplicationManager->GetEnabledPlatforms(), + selectedPlatformFlags, + partiallySelectedPlatformFlags)); + + auto dialogResponse = m_editSeedDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + // Set the data in the model + for (int row = 0; row < m_seedListContentsModel->rowCount(); ++row) + { + QModelIndex currentSeedIndex = m_seedListContentsModel->index(row, 0); + AzFramework::PlatformFlags checkedPlatforms = m_editSeedDialog->GetPlatformFlags(); + AzFramework::PlatformFlags partiallyCheckedPlatforms = m_editSeedDialog->GetPartiallySelectedPlatformFlags(); + // If the platform is partially checked, we want to keep its original status when saving the changes + AzFramework::PlatformFlags platformFlags = indexToPlatformFlagsMap[currentSeedIndex] & partiallyCheckedPlatforms | checkedPlatforms; + + m_fileTableModel->SetSeedPlatforms(m_selectedFileTableIndex, currentSeedIndex, platformFlags); + } + } + + void SeedTabWidget::OnAddSeedButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Add Seed operation: No Seed List File is selected"); + return; + } + + // Get path to the platform-specific cache folder of one of the enabled platforms + AzFramework::PlatformFlags enabledPlatforms = m_guiApplicationManager->GetEnabledPlatforms(); + AZStd::fixed_vector enabledPlatformIndices = AzFramework::PlatformHelper::GetPlatformIndicesInterpreted(enabledPlatforms); + AZStd::string platformSpecificCachePath = AzToolsFramework::PlatformAddressedAssetCatalog::GetCatalogRegistryPathForPlatform(enabledPlatformIndices[0]); + + // Create and display the Add Seed Dialog + m_addSeedDialog.reset(new AddSeedDialog(this, enabledPlatforms, platformSpecificCachePath)); + auto dialogResponse = m_addSeedDialog->exec(); + if (dialogResponse == QDialog::DialogCode::Rejected) + { + // User canceled the operation + return; + } + + // Set the data in the model + m_fileTableModel->AddSeed(m_selectedFileTableIndex, m_addSeedDialog->GetFileName(), m_addSeedDialog->GetPlatformFlags()); + } + + void SeedTabWidget::OnRemoveSeedButtonPressed() + { + if (!m_selectedFileTableIndex.isValid()) + { + AZ_Error(AssetBundler::AppWindowName, false, "Cannot perform Remove Seed operation: No Seed List File is selected"); + return; + } + + // Set the data in the model + QModelIndex currentSeedIndex = m_seedListContentsFilterModel->mapToSource(m_ui->seedFileContentsTable->selectionModel()->currentIndex()); + m_fileTableModel->RemoveSeed(m_selectedFileTableIndex, currentSeedIndex); + } + + void SeedTabWidget::OnSeedListContentsTableContextMenuRequested(const QPoint& pos) + { + if (!m_selectedFileTableIndex.isValid()) + { + return; + } + + QMenu* contextMenu = new QMenu(this); + contextMenu->setToolTipsVisible(true); + + QAction* action = contextMenu->addAction(tr("Edit Platforms")); + connect(action, &QAction::triggered, this, &SeedTabWidget::OnEditSeedButtonPressed); + action->setToolTip(tr("Change what platforms are referenced when generating an Asset List file.")); + + contextMenu->addSeparator(); + + action = contextMenu->addAction(tr("Add Seed")); + connect(action, &QAction::triggered, this, &SeedTabWidget::OnAddSeedButtonPressed); + action->setToolTip(tr("Add a new Seed to the Seed List file.")); + + action = contextMenu->addAction(tr("Remove Seed")); + connect(action, &QAction::triggered, this, &SeedTabWidget::OnRemoveSeedButtonPressed); + action->setToolTip(tr("Removes the Seed from the Seed List file.")); + + contextMenu->exec(m_ui->seedFileContentsTable->mapToGlobal(pos)); + delete contextMenu; + } + +} //namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/ui/SeedTabWidget.h b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.h new file mode 100644 index 0000000000..c1383cdd08 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.h @@ -0,0 +1,129 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#endif + +namespace Ui +{ + class SeedTabWidget; +} + +class QFileSystemModel; +class QStringListModel; + +namespace AssetBundler +{ + class GUIApplicationManager; + + class SeedListFileTableModel; + class SeedListTableModel; + + class NewFileDialog; + class EditSeedDialog; + class AddSeedDialog; + + class SeedTabWidget + : public AssetBundlerTabWidget + , public AZ::Debug::TraceMessageBus::Handler + { + Q_OBJECT + + public: + explicit SeedTabWidget(QWidget* parent, GUIApplicationManager* guiApplicationManager, const QString& assetBundlingDirectory); + virtual ~SeedTabWidget(); + + QString GetTabTitle() override { return tr("Seeds"); } + + QString GetFileTypeDisplayName() override { return tr("Seed List file"); } + + AssetBundlingFileType GetFileType() override { return AssetBundlingFileType::SeedListFileType; } + + bool HasUnsavedChanges() override; + + void Reload() override; + + bool SaveCurrentSelection() override; + + bool SaveAll() override; + + void SetModelDataSource() override; + + AzQtComponents::TableView* GetFileTableView() override; + + QModelIndex GetSelectedFileTableIndex() override; + + AssetBundlerAbstractFileTableModel* GetFileTableModel() override; + + void SetActiveProjectLabel(const QString& labelText) override; + + void ApplyConfig() override; + + void FileSelectionChanged(const QItemSelection& /*selected*/ = QItemSelection(), const QItemSelection& /*deselected*/ = QItemSelection()) override; + + void UncheckSelectDefaultSeedListsCheckBox(); + + void SetGenerateAssetListsButtonEnabled(bool isEnabled); + + ///////////////////////////////////////////////////////// + // TraceMessageBus overrides + bool OnPreError(const char* window, const char* fileName, int line, const char* func, const char* message) override; + bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override; + ///////////////////////////////////////////////////////// + + private: + + void OnNewFileButtonPressed(); + + void OnSelectDefaultSeedListsCheckBoxChanged(); + + void OnGenerateAssetListsButtonPressed(); + + void OnEditSeedButtonPressed(); + void OnEditAllButtonPressed(); + + void OnAddSeedButtonPressed(); + void OnRemoveSeedButtonPressed(); + + void OnSeedListContentsTableContextMenuRequested(const QPoint& pos); + + QSharedPointer m_ui; + QDir m_assetBundlingFolder; + + QSharedPointer m_fileTableModel; + QModelIndex m_selectedFileTableIndex; + + QSharedPointer m_generateAssetListsDialog; + + QSharedPointer m_seedListContentsFilterModel; + QSharedPointer m_seedListContentsModel; + + QSharedPointer m_editSeedDialog; + QSharedPointer m_addSeedDialog; + + bool m_hasWarnings = false; + }; +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/ui/SeedTabWidget.ui b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.ui new file mode 100644 index 0000000000..b32072696f --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/SeedTabWidget.ui @@ -0,0 +1,297 @@ + + + SeedTabWidget + + + + 0 + 0 + 813 + 673 + + + + Seed Tab Widget + + + + + + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Generate Asset Lists + + + true + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Seed List files + + + + + + + + + + Filter by file name + + + + + + + 5 + + + 5 + + + + + + Create new Seed List file + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Default Seed Lists + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Product Assets + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 5 + + + + + Filter by file name + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Edit All + + + + + + + + Add Asset + + + + + + + + + + + + + + + + + + AzQtComponents::TableView + QTreeView +
AzQtComponents/Components/Widgets/TableView.h
+ 1 +
+ + AzQtComponents::FilteredSearchWidget + QTreeView +
AzQtComponents/Components/FilteredSearchWidget.h
+ 1 +
+
+ + +
diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundler-Icon-256x256@x2.ico b/Code/Tools/AssetBundler/source/ui/style/AssetBundler-Icon-256x256@x2.ico new file mode 100644 index 0000000000..ffbf974130 --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundler-Icon-256x256@x2.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:690a47a0e2ff4c41ce23ad0bc5dd5bd525e03676a26d3367726beaa96babf207 +size 138199 diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qrc b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qrc new file mode 100644 index 0000000000..65ad7f11cd --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qrc @@ -0,0 +1,7 @@ + + + AssetBundler.qss + AssetBundlerConfig.ini + AssetBundler-Icon-256x256@x2.ico + + \ No newline at end of file diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qss b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qss new file mode 100644 index 0000000000..8603bbbb1b --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundler.qss @@ -0,0 +1,173 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +/************** General (MainWindow) **************/ + +QTabWidget:pane { + border: none; +} + +QLabel#activeProjectLabel { + font-size: 18px; + font-family: "Amazon Ember Light"; + margin-bottom: 5px; +} + +QTreeView#logTableView { + border: 1px solid #1B1B1B; + margin-left: 10px; + margin-right: 10px; + margin-bottom: 10px; +} + +QTreeView#logTableView QHeaderView::section { + background-color: #1B1B1B; +} + +/************** General (Tabs) **************/ + +QFrame#fileTableFrame, +QFrame#fileContentsFrame { + border: 1px solid #1B1B1B; +} + +QFrame#fileTableFrame { + margin-right: 10px; +} + +QFrame#fileTableHeaderFrame, +QFrame#fileContentsHeaderFrame, +QFrame#fileTableHeaderFrame QLabel, +QFrame#fileContentsHeaderFrame QLabel{ + background-color: #1B1B1B; +} + +QFrame#fileTableHeaderFrame QLabel, +QFrame#fileContentsHeaderFrame QLabel{ + background-color: #1B1B1B; + margin-left: 5px; +} + +QTabWidget QTreeView QHeaderView::section { + background-color: rgb(77, 77, 77); +} + +QWidget#PlatformSelectionWidget QLabel#platformSelectionLabel { + margin-right: 10px; +} + +QDialog#NewFileDialog QPushButton#browseFileButton, +QDialog#NewFileDialog QPushButton#createFileButton, +QDialog#NewFileDialog QPushButton#cancelButton { + margin-left: 10px; + margin-right: 10px; +} + +/************** Seeds Tab **************/ + +QWidget#SeedTabWidget QPushButton#generateAssetListsButton, +QWidget#SeedTabWidget QPushButton#browseFileButton, +QWidget#SeedTabWidget QPushButton#cancelButton, +QWidget#SeedTabWidget QPushButton#addSeedButton, +QWidget#SeedTabWidget QPushButton#applyChangesButton { + margin-left: 10px; + margin-right: 10px; +} + +QCheckBox#selectDefaultSeedListsCheckBox { + margin: 5px; +} + +QWidget#seedListContentsFilteredSearchWidget { + margin-left: 5px; +} + +QDialog QFrame#inputValuesFrame { + border: none; + margin: 10px; + padding: 10px; +} + +QDialog QFrame#lineFrame { + border: none; + margin-top: 10px; + margin-bottom: 10px; +} + +QDialog QFrame#inputValuesFrame, +QDialog QFrame#lineFrame, +QDialog#AddSeedDialog QLabel, +QDialog#AddSeedDialog QCheckBox, +QDialog#EditSeedDialog QLabel, +QDialog#EditSeedDialog QCheckBox, +QDialog#NewFileDialog QLabel, +QDialog#NewFileDialog QCheckBox { + background-color: #555555; +} + +/************** Asset List Tab **************/ + +QLabel#assetListContentsLabel { + margin-right: 10px; +} + +QWidget#fileFilteredSearchWidget, +QWidget#assetListContentsFilteredSearchWidget { + margin-left: 5px; + margin-right: 5px; +} + +QPushButton#generateBundleButton { + margin-left: 10px; + margin-right: 10px; +} + +/************** Generate Bundles Modal **************/ + +QFrame#bundleSettingsFrame { + border: none; + margin-bottom: 10px; +} + +QFrame#outputBundleLocationFrame, +QFrame#bundleSettingsFileFrame { + border: none; + margin: 10px; +} + +QFrame#bundleSettingsFrame, +QFrame#outputBundleLocationFrame, +QFrame#bundleSettingsFileFrame, +QFrame#bundleSettingsFrame QLabel { + background-color: #555555; +} + +QWidget#GenerateBundlesModal QPushButton { + margin-left: 10px; + margin-right: 10px; +} + +/************** Rules Tab **************/ + +QPushButton#runRuleButton, +QPushButton#addComparisonStepButton { + margin-left: 10px; + margin-right: 10px; +} + +QScrollArea#comparisonDataList { + border: none; +} + +QFrame#comparisonDataFrame { + padding: 10px; +} diff --git a/Code/Tools/AssetBundler/source/ui/style/AssetBundlerConfig.ini b/Code/Tools/AssetBundler/source/ui/style/AssetBundlerConfig.ini new file mode 100644 index 0000000000..876ceea40e --- /dev/null +++ b/Code/Tools/AssetBundler/source/ui/style/AssetBundlerConfig.ini @@ -0,0 +1,19 @@ +[ErrorLogDetails] +LogTypeColumnWidth=180 +LogSourceColumnWidth=130 + +[GeneralFileTableDetails] +FileTableWidth=450 +FileNameColumnWidth=250 + +[SeedsTabDetails] +CheckBoxColumnWidth=22 +SeedListFileNameColumnWidth=150 +ProjectNameColumnWidth=120 +SeedListContentsNameColumnWidth=400 + +[AssetListsTabDetails] +AssetListFileNameColumnWidth=210 +AssetListPlatformColumnWidth=70 +ProductAssetNameColumnWidth=220 +ProductAssetRelativePathColumnWidth=300 \ No newline at end of file diff --git a/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp new file mode 100644 index 0000000000..d278b9bd2c --- /dev/null +++ b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.cpp @@ -0,0 +1,386 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +// Forward declare platform-specific functions +namespace Platform +{ + /// On Windows this will return the setting for our custom title bar + /// On other platforms this will return the setting for using platform default + /// This ensures that functions like Exit, Maximize, and Minimize appear in the right platform-specific style + AzQtComponents::WindowDecorationWrapper::Option GetWindowDecorationWrapperOption(); +} // namespace Platform + +const char AssetBundlingFolderName [] = "AssetBundling"; +const char SeedListsFolderName [] = "SeedLists"; +const char AssetListsFolderName [] = "AssetLists"; +const char RulesFolderName[] = "Rules"; +const char BundleSettingsFolderName [] = "BundleSettings"; +const char BundlesFolderName [] = "Bundles"; + +namespace AssetBundler +{ + + GUIApplicationManager::Config GUIApplicationManager::loadConfig(QSettings& settings) + { + using namespace AzQtComponents; + + Config config = defaultConfig(); + + // Error Log + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("ErrorLogDetails")); + ConfigHelpers::read(settings, QStringLiteral("LogTypeColumnWidth"), config.logTypeColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("LogSourceColumnWidth"), config.logSourceColumnWidth); + } + + // General File Tables + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("GeneralFileTableDetails")); + ConfigHelpers::read(settings, QStringLiteral("FileTableWidth"), config.fileTableWidth); + ConfigHelpers::read(settings, QStringLiteral("FileNameColumnWidth"), config.fileNameColumnWidth); + } + + // Seeds Tab + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("SeedsTabDetails")); + ConfigHelpers::read(settings, QStringLiteral("CheckBoxColumnWidth"), config.checkBoxColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("SeedListFileNameColumnWidth"), config.seedListFileNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("ProjectNameColumnWidth"), config.projectNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("SeedListContentsNameColumnWidth"), config.seedListContentsNameColumnWidth); + } + + // Asset Lists Tab + { + ConfigHelpers::GroupGuard details(&settings, QStringLiteral("AssetListsTabDetails")); + ConfigHelpers::read(settings, QStringLiteral("AssetListFileNameColumnWidth"), config.assetListFileNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("AssetListPlatformColumnWidth"), config.assetListPlatformColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("ProductAssetNameColumnWidth"), config.productAssetNameColumnWidth); + ConfigHelpers::read(settings, QStringLiteral("ProductAssetRelativePathColumnWidth"), config.productAssetRelativePathColumnWidth); + } + + return config; + } + + GUIApplicationManager::Config GUIApplicationManager::defaultConfig() + { + // These are used if the values can't be read from AssetBundlerConfig.ini. + Config config; + + config.logTypeColumnWidth = 150; + config.logSourceColumnWidth = 150; + + config.fileTableWidth = 250; + config.fileNameColumnWidth = 150; + + config.checkBoxColumnWidth = 150; + config.seedListFileNameColumnWidth = 150; + config.projectNameColumnWidth = 150; + config.seedListContentsNameColumnWidth = 150; + + config.assetListFileNameColumnWidth = 150; + config.assetListPlatformColumnWidth = 150; + config.productAssetNameColumnWidth = 150; + config.productAssetRelativePathColumnWidth = 150; + + return config; + } + + GUIApplicationManager::GUIApplicationManager(int* argc, char*** argv, QObject* parent) + : ApplicationManager(argc, argv, parent) + { + } + + GUIApplicationManager::~GUIApplicationManager() + { + // Reset this before DestroyApplication, BusDisconnect needs to happen before Application::Stop() destroys the allocators. + m_platformCatalogManager.reset(); + } + + bool GUIApplicationManager::Init() + { + m_isInitializing = true; + // Initialize Asset Bundler Batch + ApplicationManager::Init(); + + AZ::IO::FixedMaxPath engineRoot = GetEngineRoot(); + + if (engineRoot.empty()) + { + // Error has already been thrown + return false; + } + + // Determine the name of the current project + auto projectOutcome = AssetBundler::GetCurrentProjectName(); + if (!projectOutcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, projectOutcome.GetError().c_str()); + return false; + } + m_currentProjectName = projectOutcome.GetValue(); + + // Set up paths to the Project folder, Project Cache folder, and determine enabled platforms + auto pathOutcome = InitializePaths(); + if (!pathOutcome.IsSuccess()) + { + AZ_Error("AssetBundler", false, pathOutcome.GetError().c_str()); + return false; + } + + // Set up platform-specific Asset Catalogs + m_platformCatalogManager = AZStd::make_unique(); + + // Define some application-level settings + QApplication::setOrganizationName("Amazon"); + QApplication::setOrganizationDomain("amazon.com"); + QApplication::setApplicationName("Asset Bundler"); + + QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates)); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + + m_isInitializing = false; + + // Create the actual Qt Application + m_qApp.reset(new QApplication(*GetArgC(), *GetArgV())); + + // Create the Main Window + m_mainWindow.reset(new MainWindow(this)); + + return true; + } + + bool GUIApplicationManager::Run() + { + // Set up the Style Manager + AzQtComponents::StyleManager styleManager(qApp); + styleManager.initialize(qApp, GetEngineRoot()); + + AZ::IO::FixedMaxPath engineRoot(GetEngineRoot()); + QDir engineRootDir(engineRoot.c_str()); + AzQtComponents::StyleManager::addSearchPaths( + QStringLiteral("style"), + engineRootDir.filePath(QStringLiteral("Code/Tools/AssetBundler/source/ui/style")), + QStringLiteral(":/AssetBundler/style"), + engineRoot); + AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:AssetBundler.qss")); + + AzQtComponents::ConfigHelpers::loadConfig(&m_fileWatcher, &m_config, QStringLiteral("style:AssetBundlerConfig.ini"), this, std::bind(&GUIApplicationManager::ApplyConfig, this)); + ApplyConfig(); + + qApp->setWindowIcon(QIcon("style:AssetBundler-Icon-256x256@x2.ico")); + + // Set up the Main Window + auto wrapper = new AzQtComponents::WindowDecorationWrapper(Platform::GetWindowDecorationWrapperOption()); + wrapper->setGuest(m_mainWindow.data()); + m_mainWindow->Activate(); + wrapper->show(); + m_mainWindow->show(); + + qApp->setQuitOnLastWindowClosed(true); + + // Run the application + return qApp->exec(); + } + + void GUIApplicationManager::AddWatchedPath(const QString& folderPath) + { + m_fileWatcher.addPath(folderPath); + } + + void GUIApplicationManager::AddWatchedPaths(const QSet& folderPaths) + { + m_fileWatcher.addPaths(folderPaths.values()); + } + + void GUIApplicationManager::RemoveWatchedPath(const QString& path) + { + m_fileWatcher.removePath(path); + } + + void GUIApplicationManager::RemoveWatchedPaths(const QSet& paths) + { + // Check whether the list is empty to get rid of the warning from Qt + if (paths.isEmpty()) + { + return; + } + + m_fileWatcher.removePaths(paths.values()); + } + + bool GUIApplicationManager::OnPreError(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) + { + // We want to display errors during initialization, then let the MainWindow handle errors during runtime + if (m_isInitializing) + { + // These are fatal initialization errors, and the application will shut down after the user closes the message box + m_qApp.reset(new QApplication(*GetArgC(), *GetArgV())); + QMessageBox errorMessageBox; + errorMessageBox.setWindowTitle("Asset Bundler"); + errorMessageBox.setText(message); + errorMessageBox.setStandardButtons(QMessageBox::Ok); + errorMessageBox.setDefaultButton(QMessageBox::Ok); + errorMessageBox.exec(); + + return true; + } + + return false; + } + + bool GUIApplicationManager::OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) + { + // Don't handle warnings, let the MainWindow print them + return false; + } + + + bool GUIApplicationManager::OnPrintf(const char* /*window*/, const char* /*message*/) + { + // This is disabled during initialization to prevent a lot of message spam printed to the CLI that gets generated on setup + return m_isInitializing; + } + + AZ::Outcome GUIApplicationManager::InitializePaths() + { + // Calculate the path to the Cache for the current project + auto pathOutcome = AssetBundler::GetProjectCacheFolderPath(); + if (!pathOutcome.IsSuccess()) + { + return AZ::Failure(pathOutcome.GetError()); + } + + m_currentProjectCacheFolder = pathOutcome.GetValue().String(); + + // Calculate the path to the current project folder + pathOutcome = AssetBundler::GetProjectFolderPath(); + if (!pathOutcome.IsSuccess()) + { + return AZ::Failure(pathOutcome.GetError()); + } + + m_currentProjectFolder = pathOutcome.GetValue().String(); + + // Generate the AssetBundling folder inside the current project + AzFramework::StringFunc::Path::ConstructFull(m_currentProjectFolder.c_str(), AssetBundlingFolderName, m_assetBundlingFolder); + + // Seed Lists folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), SeedListsFolderName, m_seedListsFolder); + AZ::Outcome createPathOutcome = AssetBundler::MakePath(m_seedListsFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Asset Lists folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), AssetListsFolderName, m_assetListsFolder); + createPathOutcome = AssetBundler::MakePath(m_assetListsFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Rules folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), RulesFolderName, m_rulesFolder); + createPathOutcome = AssetBundler::MakePath(m_rulesFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Bundle Settings Folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), BundleSettingsFolderName, m_bundleSettingsFolder); + createPathOutcome = AssetBundler::MakePath(m_bundleSettingsFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Bundles Folder + AzFramework::StringFunc::Path::ConstructFull(m_assetBundlingFolder.c_str(), BundlesFolderName, m_bundlesFolder); + createPathOutcome = AssetBundler::MakePath(m_bundlesFolder); + if (!createPathOutcome.IsSuccess()) + { + return createPathOutcome; + } + + // Determine the enabled platforms + const char* appRoot = nullptr; + AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot); + m_enabledPlatforms = GetEnabledPlatformFlags(GetEngineRoot(), appRoot, AZ::Utils::GetProjectPath().c_str()); + + // Determine which Gems are enabled for the current project + if (!AzFramework::GetGemsInfo(m_gemInfoList, *m_settingsRegistry)) + { + return AZ::Failure(AZStd::string::format("Failed to read Gems for project: %s\n", m_currentProjectName.c_str())); + } + + QObject::connect(&m_fileWatcher, &QFileSystemWatcher::directoryChanged, this, &GUIApplicationManager::DirectoryChanged); + QObject::connect(&m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &GUIApplicationManager::FileChanged); + + return AZ::Success(); + } + + void GUIApplicationManager::DirectoryChanged(const QString& directory) + { + UpdateTab(directory.toUtf8().data()); + } + + void GUIApplicationManager::FileChanged(const QString& path) + { + // FileChanged will only be called when engine or gem seed files are updated + // Otherwilse DirectoryChanged should be triggered + AZStd::string extension; + AzFramework::StringFunc::Path::GetExtension(path.toUtf8().data(), extension); + extension = extension.starts_with(".") ? extension.substr(1) : extension; + if (extension == AzToolsFramework::AssetSeedManager::GetSeedFileExtension()) + { + UpdateTab(GetSeedListsFolder()); + } + + // Many applications save an open file by writing a new file and then deleting the old one + // Add the file path back if it has been removed from the watcher file list + if (!m_fileWatcher.files().contains(path)) + { + m_fileWatcher.addPath(path); + } + } + + void GUIApplicationManager::ApplyConfig() + { + m_mainWindow->ApplyConfig(); + } + +} // namespace AssetBundler + +#include diff --git a/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.h b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.h new file mode 100644 index 0000000000..e81607d4a8 --- /dev/null +++ b/Code/Tools/AssetBundler/source/utils/GUIApplicationManager.h @@ -0,0 +1,164 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#endif + +namespace AssetBundler +{ + enum AssetBundlingFileType : int + { + SeedListFileType = 0, + AssetListFileType, + BundleSettingsFileType, + BundleFileType, + RulesFileType, + NumBundlingFileTypes + }; + + class MainWindow; + + class GUIApplicationManager + : public ApplicationManager + { + Q_OBJECT + + public: + + struct Config + { + // These default values are used if the values can't be read from AssetBundlerConfig.ini, + // and the call to defaultConfig fails. + + // Error Log + int logTypeColumnWidth = -1; + int logSourceColumnWidth = -1; + + // General File Tables + int fileTableWidth = -1; + int fileNameColumnWidth = -1; + + // Seeds Tab + int checkBoxColumnWidth = -1; + int seedListFileNameColumnWidth = -1; + int projectNameColumnWidth = -1; + int seedListContentsNameColumnWidth = -1; + + // Asset Lists Tab + int assetListFileNameColumnWidth = -1; + int assetListPlatformColumnWidth = -1; + int productAssetNameColumnWidth = -1; + int productAssetRelativePathColumnWidth = -1; + }; + + /*! + * Loads the button config data from a settings object. + */ + static Config loadConfig(QSettings& settings); + + /*! + * Returns default button config data. + */ + static Config defaultConfig(); + + explicit GUIApplicationManager(int* argc, char*** argv, QObject* parent = 0); + virtual ~GUIApplicationManager(); + + bool Init() override; + + bool Run() override; + + AZStd::string GetCurrentProjectFolder() { return m_currentProjectFolder; } + AZStd::string GetAssetBundlingFolder() { return m_assetBundlingFolder; } + AZStd::string GetSeedListsFolder() { return m_seedListsFolder; } + AZStd::string GetAssetListsFolder() { return m_assetListsFolder; } + AZStd::string GetRulesFolder() { return m_rulesFolder; } + AZStd::string GetBundleSettingsFolder() { return m_bundleSettingsFolder; } + AZStd::string GetBundlesFolder() { return m_bundlesFolder; } + AZStd::string GetCurrentProjectCacheFolder() { return m_currentProjectCacheFolder; } + + AzFramework::PlatformFlags GetEnabledPlatforms() { return m_enabledPlatforms; } + + void AddWatchedPath(const QString& path); + void AddWatchedPaths(const QSet& paths); + void RemoveWatchedPath(const QString& path); + void RemoveWatchedPaths(const QSet& paths); + + //////////////////////////////////////////////////////////////////////////////////////////// + // Override the ApplicationManager TraceMessageBus methods so that messages go through MainWindow and not the CLI + + bool OnPreError(const char* window, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* message) override; + bool OnPreWarning(const char* /*window*/, const char* /*fileName*/, int /*line*/, const char* /*func*/, const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + //////////////////////////////////////////////////////////////////////////////////////////// + + const Config& GetConfig() { return m_config; } + + Q_SIGNALS: + void ShowWindow(); + void UpdateTab(const AZStd::string& directory); + void UpdateFiles(AssetBundlingFileType fileType, const AZStd::vector& absoluteFilePaths); + + protected Q_SLOTS: + void DirectoryChanged(const QString& directory); + void FileChanged(const QString& path); + void ApplyConfig(); + + private: + /** + * Generates directory information for all paths used in this tool + * @return void on success, error message on failure + */ + AZ::Outcome InitializePaths(); + + QSharedPointer m_qApp; + + Config m_config; + + QSharedPointer m_mainWindow; + + AZStd::string m_currentProjectFolder; + AZStd::string m_assetBundlingFolder; + AZStd::string m_seedListsFolder; + AZStd::string m_assetListsFolder; + AZStd::string m_rulesFolder; + AZStd::string m_bundleSettingsFolder; + AZStd::string m_bundlesFolder; + AZStd::string m_currentProjectCacheFolder; + + AzFramework::PlatformFlags m_enabledPlatforms = AzFramework::PlatformFlags::Platform_NONE; + + AZStd::unique_ptr m_platformCatalogManager; + + bool m_isInitializing = false; + + QFileSystemWatcher m_fileWatcher; + }; + +} // namespace AssetBundler diff --git a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp index bb4fee2ceb..ccf5427771 100644 --- a/Code/Tools/AssetBundler/source/utils/applicationManager.cpp +++ b/Code/Tools/AssetBundler/source/utils/applicationManager.cpp @@ -45,8 +45,9 @@ namespace AssetBundler { const char compareVariablePrefix = '$'; - ApplicationManager::ApplicationManager(int* argc, char*** argv) - : AzToolsFramework::ToolsApplication(argc, argv) + ApplicationManager::ApplicationManager(int* argc, char*** argv, QObject* parent) + : QObject(parent) + , AzToolsFramework::ToolsApplication(argc, argv) { } @@ -55,7 +56,7 @@ namespace AssetBundler DestroyApplication(); } - void ApplicationManager::Init() + bool ApplicationManager::Init() { AZ::Debug::TraceMessageBus::Handler::BusConnect(); Start(AzFramework::Application::Descriptor()); @@ -74,6 +75,7 @@ namespace AssetBundler // There is no need to update the UserSettings file, so we can avoid a race condition by disabling save on shutdown AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + return true; } void ApplicationManager::DestroyApplication() @@ -372,6 +374,13 @@ namespace AssetBundler { using namespace AzToolsFramework; + auto validateArgsOutcome = ValidateInputArgs(parser, m_allSeedsArgs); + if (!validateArgsOutcome.IsSuccess()) + { + OutputHelpSeeds(); + return AZ::Failure(validateArgsOutcome.TakeError()); + } + SeedsParams params; params.m_ignoreFileCase = parser->HasSwitch(IgnoreFileCaseFlag); @@ -462,6 +471,13 @@ namespace AssetBundler AZ::Outcome ApplicationManager::ParseAssetListsCommandData(const AZ::CommandLine* parser) { + auto validateArgsOutcome = ValidateInputArgs(parser, m_allAssetListsArgs); + if (!validateArgsOutcome.IsSuccess()) + { + OutputHelpAssetLists(); + return AZ::Failure(validateArgsOutcome.TakeError()); + } + AssetListsParams params; // Read in Platform arg @@ -525,6 +541,13 @@ namespace AssetBundler AZ::Outcome ApplicationManager::ParseComparisonRulesCommandData(const AZ::CommandLine* parser) { + auto validateArgsOutcome = ValidateInputArgs(parser, m_allComparisonRulesArgs); + if (!validateArgsOutcome.IsSuccess()) + { + OutputHelpComparisonRules(); + return AZ::Failure(validateArgsOutcome.TakeError()); + } + ScopedTraceHandler traceHandler; ComparisonRulesParams params; @@ -907,6 +930,13 @@ namespace AssetBundler AZ::Outcome ApplicationManager::ParseCompareCommandData(const AZ::CommandLine* parser) { + auto validateArgsOutcome = ValidateInputArgs(parser, m_allCompareArgs); + if (!validateArgsOutcome.IsSuccess()) + { + OutputHelpCompare(); + return AZ::Failure(validateArgsOutcome.TakeError()); + } + ComparisonParams params; // Read in Platform arg @@ -998,6 +1028,13 @@ namespace AssetBundler AZ::Outcome ApplicationManager::ParseBundleSettingsCommandData(const AZ::CommandLine* parser) { + auto validateArgsOutcome = ValidateInputArgs(parser, m_allBundleSettingsArgs); + if (!validateArgsOutcome.IsSuccess()) + { + OutputHelpBundleSettings(); + return AZ::Failure(validateArgsOutcome.TakeError()); + } + BundleSettingsParams params; // Read in Platform arg @@ -1202,6 +1239,13 @@ namespace AssetBundler AZ::Outcome ApplicationManager::ParseBundlesCommandData(const AZ::CommandLine* parser) { + auto validateArgsOutcome = ValidateInputArgs(parser, m_allBundlesArgs); + if (!validateArgsOutcome.IsSuccess()) + { + OutputHelpBundles(); + return AZ::Failure(validateArgsOutcome.TakeError()); + } + auto parseSettingsOutcome = ParseBundleSettingsAndOverrides(parser, BundlesCommand); if (!parseSettingsOutcome.IsSuccess()) { @@ -1213,6 +1257,14 @@ namespace AssetBundler AZ::Outcome ApplicationManager::ParseBundleSeedCommandData(const AZ::CommandLine* parser) { + + auto validateArgsOutcome = ValidateInputArgs(parser, m_allBundleSeedArgs); + if (!validateArgsOutcome.IsSuccess()) + { + OutputHelpBundleSeed(); + return AZ::Failure(validateArgsOutcome.TakeError()); + } + BundleSeedParams params; params.m_addSeedList = GetAddSeedArgList(parser); @@ -1230,6 +1282,12 @@ namespace AssetBundler AZ::Outcome ApplicationManager::ValidateInputArgs(const AZ::CommandLine* parser, const AZStd::vector& validArgList) { + constexpr AZStd::string_view ApplicationArgList = "/O3DE/AzCore/Application/ValidCommandOptions"; + AZStd::vector validApplicationArgs; + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + settingsRegistry->GetObject(validApplicationArgs, ApplicationArgList); + } for (const auto& paramInfo : *parser) { // Skip positional arguments @@ -1247,10 +1305,18 @@ namespace AssetBundler break; } } + for (const auto& validArg : validApplicationArgs) + { + if (AZ::StringFunc::Equal(paramInfo.m_option, validArg)) + { + isValidArg = true; + break; + } + } if (!isValidArg) { - return AZ::Failure(AZStd::string::format("Unknown argument: \"--%s\" is not an unknown argument for this sub-command.", paramInfo.m_option.c_str())); + return AZ::Failure(AZStd::string::format(R"(Invalid argument: "--%s" is not a valid argument for this sub-command.)", paramInfo.m_option.c_str())); } } @@ -1335,10 +1401,10 @@ namespace AssetBundler } // If no platform was specified, defaulting to platforms specified in the asset processor config files - const char* appRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(appRoot, &AzFramework::ApplicationRequests::GetAppRoot); - - AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags(GetEngineRoot(), appRoot, AZ::Utils::GetProjectPath().c_str()); + AzFramework::PlatformFlags platformFlags = GetEnabledPlatformFlags( + AZStd::string_view{ AZ::Utils::GetEnginePath() }, + AZStd::string_view{ AZ::Utils::GetEnginePath() }, + AZStd::string_view{ AZ::Utils::GetProjectPath() }); auto platformsString = AzFramework::PlatformHelper::GetCommaSeparatedPlatformList(platformFlags); AZ_TracePrintf(AppWindowName, "No platform specified, defaulting to platforms ( %s ).\n", platformsString.c_str()); @@ -1522,7 +1588,7 @@ namespace AssetBundler } } - AZStd::vector defaultSeeds = GetDefaultSeeds(GetEngineRoot(), AZ::Utils::GetProjectPath(), m_currentProjectName); + AZStd::vector defaultSeeds = GetDefaultSeeds(AZ::Utils::GetProjectPath(), m_currentProjectName); if (defaultSeeds.empty()) { // Error has already been thrown @@ -2847,3 +2913,4 @@ namespace AssetBundler return !m_showVerboseOutput; } } // namespace AssetBundler +#include diff --git a/Code/Tools/AssetBundler/source/utils/applicationManager.h b/Code/Tools/AssetBundler/source/utils/applicationManager.h index 01f180a77a..d49707f489 100644 --- a/Code/Tools/AssetBundler/source/utils/applicationManager.h +++ b/Code/Tools/AssetBundler/source/utils/applicationManager.h @@ -11,6 +11,7 @@ */ #pragma once +#if !defined(Q_MOC_RUN) #include #include #include @@ -22,7 +23,7 @@ #include #include #include - +#endif namespace AssetBundler { struct SeedsParams @@ -161,16 +162,18 @@ namespace AssetBundler }; class ApplicationManager - : public AZ::Debug::TraceMessageBus::Handler + : public QObject + , public AZ::Debug::TraceMessageBus::Handler , public AzToolsFramework::ToolsApplication { + Q_OBJECT public: - explicit ApplicationManager(int* argc, char*** argv); - ~ApplicationManager(); + explicit ApplicationManager(int* argc, char*** argv, QObject* parent = 0); + virtual ~ApplicationManager(); - void Init(); + virtual bool Init(); void DestroyApplication(); - bool Run(); + virtual bool Run(); //////////////////////////////////////////////////////////////////////////////////////////// // AzFramework::Application overrides diff --git a/Code/Tools/AssetBundler/source/utils/utils.cpp b/Code/Tools/AssetBundler/source/utils/utils.cpp index b1595f7dd8..39bc1a7e13 100644 --- a/Code/Tools/AssetBundler/source/utils/utils.cpp +++ b/Code/Tools/AssetBundler/source/utils/utils.cpp @@ -31,6 +31,7 @@ AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option") #include #include #include +#include AZ_POP_DISABLE_WARNING namespace AssetBundler @@ -108,15 +109,15 @@ namespace AssetBundler const char* AssetCatalogFilename = "assetcatalog.xml"; - - const char EngineDirectoryName[] = "Engine"; + + constexpr auto EngineDirectoryName = AZ::IO::FixedMaxPath("Assets") / "Engine"; const char RestrictedDirectoryName[] = "restricted"; const char PlatformsDirectoryName[] = "Platforms"; const char GemsDirectoryName[] = "Gems"; const char GemsAssetsDirectoryName[] = "Assets"; const char GemsSeedFileName[] = "seedList"; const char EngineSeedFileName[] = "SeedAssetList"; - + namespace Internal { @@ -128,7 +129,7 @@ namespace AssetBundler AZStd::unordered_map& defaultSeedLists, AzFramework::PlatformFlags platformFlags) { - AZ::IO::FixedMaxPath engineRoot(GetEngineRoot()); + AZ::IO::FixedMaxPath engineRoot(AZ::Utils::GetEnginePath()); AZ::IO::FixedMaxPath engineRestrictedRoot = engineRoot / RestrictedDirectoryName; AZ::IO::FixedMaxPath engineLocalPath = AZ::IO::PathView(engineDirectory.LexicallyRelative(engineRoot)); @@ -201,17 +202,6 @@ namespace AssetBundler } } - AZ::IO::FixedMaxPath GetEngineRoot() - { - AZ::IO::FixedMaxPath engineRootPath; - if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) - { - settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); - } - - return engineRootPath; - } - void AddPlatformIdentifier(AZStd::string& filePath, const AZStd::string& platformIdentifier) { AZStd::string fileName; @@ -259,11 +249,11 @@ namespace AssetBundler absoluteEngineSeedFilePath.ReplaceExtension(AzToolsFramework::AssetSeedManager::GetSeedFileExtension()); if (fileIO->Exists(absoluteEngineSeedFilePath.c_str())) { - defaultSeedLists[absoluteEngineSeedFilePath.Native()] = EngineDirectoryName; + defaultSeedLists[absoluteEngineSeedFilePath.Native()] = EngineDirectoryName.String(); } // Add Seed Lists from the Platforms directory - Internal::AddPlatformsDirectorySeeds(engineDirectory, EngineDirectoryName, defaultSeedLists, platformFlag); + Internal::AddPlatformsDirectorySeeds(engineDirectory, EngineDirectoryName.String(), defaultSeedLists, platformFlag); auto absoluteProjectDefaultSeedFilePath = AZ::IO::Path(projectPath) / EngineSeedFileName; absoluteProjectDefaultSeedFilePath.ReplaceExtension(AzToolsFramework::AssetSeedManager::GetSeedFileExtension()); @@ -276,11 +266,11 @@ namespace AssetBundler return defaultSeedLists; } - AZStd::vector GetDefaultSeeds(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName) + AZStd::vector GetDefaultSeeds(AZStd::string_view projectPath, AZStd::string_view projectName) { AZStd::vector defaultSeeds; - defaultSeeds.emplace_back(GetProjectDependenciesAssetPath(enginePath, projectPath, projectName)); + defaultSeeds.emplace_back(GetProjectDependenciesAssetPath(projectPath, projectName)); return defaultSeeds; } @@ -294,34 +284,12 @@ namespace AssetBundler return projectDependenciesFilePath.LexicallyNormal(); } - AZ::IO::Path GetProjectDependenciesFileTemplate(AZStd::string_view engineRoot) - { - AZ::IO::Path projectDependenciesFileTemplate = engineRoot; - projectDependenciesFileTemplate /= DefaultProjectTemplatePath; - projectDependenciesFileTemplate /= AZStd::string::format("%s%s", ProjectName, DependenciesFileSuffix); - projectDependenciesFileTemplate.ReplaceExtension(DependenciesFileExtension); - return projectDependenciesFileTemplate.LexicallyNormal(); - } - - AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName) + AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view projectPath, AZStd::string_view projectName) { AZ::IO::Path projectDependenciesFile = GetProjectDependenciesFile(projectPath, projectName); if (!AZ::IO::FileIOBase::GetInstance()->Exists(projectDependenciesFile.c_str())) { - AZ_TracePrintf(AssetBundler::AppWindowName, "Project dependencies file %s doesn't exist.\n", projectDependenciesFile.c_str()); - - AZ::IO::Path projectDependenciesFileTemplate = GetProjectDependenciesFileTemplate(enginePath); - if (AZ::IO::FileIOBase::GetInstance()->Copy(projectDependenciesFileTemplate.c_str(), projectDependenciesFile.c_str())) - { - AZ_TracePrintf(AssetBundler::AppWindowName, "Copied project dependencies file template %s to the current project.\n", - projectDependenciesFile.c_str()); - } - else - { - AZ_Error(AppWindowName, false, "Failed to copy project dependencies file template %s from default project" - " template to the current project.\n", projectDependenciesFileTemplate.c_str()); - return {}; - } + AZ_Error(AssetBundler::AppWindowName, false, "Project dependencies file %s doesn't exist.\n", projectDependenciesFile.c_str()); } // Turn the absolute path into a cache-relative path @@ -538,6 +506,14 @@ namespace AssetBundler return platformSpecificCacheFolderPath; } + AZStd::string GenerateKeyFromAbsolutePath(const AZStd::string& absoluteFilePath) + { + AZStd::string key(absoluteFilePath); + AzFramework::StringFunc::Path::Normalize(key); + AzFramework::StringFunc::Path::StripDrive(key); + return key; + } + void ConvertToRelativePath(AZStd::string_view parentFolderPath, AZStd::string& absoluteFilePath) { absoluteFilePath = AZ::IO::PathView(absoluteFilePath).LexicallyRelative(parentFolderPath).String(); @@ -822,4 +798,26 @@ namespace AssetBundler } return false; } + + QJsonObject ReadJson(const AZStd::string& filePath) + { + QByteArray byteArray; + QFile jsonFile; + jsonFile.setFileName(filePath.c_str()); + jsonFile.open(QIODevice::ReadOnly | QIODevice::Text); + byteArray = jsonFile.readAll(); + jsonFile.close(); + + return QJsonDocument::fromJson(byteArray).object(); + } + + void SaveJson(const AZStd::string& filePath, const QJsonObject& jsonObject) + { + QFile jsonFile(filePath.c_str()); + QJsonDocument JsonDocument; + JsonDocument.setObject(jsonObject); + jsonFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + jsonFile.write(JsonDocument.toJson()); + jsonFile.close(); + } } diff --git a/Code/Tools/AssetBundler/source/utils/utils.h b/Code/Tools/AssetBundler/source/utils/utils.h index db6729098a..454a279878 100644 --- a/Code/Tools/AssetBundler/source/utils/utils.h +++ b/Code/Tools/AssetBundler/source/utils/utils.h @@ -19,7 +19,9 @@ #include #include #include - +#include +#include +#include namespace AssetBundler { @@ -137,9 +139,6 @@ namespace AssetBundler bool OnPreWarning(const char* window, const char* fileName, int line, const char* func, const char* message) override; }; - // Returns the engine root - AZ::IO::FixedMaxPath GetEngineRoot(); - /** * Determines the name of the currently enabled game project * @return Current Project name on success, error message on failure @@ -192,6 +191,8 @@ namespace AssetBundler */ AZ::IO::Path GetPlatformSpecificCacheFolderPath(); + AZStd::string GenerateKeyFromAbsolutePath(const AZStd::string& absoluteFilePath); + void ConvertToRelativePath(AZStd::string_view parentFolderPath, AZStd::string& absoluteFilePath); AZ::Outcome MakePath(const AZStd::string& path); @@ -207,16 +208,13 @@ namespace AssetBundler const AZStd::vector& gemInfoList, AzFramework::PlatformFlags platformFlags); //! Returns a vector of relative paths to Assets that should be included as default Seeds, but are not already in a Seed List file. - AZStd::vector GetDefaultSeeds(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName); + AZStd::vector GetDefaultSeeds(AZStd::string_view projectPath, AZStd::string_view projectName); //! Returns the absolute path of {ProjectName}_Dependencies.xml AZ::IO::Path GetProjectDependenciesFile(AZStd::string_view productPath, AZStd::string_view projectName); - //! Returns the absolute path of the project dependencies file in the default project template - AZ::IO::Path GetProjectDependenciesFileTemplate(AZStd::string_view enginePath); - //! Creates the ProjectName_Dependencies.xml file if it does not exist, and adds returns the relative path to the asset in the Cache. - AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view enginePath, AZStd::string_view projectPath, AZStd::string_view projectName); + AZ::IO::Path GetProjectDependenciesAssetPath(AZStd::string_view projectPath, AZStd::string_view projectName); //! Returns the map from gem seed list file path to gem name AZStd::unordered_map GetGemSeedListFilePathToGemNameMap(const AZStd::vector& gemInfoList, AzFramework::PlatformFlags platformFlags); @@ -229,6 +227,9 @@ namespace AssetBundler //! Please note that the game project could be in a different location to the engine therefore we need the assetRoot param. AzFramework::PlatformFlags GetEnabledPlatformFlags(AZStd::string_view enginePath, AZStd::string_view assetRoot, AZStd::string_view projectPath); + QJsonObject ReadJson(const AZStd::string& filePath); + void SaveJson(const AZStd::string& filePath, const QJsonObject& jsonObject); + //! Filepath is a helper class that is used to find the absolute path of a file //! if the inputted file path is an absolute path than it does nothing //! if the inputted file path is a relative path than based on whether the user diff --git a/Code/Tools/AssetBundler/tests/Engine/SeedAssetList.seed b/Code/Tools/AssetBundler/tests/Assets/Engine/SeedAssetList.seed similarity index 100% rename from Code/Tools/AssetBundler/tests/Engine/SeedAssetList.seed rename to Code/Tools/AssetBundler/tests/Assets/Engine/SeedAssetList.seed diff --git a/Code/Tools/AssetBundler/tests/tests_main.cpp b/Code/Tools/AssetBundler/tests/tests_main.cpp index e1535bf0f5..9e12623b0d 100644 --- a/Code/Tools/AssetBundler/tests/tests_main.cpp +++ b/Code/Tools/AssetBundler/tests/tests_main.cpp @@ -88,7 +88,7 @@ namespace AssetBundler const char RelativeTestFolder[] = "Code/Tools/AssetBundler/tests"; const char GemsFolder[] = "Gems"; - const char EngineFolder[] = "Engine"; + constexpr auto EngineFolder = AZ::IO::FixedMaxPath("Assets") / "Engine"; const char PlatformsFolder[] = "Platforms"; const char DummyProjectFolder[] = "DummyProject"; @@ -113,14 +113,14 @@ namespace AssetBundler AZ::SettingsRegistry::Register(&m_registry); } - const char* engineRoot = nullptr; - AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot); - if (!engineRoot) + AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath(); + if (engineRoot.empty()) { GTEST_FATAL_FAILURE_(AZStd::string::format("Unable to locate engine root.\n").c_str()); } - AzFramework::StringFunc::Path::Join(engineRoot, RelativeTestFolder, m_data->m_testEngineRoot); + + m_data->m_testEngineRoot = (engineRoot / RelativeTestFolder).LexicallyNormal().String(); m_data->m_localFileIO = aznew AZ::IO::LocalFileIO(); m_data->m_priorFileIO = AZ::IO::FileIOBase::GetInstance(); @@ -132,8 +132,8 @@ namespace AssetBundler AddGemData(m_data->m_testEngineRoot.c_str(), "GemA"); AddGemData(m_data->m_testEngineRoot.c_str(), "GemB"); - AZStd::string absoluteEngineSeedFilePath; - AzFramework::StringFunc::Path::ConstructFull(m_data->m_testEngineRoot.c_str(), EngineFolder, "SeedAssetList", AzToolsFramework::AssetSeedManager::GetSeedFileExtension(), absoluteEngineSeedFilePath, true); + auto absoluteEngineSeedFilePath = m_data->m_testEngineRoot / EngineFolder / "SeedAssetList"; + absoluteEngineSeedFilePath.ReplaceExtension(AzToolsFramework::AssetSeedManager::GetSeedFileExtension()); m_data->m_gemSeedFilePairList.emplace_back(AZStd::make_pair(absoluteEngineSeedFilePath, true)); AddGemData(m_data->m_testEngineRoot.c_str(), "GemC", false); @@ -213,7 +213,7 @@ namespace AssetBundler AZStd::unique_ptr m_application = {}; AZ::IO::FileIOBase* m_priorFileIO = nullptr; AZ::IO::FileIOBase* m_localFileIO = nullptr; - AZStd::string m_testEngineRoot; + AZ::IO::Path m_testEngineRoot; }; const int GemAIndex = 0; diff --git a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake index e065f9a1a2..be1e85d370 100644 --- a/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake +++ b/Code/Tools/AssetProcessor/Platform/Mac/assetprocessor_mac.cmake @@ -9,13 +9,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_bundle_resources( - TARGET AssetProcessor - FILES - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/xmlfilter.txt - ${CMAKE_SOURCE_DIR}/Code/Tools/RC/Config/rc/rc.ini -) - # Set resources directory for app icons target_sources(AssetProcessor PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Platform/Mac/Images.xcassets) set_target_properties(AssetProcessor PROPERTIES diff --git a/Code/Tools/AssetProcessor/assetprocessor_gui_files.cmake b/Code/Tools/AssetProcessor/assetprocessor_gui_files.cmake index 79771a9d37..ab7a1e4a9f 100644 --- a/Code/Tools/AssetProcessor/assetprocessor_gui_files.cmake +++ b/Code/Tools/AssetProcessor/assetprocessor_gui_files.cmake @@ -31,7 +31,9 @@ set(FILES native/ui/GoToButton.h native/ui/GoToButton.cpp native/ui/GoToButton.ui - native/ui/MainWindow.h + native/ui/JobTreeViewItemDelegate.h + native/ui/JobTreeViewItemDelegate.cpp + native/ui/MainWindow.ui native/ui/MainWindow.cpp native/ui/MainWindow.ui native/ui/ProductAssetDetailsPanel.h diff --git a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.cpp b/Code/Tools/AssetProcessor/native/ui/JobTreeViewItemDelegate.cpp similarity index 58% rename from Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.cpp rename to Code/Tools/AssetProcessor/native/ui/JobTreeViewItemDelegate.cpp index 3c628d1b34..e0da06ad79 100644 --- a/Code/Sandbox/Editor/LensFlareEditor/LensFlareReferenceTree.cpp +++ b/Code/Tools/AssetProcessor/native/ui/JobTreeViewItemDelegate.cpp @@ -9,18 +9,17 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -// Original file Copyright Crytek GMBH or its affiliates, used under license. -#include "EditorDefs.h" -#include "LensFlareReferenceTree.h" +#include "JobTreeViewItemDelegate.h" -BEGIN_MESSAGE_MAP (CLensFlareReferenceTree, CXTTreeCtrl) -END_MESSAGE_MAP () - -CLensFlareReferenceTree::CLensFlareReferenceTree() +namespace AssetProcessor { + void JobTreeViewItemDelegate::initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const + { + AzQtComponents::TableViewItemDelegate::initStyleOption(option, index); + + option->features &= ~(QStyleOptionViewItem::WrapText); + } } -CLensFlareReferenceTree::~CLensFlareReferenceTree() -{ -} +#include diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/EditorMeshBus.h b/Code/Tools/AssetProcessor/native/ui/JobTreeViewItemDelegate.h similarity index 54% rename from Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/EditorMeshBus.h rename to Code/Tools/AssetProcessor/native/ui/JobTreeViewItemDelegate.h index 19cad8cd29..fbe45a3f75 100644 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/EditorMeshBus.h +++ b/Code/Tools/AssetProcessor/native/ui/JobTreeViewItemDelegate.h @@ -9,20 +9,24 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ + #pragma once -#include +#if !defined(Q_MOC_RUN) +#include +#endif -namespace LmbrCentral +namespace AssetProcessor { - class EditorMeshBusRequests : - public AZ::EBusTraits + class JobTreeViewItemDelegate + : public AzQtComponents::TableViewItemDelegate { - public: - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; + Q_OBJECT - virtual bool AddMeshComponentWithAssetId(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) = 0; + public: + using AzQtComponents::TableViewItemDelegate::TableViewItemDelegate; + + protected: + void initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const override; }; - using EditorMeshBus = AZ::EBus; -} +} // namespace AssetProcessor diff --git a/Code/Tools/AssetProcessor/native/ui/MainWindow.cpp b/Code/Tools/AssetProcessor/native/ui/MainWindow.cpp index 3a874a464c..79019ab8fc 100644 --- a/Code/Tools/AssetProcessor/native/ui/MainWindow.cpp +++ b/Code/Tools/AssetProcessor/native/ui/MainWindow.cpp @@ -32,6 +32,7 @@ #include #include "native/ui/ui_MainWindow.h" +#include "native/ui/JobTreeViewItemDelegate.h" #include "../utilities/GUIApplicationManager.h" @@ -221,6 +222,7 @@ void MainWindow::Activate() ui->jobTreeView->setModel(m_jobSortFilterProxy); ui->jobTreeView->setSortingEnabled(true); ui->jobTreeView->header()->setDefaultAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + ui->jobTreeView->setItemDelegate(new AssetProcessor::JobTreeViewItemDelegate(ui->jobTreeView)); ui->jobTreeView->setToolTip(tr("Click to view Job Log")); diff --git a/Code/Tools/AssetProcessor/native/utilities/MissingDependencyScanner.cpp b/Code/Tools/AssetProcessor/native/utilities/MissingDependencyScanner.cpp index 73125fd58a..9daf97cf79 100644 --- a/Code/Tools/AssetProcessor/native/utilities/MissingDependencyScanner.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/MissingDependencyScanner.cpp @@ -20,30 +20,32 @@ AZ_POP_DISABLE_WARNING #include "native/AssetDatabase/AssetDatabase.h" #include "native/assetprocessor.h" #include +#include #include #include #include #include +#include #include #include #include #include -#include namespace AssetProcessor { - const char* EngineFolder = "Engine"; + constexpr auto EngineFolder = AZ::IO::FixedMaxPath("Assets") / "Engine"; AZStd::string GetXMLDependenciesFile(const AZStd::string& fullPath, const AZStd::vector& gemInfoList, AZStd::string& tokenName) { AZ::IO::Path xmlDependenciesFileFullPath; - tokenName = EngineFolder; + tokenName = EngineFolder.String(); for (const AzFramework::GemInfo& gemElement : gemInfoList) { for (const AZ::IO::Path& absoluteSourcePath : gemElement.m_absoluteSourcePaths) { - if (AZ::StringFunc::StartsWith(fullPath, absoluteSourcePath.Native()) || AZ::StringFunc::Equal(absoluteSourcePath.Native(), fullPath)) + if (AZ::IO::PathView(fullPath).IsRelativeTo(absoluteSourcePath)) { + xmlDependenciesFileFullPath = absoluteSourcePath; xmlDependenciesFileFullPath /= AzFramework::GemInfo::GetGemAssetFolder(); xmlDependenciesFileFullPath /= AZStd::string::format("%s_Dependencies.xml", gemElement.m_gemName.c_str());; if (AZ::IO::FileIOBase::GetInstance()->Exists(xmlDependenciesFileFullPath.c_str())) @@ -57,7 +59,7 @@ namespace AssetProcessor // if we are here than either the %gemName%_Dependencies.xml file does not exists or the user inputted path is not inside a gems folder, // in both the cases we will return the engine dependencies file - xmlDependenciesFileFullPath = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@"); + xmlDependenciesFileFullPath = AZ::Utils::GetEnginePath(); xmlDependenciesFileFullPath /= EngineFolder; xmlDependenciesFileFullPath /= "Engine_Dependencies.xml"; diff --git a/Code/Tools/CMakeLists.txt b/Code/Tools/CMakeLists.txt index 65a1bf85ce..db5476756b 100644 --- a/Code/Tools/CMakeLists.txt +++ b/Code/Tools/CMakeLists.txt @@ -25,3 +25,4 @@ add_subdirectory(AssetBundler) add_subdirectory(GridHub) add_subdirectory(Standalone) add_subdirectory(TestImpactFramework) +add_subdirectory(ProjectManager) diff --git a/Code/CryEngine/CryFont/CMakeLists.txt b/Code/Tools/ProjectManager/CMakeLists.txt similarity index 54% rename from Code/CryEngine/CryFont/CMakeLists.txt rename to Code/Tools/ProjectManager/CMakeLists.txt index 9e2f29f7b6..8315ef831c 100644 --- a/Code/CryEngine/CryFont/CMakeLists.txt +++ b/Code/Tools/ProjectManager/CMakeLists.txt @@ -9,16 +9,33 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) + return() +endif() + ly_add_target( - NAME CryFont ${PAL_TRAIT_MONOLITHIC_DRIVEN_LIBRARY_TYPE} - NAMESPACE Legacy + NAME ProjectManager APPLICATION + OUTPUT_NAME o3de + NAMESPACE AZ + AUTOMOC + AUTOUIC + AUTORCC FILES_CMAKE - cryfont_files.cmake + project_manager_files.cmake + Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake INCLUDE_DIRECTORIES - PRIVATE + PUBLIC . + PRIVATE + source + BUILD_DEPENDENCIES PRIVATE - 3rdParty::freetype - Legacy::CryCommon + 3rdParty::Qt::Core + 3rdParty::Qt::Concurrent + 3rdParty::Qt::Widgets + AZ::AzCore + AZ::AzFramework + AZ::AzToolsFramework + AZ::AzQtComponents ) diff --git a/Gems/Visibility/CMakeLists.txt b/Code/Tools/ProjectManager/Platform/Android/PAL_android.cmake similarity index 95% rename from Gems/Visibility/CMakeLists.txt rename to Code/Tools/ProjectManager/Platform/Android/PAL_android.cmake index 20a680bce9..4d5680a30d 100644 --- a/Gems/Visibility/CMakeLists.txt +++ b/Code/Tools/ProjectManager/Platform/Android/PAL_android.cmake @@ -8,5 +8,3 @@ # remove or modify any license notices. This file is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # - -add_subdirectory(Code) diff --git a/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Platform/Mac/PAL_mac.cmake b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Mac/PAL_mac.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Platform/iOS/PAL_ios.cmake b/Code/Tools/ProjectManager/Platform/iOS/PAL_ios.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/ProjectManager/Platform/iOS/PAL_ios.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/ProjectManager/Qt/FirstTimeUse.cpp b/Code/Tools/ProjectManager/Qt/FirstTimeUse.cpp new file mode 100644 index 0000000000..640849740e --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/FirstTimeUse.cpp @@ -0,0 +1,31 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include + +#include + +namespace ProjectManager +{ + FirstTimeUse::FirstTimeUse(QWidget* parent) + : QWidget(parent) + , m_ui(new Ui::FirstTimeUseClass()) + { + m_ui->setupUi(this); + } + + FirstTimeUse::~FirstTimeUse() + { + } + + //#include +} // namespace ProjectManager diff --git a/Code/Framework/AzFramework/AzFramework/API/AtomActiveInterface.h b/Code/Tools/ProjectManager/Qt/FirstTimeUse.h similarity index 63% rename from Code/Framework/AzFramework/AzFramework/API/AtomActiveInterface.h rename to Code/Tools/ProjectManager/Qt/FirstTimeUse.h index 80d4f6c867..85f344f3fe 100644 --- a/Code/Framework/AzFramework/AzFramework/API/AtomActiveInterface.h +++ b/Code/Tools/ProjectManager/Qt/FirstTimeUse.h @@ -11,16 +11,26 @@ */ #pragma once -#include +#if !defined(Q_MOC_RUN) +#include +#endif -namespace AzFramework +namespace Ui { - class AtomActiveInterface - { - public: - AZ_RTTI(AtomActiveInterface, "{4BB59C86-0848-485D-AB28-700540470B2B}"); + class FirstTimeUseClass; +} - AtomActiveInterface() = default; - virtual ~AtomActiveInterface() = default; +namespace ProjectManager +{ + class FirstTimeUse : public QWidget + { + + public: + explicit FirstTimeUse(QWidget* parent); + ~FirstTimeUse(); + + private: + QScopedPointer m_ui; }; -} // namespace AzFramework + +} // namespace ProjectManager diff --git a/Code/Tools/ProjectManager/Qt/FirstTimeUse.ui b/Code/Tools/ProjectManager/Qt/FirstTimeUse.ui new file mode 100644 index 0000000000..fdc195731f --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/FirstTimeUse.ui @@ -0,0 +1,93 @@ + + + FirstTimeUseClass + + + + 0 + 0 + 881 + 555 + + + + Form + + + + + + + + + 30 + + + + READY. SET. CREATE! + + + + + + + <html><head/><body><p>Welcome to O3DE! Start something new by creating a project. Not sure what to create? </p><p>Explore what’s available by downloading our sample project.</p></body></html> + + + Qt::AutoText + + + + + + + + + + + + 0 + 0 + + + + Create Project + + + + :/Resources/Add.svg:/Resources/Add.svg + + + + 16 + 16 + + + + + + + + + 0 + 0 + + + + Open a Project + + + + :/Resources/Select_Folder.svg:/Resources/Select_Folder.svg + + + + + + + + + + + + diff --git a/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.cpp b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.cpp new file mode 100644 index 0000000000..4a8486f877 --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.cpp @@ -0,0 +1,49 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include + +#include +#include + +#include + +#include + +namespace ProjectManager +{ + ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath) + : QMainWindow(parent) + , m_ui(new Ui::ProjectManagerWindowClass()) + { + m_ui->setupUi(this); + + QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast(engineRootPath.Native().size())); + const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources"); + const auto qrcPath = QStringLiteral(":/ProjectManagerWindow"); + AzQtComponents::StyleManager::addSearchPaths("projectmanagerwindow", pathOnDisk, qrcPath, engineRootPath); + + AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("projectlauncherwindow:ProjectManagerWindow.qss")); + + + FirstTimeUse* firstTimeUse = new FirstTimeUse(m_ui->centralwidget); + + firstTimeUse->show(); + } + + ProjectManagerWindow::~ProjectManagerWindow() + { + } + + //#include +} // namespace ProjectManager diff --git a/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.h b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.h new file mode 100644 index 0000000000..a62e823a92 --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.h @@ -0,0 +1,38 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ +#pragma once + +#if !defined(Q_MOC_RUN) +#include + +#include +#endif + +namespace Ui +{ + class ProjectManagerWindowClass; +} + +namespace ProjectManager +{ + class ProjectManagerWindow : public QMainWindow + { + + public: + explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath); + ~ProjectManagerWindow(); + + private: + QScopedPointer m_ui; + }; + +} // namespace ProjectManager diff --git a/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.ui b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.ui new file mode 100644 index 0000000000..60ec2dd674 --- /dev/null +++ b/Code/Tools/ProjectManager/Qt/ProjectManagerWindow.ui @@ -0,0 +1,61 @@ + + + ProjectManagerWindowClass + + + + 0 + 0 + 800 + 600 + + + + O3DE Project Manager + + + + + + + + 0 + 0 + 800 + 36 + + + + + 16 + + + + + Icon + + + + :/Resources/o3de_editor.ico:/Resources/o3de_editor.ico + + + + + Projects + + + + + Engine + + + + + + + + + + + + diff --git a/Code/Tools/ProjectManager/Resources/Add.svg b/Code/Tools/ProjectManager/Resources/Add.svg new file mode 100644 index 0000000000..d2b9b2e0a6 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/Add.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Code/Tools/ProjectManager/Resources/Select_Folder.svg b/Code/Tools/ProjectManager/Resources/Select_Folder.svg new file mode 100644 index 0000000000..72dcd3385e --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/Select_Folder.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Code/Tools/ProjectManager/Resources/o3de_editor.ico b/Code/Tools/ProjectManager/Resources/o3de_editor.ico new file mode 100644 index 0000000000..0680ceea19 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/o3de_editor.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c042fce57915fc749abc7b37de765fd697c3c4d7de045a3d44805aa0ce29901a +size 107016 diff --git a/Code/Tools/ProjectManager/project_manager.qrc b/Code/Tools/ProjectManager/project_manager.qrc new file mode 100644 index 0000000000..408398584b --- /dev/null +++ b/Code/Tools/ProjectManager/project_manager.qrc @@ -0,0 +1,8 @@ + + + Resources/ProjectManager.qss + Resources/Add.svg + Resources/Select_Folder.svg + Resources/o3de_editor.ico + + \ No newline at end of file diff --git a/cmake/3rdParty/Finddyad.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake similarity index 70% rename from cmake/3rdParty/Finddyad.cmake rename to Code/Tools/ProjectManager/project_manager_files.cmake index 179ce45bce..4d36550e56 100644 --- a/cmake/3rdParty/Finddyad.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -9,8 +9,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target( - NAME dyad - VERSION 0.2.0-17-amazon - INCLUDE_DIRECTORIES src +set(FILES + project_manager.qrc + source/main.cpp + Qt/FirstTimeUse.h + Qt/FirstTimeUse.cpp + Qt/FirstTimeUse.ui + Qt/ProjectManagerWindow.h + Qt/ProjectManagerWindow.cpp + Qt/ProjectManagerWindow.ui ) diff --git a/Code/Tools/ProjectManager/source/main.cpp b/Code/Tools/ProjectManager/source/main.cpp new file mode 100644 index 0000000000..ecfae3b28e --- /dev/null +++ b/Code/Tools/ProjectManager/source/main.cpp @@ -0,0 +1,55 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +int main(int argc, char* argv[]) +{ + QApplication::setOrganizationName("O3DE"); + QApplication::setOrganizationDomain("o3de.org"); + QCoreApplication::setApplicationName("ProjectManager"); + QCoreApplication::setApplicationVersion("1.0"); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); + + QApplication app(argc, argv); + + // Need to use settings registry to get EngineRootFolder + AZ::IO::FixedMaxPath engineRootPath; + { + AZ::ComponentApplication componentApplication; + auto settingsRegistry = AZ::SettingsRegistry::Get(); + settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); + } + + AzQtComponents::StyleManager styleManager(&app); + styleManager.initialize(&app, engineRootPath); + + ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath); + window.show(); + + return app.exec(); +} diff --git a/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp b/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp index 4de42eb944..989eccd526 100644 --- a/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.cpp @@ -13,9 +13,135 @@ #include #include #include +#include +#include +#include namespace AZ { + namespace Python + { + static const char* const None = "None"; + + class PythonBehaviorInfo final + { + public: + AZ_RTTI(PythonBehaviorInfo, "{8055BD03-5B3B-490D-AEC5-1B1E2616D529}"); + AZ_CLASS_ALLOCATOR(PythonBehaviorInfo, AZ::SystemAllocator, 0); + + static void Reflect(AZ::ReflectContext* context); + + PythonBehaviorInfo(const AZ::BehaviorClass* behaviorClass); + PythonBehaviorInfo() = delete; + + protected: + bool IsMemberLike(const AZ::BehaviorMethod& method, const AZ::TypeId& typeId) const; + AZStd::string FetchPythonType(const AZ::BehaviorParameter& param) const; + void WriteMethod(AZStd::string_view methodName, const AZ::BehaviorMethod& behaviorMethod); + + private: + const AZ::BehaviorClass* m_behaviorClass = nullptr; + AZStd::vector m_methodList; + }; + + PythonBehaviorInfo::PythonBehaviorInfo(const AZ::BehaviorClass* behaviorClass) + : m_behaviorClass(behaviorClass) + { + AZ_Assert(m_behaviorClass, "PythonBehaviorInfo requires a valid behaviorClass pointer"); + for (const auto& entry : behaviorClass->m_methods) + { + WriteMethod(entry.first, *entry.second); + } + } + + void PythonBehaviorInfo::Reflect(AZ::ReflectContext* context) + { + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->Class() + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + ->Attribute(AZ::Script::Attributes::Module, "scene.graph") + ->Property("className", [](const PythonBehaviorInfo& self) + { return self.m_behaviorClass->m_name; }, nullptr) + ->Property("classUuid", [](const PythonBehaviorInfo& self) + { return self.m_behaviorClass->m_typeId.ToString(); }, nullptr) + ->Property("methodList", BehaviorValueGetter(&PythonBehaviorInfo::m_methodList), nullptr); + } + } + + bool PythonBehaviorInfo::IsMemberLike(const AZ::BehaviorMethod& method, const AZ::TypeId& typeId) const + { + return method.IsMember() || (method.GetNumArguments() > 0 && method.GetArgument(0)->m_typeId == typeId); + } + + AZStd::string PythonBehaviorInfo::FetchPythonType(const AZ::BehaviorParameter& param) const + { + using namespace AzToolsFramework; + EditorPythonConsoleInterface* editorPythonConsoleInterface = AZ::Interface::Get(); + if (editorPythonConsoleInterface) + { + return editorPythonConsoleInterface->FetchPythonTypeName(param); + } + return None; + } + + void PythonBehaviorInfo::WriteMethod(AZStd::string_view methodName, const AZ::BehaviorMethod& behaviorMethod) + { + // if the method is a static method then it is not a part of the abstract class + const bool isMemberLike = IsMemberLike(behaviorMethod, m_behaviorClass->m_typeId); + if (isMemberLike == false) + { + return; + } + + AZStd::string buffer; + AZStd::vector pythonArgs; + + AzFramework::StringFunc::Append(buffer, "def "); + AzFramework::StringFunc::Append(buffer, methodName.data()); + AzFramework::StringFunc::Append(buffer, "("); + + pythonArgs.emplace_back("self"); + + AZStd::string bufferArg; + for (size_t argIndex = 1; argIndex < behaviorMethod.GetNumArguments(); ++argIndex) + { + const AZStd::string* name = behaviorMethod.GetArgumentName(argIndex); + if (!name || name->empty()) + { + bufferArg = AZStd::string::format(" arg%zu", argIndex); + } + else + { + bufferArg = *name; + } + + AZStd::string_view type = FetchPythonType(*behaviorMethod.GetArgument(argIndex)); + if (!type.empty()) + { + AzFramework::StringFunc::Append(bufferArg, ": "); + AzFramework::StringFunc::Append(bufferArg, type.data()); + } + + pythonArgs.push_back(bufferArg); + bufferArg.clear(); + } + + AZStd::string resultValue{ None }; + if (behaviorMethod.HasResult() && behaviorMethod.GetResult()) + { + resultValue = FetchPythonType(*behaviorMethod.GetResult()); + } + + AZStd::string argsList; + AzFramework::StringFunc::Join(buffer, pythonArgs.begin(), pythonArgs.end(), ","); + AzFramework::StringFunc::Append(buffer, ") -> "); + AzFramework::StringFunc::Append(buffer, resultValue.c_str()); + m_methodList.emplace_back(buffer); + } + } + namespace SceneAPI { namespace Containers @@ -25,11 +151,29 @@ namespace AZ AZ::BehaviorContext* behaviorContext = azrtti_cast(context); if (behaviorContext) { + Python::PythonBehaviorInfo::Reflect(context); + + behaviorContext->Class(); + behaviorContext->Class() ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Module, "scene.graph") + ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Method("CastWithTypeName", &GraphObjectProxy::CastWithTypeName) ->Method("Invoke", &GraphObjectProxy::Invoke) + ->Method("GetClassInfo", [](GraphObjectProxy& self) -> Python::PythonBehaviorInfo* + { + if (self.m_pythonBehaviorInfo) + { + return self.m_pythonBehaviorInfo.get(); + } + if (self.m_behaviorClass) + { + self.m_pythonBehaviorInfo = AZStd::make_shared(self.m_behaviorClass); + return self.m_pythonBehaviorInfo.get(); + } + return nullptr; + }) ; } } diff --git a/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.h b/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.h index 094b896364..d83a147e5f 100644 --- a/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.h +++ b/Code/Tools/SceneAPI/SceneCore/Containers/GraphObjectProxy.h @@ -16,6 +16,11 @@ namespace AZ { + namespace Python + { + class PythonBehaviorInfo; + } + namespace SceneAPI { namespace Containers @@ -44,6 +49,7 @@ namespace AZ private: AZStd::shared_ptr m_graphObject; const AZ::BehaviorClass* m_behaviorClass = nullptr; + AZStd::shared_ptr m_pythonBehaviorInfo; }; } // Containers diff --git a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp index cb23e73b0e..8d7fb63baf 100644 --- a/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Tests/Containers/SceneBehaviorTests.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -378,6 +379,25 @@ namespace AZ MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&)); }; + class MockEditorPythonConsoleInterface final + : public AzToolsFramework::EditorPythonConsoleInterface + { + public: + MockEditorPythonConsoleInterface() + { + AZ::Interface::Register(this); + } + + ~MockEditorPythonConsoleInterface() + { + AZ::Interface::Unregister(this); + } + + MOCK_CONST_METHOD1(GetModuleList, void(AZStd::vector&)); + MOCK_CONST_METHOD1(GetGlobalFunctionList, void(GlobalFunctionCollection&)); + MOCK_METHOD1(FetchPythonTypeName, AZStd::string(const AZ::BehaviorParameter&)); + }; + // // SceneGraphBehaviorScriptTest // @@ -386,6 +406,7 @@ namespace AZ { public: AZStd::unique_ptr m_componentApplication; + AZStd::unique_ptr m_editorPythonConsoleInterface; AZStd::unique_ptr m_scriptContext; AZStd::unique_ptr m_behaviorContext; AZStd::unique_ptr m_serializeContext; @@ -454,6 +475,15 @@ namespace AZ { return this->m_serializeContext.get(); })); + + m_editorPythonConsoleInterface = AZStd::make_unique(); + } + + void SetupEditorPythonConsoleInterface() + { + EXPECT_CALL(*m_editorPythonConsoleInterface, FetchPythonTypeName(::testing::_)) + .Times(4) + .WillRepeatedly(::testing::Invoke([](const AZ::BehaviorParameter&) {return "int"; })); } void TearDown() override @@ -562,6 +592,38 @@ namespace AZ ExpectExecute("TestExpectEquals(value, 17)"); } + TEST_F(SceneGraphBehaviorScriptTest, GraphObjectProxy_GetClassInfo_Loads) + { + SetupEditorPythonConsoleInterface(); + + ExpectExecute("builder = MockBuilder()"); + ExpectExecute("builder:BuildSceneGraph()"); + ExpectExecute("scene = builder:GetScene()"); + ExpectExecute("nodeG = scene.graph:FindWithPath('A.C.E.G')"); + ExpectExecute("proxy = scene.graph:GetNodeContent(nodeG)"); + ExpectExecute("TestExpectTrue(proxy:CastWithTypeName('MockIGraphObject'))"); + ExpectExecute("info = proxy:GetClassInfo()"); + ExpectExecute("TestExpectTrue(info ~= nil)"); + } + + TEST_F(SceneGraphBehaviorScriptTest, GraphObjectProxy_GetClassInfo_CorrectFormats) + { + SetupEditorPythonConsoleInterface(); + + ExpectExecute("builder = MockBuilder()"); + ExpectExecute("builder:BuildSceneGraph()"); + ExpectExecute("scene = builder:GetScene()"); + ExpectExecute("nodeG = scene.graph:FindWithPath('A.C.E.G')"); + ExpectExecute("proxy = scene.graph:GetNodeContent(nodeG)"); + ExpectExecute("TestExpectTrue(proxy:CastWithTypeName('MockIGraphObject'))"); + ExpectExecute("info = proxy:GetClassInfo()"); + ExpectExecute("TestExpectTrue(info.className == 'MockIGraphObject')"); + ExpectExecute("TestExpectTrue(info.classUuid == '{66A082CC-851D-4E1F-ABBD-45B58A216CFA}')"); + ExpectExecute("TestExpectTrue(info.methodList[1] == 'def GetId(self) -> int')"); + ExpectExecute("TestExpectTrue(info.methodList[2] == 'def SetId(self, arg1: int) -> None')"); + ExpectExecute("TestExpectTrue(info.methodList[3] == 'def AddAndSet(self, arg1: int, arg2: int) -> None')"); + } + // // SceneManifestBehaviorScriptTest is meant to test the script abilities of the SceneManifest // diff --git a/Code/Tools/SceneAPI/SceneData/GraphData/BlendShapeData.h b/Code/Tools/SceneAPI/SceneData/GraphData/BlendShapeData.h index 9ae287da46..403ab867f2 100644 --- a/Code/Tools/SceneAPI/SceneData/GraphData/BlendShapeData.h +++ b/Code/Tools/SceneAPI/SceneData/GraphData/BlendShapeData.h @@ -31,7 +31,7 @@ namespace AZ public: AZ_RTTI(BlendShapeData, "{FF875C22-2E4F-4CE3-BA49-09BF78C70A09}", SceneAPI::DataTypes::IBlendShapeData) - SCENE_DATA_API static void Reflect(ReflectContext* context); + static void Reflect(ReflectContext* context); // Maximum number of color sets matches limitation set in assImp (AI_MAX_NUMBER_OF_COLOR_SETS) static constexpr AZ::u8 MaxNumColorSets = 8; diff --git a/Gems/AWSClientAuth/cdk/README.md b/Gems/AWSClientAuth/cdk/README.md index d604057a65..4fe668cb9d 100644 --- a/Gems/AWSClientAuth/cdk/README.md +++ b/Gems/AWSClientAuth/cdk/README.md @@ -26,9 +26,9 @@ Once the python and pip are set up, you can install the required dependencies. Set variables ``` -set O3D_AWS_DEPLOY_REGION="us-west-2" -set O3D_AWS_DEPLOY_ACCOUNT="" -set O3D_AWS_PROJECT_NAME="AWSIProject" +set O3DE_AWS_DEPLOY_REGION="us-west-2" +set O3DE_AWS_DEPLOY_ACCOUNT="" +set O3DE_AWS_PROJECT_NAME="AWSIProject" If you want to add 3rd party providers fill values in utils/constant.py ``` diff --git a/Gems/AWSClientAuth/cdk/app.py b/Gems/AWSClientAuth/cdk/app.py index d6bba06f39..3b57eea07f 100755 --- a/Gems/AWSClientAuth/cdk/app.py +++ b/Gems/AWSClientAuth/cdk/app.py @@ -16,11 +16,11 @@ from aws_client_auth.client_auth_stack import AWSClientAuthStack import os """Configuration""" -REGION = os.environ.get('O3D_AWS_DEPLOY_REGION', os.environ['CDK_DEFAULT_REGION']) -ACCOUNT = os.environ.get('O3D_AWS_DEPLOY_ACCOUNT', os.environ['CDK_DEFAULT_ACCOUNT']) +REGION = os.environ.get('O3DE_AWS_DEPLOY_REGION', os.environ['CDK_DEFAULT_REGION']) +ACCOUNT = os.environ.get('O3DE_AWS_DEPLOY_ACCOUNT', os.environ['CDK_DEFAULT_ACCOUNT']) # Set the common prefix to group stacks in a project together. -PROJECT_NAME = os.environ.get('O3D_AWS_PROJECT_NAME', f'O3D-AWS-PROJECT').upper() +PROJECT_NAME = os.environ.get('O3DE_AWS_PROJECT_NAME', f'O3DE-AWS-PROJECT').upper() env = core.Environment(account=ACCOUNT, region=REGION) app = core.App() diff --git a/Gems/AWSClientAuth/cdk/cognito/cognito_identity_pool.py b/Gems/AWSClientAuth/cdk/cognito/cognito_identity_pool.py index b09269bf3e..d030f8573c 100755 --- a/Gems/AWSClientAuth/cdk/cognito/cognito_identity_pool.py +++ b/Gems/AWSClientAuth/cdk/cognito/cognito_identity_pool.py @@ -58,7 +58,7 @@ class CognitoIdentityPool: self._identity_pool.add_depends_on(cognito_user_pool.get_user_pool()) self._identity_pool.add_depends_on(cognito_user_pool.get_user_pool_client()) - # Create roles to associate with Cognito Idenity pool + # Create roles to associate with Cognito Identity pool self._auth_role = CognitoIdentityPoolRole(scope, feature_name, project_name, env, self._identity_pool, authenticated=True) self._unauth_role = CognitoIdentityPoolRole(scope, feature_name, project_name, env, diff --git a/Gems/AWSClientAuth/cdk/utils/name_utils.py b/Gems/AWSClientAuth/cdk/utils/name_utils.py index 8c8f6a7e82..bab4cd0389 100755 --- a/Gems/AWSClientAuth/cdk/utils/name_utils.py +++ b/Gems/AWSClientAuth/cdk/utils/name_utils.py @@ -8,7 +8,7 @@ remove or modify any license notices. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ - +import re from aws_cdk import core @@ -21,7 +21,9 @@ def format_aws_resource_id(feature_name: str, project_name: str, env: core.Envir def format_aws_resource_sid(feature_name: str, project_name: str, resource_type: str): - return f'{project_name}{feature_name}{resource_type}SId' + sid = f'{project_name}{feature_name}{resource_type}SId' + # Strip out all chars not valid in a sid + return re.sub(r'[^a-zA-Z0-9]', '', sid) def format_aws_resource_authenticated_id(feature_name: str, project_name: str, env: core.Environment, diff --git a/Gems/AWSCore/Code/CMakeLists.txt b/Gems/AWSCore/Code/CMakeLists.txt index 468530be31..a58b02d1d4 100644 --- a/Gems/AWSCore/Code/CMakeLists.txt +++ b/Gems/AWSCore/Code/CMakeLists.txt @@ -86,7 +86,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_target( - NAME AWSCore.ResourceMappintTool MODULE + NAME AWSCore.ResourceMappingTool MODULE NAMESPACE Gem OUTPUT_SUBDIRECTORY AWSCoreEditorQtBin FILES_CMAKE @@ -94,15 +94,11 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) INCLUDE_DIRECTORIES PRIVATE Include/Private - PUBLIC - Include/Public BUILD_DEPENDENCIES PRIVATE - 3rdParty::Qt::Core - 3rdParty::Qt::Widgets - AZ::AzToolsFramework + Gem::AWSCore.Editor.Static ) - ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappintTool) + ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappingTool) endif() ################################################################################ diff --git a/Gems/AWSCore/Code/Include/Public/ScriptCanvas/AWSScriptBehaviorS3.h b/Gems/AWSCore/Code/Include/Public/ScriptCanvas/AWSScriptBehaviorS3.h index 5d7baf19a1..9d779e3629 100644 --- a/Gems/AWSCore/Code/Include/Public/ScriptCanvas/AWSScriptBehaviorS3.h +++ b/Gems/AWSCore/Code/Include/Public/ScriptCanvas/AWSScriptBehaviorS3.h @@ -75,6 +75,16 @@ namespace AWSCore class AWSScriptBehaviorS3 : public AWSScriptBehaviorBase { + static constexpr const char AWSScriptBehaviorS3Name[] = "AWSScriptBehaviorS3"; + static constexpr const char OutputFileIsEmptyErrorMessage[] = "Request validation failed, output file is empty."; + static constexpr const char OutputFileMissFullPathErrorMessage[] = "Request validation failed, output file miss full path."; + static constexpr const char OutputFileIsDirectoryErrorMessage[] = "Request validation failed, output file is a directory."; + static constexpr const char OutputFileDirectoryNotExistErrorMessage[] = "Request validation failed, output file directory doesn't exist."; + static constexpr const char OutputFileIsReadOnlyErrorMessage[] = "Request validation failed, output file is read-only."; + static constexpr const char BucketNameIsEmptyErrorMessage[] = "Request validation failed, bucket name is empty"; + static constexpr const char ObjectKeyNameIsEmptyErrorMessage[] = "Request validation failed, object key name is empty."; + static constexpr const char RegionNameIsEmptyErrorMessage[] = "Request validation failed, region name is empty."; + public: AWS_SCRIPT_BEHAVIOR_DEFINITION(AWSScriptBehaviorS3, "{7F4E956C-7463-4236-B320-C992D36A9C6E}"); @@ -87,7 +97,7 @@ namespace AWSCore private: using S3NotificationFunctionType = void(AWSScriptBehaviorS3Notifications::*)(const AZStd::string&); static bool ValidateGetObjectRequest(S3NotificationFunctionType notificationFunc, - const AZStd::string& bucket, const AZStd::string& objectKey, const AZStd::string& region, const AZStd::string& outFile); + const AZStd::string& bucket, const AZStd::string& objectKey, const AZStd::string& region, AZStd::string& outFile); static bool ValidateHeadObjectRequest(S3NotificationFunctionType notificationFunc, const AZStd::string& bucket, const AZStd::string& key, const AZStd::string& region); diff --git a/Gems/AWSCore/Code/Source/AWSCoreResourceMappingToolModule.cpp b/Gems/AWSCore/Code/Source/AWSCoreResourceMappingToolModule.cpp new file mode 100644 index 0000000000..794ee6c880 --- /dev/null +++ b/Gems/AWSCore/Code/Source/AWSCoreResourceMappingToolModule.cpp @@ -0,0 +1,44 @@ +/* +* All or portions of this file Copyright(c) Amazon.com, Inc.or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include + +namespace AWSCore +{ + class AWSCoreResourceMappingToolModule + : public AZ::Module + { + public: + AZ_RTTI(AWSCoreResourceMappingToolModule, "{9D16F400-009C-47FF-A186-E48BEB73D94D}", AZ::Module); + AZ_CLASS_ALLOCATOR(AWSCoreResourceMappingToolModule, AZ::SystemAllocator, 0); + + AWSCoreResourceMappingToolModule() + { + m_descriptors.insert(m_descriptors.end(), + { + AWSCoreEditorSystemComponent::CreateDescriptor(), + }); + } + + ~AWSCoreResourceMappingToolModule() override = default; + + AZ::ComponentTypeList GetRequiredSystemComponents() const override + { + return AZ::ComponentTypeList{azrtti_typeid()}; + } + }; +} + +// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM +// The first parameter should be GemName_GemIdLower +// The second should be the fully qualified name of the class above +AZ_DECLARE_MODULE_CLASS(Gem_AWSCore_ResourceMappingTool, AWSCore::AWSCoreResourceMappingToolModule) diff --git a/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp b/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp index fdd5fa3c92..bec352bf35 100644 --- a/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp +++ b/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp @@ -117,7 +117,7 @@ namespace AWSCore result.m_content.append(AZStd::string::format(Detail::FOOTER_FMT, m_boundary.c_str())); // Populate the metadata - result.m_contentLength = AZStd::string::format("%lu", result.m_content.length()); + result.m_contentLength = AZStd::string::format("%zu", result.m_content.length()); result.m_contentType = AZStd::string::format("multipart/form-data; boundary=%s", m_boundary.c_str()); return result; diff --git a/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorS3.cpp b/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorS3.cpp index 742a6826af..1f529572f1 100644 --- a/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorS3.cpp +++ b/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorS3.cpp @@ -43,7 +43,7 @@ namespace AWSCore void AWSScriptBehaviorS3::ReflectBehaviors(AZ::BehaviorContext* behaviorContext) { - behaviorContext->Class("AWSScriptBehaviorS3") + behaviorContext->Class(AWSScriptBehaviorS3Name) ->Attribute(AZ::Script::Attributes::Category, "AWSCore") ->Method("GetObject", &AWSScriptBehaviorS3::GetObject, {{{"Bucket Resource KeyName", "The resource key name of the bucket in resource mapping config file."}, @@ -86,7 +86,9 @@ namespace AWSCore void AWSScriptBehaviorS3::GetObjectRaw( const AZStd::string& bucket, const AZStd::string& objectKey, const AZStd::string& region, const AZStd::string& outFile) { - if (!ValidateGetObjectRequest(&AWSScriptBehaviorS3NotificationBus::Events::OnGetObjectError, bucket, objectKey, region, outFile)) + AZStd::string normalizedOutFile = outFile; + if (!ValidateGetObjectRequest( + &AWSScriptBehaviorS3NotificationBus::Events::OnGetObjectError, bucket, objectKey, region, normalizedOutFile)) { return; } @@ -112,10 +114,10 @@ namespace AWSCore job->request.SetBucket(Aws::String(bucket.c_str())); job->request.SetKey(Aws::String(objectKey.c_str())); - Aws::String outFileName(outFile.c_str()); + Aws::String outFileName(normalizedOutFile.c_str()); job->request.SetResponseStreamFactory([outFileName]() { return Aws::New( - "AWSScriptBehaviorS3", outFileName.c_str(), + AWSScriptBehaviorS3Name, outFileName.c_str(), std::ios_base::out | std::ios_base::in | std::ios_base::binary | std::ios_base::trunc); }); job->Start(); @@ -163,20 +165,44 @@ namespace AWSCore } bool AWSScriptBehaviorS3::ValidateGetObjectRequest(S3NotificationFunctionType notificationFunc, - const AZStd::string& bucket, const AZStd::string& objectKey, const AZStd::string& region, const AZStd::string& outFile) + const AZStd::string& bucket, const AZStd::string& objectKey, const AZStd::string& region, AZStd::string& outFile) { if (ValidateHeadObjectRequest(notificationFunc, bucket, objectKey, region)) { - if (!AzFramework::StringFunc::Path::IsValid(outFile.c_str())) + AzFramework::StringFunc::Path::Normalize(outFile); + if (outFile.empty()) { - AZ_Warning("AWSScriptBehaviorS3", false, "Request validation failed, outfile is not valid."); - AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, "Request validation failed, outfile is not valid."); + AZ_Warning(AWSScriptBehaviorS3Name, false, OutputFileIsEmptyErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, OutputFileIsEmptyErrorMessage); return false; } + if (!AzFramework::StringFunc::Path::HasDrive(outFile.c_str())) + { + AZ_Warning(AWSScriptBehaviorS3Name, false, OutputFileMissFullPathErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, OutputFileMissFullPathErrorMessage); + return false; + } + if (AZ::IO::FileIOBase::GetInstance()->IsDirectory(outFile.c_str())) + { + AZ_Warning(AWSScriptBehaviorS3Name, false, OutputFileIsDirectoryErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, OutputFileIsDirectoryErrorMessage); + return false; + } + auto lastSeparator = outFile.find_last_of(AZ_CORRECT_FILESYSTEM_SEPARATOR); + if (lastSeparator != AZStd::string::npos) + { + auto parentPath = outFile.substr(0, lastSeparator); + if (!AZ::IO::FileIOBase::GetInstance()->Exists(parentPath.c_str())) + { + AZ_Warning(AWSScriptBehaviorS3Name, false, OutputFileDirectoryNotExistErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, OutputFileDirectoryNotExistErrorMessage); + return false; + } + } if (AZ::IO::FileIOBase::GetInstance()->IsReadOnly(outFile.c_str())) { - AZ_Warning("AWSScriptBehaviorS3", false, "Request validation failed, outfile is read-only."); - AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, "Request validation failed, outfile is read-only."); + AZ_Warning(AWSScriptBehaviorS3Name, false, OutputFileIsReadOnlyErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, OutputFileIsReadOnlyErrorMessage); return false; } return true; @@ -189,20 +215,20 @@ namespace AWSCore { if (bucket.empty()) { - AZ_Warning("AWSScriptBehaviorS3", false, "Request validation failed, bucket name is required."); - AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, "Request validation failed, bucket name is required."); + AZ_Warning(AWSScriptBehaviorS3Name, false, BucketNameIsEmptyErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, BucketNameIsEmptyErrorMessage); return false; } if (objectKey.empty()) { - AZ_Warning("AWSScriptBehaviorS3", false, "Request validation failed, object key name is required."); - AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, "Request validation failed, object key name is required."); + AZ_Warning(AWSScriptBehaviorS3Name, false, ObjectKeyNameIsEmptyErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, ObjectKeyNameIsEmptyErrorMessage); return false; } if (region.empty()) { - AZ_Warning("AWSScriptBehaviorS3", false, "Request validation failed, region name is required."); - AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, "Request validation failed, region name is required."); + AZ_Warning(AWSScriptBehaviorS3Name, false, RegionNameIsEmptyErrorMessage); + AWSScriptBehaviorS3NotificationBus::Broadcast(notificationFunc, RegionNameIsEmptyErrorMessage); return false; } return true; diff --git a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp index fe258580e0..3489f09ac3 100644 --- a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp +++ b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp @@ -11,6 +11,7 @@ */ #include +#include #include #include @@ -38,7 +39,37 @@ public: MOCK_METHOD1(OnGetObjectError, void(const AZStd::string&)); }; -using AWSScriptBehaviorS3Test = UnitTest::ScopedAllocatorSetupFixture; +class AWSScriptBehaviorS3Test + : public AWSCoreFixture +{ +public: + void CreateReadOnlyTestFile(const AZStd::string& filePath) + { + AZ::IO::SystemFile file; + if (!file.Open( + filePath.c_str(), + AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY)) + { + AZ_Assert(false, "Failed to open test file at %s", filePath.c_str()); + } + AZStd::string testContent = "It is a test file"; + if (file.Write(testContent.c_str(), testContent.size()) != testContent.size()) + { + AZ_Assert(false, "Failed to write test file with content %s", testContent.c_str()); + } + file.Close(); + AZ_Assert(AZ::IO::SystemFile::SetWritable(filePath.c_str(), false), "Failed to mark test file as read-only"); + } + + void RemoveReadOnlyTestFile(const AZStd::string& filePath) + { + if (!filePath.empty()) + { + AZ_Assert(AZ::IO::SystemFile::SetWritable(filePath.c_str(), true), "Failed to mark test file as writeable"); + AZ_Assert(AZ::IO::SystemFile::Delete(filePath.c_str()), "Failed to delete test config file at %s", filePath.c_str()); + } + } +}; TEST_F(AWSScriptBehaviorS3Test, HeadObjectRaw_CallWithEmptyBucketName_InvokeOnError) { @@ -96,6 +127,40 @@ TEST_F(AWSScriptBehaviorS3Test, GetObjectRaw_CallWithEmptyOutfileName_InvokeOnEr AWSScriptBehaviorS3::GetObjectRaw("dummyBucket", "dummyObject", "dummyRegion", ""); } +TEST_F(AWSScriptBehaviorS3Test, GetObjectRaw_CallWithOutfileNameMissFullPath_InvokeOnError) +{ + AWSScriptBehaviorS3NotificationBusHandlerMock s3HandlerMock; + EXPECT_CALL(s3HandlerMock, OnGetObjectError(::testing::_)).Times(1); + AWSScriptBehaviorS3::GetObjectRaw("dummyBucket", "dummyObject", "dummyRegion", "dummyOut.txt"); +} + +TEST_F(AWSScriptBehaviorS3Test, GetObjectRaw_CallWithOutfileNameIsDirectory_InvokeOnError) +{ + AWSScriptBehaviorS3NotificationBusHandlerMock s3HandlerMock; + EXPECT_CALL(s3HandlerMock, OnGetObjectError(::testing::_)).Times(1); + AWSScriptBehaviorS3::GetObjectRaw("dummyBucket", "dummyObject", "dummyRegion", AZ::Test::GetCurrentExecutablePath()); +} + +TEST_F(AWSScriptBehaviorS3Test, GetObjectRaw_CallWithOutfileDirectoryNoExist_InvokeOnError) +{ + AWSScriptBehaviorS3NotificationBusHandlerMock s3HandlerMock; + EXPECT_CALL(s3HandlerMock, OnGetObjectError(::testing::_)).Times(1); + AZStd::string dummyDirectory = AZStd::string::format("%s/dummyDirectory/dummyOut.txt", AZ::Test::GetCurrentExecutablePath().c_str()); + AWSScriptBehaviorS3::GetObjectRaw("dummyBucket", "dummyObject", "dummyRegion", dummyDirectory); +} + +TEST_F(AWSScriptBehaviorS3Test, GetObjectRaw_CallWithOutfileIsReadOnly_InvokeOnError) +{ + AWSScriptBehaviorS3NotificationBusHandlerMock s3HandlerMock; + EXPECT_CALL(s3HandlerMock, OnGetObjectError(::testing::_)).Times(1); + AZStd::string randomTestFile = AZStd::string::format("%s/test%s.txt", + AZ::Test::GetCurrentExecutablePath().c_str(), AZ::Uuid::CreateRandom().ToString(false, false).c_str()); + AzFramework::StringFunc::Path::Normalize(randomTestFile); + CreateReadOnlyTestFile(randomTestFile); + AWSScriptBehaviorS3::GetObjectRaw("dummyBucket", "dummyObject", "dummyRegion", randomTestFile); + RemoveReadOnlyTestFile(randomTestFile); +} + TEST_F(AWSScriptBehaviorS3Test, GetObject_NoBucketNameInResourceMappingFound_InvokeOnError) { AWSScriptBehaviorS3NotificationBusHandlerMock s3HandlerMock; diff --git a/Gems/AWSCore/Code/awscore_resourcemappingtool_files.cmake b/Gems/AWSCore/Code/awscore_resourcemappingtool_files.cmake index b67c50e955..466a2c917f 100644 --- a/Gems/AWSCore/Code/awscore_resourcemappingtool_files.cmake +++ b/Gems/AWSCore/Code/awscore_resourcemappingtool_files.cmake @@ -10,6 +10,5 @@ # set(FILES - Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h - Source/Editor/UI/AWSCoreResourceMappingToolAction.cpp + Source/AWSCoreResourceMappingToolModule.cpp ) diff --git a/Gems/AWSCore/cdk/README.md b/Gems/AWSCore/cdk/README.md index c49155a422..e4c0335c9c 100644 --- a/Gems/AWSCore/cdk/README.md +++ b/Gems/AWSCore/cdk/README.md @@ -44,9 +44,9 @@ $ pip install -r requirements.txt ## Set environment variables or accept defaults -* O3D_AWS_DEPLOY_REGION*: The region to deploy the stacks into, will default to CDK_DEFAULT_REGION -* O3D_AWS_DEPLOY_ACCOUNT*: The account to deploy stacks into, will default to CDK_DEFAULT_ACCOUNT -* O3D_AWS_PROJECT_NAME*: The name of the O3DE project stacks should be deployed for will default to AWS-PROJECT +* O3DE_AWS_DEPLOY_REGION*: The region to deploy the stacks into, will default to CDK_DEFAULT_REGION +* O3DE_AWS_DEPLOY_ACCOUNT*: The account to deploy stacks into, will default to CDK_DEFAULT_ACCOUNT +* O3DE_AWS_PROJECT_NAME*: The name of the O3DE project stacks should be deployed for will default to AWS-PROJECT See https://docs.aws.amazon.com/cdk/latest/guide/environments.html for more information including how to pass parameters to use for environment variables. diff --git a/Gems/AWSCore/cdk/app.py b/Gems/AWSCore/cdk/app.py index 2e5b196e02..2d8bfa4181 100755 --- a/Gems/AWSCore/cdk/app.py +++ b/Gems/AWSCore/cdk/app.py @@ -22,11 +22,11 @@ from core.aws_core import AWSCore from example.example_resources_stack import ExampleResources """Configuration""" -REGION = os.environ.get('O3D_AWS_DEPLOY_REGION', os.environ.get('CDK_DEFAULT_REGION')) -ACCOUNT = os.environ.get('O3D_AWS_DEPLOY_ACCOUNT', os.environ.get('CDK_DEFAULT_ACCOUNT')) +REGION = os.environ.get('O3DE_AWS_DEPLOY_REGION', os.environ.get('CDK_DEFAULT_REGION')) +ACCOUNT = os.environ.get('O3DE_AWS_DEPLOY_ACCOUNT', os.environ.get('CDK_DEFAULT_ACCOUNT')) # Set the common prefix to group stacks in a project together. -PROJECT_NAME = os.environ.get('O3D_AWS_PROJECT_NAME', f'AWS-PROJECT').upper() +PROJECT_NAME = os.environ.get('O3DE_AWS_PROJECT_NAME', f'O3DE-AWS-PROJECT').upper() # The name of this feature FEATURE_NAME = 'Core' diff --git a/Gems/AWSCore/cdk/core/core_stack.py b/Gems/AWSCore/cdk/core/core_stack.py index 7bf8676987..997d15ef6b 100755 --- a/Gems/AWSCore/cdk/core/core_stack.py +++ b/Gems/AWSCore/cdk/core/core_stack.py @@ -27,7 +27,7 @@ class CoreStack(core.Stack): """ # Resource groups cannot start with 'AWS' or 'aws' so add this prefix - RESOURCE_GROUP_PREFIX = 'O3D' + RESOURCE_GROUP_PREFIX = 'O3DE' def __init__(self, scope: core.Construct, id_: str, project_name: str, feature_name: str, **kwargs) -> None: super().__init__(scope, id_, **kwargs) diff --git a/Gems/AWSMetrics/cdk/README.md b/Gems/AWSMetrics/cdk/README.md index 3f0544a9ce..6f2c774bc3 100644 --- a/Gems/AWSMetrics/cdk/README.md +++ b/Gems/AWSMetrics/cdk/README.md @@ -42,9 +42,9 @@ $ pip install -r requirements.txt ## Set environment variables or accept defaults -* O3D_AWS_DEPLOY_REGION*: The region to deploy the stacks into, will default to CDK_DEFAULT_REGION -* O3D_AWS_DEPLOY_ACCOUNT*: The account to deploy stacks into, will default to CDK_DEFAULT_ACCOUNT -* O3D_AWS_PROJECT_NAME*: The name of the O3DE project stacks should be deployed for will default to AWS-PROJECT +* O3DE_AWS_DEPLOY_REGION*: The region to deploy the stacks into, will default to CDK_DEFAULT_REGION +* O3DE_AWS_DEPLOY_ACCOUNT*: The account to deploy stacks into, will default to CDK_DEFAULT_ACCOUNT +* O3DE_AWS_PROJECT_NAME*: The name of the O3DE project stacks should be deployed for will default to AWS-PROJECT See https://docs.aws.amazon.com/cdk/latest/guide/environments.html for more information including how to pass parameters to use for environment variables. diff --git a/Gems/AWSMetrics/cdk/app.py b/Gems/AWSMetrics/cdk/app.py index 21f8c8f802..469925e533 100755 --- a/Gems/AWSMetrics/cdk/app.py +++ b/Gems/AWSMetrics/cdk/app.py @@ -17,11 +17,11 @@ from aws_metrics.aws_metrics_construct import AWSMetrics import os """Configuration""" -REGION = os.environ.get('O3D_AWS_DEPLOY_REGION', os.environ['CDK_DEFAULT_REGION']) -ACCOUNT = os.environ.get('O3D_AWS_DEPLOY_ACCOUNT', os.environ['CDK_DEFAULT_ACCOUNT']) +REGION = os.environ.get('O3DE_AWS_DEPLOY_REGION', os.environ['CDK_DEFAULT_REGION']) +ACCOUNT = os.environ.get('O3DE_AWS_DEPLOY_ACCOUNT', os.environ['CDK_DEFAULT_ACCOUNT']) # Set the common prefix to group stacks in a project together. Defaults to LY-AWS. -PROJECT_NAME = os.environ.get('O3D_AWS_PROJECT_NAME', f'AWS-PROJECT').upper() +PROJECT_NAME = os.environ.get('O3DE_AWS_PROJECT_NAME', f'O3DE-AWS-PROJECT').upper() # The name of this feature FEATURE_NAME = 'AWSMetrics' diff --git a/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py b/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py index f1a356addf..fe85615d8d 100755 --- a/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py +++ b/Gems/AWSMetrics/cdk/aws_metrics/batch_processing.py @@ -259,7 +259,7 @@ class BatchProcessing: ) policy_statements.append(input_stream_policy_statement) - log_policy_statetement = iam.PolicyStatement( + log_policy_statement = iam.PolicyStatement( actions=[ 'logs:PutLogEvents', ], @@ -268,7 +268,7 @@ class BatchProcessing: self._firehose_delivery_stream_log_group.log_group_arn ] ) - policy_statements.append(log_policy_statetement) + policy_statements.append(log_policy_statement) data_catalog_policy_statement = iam.PolicyStatement( actions=[ diff --git a/Gems/AssetValidation/Code/Source/AssetSeedUtil.h b/Gems/AssetValidation/Code/Source/AssetSeedUtil.h index 4a6ff1f1d8..60d94e8903 100644 --- a/Gems/AssetValidation/Code/Source/AssetSeedUtil.h +++ b/Gems/AssetValidation/Code/Source/AssetSeedUtil.h @@ -30,7 +30,7 @@ namespace AssetValidation::AssetSeed constexpr char GemsDirectoryName[] = "Gems"; constexpr char GemsSeedFileName[] = "seedList"; constexpr char EngineSeedFileName[] = "SeedAssetList"; - constexpr char EngineDirectoryName[] = "Engine"; + constexpr auto EngineDirectoryName = AZ::IO::FixedMaxPath("Assets") / "Engine"; void AddPlatformSeeds(const AZStd::string& rootFolder, AZStd::vector& defaultSeedLists, AzFramework::PlatformFlags platformFlags); diff --git a/Gems/AssetValidation/Code/Tests/AssetValidationTest.cpp b/Gems/AssetValidation/Code/Tests/AssetValidationTest.cpp index a5ff671fc3..5003c4484c 100644 --- a/Gems/AssetValidation/Code/Tests/AssetValidationTest.cpp +++ b/Gems/AssetValidation/Code/Tests/AssetValidationTest.cpp @@ -32,20 +32,21 @@ TEST_F(AssetValidationTest, DefaultSeedList_ReturnsExpectedSeedLists) { AZStd::vector gemInfo; - AZStd::string gemSeedList, engineSeedList, projectSeedList; + AZ::IO::Path gemSeedList, engineSeedList, projectSeedList; - ASSERT_TRUE(CreateDummyFile((AZ::IO::Path("mockGem") / AzFramework::GemInfo::GetGemAssetFolder()).c_str(), "seedList", "Mock Gem Seed List", gemSeedList)); - ASSERT_TRUE(CreateDummyFile("Engine", "SeedAssetList", "Engine Seed List", engineSeedList)); + ASSERT_TRUE(CreateDummyFile((AZ::IO::Path("mockGem") / AzFramework::GemInfo::GetGemAssetFolder()).c_str(), "seedList", "Mock Gem Seed List", gemSeedList.Native())); + ASSERT_TRUE(CreateDummyFile((AZ::IO::Path("Assets") / "Engine").c_str(), "SeedAssetList", "Engine Seed List", engineSeedList.Native())); AZ::SettingsRegistryInterface::FixedValueString projectName = AZ::Utils::GetProjectName(); ASSERT_FALSE(projectName.empty()); - ASSERT_TRUE(CreateDummyFile(projectName.c_str(), "SeedAssetList", "Project Seed List", projectSeedList)); + ASSERT_TRUE(CreateDummyFile(projectName.c_str(), "SeedAssetList", "Project Seed List", projectSeedList.Native())); AzFramework::GemInfo mockGem("MockGem"); mockGem.m_absoluteSourcePaths.push_back((m_tempDir / "mockGem").string().c_str()); gemInfo.push_back(mockGem); - AZStd::vector defaultSeedLists = AssetValidation::AssetSeed::GetDefaultSeedListFiles(gemInfo, AzFramework::PlatformFlags::Platform_PC); + AZStd::vector defaultSeedStringList = AssetValidation::AssetSeed::GetDefaultSeedListFiles(gemInfo, AzFramework::PlatformFlags::Platform_PC); + AZStd::vector defaultSeedLists{ AZStd::make_move_iterator(defaultSeedStringList.begin()), AZStd::make_move_iterator(defaultSeedStringList.end()) }; ASSERT_THAT(defaultSeedLists, ::testing::UnorderedElementsAre(gemSeedList, engineSeedList, projectSeedList)); } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp index 14f125c283..1af6563577 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.cpp @@ -129,7 +129,7 @@ namespace ImageProcessingAtom { AZStd::string fullPath; AZ::StringFunc::Path::Join(watchFolder.c_str(), assetInfo.m_relativePath.c_str(), fullPath); - if (RenerThumbnailFromImage(thumbnailKey, thumbnailSize, IImageObjectPtr(LoadImageFromFile(fullPath)))) + if (RenderThumbnailFromImage(thumbnailKey, thumbnailSize, IImageObjectPtr(LoadImageFromFile(fullPath)))) { return; } @@ -139,7 +139,7 @@ namespace ImageProcessingAtom auto productKey = azrtti_cast(thumbnailKey.data()); if (productKey) { - if (RenerThumbnailFromImage(thumbnailKey, thumbnailSize, Utils::LoadImageFromImageAsset(productKey->GetAssetId()))) + if (RenderThumbnailFromImage(thumbnailKey, thumbnailSize, Utils::LoadImageFromImageAsset(productKey->GetAssetId()))) { return; } @@ -149,7 +149,7 @@ namespace ImageProcessingAtom thumbnailKey, &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender); } - bool ImageThumbnailSystemComponent::RenerThumbnailFromImage( + bool ImageThumbnailSystemComponent::RenderThumbnailFromImage( AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize, IImageObjectPtr previewImage) const { if (!previewImage) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h index 943857fd35..ca2453b532 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnailSystemComponent.h @@ -52,7 +52,7 @@ namespace ImageProcessingAtom bool Installed() const override; void RenderThumbnail(AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize) override; - bool RenerThumbnailFromImage( + bool RenderThumbnailFromImage( AzToolsFramework::Thumbnailer::SharedThumbnailKey thumbnailKey, int thumbnailSize, IImageObjectPtr previewImage) const; }; } // namespace Thumbnails diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset index dcbaea96aa..01595a3425 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset @@ -7,7 +7,10 @@ "UUID": "{2828FBFE-BDF9-45A7-9370-F93822719CCF}", "Name": "UserInterface_Compressed", "SuppressEngineReduce": true, - "PixelFormat": "R8G8B8X8" + "PixelFormat": "R8G8B8A8", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ "_ui" ] }, "PlatformsPresets": { "es3": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset index 5ccaa3ac16..78c63790ab 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Lossless.preset @@ -7,32 +7,35 @@ "UUID": "{83003128-F63E-422B-AEC2-68F0A947225F}", "Name": "UserInterface_Lossless", "SuppressEngineReduce": true, - "PixelFormat": "R8G8B8X8" + "PixelFormat": "R8G8B8A8", + "SourceColor": "Linear", + "DestColor": "Linear", + "FileMasks": [ "_ui" ] }, "PlatformsPresets": { "es3": { "UUID": "{83003128-F63E-422B-AEC2-68F0A947225F}", "Name": "UserInterface_Lossless", "SuppressEngineReduce": true, - "PixelFormat": "R8G8B8X8" + "PixelFormat": "R8G8B8A8" }, "ios": { "UUID": "{83003128-F63E-422B-AEC2-68F0A947225F}", "Name": "UserInterface_Lossless", "SuppressEngineReduce": true, - "PixelFormat": "R8G8B8X8" + "PixelFormat": "R8G8B8A8" }, "osx_gl": { "UUID": "{83003128-F63E-422B-AEC2-68F0A947225F}", "Name": "UserInterface_Lossless", "SuppressEngineReduce": true, - "PixelFormat": "R8G8B8X8" + "PixelFormat": "R8G8B8A8" }, "provo": { "UUID": "{83003128-F63E-422B-AEC2-68F0A947225F}", "Name": "UserInterface_Lossless", "SuppressEngineReduce": true, - "PixelFormat": "R8G8B8X8" + "PixelFormat": "R8G8B8A8" } } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.azsl index c1fa41991e..8294911b44 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/SsaoCompute.azsl @@ -277,6 +277,8 @@ void MainCS(uint3 thread_id : SV_GroupThreadID, uint3 group_id : SV_GroupID, uin // Gather depth values float2 depthGatherUV = mad(float2(ldsPosition), GetPixelSize(), ldsOffsetUV); + // Gather on some GPUs will fall onto same pixels in adjacent coordinates due to rounding errors + depthGatherUV += GetHalfPixelSize(); float4 depthGather = PassSrg::m_linearDepth.Gather(PassSrg::PointSampler, depthGatherUV); WriteDepthGatherToLDS(ldsPosition, depthGather); diff --git a/Gems/Atom/Feature/Common/Code/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/CMakeLists.txt index 93da352c6e..6f087edefe 100644 --- a/Gems/Atom/Feature/Common/Code/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/CMakeLists.txt @@ -30,7 +30,6 @@ ly_add_target( PUBLIC Include Source - 3rdParty/ACES COMPILE_DEFINITIONS PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS @@ -58,6 +57,7 @@ ly_add_target( ${pal_source_dir} PUBLIC Include + 3rdParty/ACES COMPILE_DEFINITIONS PRIVATE IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h index a89875aaa6..ff84f77a3e 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h @@ -36,10 +36,11 @@ namespace AZ void RemoveProbe(ReflectionProbeHandle& probe) override; void SetProbeOuterExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& outerExtents) override; void SetProbeInnerExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& innerExtents) override; - void SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance& cubeMapImage) override; + void SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance& cubeMapImage, const AZStd::string& relativePath) override; void SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) override; - void BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback) override; - void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) override; + void BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback, const AZStd::string& relativePath) override; + bool CheckCubeMapAssetNotification(const AZStd::string& relativePath, Data::Asset& outCubeMapAsset, CubeMapAssetNotificationType& outNotificationType) override; + bool IsCubeMapReferenced(const AZStd::string& relativePath) override; bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const override { return (probe.get() != nullptr); } void ShowProbeVisualization(const ReflectionProbeHandle& probe, bool showVisualization) override; @@ -72,10 +73,9 @@ namespace AZ // AssetBus::MultiHandler overrides... void OnAssetReady(Data::Asset asset) override; void OnAssetError(Data::Asset asset) override; - void OnAssetReloaded(Data::Asset asset) override; // notifies and removes the notification entry - void HandleAssetNotification(Data::Asset asset, CubeMapAssetNotificationType notificationTyp); + void HandleAssetNotification(Data::Asset asset, CubeMapAssetNotificationType notificationType); // list of reflection probes const size_t InitialProbeAllocationSize = 64; @@ -86,9 +86,8 @@ namespace AZ { AZStd::string m_relativePath; AZ::Data::AssetId m_assetId; - bool m_existingAsset = false; - NotifyCubeMapAssetReadyCallback m_callback; Data::Asset m_asset; + CubeMapAssetNotificationType m_notificationType = CubeMapAssetNotificationType::None; }; typedef AZStd::vector NotifyCubeMapAssetVector; NotifyCubeMapAssetVector m_notifyCubeMapAssets; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h index 8b277e97c8..03c44d0442 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h @@ -30,11 +30,11 @@ namespace AZ enum CubeMapAssetNotificationType { + None, Ready, Error, Reloaded }; - using NotifyCubeMapAssetReadyCallback = AZStd::function& cubeMapAsset, CubeMapAssetNotificationType notificationType)>; // ReflectionProbeFeatureProcessorInterface provides an interface to the feature processor for code outside of Atom class ReflectionProbeFeatureProcessorInterface @@ -47,10 +47,11 @@ namespace AZ virtual void RemoveProbe(ReflectionProbeHandle& handle) = 0; virtual void SetProbeOuterExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& outerExtents) = 0; virtual void SetProbeInnerExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& innerExtents) = 0; - virtual void SetProbeCubeMap(const ReflectionProbeHandle& handle, Data::Instance& cubeMapImage) = 0; + virtual void SetProbeCubeMap(const ReflectionProbeHandle& handle, Data::Instance& cubeMapImage, const AZStd::string& relativePath) = 0; virtual void SetProbeTransform(const ReflectionProbeHandle& handle, const AZ::Transform& transform) = 0; - virtual void BakeProbe(const ReflectionProbeHandle& handle, BuildCubeMapCallback callback) = 0; - virtual void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) = 0; + virtual void BakeProbe(const ReflectionProbeHandle& handle, BuildCubeMapCallback callback, const AZStd::string& relativePath) = 0; + virtual bool CheckCubeMapAssetNotification(const AZStd::string& relativePath, Data::Asset& outCubeMapAsset, CubeMapAssetNotificationType& outNotificationType) = 0; + virtual bool IsCubeMapReferenced(const AZStd::string& relativePath) = 0; virtual bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const = 0; virtual void ShowProbeVisualization(const ReflectionProbeHandle& probe, bool showVisualization) = 0; }; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h index f1d8337a35..e79dc6d29e 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/LightingPreset.h @@ -61,13 +61,14 @@ namespace AZ AZ_TYPE_INFO(AZ::Render::LightConfig, "{02644F52-9483-47A8-9028-37671695C34E}"); static void Reflect(AZ::ReflectContext* context); - AZ::Vector3 m_direction = AZ::Vector3::CreateAxisY(); + // Setting default direction to produce a visible shadow + AZ::Vector3 m_direction = AZ::Vector3(1.0f / 3.0f, 1.0f / 3.0f, -1.0f / 3.0f); AZ::Color m_color = AZ::Color::CreateOne(); float m_intensity = 1.0f; - uint16_t m_shadowCascadeCount = 1; - float m_shadowRatioLogarithmUniform = 0.5f; + uint16_t m_shadowCascadeCount = 4; + float m_shadowRatioLogarithmUniform = 1.0f; float m_shadowFarClipDistance = 20.0f; - ShadowmapSize m_shadowmapSize = ShadowmapSize::Size1024; + ShadowmapSize m_shadowmapSize = ShadowmapSize::Size2048; bool m_enableShadowDebugColoring = false; }; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 0826739119..e0b79e23aa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -120,13 +120,13 @@ namespace AZ { // stencil Srg // Note: the stencil pass uses a slightly reduced inner AABB to avoid seams - Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f); - Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_position) * Matrix3x4::CreateScale(innerExtentsReduced); + Vector3 innerExtentsReduced = m_innerExtents * m_transform.GetScale() - Vector3(0.1f, 0.1f, 0.1f); + Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced); m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil); m_stencilSrg->Compile(); // blend weight Srg - Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_position) * Matrix3x4::CreateScale(m_outerExtents); + Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents * m_transform.GetScale()); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); @@ -149,7 +149,7 @@ namespace AZ m_renderOuterSrg->Compile(); // render inner Srg - Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_position) * Matrix3x4::CreateScale(m_innerExtents); + Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents * m_transform.GetScale()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldInner); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); @@ -208,30 +208,36 @@ namespace AZ void ReflectionProbe::SetTransform(const AZ::Transform& transform) { - m_position = transform.GetTranslation(); - m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, transform); - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f); - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f); + m_transform = transform; + + // avoid scaling the visualization sphere + AZ::Transform visualizationTransform = m_transform; + visualizationTransform.ExtractScale(); + m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, visualizationTransform); + + m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f); + m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetOuterExtents(const AZ::Vector3& outerExtents) { m_outerExtents = outerExtents; - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f); + m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetInnerExtents(const AZ::Vector3& innerExtents) { m_innerExtents = innerExtents; - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f); + m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f); m_updateSrg = true; } - void ReflectionProbe::SetCubeMapImage(const Data::Instance& cubeMapImage) + void ReflectionProbe::SetCubeMapImage(const Data::Instance& cubeMapImage, const AZStd::string& relativePath) { m_cubeMapImage = cubeMapImage; + m_cubeMapRelativePath = relativePath; m_updateSrg = true; } @@ -261,7 +267,7 @@ namespace AZ m_environmentCubeMapPipelineId = environmentCubeMapPipeline->GetId(); AZStd::shared_ptr passData = AZStd::make_shared(); - passData->m_position = m_position; + passData->m_position = m_transform.GetTranslation(); RPI::PassDescriptor environmentCubeMapPassDescriptor(Name("EnvironmentCubeMapPass")); environmentCubeMapPassDescriptor.m_passData = passData; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 22645a4ed3..ab0e7a81d3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -75,20 +75,22 @@ namespace AZ void Init(RPI::Scene* scene, ReflectionRenderData* reflectionRenderData); void Simulate(uint32_t probeIndex); - const Vector3& GetPosition() const { return m_position; } + const Vector3& GetPosition() const { return m_transform.GetTranslation(); } void SetTransform(const AZ::Transform& transform); - const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } + AZ::Vector3 GetOuterExtents() const { return m_outerExtents * m_transform.GetScale(); } void SetOuterExtents(const AZ::Vector3& outerExtents); - const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; } + AZ::Vector3 GetInnerExtents() const { return m_innerExtents * m_transform.GetScale(); } void SetInnerExtents(const AZ::Vector3& innerExtents); const Aabb& GetOuterAabbWs() const { return m_outerAabbWs; } const Aabb& GetInnerAabbWs() const { return m_innerAabbWs; } const Data::Instance& GetCubeMapImage() const { return m_cubeMapImage; } - void SetCubeMapImage(const Data::Instance& cubeMapImage); + void SetCubeMapImage(const Data::Instance& cubeMapImage, const AZStd::string& relativePath); + + const AZStd::string& GetCubeMapRelativePath() const { return m_cubeMapRelativePath; } bool GetUseParallaxCorrection() const { return m_useParallaxCorrection; } void SetUseParallaxCorrection(bool useParallaxCorrection) { m_useParallaxCorrection = useParallaxCorrection; } @@ -122,8 +124,8 @@ namespace AZ // scene RPI::Scene* m_scene = nullptr; - // probe capture position - AZ::Vector3 m_position = AZ::Vector3(0.0f, 0.0f, 0.0f); + // probe volume transform + AZ::Transform m_transform = AZ::Transform::CreateIdentity(); // extents of the probe volume AZ::Vector3 m_outerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); @@ -135,6 +137,7 @@ namespace AZ // cubemap Data::Instance m_cubeMapImage; + AZStd::string m_cubeMapRelativePath; bool m_useParallaxCorrection = false; // probe visualization diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index a0d3e6ac51..740069fc6b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -178,9 +178,9 @@ namespace AZ if (assetId.IsValid()) { - Data::AssetBus::MultiHandler::BusConnect(assetId); notificationEntry.m_assetId = assetId; notificationEntry.m_asset.Create(assetId, true); + Data::AssetBus::MultiHandler::BusConnect(assetId); } } @@ -257,10 +257,10 @@ namespace AZ m_probeSortRequired = true; } - void ReflectionProbeFeatureProcessor::SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance& cubeMapImage) + void ReflectionProbeFeatureProcessor::SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance& cubeMapImage, const AZStd::string& relativePath) { AZ_Assert(probe.get(), "SetProbeCubeMap called with an invalid handle"); - probe->SetCubeMapImage(cubeMapImage); + probe->SetCubeMapImage(cubeMapImage, relativePath); } void ReflectionProbeFeatureProcessor::SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) @@ -270,14 +270,11 @@ namespace AZ m_probeSortRequired = true; } - void ReflectionProbeFeatureProcessor::BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback) + void ReflectionProbeFeatureProcessor::BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback, const AZStd::string& relativePath) { AZ_Assert(probe.get(), "BakeProbe called with an invalid handle"); probe->BuildCubeMap(callback); - } - void ReflectionProbeFeatureProcessor::NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) - { // check to see if this is an existing asset AZ::Data::AssetId assetId; AZ::Data::AssetCatalogRequestBus::BroadcastResult( @@ -287,15 +284,46 @@ namespace AZ azrtti_typeid(), false); - bool existingAsset = assetId.IsValid(); - m_notifyCubeMapAssets.push_back({ relativePath, assetId, existingAsset, callback }); - - if (existingAsset) + // we only track notifications for new cubemap assets, existing assets are automatically reloaded by the RPI + if (!assetId.IsValid()) { - Data::AssetBus::MultiHandler::BusConnect(assetId); + m_notifyCubeMapAssets.push_back({ relativePath, assetId }); } } + bool ReflectionProbeFeatureProcessor::CheckCubeMapAssetNotification(const AZStd::string& relativePath, Data::Asset& outCubeMapAsset, CubeMapAssetNotificationType& outNotificationType) + { + for (NotifyCubeMapAssetVector::iterator itNotification = m_notifyCubeMapAssets.begin(); itNotification != m_notifyCubeMapAssets.end(); ++itNotification) + { + if (itNotification->m_relativePath == relativePath) + { + outNotificationType = itNotification->m_notificationType; + if (outNotificationType != CubeMapAssetNotificationType::None) + { + outCubeMapAsset = itNotification->m_asset; + m_notifyCubeMapAssets.erase(itNotification); + } + + return true; + } + } + + return false; + } + + bool ReflectionProbeFeatureProcessor::IsCubeMapReferenced(const AZStd::string& relativePath) + { + for (auto& reflectionProbe : m_reflectionProbes) + { + if (reflectionProbe->GetCubeMapRelativePath() == relativePath) + { + return true; + } + } + + return false; + } + void ReflectionProbeFeatureProcessor::ShowProbeVisualization(const ReflectionProbeHandle& probe, bool showVisualization) { AZ_Assert(probe.get(), "ShowProbeVisualization called with an invalid handle"); @@ -509,17 +537,9 @@ namespace AZ { if (itNotification->m_assetId == asset.GetId()) { - if (itNotification->m_existingAsset && notificationType == CubeMapAssetNotificationType::Ready) - { - // existing cubemap assets only notify on reload or error - break; - } - - // notify - itNotification->m_callback(Data::static_pointer_cast(asset), notificationType); - - // remove the entry from the list - m_notifyCubeMapAssets.erase(itNotification); + // store the cubemap asset + itNotification->m_asset = Data::static_pointer_cast(asset); + itNotification->m_notificationType = notificationType; // stop notifications on this asset Data::AssetBus::MultiHandler::BusDisconnect(itNotification->m_assetId); @@ -540,11 +560,5 @@ namespace AZ HandleAssetNotification(asset, CubeMapAssetNotificationType::Error); } - - void ReflectionProbeFeatureProcessor::OnAssetReloaded(Data::Asset asset) - { - HandleAssetNotification(asset, CubeMapAssetNotificationType::Reloaded); - } - } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp b/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp index 77924b87a3..91ad31648b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Utils/LightingPreset.cpp @@ -30,7 +30,7 @@ namespace AZ if (auto serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(3) + ->Version(4) ->Field("compensateValue", &ExposureControlConfig::m_manualCompensationValue) ->Field("exposureControlType", &ExposureControlConfig::m_exposureControlType) ->Field("autoExposureMin", &ExposureControlConfig::m_autoExposureMin) diff --git a/Gems/Atom/RHI/Code/Tests/Buffer.h b/Gems/Atom/RHI/Code/Tests/Buffer.h index cfa216293f..a5538b0071 100644 --- a/Gems/Atom/RHI/Code/Tests/Buffer.h +++ b/Gems/Atom/RHI/Code/Tests/Buffer.h @@ -30,6 +30,8 @@ namespace UnitTest void ShutdownInternal() override; }; + class BufferPool; + class Buffer : public AZ::RHI::Buffer { diff --git a/Gems/Atom/RHI/Code/Tests/Query.h b/Gems/Atom/RHI/Code/Tests/Query.h index 6220ae5f55..80b47f3e42 100644 --- a/Gems/Atom/RHI/Code/Tests/Query.h +++ b/Gems/Atom/RHI/Code/Tests/Query.h @@ -21,7 +21,6 @@ namespace UnitTest class Query : public AZ::RHI::Query { - friend class QueryPool; public: AZ_CLASS_ALLOCATOR(Query, AZ::SystemAllocator, 0); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphExecuteGroupBase.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphExecuteGroupBase.cpp index 809790a7d5..6251eca7dc 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphExecuteGroupBase.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphExecuteGroupBase.cpp @@ -32,7 +32,7 @@ namespace AZ AZ_Assert(commandList && commandList->IsRecording() == false, "Command list not valid."); } } -#endif() +#endif return AZStd::move(m_workRequest); } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt index fb4750ce93..4cd6ad8182 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt @@ -33,6 +33,7 @@ ly_add_target( AZ::AzQtComponents 3rdParty::Qt::Core 3rdParty::Qt::Gui + 3rdParty::Qt::Network 3rdParty::Qt::Widgets 3rdParty::Python Gem::Atom_RPI.Edit diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Communication/LocalServer.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Communication/LocalServer.h new file mode 100644 index 0000000000..4482566113 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Communication/LocalServer.h @@ -0,0 +1,56 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#include +#include +#include +#include +#endif + +namespace AtomToolsFramework +{ + //! A named local server that will manage connections and forward recieved data + class LocalServer : public QObject + { + Q_OBJECT + public: + LocalServer(); + ~LocalServer(); + + //! Start a named local server + bool Connect(const QString& serverName); + + //! Stop the server + void Disconnect(); + + //! Get server status + bool IsConnected() const; + + using ReadHandler = AZStd::function; + + //! Set a handler that recieved data will be forwarded to + void SetReadHandler(ReadHandler handler); + + private: + void AddConnection(QLocalSocket* connection); + void ReadFromConnection(QLocalSocket* connection); + void DeleteConnection(QLocalSocket* connection); + + QString m_serverName; + QLocalServer m_server; + ReadHandler m_readHandler; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Communication/LocalSocket.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Communication/LocalSocket.h new file mode 100644 index 0000000000..4eb4d533ed --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Communication/LocalSocket.h @@ -0,0 +1,45 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +#if !defined(Q_MOC_RUN) +#include +#endif + +namespace AtomToolsFramework +{ + //! LocalSocket enables interprocess communication by establ;ishing a connection and sending data to a LocalServer + class LocalSocket : public QObject + { + Q_OBJECT + public: + LocalSocket(); + ~LocalSocket(); + + //! Attempt to connect to a named local server + bool Connect(const QString& serverName); + + //! Sever connection from server + void Disconnect(); + + //! Get the sockets connection status + bool IsConnected() const; + + //! Send a stream of data to the connected local server + bool Send(const QByteArray& buffer); + + private: + QString m_serverName; + QLocalSocket m_socket; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Communication/LocalServer.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Communication/LocalServer.cpp new file mode 100644 index 0000000000..6f26b00c4f --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Communication/LocalServer.cpp @@ -0,0 +1,108 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include + +namespace AtomToolsFramework +{ + LocalServer::LocalServer() + { + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Creating local server\n"); + m_server.setSocketOptions(QLocalServer::WorldAccessOption); + + QObject::connect(&m_server, &QLocalServer::newConnection, this, [this]() { AddConnection(m_server.nextPendingConnection()); }); + } + + LocalServer::~LocalServer() + { + Disconnect(); + } + + bool LocalServer::Connect(const QString& serverName) + { + Disconnect(); + + m_serverName = serverName; + + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting: %s\n", m_serverName.toUtf8().constData()); + if (m_server.listen(m_serverName)) + { + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Started: %s\n", m_serverName.toUtf8().constData()); + return true; + } + + if (m_server.serverError() == QAbstractSocket::AddressInUseError) + { + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Restarting: %s\n", m_serverName.toUtf8().constData()); + Disconnect(); + + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting: %s\n", m_serverName.toUtf8().constData()); + if (m_server.listen(m_serverName)) + { + return true; + } + } + + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Starting failed: %s\n", m_serverName.toUtf8().constData()); + Disconnect(); + return false; + } + + void LocalServer::Disconnect() + { + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Disconnecting: %s\n", m_serverName.toUtf8().constData()); + QLocalServer::removeServer(m_serverName); + } + + bool LocalServer::IsConnected() const + { + return m_server.isListening(); + } + + void LocalServer::SetReadHandler(LocalServer::ReadHandler handler) + { + m_readHandler = handler; + } + + void LocalServer::AddConnection(QLocalSocket* connection) + { + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Connection added: %s\n", m_serverName.toUtf8().constData()); + QObject::connect(connection, &QLocalSocket::readyRead, this, [this, connection]() { ReadFromConnection(connection); }); + QObject::connect(connection, &QLocalSocket::disconnected, this, [this, connection]() { DeleteConnection(connection); }); + } + + void LocalServer::ReadFromConnection(QLocalSocket* connection) + { + if (connection) + { + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Data received: %s\n", m_serverName.toUtf8().constData()); + QByteArray buffer = connection->readAll(); + if (m_readHandler) + { + m_readHandler(buffer); + } + } + } + + void LocalServer::DeleteConnection(QLocalSocket* connection) + { + if (connection) + { + AZ_TracePrintf("AtomToolsFramework::LocalServer", "Deleting connection: %s\n", m_serverName.toUtf8().constData()); + connection->deleteLater(); + } + } +} // namespace AtomToolsFramework + +#include diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Communication/LocalSocket.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Communication/LocalSocket.cpp new file mode 100644 index 0000000000..020998bf1a --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Communication/LocalSocket.cpp @@ -0,0 +1,86 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include +#include + +namespace AtomToolsFramework +{ + LocalSocket::LocalSocket() + { + } + + LocalSocket::~LocalSocket() + { + Disconnect(); + } + + bool LocalSocket::Connect(const QString& serverName) + { + Disconnect(); + + m_serverName = serverName; + + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connecting to: %s\n", m_serverName.toUtf8().constData()); + m_socket.connectToServer(m_serverName); + + if (IsConnected()) + { + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Waiting for connection to: %s\n", m_serverName.toUtf8().constData()); + if (m_socket.waitForConnected()) + { + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connected to: %s\n", m_serverName.toUtf8().constData()); + return true; + } + } + + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Connecting failed: %s\n", m_serverName.toUtf8().constData()); + Disconnect(); + return false; + } + + void LocalSocket::Disconnect() + { + if (IsConnected()) + { + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Disconnecting from: %s\n", m_serverName.toUtf8().constData()); + m_socket.disconnectFromServer(); + m_socket.waitForDisconnected(); + + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Closing socket\n"); + m_socket.close(); + } + } + + bool LocalSocket::IsConnected() const + { + return m_socket.isOpen(); + } + + bool LocalSocket::Send(const QByteArray& buffer) + { + if (IsConnected()) + { + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Sending data to: %s\n", m_serverName.toUtf8().constData()); + m_socket.write(buffer); + + AZ_TracePrintf("AtomToolsFramework::LocalSocket", "Waiting for write to: %s\n", m_serverName.toUtf8().constData()); + m_socket.waitForBytesWritten(); + return true; + } + return false; + } +} // namespace AtomToolsFramework + +#include diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp index 5784355498..8afd1dc8d5 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/DynamicProperty/DynamicProperty.cpp @@ -211,10 +211,7 @@ namespace AtomToolsFramework AZStd::string DynamicProperty::GetDescription() const { - return AZStd::string::format("%s%s(Script Name = '%s')", - m_config.m_description.c_str(), - m_config.m_description.empty() ? "" : "\n", - m_config.m_id.GetCStr()); + return m_config.m_description; } AZ::Crc32 DynamicProperty::GetVisibility() const diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp index 952e241143..41a627bef7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Util/MaterialPropertyUtil.cpp @@ -91,6 +91,13 @@ namespace AtomToolsFramework propertyConfig.m_vectorLabels = propertyDefinition.m_vectorLabels; propertyConfig.m_visible = propertyDefinition.m_visibility != AZ::RPI::MaterialPropertyVisibility::Hidden; propertyConfig.m_readOnly = propertyDefinition.m_visibility == AZ::RPI::MaterialPropertyVisibility::Disabled; + + // Update the description for material properties to include script name assuming id is set beforehand + propertyConfig.m_description = AZStd::string::format( + "%s%s(Script Name = '%s')", + propertyConfig.m_description.c_str(), + propertyConfig.m_description.empty() ? "" : "\n", + propertyConfig.m_id.GetCStr()); } void ConvertToPropertyConfig(AtomToolsFramework::DynamicPropertyConfig& propertyConfig, const AZ::RPI::MaterialPropertyDynamicMetadata& propertyMetaData) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index e8539711f7..d8ceccc724 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -10,6 +10,8 @@ # set(FILES + Include/AtomToolsFramework/Communication/LocalServer.h + Include/AtomToolsFramework/Communication/LocalSocket.h Include/AtomToolsFramework/Debug/TraceRecorder.h Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h @@ -22,6 +24,8 @@ set(FILES Include/AtomToolsFramework/Util/MaterialPropertyUtil.h Include/AtomToolsFramework/Util/Util.h Include/AtomToolsFramework/Viewport/RenderViewportWidget.h + Source/Communication/LocalServer.cpp + Source/Communication/LocalSocket.cpp Source/Debug/TraceRecorder.cpp Source/DynamicProperty/DynamicProperty.cpp Source/DynamicProperty/DynamicPropertyGroup.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt index 40d6a8f30a..134f605200 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt @@ -93,6 +93,7 @@ ly_add_target( ly_add_target( NAME MaterialEditor EXECUTABLE NAMESPACE Gem + AUTOMOC FILES_CMAKE materialeditor_files.cmake Source/Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h index 84406d8402..0727547b13 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportNotificationBus.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include #include @@ -66,6 +67,9 @@ namespace MaterialEditor //! Notify when field of view changes virtual void OnFieldOfViewChanged([[maybe_unused]] float fieldOfView) {} + + //! Notify when tone mapping changes + virtual void OnDisplayMapperOperationTypeChanged([[maybe_unused]] AZ::Render::DisplayMapperOperationType operationType) {} }; using MaterialViewportNotificationBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h index ea6be4f21a..0c9b6e945d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Viewport/MaterialViewportRequestBus.h @@ -11,6 +11,7 @@ */ #pragma once +#include #include #include #include @@ -147,6 +148,12 @@ namespace MaterialEditor //! Get field of view virtual float GetFieldOfView() const = 0; + + //! Set tone mapping type + virtual void SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) = 0; + + //! Get tone mapping type + virtual AZ::Render::DisplayMapperOperationType GetDisplayMapperOperationType() const = 0; }; using MaterialViewportRequestBus = AZ::EBus; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h index 538777b762..55e6ddac20 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Window/MaterialEditorWindowRequestBus.h @@ -28,6 +28,9 @@ namespace MaterialEditor static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + //! Bring main window to foreground + virtual void ActivateWindow() = 0; + //! Add dockable widget in main window //! @param name title of the dockable window //! @param widget docked window content diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp index 3919684864..288530a4e4 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp @@ -762,6 +762,8 @@ namespace MaterialEditor // in the hierarchy are applied m_materialTypeSourceData.EnumerateProperties([this, &parentPropertyValues](const AZStd::string& groupNameId, const AZStd::string& propertyNameId, const auto& propertyDefinition) { AtomToolsFramework::DynamicPropertyConfig propertyConfig; + + // Assign id before conversion so it can be used in dynamic description propertyConfig.m_id = MaterialPropertyId(groupNameId, propertyNameId).GetCStr(); const auto& propertyIndex = m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id); @@ -792,7 +794,8 @@ namespace MaterialEditor propertyConfig.m_nameId = "materialType"; propertyConfig.m_displayName = "Material Type"; propertyConfig.m_groupName = "Details"; - propertyConfig.m_description = propertyConfig.m_displayName; + propertyConfig.m_description = "The material type defines the layout, properties, default values, shader connections, and other " + "data needed to create and edit a derived material."; propertyConfig.m_defaultValue = AZStd::any(materialTypeAsset); propertyConfig.m_originalValue = propertyConfig.m_defaultValue; propertyConfig.m_parentValue = propertyConfig.m_defaultValue; @@ -806,7 +809,8 @@ namespace MaterialEditor propertyConfig.m_nameId = "parentMaterial"; propertyConfig.m_displayName = "Parent Material"; propertyConfig.m_groupName = "Details"; - propertyConfig.m_description = propertyConfig.m_displayName; + propertyConfig.m_description = + "The parent material provides an initial configuration whose properties are inherited and overriden by a derived material."; propertyConfig.m_defaultValue = AZStd::any(parentMaterialAsset); propertyConfig.m_originalValue = propertyConfig.m_defaultValue; propertyConfig.m_parentValue = propertyConfig.m_defaultValue; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp index a7aecf0b1f..b1a795b9f9 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentModule.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -32,7 +31,6 @@ namespace MaterialEditor return AZ::ComponentTypeList{ azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), }; } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index 2fd1aac211..dbb1d18e49 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -109,7 +109,6 @@ namespace MaterialEditor void MaterialDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("TargetManagerService", 0x6d5708bc)); required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); @@ -135,31 +134,16 @@ namespace MaterialEditor m_documentMap.clear(); MaterialDocumentSystemRequestBus::Handler::BusConnect(); MaterialDocumentNotificationBus::Handler::BusConnect(); - AzFramework::TmMsgBus::Handler::BusConnect(AZ_CRC("OpenInMaterialEditor", 0x9f92aac8)); } void MaterialDocumentSystemComponent::Deactivate() { AZ::TickBus::Handler::BusDisconnect(); - AzFramework::TmMsgBus::Handler::BusDisconnect(); MaterialDocumentNotificationBus::Handler::BusDisconnect(); MaterialDocumentSystemRequestBus::Handler::BusDisconnect(); m_documentMap.clear(); } - void MaterialDocumentSystemComponent::OnReceivedMsg(AzFramework::TmMsgPtr msg) - { - if (msg->GetId() == AZ_CRC("OpenInMaterialEditor", 0x9f92aac8)) - { - const char* documentPath = reinterpret_cast(msg->GetCustomBlob()); - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, documentPath); - } - else - { - AZ_Assert(false, "We received a message of an unrecognized class type!"); - } - } - AZ::Uuid MaterialDocumentSystemComponent::CreateDocument() { auto document = AZStd::make_unique(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h index b6c541421d..4b0ee424a7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -35,7 +34,6 @@ namespace MaterialEditor class MaterialDocumentSystemComponent : public AZ::Component , private AZ::TickBus::Handler - , private AzFramework::TmMsgBus::Handler , private MaterialDocumentNotificationBus::Handler , private MaterialDocumentSystemRequestBus::Handler { @@ -72,11 +70,6 @@ namespace MaterialEditor void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; //////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AzFramework::TmMsgBus::Handler overrides... - void OnReceivedMsg(AzFramework::TmMsgPtr msg) override; - ////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// // MaterialDocumentSystemRequestBus::Handler overrides... AZ::Uuid CreateDocument() override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp index 66be1c23bb..1f32c2a66b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.cpp @@ -45,6 +45,7 @@ #include #include +#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT @@ -90,6 +91,14 @@ namespace MaterialEditor }); } + MaterialEditorApplication::~MaterialEditorApplication() + { + AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); + MaterialEditorWindowNotificationBus::Handler::BusDisconnect(); + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + void MaterialEditorApplication::CreateReflectionManager() { Application::CreateReflectionManager(); @@ -299,12 +308,19 @@ namespace MaterialEditor return false; } - void MaterialEditorApplication::ProcessCommandLine() + void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine) { - const AZStd::string timeoputSwitchName = "timeout"; - if (m_commandLine.HasSwitch(timeoputSwitchName)) + const AZStd::string activateWindowSwitchName = "activatewindow"; + if (commandLine.HasSwitch(activateWindowSwitchName)) { - const AZStd::string& timeoutValue = m_commandLine.GetSwitchValue(timeoputSwitchName, 0); + MaterialEditor::MaterialEditorWindowRequestBus::Broadcast( + &MaterialEditor::MaterialEditorWindowRequestBus::Handler::ActivateWindow); + } + + const AZStd::string timeoputSwitchName = "timeout"; + if (commandLine.HasSwitch(timeoputSwitchName)) + { + const AZStd::string& timeoutValue = commandLine.GetSwitchValue(timeoputSwitchName, 0); const uint32_t timeoutInMs = atoi(timeoutValue.c_str()); AZ_Printf("MaterialEditor", "Timeout scheduled, shutting down in %u ms", timeoutInMs); QTimer::singleShot(timeoutInMs, [this] { @@ -315,10 +331,10 @@ namespace MaterialEditor // Process command line options for running one or more python scripts on startup const AZStd::string runPythonScriptSwitchName = "runpython"; - size_t runPythonScriptCount = m_commandLine.GetNumSwitchValues(runPythonScriptSwitchName); + size_t runPythonScriptCount = commandLine.GetNumSwitchValues(runPythonScriptSwitchName); for (size_t runPythonScriptIndex = 0; runPythonScriptIndex < runPythonScriptCount; ++runPythonScriptIndex) { - const AZStd::string runPythonScriptPath = m_commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); + const AZStd::string runPythonScriptPath = commandLine.GetSwitchValue(runPythonScriptSwitchName, runPythonScriptIndex); AZStd::vector runPythonArgs; AZ_Printf("MaterialEditor", "Launching script: %s", runPythonScriptPath.c_str()); @@ -329,17 +345,17 @@ namespace MaterialEditor } // Process command line options for opening one or more material documents on startup - size_t openDocumentCount = m_commandLine.GetNumMiscValues(); + size_t openDocumentCount = commandLine.GetNumMiscValues(); for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex) { - const AZStd::string openDocumentPath = m_commandLine.GetMiscValue(openDocumentIndex); + const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex); AZ_Printf("MaterialEditor", "Opening document: %s", openDocumentPath.c_str()); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath); } const AZStd::string exitAfterCommandsSwitchName = "exitaftercommands"; - if (m_commandLine.HasSwitch(exitAfterCommandsSwitchName)) + if (commandLine.HasSwitch(exitAfterCommandsSwitchName)) { ExitMainLoop(); } @@ -409,9 +425,56 @@ namespace MaterialEditor bool MaterialEditorApplication::LaunchDiscoveryService() { - const QStringList arguments = { "-fail_silently" }; + // Determine if this is the first launch of the tool by attempting to connect to a running server + if (m_socket.Connect(QApplication::applicationName())) + { + // If the server was located, the application is already running. + // Forward commandline options to other application instance. + QByteArray buffer; + buffer.append("ProcessCommandLine:"); - return AtomToolsFramework::LaunchTool("GridHub", AZ_TRAIT_MATERIALEDITOR_EXT, arguments); + // Add the command line options from this process to the message, skipping the executable path + for (int argi = 1; argi < m_argC; ++argi) + { + buffer.append(QString(m_argV[argi]).append("\n").toUtf8()); + } + + // Inject command line option to always bring the main window to the foreground + buffer.append("--activatewindow\n"); + + m_socket.Send(buffer); + m_socket.Disconnect(); + return false; + } + + // Setup server to handle basic commands + m_server.SetReadHandler([this](const QByteArray& buffer) { + // Handle commmand line params from connected socket + if (buffer.startsWith("ProcessCommandLine:")) + { + // Remove header and parse commands + AZStd::string params(buffer.data(), buffer.size()); + params = params.substr(strlen("ProcessCommandLine:")); + + AZStd::vector tokens; + AZ::StringFunc::Tokenize(params, tokens, "\n"); + + if (!tokens.empty()) + { + AZ::CommandLine commandLine; + commandLine.Parse(tokens); + ProcessCommandLine(commandLine); + } + } + }); + + // Launch local server + if (!m_server.Connect(QApplication::applicationName())) + { + return false; + } + + return true; } void MaterialEditorApplication::StartInternal() @@ -421,10 +484,14 @@ namespace MaterialEditor return; } - //[GFX TODO][ATOM-415] Try to factor out some of this stuff with AtomSampleViewerApplication - WriteStartupLog(); + if (!LaunchDiscoveryService()) + { + ExitMainLoop(); + return; + } + AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect(); AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); @@ -434,8 +501,6 @@ namespace MaterialEditor LoadSettings(); - LaunchDiscoveryService(); - MaterialEditorWindowNotificationBus::Handler::BusConnect(); MaterialEditor::MaterialEditorWindowFactoryRequestBus::Broadcast( @@ -450,7 +515,7 @@ namespace MaterialEditor } // Delay execution of commands and scripts post initialization - QTimer::singleShot(0, [this]() { ProcessCommandLine(); }); + QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); }); } bool MaterialEditorApplication::GetAssetDatabaseLocation(AZStd::string& result) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h index 63ccbf3cec..2c66fd7c16 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/MaterialEditorApplication.h @@ -12,22 +12,20 @@ #pragma once - +#include +#include +#include +#include #include #include -#include #include - +#include #include #include #include - #include #include -#include -#include - #include #include @@ -51,7 +49,7 @@ namespace MaterialEditor using Base = AzFramework::Application; MaterialEditorApplication(int* argc, char*** argv); - virtual ~MaterialEditorApplication() = default; + virtual ~MaterialEditorApplication(); ////////////////////////////////////////////////////////////////////////// // AzFramework::Application @@ -110,7 +108,7 @@ namespace MaterialEditor void CompileCriticalAssets(); - void ProcessCommandLine(); + void ProcessCommandLine(const AZ::CommandLine& commandLine); void WriteStartupLog(); void LoadSettings(); @@ -138,5 +136,8 @@ namespace MaterialEditor bool m_activatedLocalUserSettings = false; QTimer m_timer; + + AtomToolsFramework::LocalSocket m_socket; + AtomToolsFramework::LocalServer m_server; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp index d6f2092d27..abaf50804f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.cpp @@ -508,6 +508,17 @@ namespace MaterialEditor return m_fieldOfView; } + void MaterialViewportComponent::SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) + { + m_displayMapperOperationType = operationType; + MaterialViewportNotificationBus::Broadcast(&MaterialViewportNotificationBus::Events::OnDisplayMapperOperationTypeChanged, operationType); + } + + AZ::Render::DisplayMapperOperationType MaterialViewportComponent::GetDisplayMapperOperationType() const + { + return m_displayMapperOperationType; + } + void MaterialViewportComponent::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) { AZ::TickBus::QueueFunction([this]() { diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h index 036974e123..8332cb862c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportComponent.h @@ -12,6 +12,8 @@ #pragma once +#include + #include #include @@ -85,6 +87,8 @@ namespace MaterialEditor bool GetAlternateSkyboxEnabled() const override; void SetFieldOfView(float fieldOfView) override; float GetFieldOfView() const override; + void SetDisplayMapperOperationType(AZ::Render::DisplayMapperOperationType operationType) override; + AZ::Render::DisplayMapperOperationType GetDisplayMapperOperationType() const override; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -111,5 +115,6 @@ namespace MaterialEditor bool m_gridEnabled = true; bool m_alternateSkyboxEnabled = false; float m_fieldOfView = 90.0f; + AZ::Render::DisplayMapperOperationType m_displayMapperOperationType = AZ::Render::DisplayMapperOperationType::Aces; }; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index 53a2dc2ce6..5939a40db6 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -147,9 +148,11 @@ namespace MaterialEditor m_postProcessEntity->Activate(); // Init directional light processor - m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); + // Init display mapper processor + m_displayMapperFeatureProcessor = m_scene->GetFeatureProcessor(); + // Init Skybox m_skyboxFeatureProcessor = m_scene->GetFeatureProcessor(); @@ -423,6 +426,13 @@ namespace MaterialEditor MaterialEditorViewportInputControllerRequestBus::Broadcast(&MaterialEditorViewportInputControllerRequestBus::Handler::SetFieldOfView, fieldOfView); } + void MaterialViewportRenderer::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) + { + AZ::Render::DisplayMapperConfigurationDescriptor desc; + desc.m_operationType = operationType; + m_displayMapperFeatureProcessor->RegisterDisplayMapperConfiguration(desc); + } + void MaterialViewportRenderer::OnAssetReady(AZ::Data::Asset asset) { if (m_modelAssetId == asset.GetId()) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h index e014d9eada..744a887396 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h @@ -27,6 +27,11 @@ namespace AZ { + namespace Render + { + class DisplayMapperFeatureProcessorInterface; + } + class Entity; class Component; @@ -71,6 +76,7 @@ namespace MaterialEditor void OnGridEnabledChanged(bool enable) override; void OnAlternateSkyboxEnabledChanged(bool enable) override; void OnFieldOfViewChanged(float fieldOfView) override; + void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override; // AZ::Data::AssetBus::Handler interface overrides... void OnAssetReady(AZ::Data::Asset asset) override; @@ -92,6 +98,7 @@ namespace MaterialEditor AZ::RPI::RenderPipelinePtr m_renderPipeline; AZ::RPI::ScenePtr m_scene; AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr; + AZ::Render::DisplayMapperFeatureProcessorInterface* m_displayMapperFeatureProcessor = nullptr; AZ::Entity* m_cameraEntity = nullptr; AZ::Component* m_cameraComponent = nullptr; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp index 1e116b4a22..6e47de189c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.cpp @@ -129,6 +129,12 @@ namespace MaterialEditor MaterialEditorWindowRequestBus::Handler::BusDisconnect(); } + void MaterialEditorWindow::ActivateWindow() + { + activateWindow(); + raise(); + } + bool MaterialEditorWindow::AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) { auto dockWidgetItr = m_dockWidgets.find(name); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h index 6bd6e6b165..778e11275f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindow.h @@ -61,6 +61,7 @@ namespace MaterialEditor private: // MaterialEditorWindowRequestBus::Handler overrides... + void ActivateWindow() override; bool AddDockWidget(const AZStd::string& name, QWidget* widget, uint32_t area, uint32_t orientation) override; void RemoveDockWidget(const AZStd::string& name) override; void SetDockWidgetVisible(const AZStd::string& name, bool visible) override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index a1ff8da635..820cee30f9 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -50,6 +50,7 @@ namespace MaterialEditor ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "materialeditor") + ->Event("ActivateWindow", &MaterialEditorWindowRequestBus::Events::ActivateWindow) ->Event("SetDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::SetDockWidgetVisible) ->Event("IsDockWidgetVisible", &MaterialEditorWindowRequestBus::Events::IsDockWidgetVisible) ->Event("GetDockWidgetNames", &MaterialEditorWindowRequestBus::Events::GetDockWidgetNames) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp index dad4a34b1e..2af73bf436 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp @@ -38,7 +38,7 @@ namespace MaterialEditor m_toggleGrid->setCheckable(true); connect(m_toggleGrid, &QAction::triggered, [this]() { MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Events::SetGridEnabled, m_toggleGrid->isChecked()); - }); + }); bool enableGrid = false; MaterialViewportRequestBus::BroadcastResult(enableGrid, &MaterialViewportRequestBus::Events::GetGridEnabled); m_toggleGrid->setChecked(enableGrid); @@ -49,31 +49,39 @@ namespace MaterialEditor connect(m_toggleShadowCatcher, &QAction::triggered, [this]() { MaterialViewportRequestBus::Broadcast( &MaterialViewportRequestBus::Events::SetShadowCatcherEnabled, m_toggleShadowCatcher->isChecked()); - }); + }); bool enableShadowCatcher = false; MaterialViewportRequestBus::BroadcastResult(enableShadowCatcher, &MaterialViewportRequestBus::Events::GetShadowCatcherEnabled); m_toggleShadowCatcher->setChecked(enableShadowCatcher); // Add mapping selection button - //[GFX TODO][ATOM-3992] + QToolButton* toneMappingButton = new QToolButton(this); QMenu* toneMappingMenu = new QMenu(toneMappingButton); - toneMappingMenu->addAction("None", [this]() { - MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "None"); - }); - toneMappingMenu->addAction("Gamma2.2", [this]() { - MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "Gamma2.2"); - }); - toneMappingMenu->addAction("ACES", [this]() { - MaterialEditorSettingsRequestBus::Broadcast(&MaterialEditorSettingsRequests::SetStringProperty, "toneMapping", "ACES"); - }); + + m_operationNames = + { + { AZ::Render::DisplayMapperOperationType::Reinhard, "Reinhard" }, + { AZ::Render::DisplayMapperOperationType::GammaSRGB, "GammaSRGB" }, + { AZ::Render::DisplayMapperOperationType::Passthrough, "Passthrough" }, + { AZ::Render::DisplayMapperOperationType::AcesLut, "AcesLut" }, + { AZ::Render::DisplayMapperOperationType::Aces, "Aces" } + }; + for (auto operationNamePair : m_operationNames) + { + m_operationActions[operationNamePair.first] = toneMappingMenu->addAction(operationNamePair.second, [operationNamePair]() { + MaterialViewportRequestBus::Broadcast( + &MaterialViewportRequestBus::Events::SetDisplayMapperOperationType, + operationNamePair.first); + }); + m_operationActions[operationNamePair.first]->setCheckable(true); + } + m_operationActions[AZ::Render::DisplayMapperOperationType::Aces]->setChecked(true); toneMappingButton->setMenu(toneMappingMenu); toneMappingButton->setText("Tone Mapping"); toneMappingButton->setIcon(QIcon(":/Icons/toneMapping.svg")); toneMappingButton->setPopupMode(QToolButton::InstantPopup); - - // hiding button until DisplayMapper supports changing settings at run time - toneMappingButton->setVisible(false); + toneMappingButton->setVisible(true); addWidget(toneMappingButton); // Add model combo box @@ -99,6 +107,14 @@ namespace MaterialEditor m_toggleGrid->setChecked(enable); } + void MaterialEditorToolBar::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) + { + for (auto operationActionPair : m_operationActions) + { + operationActionPair.second->setChecked(operationActionPair.first == operationType); + } + } + void MaterialEditorToolBar::OnShadowCatcherEnabledChanged(bool enable) { m_toggleShadowCatcher->setChecked(enable); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h index 147608bc23..25077c1868 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.h @@ -33,8 +33,12 @@ namespace MaterialEditor // MaterialViewportNotificationBus::Handler overrides... void OnShadowCatcherEnabledChanged([[maybe_unused]] bool enable) override; void OnGridEnabledChanged([[maybe_unused]] bool enable) override; + void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override; QAction* m_toggleGrid = {}; QAction* m_toggleShadowCatcher = {}; + + AZStd::unordered_map m_operationNames; + AZStd::unordered_map m_operationActions; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp index 8efed36197..fd50ace918 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.cpp @@ -36,6 +36,7 @@ namespace MaterialEditor ->Field("enableShadowCatcher", &GeneralViewportSettings::m_enableShadowCatcher) ->Field("enableAlternateSkybox", &GeneralViewportSettings::m_enableAlternateSkybox) ->Field("fieldOfView", &GeneralViewportSettings::m_fieldOfView) + ->Field("displayMapperOperationType", &GeneralViewportSettings::m_displayMapperOperationType) ; if (auto editContext = serializeContext->GetEditContext()) @@ -50,6 +51,12 @@ namespace MaterialEditor ->DataElement(AZ::Edit::UIHandlers::Slider, &GeneralViewportSettings::m_fieldOfView, "Field Of View", "") ->Attribute(AZ::Edit::Attributes::Min, 60.0f) ->Attribute(AZ::Edit::Attributes::Max, 120.0f) + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &GeneralViewportSettings::m_displayMapperOperationType, "Display Mapper Type", "") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::Aces, "Aces") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::AcesLut, "AcesLut") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::Passthrough, "Passthrough") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::GammaSRGB, "GammaSRGB") + ->EnumAttribute(AZ::Render::DisplayMapperOperationType::Reinhard, "Reinhard") ; } } @@ -66,6 +73,7 @@ namespace MaterialEditor ->Property("enableShadowCatcher", BehaviorValueProperty(&GeneralViewportSettings::m_enableShadowCatcher)) ->Property("enableAlternateSkybox", BehaviorValueProperty(&GeneralViewportSettings::m_enableAlternateSkybox)) ->Property("fieldOfView", BehaviorValueProperty(&GeneralViewportSettings::m_fieldOfView)) + ->Property("displayMapperOperationType", BehaviorValueProperty(&GeneralViewportSettings::m_displayMapperOperationType)) ; } } @@ -298,6 +306,7 @@ namespace MaterialEditor MaterialViewportRequestBus::BroadcastResult( m_generalSettings.m_enableAlternateSkybox, &MaterialViewportRequestBus::Events::GetAlternateSkyboxEnabled); MaterialViewportRequestBus::BroadcastResult(m_generalSettings.m_fieldOfView, &MaterialViewportRequestBus::Handler::GetFieldOfView); + MaterialViewportRequestBus::BroadcastResult(m_generalSettings.m_displayMapperOperationType, &MaterialViewportRequestBus::Handler::GetDisplayMapperOperationType); AtomToolsFramework::InspectorRequestBus::Handler::BusDisconnect(); AtomToolsFramework::InspectorWidget::Reset(); @@ -343,6 +352,12 @@ namespace MaterialEditor RefreshGroup("general"); } + void ViewportSettingsInspector::OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) + { + m_generalSettings.m_displayMapperOperationType = operationType; + RefreshGroup("general"); + } + void ViewportSettingsInspector::BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) { AZ_UNUSED(pNode); @@ -370,6 +385,7 @@ namespace MaterialEditor MaterialViewportRequestBus::Broadcast( &MaterialViewportRequestBus::Events::SetAlternateSkyboxEnabled, m_generalSettings.m_enableAlternateSkybox); MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Handler::SetFieldOfView, m_generalSettings.m_fieldOfView); + MaterialViewportRequestBus::Broadcast(&MaterialViewportRequestBus::Handler::SetDisplayMapperOperationType, m_generalSettings.m_displayMapperOperationType); } AZStd::string ViewportSettingsInspector::GetDefaultUniqueSaveFilePath(const AZStd::string& baseName) const diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h index 08e22a380c..c61acb2e4c 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ViewportSettingsInspector/ViewportSettingsInspector.h @@ -13,6 +13,7 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include #include #include @@ -32,6 +33,7 @@ namespace MaterialEditor bool m_enableShadowCatcher = true; bool m_enableAlternateSkybox = false; float m_fieldOfView = 90.0f; + AZ::Render::DisplayMapperOperationType m_displayMapperOperationType = AZ::Render::DisplayMapperOperationType::Aces; }; //! Provides controls for viewing and editing a material document settings. @@ -74,6 +76,7 @@ namespace MaterialEditor void OnGridEnabledChanged(bool enable) override; void OnAlternateSkyboxEnabledChanged(bool enable) override; void OnFieldOfViewChanged(float fieldOfView) override; + void OnDisplayMapperOperationTypeChanged(AZ::Render::DisplayMapperOperationType operationType) override; // AzToolsFramework::IPropertyEditorNotify overrides... void BeforePropertyModified(AzToolsFramework::InstanceDataNode* pNode) override; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp index 92d76c4373..8c55adba46 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/main.cpp @@ -1,30 +1,31 @@ /* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#if !defined(Q_MOC_RUN) +#include #include #include -#include -#include #include -#include #include -#include -#include +#include +#include #include +#include +#include -#include #include - -#include +#include +#endif int main(int argc, char** argv) { @@ -45,15 +46,16 @@ int main(int argc, char** argv) AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware); MaterialEditor::MaterialEditorApplication app(&argc, &argv); + + auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app); + app.installEventFilter(globalEventFilter); + AZ::IO::FixedMaxPath engineRootPath; if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) { settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder); } - auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app); - app.installEventFilter(globalEventFilter); - AzQtComponents::StyleManager styleManager(&app); styleManager.initialize(&app, engineRootPath); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp index f2fd70c0e6..50b2cbb53a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentModule.cpp @@ -13,7 +13,6 @@ #include #include -#include #include #include @@ -32,7 +31,6 @@ namespace ShaderManagementConsole return AZ::ComponentTypeList{ azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), }; } } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp index f0d72c61c3..31dabe2bac 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.cpp @@ -105,7 +105,6 @@ namespace ShaderManagementConsole void ShaderManagementConsoleDocumentSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) { - required.push_back(AZ_CRC("TargetManagerService", 0x6d5708bc)); required.push_back(AZ_CRC("AssetProcessorToolsConnection", 0x734669bc)); required.push_back(AZ_CRC("AssetDatabaseService", 0x3abf5601)); required.push_back(AZ_CRC("PropertyManagerService", 0x63a3d7ad)); @@ -130,13 +129,11 @@ namespace ShaderManagementConsole { m_documentMap.clear(); ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusConnect(); - AzFramework::TmMsgBus::Handler::BusConnect(AZ_CRC("OpenInShaderManagementConsole", 0x9f92aac8)); } void ShaderManagementConsoleDocumentSystemComponent::Deactivate() { ShaderManagementConsoleDocumentSystemRequestBus::Handler::BusDisconnect(); - AzFramework::TmMsgBus::Handler::BusDisconnect(); m_documentMap.clear(); } @@ -159,19 +156,6 @@ namespace ShaderManagementConsole return m_documentMap.erase(documentId) != 0; } - void ShaderManagementConsoleDocumentSystemComponent::OnReceivedMsg(AzFramework::TmMsgPtr msg) - { - if (msg->GetId() == AZ_CRC("OpenInShaderManagementConsole", 0x9f92aac8)) - { - const char* documentPath = reinterpret_cast(msg->GetCustomBlob()); - ShaderManagementConsoleDocumentSystemRequestBus::Broadcast(&ShaderManagementConsoleDocumentSystemRequestBus::Events::OpenDocument, documentPath); - } - else - { - AZ_Assert(false, "We received a message of an unrecognized class type!"); - } - } - AZ::Uuid ShaderManagementConsoleDocumentSystemComponent::OpenDocument(AZStd::string_view path) { return OpenDocumentImpl(path, true); diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h index 60c205aa72..2bd7306b8b 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Document/ShaderManagementConsoleDocumentSystemComponent.h @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -30,7 +29,6 @@ namespace ShaderManagementConsole //! ShaderManagementConsoleDocumentSystemComponent is the central component of the Shader Management Console Core gem class ShaderManagementConsoleDocumentSystemComponent : public AZ::Component - , private AzFramework::TmMsgBus::Handler , private ShaderManagementConsoleDocumentSystemRequestBus::Handler { public: @@ -55,11 +53,6 @@ namespace ShaderManagementConsole void Deactivate() override; //////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // TmMsgBus::Handler overrides... - void OnReceivedMsg(AzFramework::TmMsgPtr msg) override; - ////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////// // ShaderManagementConsoleDocumentSystemRequestBus::Handler overrides... AZ::Uuid CreateDocument() override; diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeEditorModule.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeEditorModule.cpp index c955523d09..f2c2a6f5aa 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeEditorModule.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeEditorModule.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include "./Editor/AssetCollectionAsyncLoaderTestComponent.h" @@ -33,7 +32,6 @@ namespace AZ { // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. m_descriptors.insert(m_descriptors.end(), { - BuilderComponent::CreateDescriptor(), AssetCollectionAsyncLoaderTestComponent::CreateDescriptor(), }); } diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp index 1998642a02..90731488f4 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.cpp @@ -62,12 +62,10 @@ namespace AZ AtomBridgeSystemComponent::AtomBridgeSystemComponent() { - AZ::Interface::Register(this); } AtomBridgeSystemComponent::~AtomBridgeSystemComponent() { - AZ::Interface::Unregister(this); } void AtomBridgeSystemComponent::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided) @@ -146,15 +144,6 @@ namespace AZ { static const AZ::Uuid legacyRenderComponentUuids[] = { AZ::Uuid("{FC315B86-3280-4D03-B4F0-5553D7D08432}"), // EditorMeshComponent - AZ::Uuid("{4B85E77D-91F9-40C5-8FCB-B494000A9E69}"), // EditorLensFlareComponent - AZ::Uuid("{7C18B273-5BA3-4E0F-857D-1F30BD6B0733}"), // EditorLightComponent - AZ::Uuid("{00818135-138D-42AD-8657-FF3FD38D9E7A}"), // EditorPointLightComponent - AZ::Uuid("{1DE624B1-876F-4E0A-96A6-7B248FA2076F}"), // EditorAreaLightComponent - AZ::Uuid("{41928E34-B558-4559-82CF-8B5795A38CB4}"), // EditorProjectorLightComponent - AZ::Uuid("{BA3890BD-D2E7-4DB6-95CD-7E7D5525567A}"), // EditorDecalComponent - AZ::Uuid("{8DBD6035-583E-409F-AFD9-F36829A0655D}"), // EditorEnvProbeComponent - AZ::Uuid("{9C86E09D-0727-476E-A4A1-25989CDBF9C6}"), // EditorHighQualityShadowComponent - AZ::Uuid("{045C0C58-C13E-49B0-A471-D4AC5D3FC6BD}"), // EditorGeometryCacheComponent }; const AZStd::string deprecatedString = " (DEPRECATED By Atom)"; diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h index 2ffd966216..da75d3c35c 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomBridgeSystemComponent.h @@ -17,7 +17,6 @@ #include -#include #include #include @@ -37,7 +36,6 @@ namespace AZ class AtomBridgeSystemComponent : public Component - , public AzFramework::AtomActiveInterface , public AzFramework::Render::RenderSystemRequestBus::Handler , public AzFramework::Components::DeprecatedComponentsRequestBus::Handler , public Render::Bootstrap::NotificationBus::Handler diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp index bee6d31275..8a063cd7a7 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.cpp @@ -244,9 +244,6 @@ namespace AZ::AtomBridge } //////////////////////////////////////////////////////////////////////// - // Partial implementation of the DebugDisplayRequestBus on Atom. - // Commented out function prototypes are waiting to be implemented. - // work tracked in [ATOM-3459] AtomDebugDisplayViewportInterface::AtomDebugDisplayViewportInterface(AZ::RPI::ViewportContextPtr viewportContextPtr) { ResetRenderState(); @@ -272,9 +269,8 @@ namespace AZ::AtomBridge InitInternal(scene, nullptr); } - void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr) + void AtomDebugDisplayViewportInterface::UpdateAuxGeom(RPI::Scene* scene, AZ::RPI::View* view) { - AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); if (!scene) { m_auxGeomPtr = nullptr; @@ -286,20 +282,46 @@ namespace AZ::AtomBridge m_auxGeomPtr = nullptr; return; } - if (m_defaultInstance) + // default instance draws to all viewports in the default scene + if (m_defaultInstance || !view) { m_auxGeomPtr = auxGeomFP->GetDrawQueue(); } else { - m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(viewportContextPtr->GetDefaultView().get()); + // cache the aux geom draw interface for the current view (aka camera) + m_auxGeomPtr = auxGeomFP->GetOrCreateDrawQueueForView(view); } + } + + void AtomDebugDisplayViewportInterface::InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr) + { + AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); + UpdateAuxGeom(scene, viewportContextPtr ? viewportContextPtr->GetDefaultView().get() : nullptr); AzFramework::DebugDisplayRequestBus::Handler::BusConnect(m_viewportId); + if (!m_defaultInstance) // only the per viewport instances need to listen for viewport changes + { + AZ::RPI::ViewportContextIdNotificationBus::Handler::BusConnect(viewportContextPtr->GetId()); + } + } + + + void AtomDebugDisplayViewportInterface::OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) + { + ResetRenderState(); + if (!m_defaultInstance) + { + // handle viewport update (view change, scene change, etc + auto viewportContextManager = AZ::Interface::Get(); + AZ::RPI::ViewportContextPtr viewportContextPtr = viewportContextManager->GetViewportContextById(m_viewportId); + UpdateAuxGeom(viewportContextPtr->GetRenderScene().get(), viewportContextPtr->GetDefaultView().get()); + } } AtomDebugDisplayViewportInterface::~AtomDebugDisplayViewportInterface() { AzFramework::DebugDisplayRequestBus::Handler::BusDisconnect(m_viewportId); + AZ::RPI::ViewportContextIdNotificationBus::Handler::BusDisconnect(); m_viewportId = AzFramework::InvalidViewportId; m_auxGeomPtr = nullptr; } @@ -1234,8 +1256,15 @@ namespace AZ::AtomBridge int srcOffsetX [[maybe_unused]], int srcOffsetY [[maybe_unused]]) { + // abort draw if draw is invalid or font query interface is missing. + if (!text || size == 0.0f || !AZ::Interface::Get()) + { + return; + } + AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface::Get()->GetDefaultFontDrawInterface(); - if (!fontDrawInterface || !text || size == 0.0f) + // abort draw if font draw interface is missing + if (!fontDrawInterface) { return; } @@ -1263,13 +1292,15 @@ namespace AZ::AtomBridge const char* text, bool center) { - auto fontQueryInterface = AZ::Interface::Get(); - if (!fontQueryInterface) + // abort draw if draw is invalid or font query interface is missing. + if (!text || size == 0.0f || !AZ::Interface::Get()) { return; } - AzFramework::FontDrawInterface* fontDrawInterface = fontQueryInterface->GetDefaultFontDrawInterface(); - if (!fontDrawInterface || !text || size == 0.0f) + + AzFramework::FontDrawInterface* fontDrawInterface = AZ::Interface::Get()->GetDefaultFontDrawInterface(); + // abort draw if font draw interface is missing + if (!fontDrawInterface) { return; } diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h index 021d816ca4..c872e2b81e 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h +++ b/Gems/AtomLyIntegration/AtomBridge/Code/Source/AtomDebugDisplayViewportInterface.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace AZ::AtomBridge { @@ -121,6 +122,7 @@ namespace AZ::AtomBridge class AtomDebugDisplayViewportInterface final : public AzFramework::DebugDisplayRequestBus::Handler + , public AZ::RPI::ViewportContextIdNotificationBus::Handler { public: AZ_RTTI(AtomDebugDisplayViewportInterface, "{09AF6A46-0100-4FBF-8F94-E6B221322D14}", AzFramework::DebugDisplayRequestBus::Handler); @@ -198,6 +200,12 @@ namespace AZ::AtomBridge void PopMatrix() override; private: + + // ViewportContextIdNotificationBus handlers + void OnViewportDefaultViewChanged(AZ::RPI::ViewPtr view) override; + + + // internal helper functions using LineSegmentFilterFunc = AZStd::function; enum CircleAxis { @@ -245,6 +253,7 @@ namespace AZ::AtomBridge const AZ::Matrix3x4& GetCurrentTransform() const; + void UpdateAuxGeom(RPI::Scene* scene, AZ::RPI::View* view); void InitInternal(RPI::Scene* scene, AZ::RPI::ViewportContextPtr viewportContextPtr); AZ::RPI::ViewportContextPtr GetViewportContext() const; @@ -254,10 +263,12 @@ namespace AZ::AtomBridge RenderState m_rendState; AZ::RPI::AuxGeomDrawPtr m_auxGeomPtr; - bool m_defaultInstance = false; // only true for drawing to a particular viewport. What would 2D drawing mean in a scene with several windows? + + // m_defaultInstance is true for the instance that multicasts the debug draws to all viewports + // (with an AuxGeom render pass) in the default scene. + bool m_defaultInstance = false; AzFramework::ViewportId m_viewportId = AzFramework::InvalidViewportId; // Address this instance answers on. - AZ::RPI::ViewportContext::SceneChangedEvent::Handler - m_sceneChangeHandler; + AZ::RPI::ViewportContext::SceneChangedEvent::Handler m_sceneChangeHandler; }; // this is duplicated from Cry_Math.h, GetBasisVectors. diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/BuilderComponent.cpp b/Gems/AtomLyIntegration/AtomBridge/Code/Source/BuilderComponent.cpp deleted file mode 100644 index b6ff2cb66d..0000000000 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/BuilderComponent.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include -#include -#include -#include - -#include - -#include - -namespace AZ -{ - namespace AtomBridge - { - void BuilderComponent::Reflect(AZ::ReflectContext* context) - { - if (auto* serialize = azrtti_cast(context)) - { - serialize->Class() - ->Version(0) - ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder })) - ; - } - } - - BuilderComponent::BuilderComponent() - { - AZ::Interface::Register(this); - } - - BuilderComponent::~BuilderComponent() - { - AZ::Interface::Unregister(this); - } - - void BuilderComponent::Activate() - { - } - - void BuilderComponent::Deactivate() - { - } - } // namespace RPI -} // namespace AZ diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/Source/BuilderComponent.h b/Gems/AtomLyIntegration/AtomBridge/Code/Source/BuilderComponent.h deleted file mode 100644 index 4e75fd2a88..0000000000 --- a/Gems/AtomLyIntegration/AtomBridge/Code/Source/BuilderComponent.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include - -namespace AZ -{ - namespace AtomBridge - { - class BuilderComponent final - : public AZ::Component - , public AzFramework::AtomActiveInterface - { - public: - AZ_COMPONENT(BuilderComponent, "{D1FE015B-8431-4155-8FD0-8197F246901A}"); - static void Reflect(AZ::ReflectContext* context); - - BuilderComponent(); - ~BuilderComponent() override; - - // AZ::Component overrides... - void Activate() override; - void Deactivate() override; - }; - } // namespace RPI -} // namespace AZ diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_editor_files.cmake b/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_editor_files.cmake index f2cf8c6c14..55ed9f28a0 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_editor_files.cmake +++ b/Gems/AtomLyIntegration/AtomBridge/Code/atombridge_editor_files.cmake @@ -13,8 +13,6 @@ set(FILES Source/AtomBridgeEditorModule.cpp Source/AtomBridgeModule.cpp Source/AtomBridgeModule.h - Source/BuilderComponent.cpp - Source/BuilderComponent.h Source/Editor/AssetCollectionAsyncLoaderTestComponent.cpp Source/Editor/AssetCollectionAsyncLoaderTestComponent.h ) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h index 8e60cc2055..fd66534197 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/FFont.h @@ -226,7 +226,7 @@ namespace AZ private: virtual ~FFont(); - bool InitFont(); + bool InitFont(AZ::RPI::Scene* renderScene); bool InitTexture(); bool InitCache(); diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp index b1275b5b3b..dec52234bb 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.cpp @@ -65,27 +65,38 @@ namespace AZ void AtomFontSystemComponent::Activate() { - AZ::CryFontCreationRequestBus::Handler::BusConnect(); + CrySystemEventBus::Handler::BusConnect(); } void AtomFontSystemComponent::Deactivate() { - AZ::CryFontCreationRequestBus::Handler::BusDisconnect(); + CrySystemEventBus::Handler::BusDisconnect(); } - bool AtomFontSystemComponent::CreateCryFont(SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) + void LoadFont(ICryFont& cryFont, const AZStd::string& fontName) + { + IFFont* font = cryFont.NewFont(fontName.c_str()); + AZ_Assert(font, "Could not instantiate font: %s", fontName.c_str()); + + const AZStd::string fontPath = "Fonts/" + fontName + ".font"; + if (!font->Load(fontPath.c_str())) + { + AZ_Error("AtomFont", false, "Could not load font: %s", fontPath.c_str()); + } + } + + void AtomFontSystemComponent::OnCrySystemInitialized(ISystem& system, const SSystemInitParams&) { - ISystem* system = env.pSystem; #if !defined(AZ_MONOLITHIC_BUILD) // When module is linked dynamically, we must set our gEnv pointer. // When module is linked statically, we'll share the application's gEnv pointer. - gEnv = system->GetGlobalEnvironment(); + gEnv = system.GetGlobalEnvironment(); #endif - if (env.IsDedicated()) + if (gEnv->IsDedicated()) { #if defined(USE_NULLFONT) - env.pCryFont = new AtomNullFont(); + gEnv->pCryFont = new AtomNullFont(); #else // The NULL font implementation must be present for all platforms // supporting running as a pure dedicated server. @@ -96,12 +107,17 @@ namespace AZ else { #if defined(USE_NULLFONT) && defined(USE_NULLFONT_ALWAYS) - env.pCryFont = new AtomNullFont(); + gEnv->pCryFont = new AtomNullFont(); #else - env.pCryFont = new AtomFont(system); + gEnv->pCryFont = new AtomFont(&system); #endif } - return env.pCryFont != 0; + + if (gEnv->pCryFont) + { + LoadFont(*gEnv->pCryFont, "default"); + LoadFont(*gEnv->pCryFont, "default-ui"); + } } void AtomFontSystemComponent::OnCrySystemShutdown([[maybe_unused]] ISystem& system) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h index 23ce20c307..05e30661f2 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/AtomFontSystemComponent.h @@ -13,7 +13,6 @@ #include -#include #include namespace AZ @@ -22,7 +21,6 @@ namespace AZ { class AtomFontSystemComponent : public AZ::Component - , private AZ::CryFontCreationRequestBus::Handler , private CrySystemEventBus::Handler { public: @@ -43,12 +41,12 @@ namespace AZ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - // CryFontCreationBus - bool CreateCryFont(SSystemGlobalEnvironment& env, const SSystemInitParams& initParams) override; + // CrySystemEventBus + void OnCrySystemInitialized(ISystem& system, const SSystemInitParams& initParams); //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// - // CryFontCreationBus + // CrySystemEventBus void OnCrySystemShutdown(ISystem& system) override; //////////////////////////////////////////////////////////////////////// }; diff --git a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp index 20879876e7..d36307e4ec 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp +++ b/Gems/AtomLyIntegration/AtomFont/Code/Source/FFont.cpp @@ -99,7 +99,7 @@ AZ::RPI::WindowContextSharedPtr AZ::FFont::GetDefaultWindowContext() const return {}; } -bool AZ::FFont::InitFont() +bool AZ::FFont::InitFont(AZ::RPI::Scene* renderScene) { auto initializationState = InitializationState::Uninitialized; // Do an atomic transition to Initializing if we're in the Uninitialized state. @@ -111,8 +111,13 @@ bool AZ::FFont::InitFont() return initializationState == InitializationState::Initialized; } + if (!renderScene) + { + return false; + } + // Create and initialize DynamicDrawContext for font draw - AZ::RPI::Ptr dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(GetDefaultViewportContext()->GetRenderScene().get()); + AZ::RPI::Ptr dynamicDraw = m_atomFont->GetOrCreateDynamicDrawForScene(renderScene); // Save draw srg input indices for later use Data::Instance drawSrg = dynamicDraw->NewDrawSrg(); @@ -299,7 +304,7 @@ void AZ::FFont::DrawStringUInternal( const TextDrawContext& ctx) { // Lazily ensure we're initialized before attempting to render. - if (!InitFont()) + if (!viewportContext || !InitFont(viewportContext->GetRenderScene().get())) { return; } @@ -1623,7 +1628,7 @@ void AZ::FFont::ScaleCoord(const RHI::Viewport& viewport, float& x, float& y) co void AZ::FFont::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) { - InitFont(); + InitFont(bootstrapScene); } static void SetCommonContextFlags(AZ::TextDrawContext& ctx, const AzFramework::TextDrawParameters& params) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.cpp new file mode 100644 index 0000000000..138d619d97 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.cpp @@ -0,0 +1,355 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#include "AttachmentComponent.h" +#include +#include +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + /// Behavior Context handler for AttachmentComponentNotificationBus + class BehaviorAttachmentComponentNotificationBusHandler : public LmbrCentral::AttachmentComponentNotificationBus::Handler, + public AZ::BehaviorEBusHandler + { + public: + AZ_EBUS_BEHAVIOR_BINDER( + BehaviorAttachmentComponentNotificationBusHandler, "{636B95A0-5C7D-4EE7-8645-955665315451}", AZ::SystemAllocator, + OnAttached, OnDetached); + + void OnAttached(AZ::EntityId id) override + { + Call(FN_OnAttached, id); + } + + void OnDetached(AZ::EntityId id) override + { + Call(FN_OnDetached, id); + } + }; + + void AttachmentConfiguration::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1) + ->Field("Target ID", &AttachmentConfiguration::m_targetId) + ->Field("Target Bone Name", &AttachmentConfiguration::m_targetBoneName) + ->Field("Target Offset", &AttachmentConfiguration::m_targetOffset) + ->Field("Attached Initially", &AttachmentConfiguration::m_attachedInitially) + ->Field("Scale Source", &AttachmentConfiguration::m_scaleSource); + } + AZ::BehaviorContext* behaviorContext = azrtti_cast(context); + if (behaviorContext) + { + behaviorContext->EBus("AttachmentComponentRequestBus") + ->Event("Attach", &LmbrCentral::AttachmentComponentRequestBus::Events::Attach) + ->Event("Detach", &LmbrCentral::AttachmentComponentRequestBus::Events::Detach) + ->Event("SetAttachmentOffset", &LmbrCentral::AttachmentComponentRequestBus::Events::SetAttachmentOffset); + + behaviorContext->EBus("AttachmentComponentNotificationBus") + ->Handler(); + } + } + + void AttachmentComponent::Reflect(AZ::ReflectContext* context) + { + AttachmentConfiguration::Reflect(context); + + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class()->Version(1)->Field( + "Configuration", &AttachmentComponent::m_initialConfiguration); + } + } + + //========================================================================= + // BoneFollower + //========================================================================= + + void BoneFollower::Activate(AZ::Entity* owner, const AttachmentConfiguration& configuration, bool targetCanAnimate) + { + AZ_Assert(owner, "owner is required"); + AZ_Assert(!m_ownerId.IsValid(), "BoneFollower is already Activated"); + + m_ownerId = owner->GetId(); + m_targetCanAnimate = targetCanAnimate; + m_isUpdatingOwnerTransform = false; + m_scaleSource = configuration.m_scaleSource; + + m_cachedOwnerTransform = AZ::Transform::CreateIdentity(); + EBUS_EVENT_ID_RESULT(m_cachedOwnerTransform, m_ownerId, AZ::TransformBus, GetWorldTM); + + if (configuration.m_attachedInitially) + { + Attach(configuration.m_targetId, configuration.m_targetBoneName.c_str(), configuration.m_targetOffset); + } + + LmbrCentral::AttachmentComponentRequestBus::Handler::BusConnect(m_ownerId); + } + + void BoneFollower::Deactivate() + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower was never Activated"); + + LmbrCentral::AttachmentComponentRequestBus::Handler::BusDisconnect(); + Detach(); + m_ownerId.SetInvalid(); + } + + AZ::EntityId BoneFollower::GetTargetEntityId() + { + return m_targetId; + } + + AZ::Transform BoneFollower::GetOffset() + { + return m_targetOffset; + } + + void BoneFollower::Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use.") + + // safe to try and detach, even if we weren't attached + Detach(); + + if (!targetId.IsValid()) + { + return; + } + + if (targetId == m_ownerId) + { + AZ_Error("Attachment Component", false, "AttachmentComponent cannot target itself"); + return; + } + + // Note: the target entity may not be activated yet. That's ok. + // When mesh is ready we are notified via MeshComponentEvents::OnModelReady + // When transform is ready we are notified via TransformNotificationBus::OnTransformChanged + + m_targetId = targetId; + m_targetBoneName = targetBoneName; + m_targetOffset = offset; + + BindTargetBone(); + + m_targetBoneTransform = AZ::Transform::Identity(); + + m_isTargetEntityTransformKnown = false; // target's transform may not be available yet + + AZ::TransformBus::EventResult( + m_cachedOwnerTransform, m_ownerId, &AZ::TransformBus::Events::GetWorldTM); // owner query will always succeed + + MeshComponentNotificationBus::Handler::BusConnect(m_targetId); // fires OnModelReady if asset is already ready + AZ::TransformNotificationBus::Handler::BusConnect(m_targetId); + if (m_targetCanAnimate) + { + // Only register for per-frame updates when target can animate + AZ::TickBus::Handler::BusConnect(); + } + + // update owner's transform + UpdateOwnerTransformIfNecessary(); + + // alert others that we've attached + LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); + } + + void BoneFollower::Detach() + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); + + if (m_targetId.IsValid()) + { + // alert others that we're detaching + EBUS_EVENT_ID(m_targetId, LmbrCentral::AttachmentComponentNotificationBus, OnDetached, m_ownerId); + + MeshComponentNotificationBus::Handler::BusDisconnect(); + AZ::TransformNotificationBus::Handler::BusDisconnect(m_targetId); + AZ::TickBus::Handler::BusDisconnect(); + + m_targetId.SetInvalid(); + } + } + + const char* BoneFollower::GetJointName() + { + return m_targetBoneName.c_str(); + } + + void BoneFollower::SetAttachmentOffset(const AZ::Transform& offset) + { + AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); + + if (m_targetId.IsValid()) + { + m_targetOffset = offset; + UpdateOwnerTransformIfNecessary(); + } + } + + void BoneFollower::OnModelReady([[maybe_unused]] const AZ::Data::Asset& modelAsset, [[maybe_unused]] const AZ::Data::Instance& model) + { + // reset character values + BindTargetBone(); + m_targetBoneTransform = QueryBoneTransform(); + + // move owner if necessary + UpdateOwnerTransformIfNecessary(); + } + + void BoneFollower::BindTargetBone() + { + m_targetBoneId = -1; + LmbrCentral::SkeletalHierarchyRequestBus::EventResult( + m_targetBoneId, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointIndexByName, m_targetBoneName.c_str()); + } + + void BoneFollower::UpdateOwnerTransformIfNecessary() + { + // Can't update until target entity's transform is known + if (!m_isTargetEntityTransformKnown) + { + if (AZ::TransformBus::GetNumOfEventHandlers(m_targetId) == 0) + { + return; + } + + AZ::TransformBus::EventResult(m_targetEntityTransform, m_targetId, &AZ::TransformBus::Events::GetWorldTM); + m_isTargetEntityTransformKnown = true; + } + + AZ::Transform finalTransform; + if (m_scaleSource == AttachmentConfiguration::ScaleSource::WorldScale) + { + // apply offset in world-space + finalTransform = m_targetEntityTransform * m_targetBoneTransform; + finalTransform.SetScale(AZ::Vector3::CreateOne()); + finalTransform *= m_targetOffset; + } + else if (m_scaleSource == AttachmentConfiguration::ScaleSource::TargetEntityScale) + { + // apply offset in target-entity-space (ignoring bone scale) + AZ::Transform boneNoScale = m_targetBoneTransform; + boneNoScale.SetScale(AZ::Vector3::CreateOne()); + + finalTransform = m_targetEntityTransform * boneNoScale * m_targetOffset; + } + else // AttachmentConfiguration::ScaleSource::TargetEntityScale + { + // apply offset in target-bone-space + finalTransform = m_targetEntityTransform * m_targetBoneTransform * m_targetOffset; + } + + if (m_cachedOwnerTransform != finalTransform) + { + AZ_Warning( + "Attachment Component", !m_isUpdatingOwnerTransform, + "AttachmentComponent detected a cycle when updating transform, do not target child entities."); + if (!m_isUpdatingOwnerTransform) + { + m_cachedOwnerTransform = finalTransform; + m_isUpdatingOwnerTransform = true; + EBUS_EVENT_ID(m_ownerId, AZ::TransformBus, SetWorldTM, finalTransform); + m_isUpdatingOwnerTransform = false; + } + } + } + + AZ::Transform BoneFollower::QueryBoneTransform() const + { + AZ::Transform boneTransform = AZ::Transform::CreateIdentity(); + + if (m_targetBoneId >= 0) + { + LmbrCentral::SkeletalHierarchyRequestBus::EventResult( + boneTransform, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointTransformCharacterRelative, m_targetBoneId); + } + + return boneTransform; + } + + // fires when target's transform changes + void BoneFollower::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) + { + m_targetEntityTransform = world; + m_isTargetEntityTransformKnown = true; + UpdateOwnerTransformIfNecessary(); + } + + void BoneFollower::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) + { + m_targetBoneTransform = QueryBoneTransform(); + UpdateOwnerTransformIfNecessary(); + } + + int BoneFollower::GetTickOrder() + { + return AZ::TICK_ATTACHMENT; + } + + void BoneFollower::Reattach(bool detachFirst) + { +#ifdef AZ_ENABLE_TRACING + AZ::Entity* ownerEntity = nullptr; + AZ::Entity* targetEntity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(ownerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_ownerId); + AZ::ComponentApplicationBus::BroadcastResult(targetEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_targetId); + AZ_TracePrintf( + "BoneFollower", "Reattaching entity '%s' to entity '%s'", ownerEntity ? ownerEntity->GetName().c_str() : "", + targetEntity ? targetEntity->GetName().c_str() : ""); +#endif + + if (m_targetId.IsValid() && detachFirst) + { + LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnDetached, m_ownerId); + } + + if (m_targetId != m_ownerId) + { + LmbrCentral::AttachmentComponentNotificationBus::Event(m_targetId, &LmbrCentral::AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); + } + } + + //========================================================================= + // AttachmentComponent + //========================================================================= + + void AttachmentComponent::Activate() + { +#ifdef AZ_ENABLE_TRACING + bool isStaticTransform = false; + AZ::TransformBus::EventResult(isStaticTransform, GetEntityId(), &AZ::TransformBus::Events::IsStaticTransform); + AZ_Warning( + "Attachment Component", !isStaticTransform, "Attachment needs to move, but entity '%s' %s has a static transform.", + GetEntity()->GetName().c_str(), GetEntityId().ToString().c_str()); +#endif + + m_boneFollower.Activate(GetEntity(), m_initialConfiguration, true); + } + + void AttachmentComponent::Deactivate() + { + m_boneFollower.Deactivate(); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h new file mode 100644 index 0000000000..ac03663f22 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/AttachmentComponent.h @@ -0,0 +1,189 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include +#include +#include +#include +#include + +struct ISkeletonPose; + +namespace AZ +{ + namespace Render + { + /*! + * Configuration data for AttachmentComponent. + */ + struct AttachmentConfiguration + { + AZ_TYPE_INFO(AttachmentConfiguration, "{74B5DC69-DE44-4640-836A-55339E116795}"); + + virtual ~AttachmentConfiguration() = default; + + static void Reflect(AZ::ReflectContext* context); + + //! Attach to this entity. + AZ::EntityId m_targetId; + + //! Attach to this bone on target entity. + AZStd::string m_targetBoneName; + + //! Offset from target. + AZ::Transform m_targetOffset = AZ::Transform::Identity(); + + //! Whether to attach to target upon activation. + //! If false, the entity remains detached until Attach() is called. + bool m_attachedInitially = true; + + //! Source from which to retrieve scale information. + enum class ScaleSource : AZ::u8 + { + WorldScale, // Scaled in world space. + TargetEntityScale, // Adopt scaling of attachment target entity. + TargetBoneScale, // Adopt scaling of attachment target entity/joint. + }; + ScaleSource m_scaleSource = ScaleSource::WorldScale; + }; + + /* + * Common functionality for game and editor attachment components. + * The BoneFollower tracks movement of the target's bone and + * updates the owning entity's TransformComponent to follow. + * This class should be a member within the attachment component + * and be activated/deactivated along with the component. + * \ref AttachmentComponent + */ + class BoneFollower + : public LmbrCentral::AttachmentComponentRequestBus::Handler + , public AZ::TransformNotificationBus::Handler + , public AZ::Render::MeshComponentNotificationBus::Handler + , public AZ::Data::AssetBus::Handler + , public AZ::TickBus::Handler + { + public: + void Activate(AZ::Entity* owner, const AttachmentConfiguration& initialConfiguration, bool targetCanAnimate); + void Deactivate(); + + //////////////////////////////////////////////////////////////////////// + // AttachmentComponentRequests + void Reattach(bool detachFirst); + void Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) override; + void Detach() override; + void SetAttachmentOffset(const AZ::Transform& offset) override; + const char* GetJointName() override; + AZ::EntityId GetTargetEntityId() override; + AZ::Transform GetOffset() override; + //////////////////////////////////////////////////////////////////////// + + private: + + //////////////////////////////////////////////////////////////////////// + // AZ::TickBus + //! Check target bone transform every frame. + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + //! Make sure target bone transform updates after animation update. + int GetTickOrder() override; + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // AZ::TransformNotificationBus + //! When target's transform changes + void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; + //////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////// + // MeshComponentEvents + //! When target's mesh changes + void OnModelReady(const AZ::Data::Asset& modelAsset, const AZ::Data::Instance& model) override; + //////////////////////////////////////////////////////////////////////// + + void BindTargetBone(); + + AZ::Transform QueryBoneTransform() const; + + void UpdateOwnerTransformIfNecessary(); + + //! Entity which which is being attached. + AZ::EntityId m_ownerId; + + //! Whether to query bone position per-frame (false while in editor) + bool m_targetCanAnimate = false; + + AZ::EntityId m_targetId; + AZStd::string m_targetBoneName; + AZ::Transform m_targetOffset; //!< local transform + AZ::Transform m_targetBoneTransform; //!< local transform of bone + AZ::Transform m_targetEntityTransform; //!< world transform of target + bool m_isTargetEntityTransformKnown = false; + + //! Cached value, so we don't update owner's position unnecessarily. + AZ::Transform m_cachedOwnerTransform; + bool m_isUpdatingOwnerTransform = false; //!< detect infinite loops when updating owner's transform + + // Cached character values to avoid repeated lookup. + // These are set by calling ResetCharacter() + int m_targetBoneId; //!< negative when bone not found + + AttachmentConfiguration::ScaleSource m_scaleSource; + }; + + /*! + * The AttachmentComponent lets an entity stick to a particular bone on + * a target entity. This is achieved by tracking movement of the target's + * bone and updating the entity's TransformComponent accordingly. + */ + class AttachmentComponent + : public AZ::Component + { + public: + AZ_COMPONENT(AttachmentComponent, "{2D17A64A-7AC5-4C02-AC36-C5E8141FFDDF}"); + + friend class EditorAttachmentComponent; + + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); + } + + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); + } + + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); + } + + ~AttachmentComponent() override = default; + + private: + //////////////////////////////////////////////////////////////////////// + // AZ::Component + void Activate() override; + void Deactivate() override; + //////////////////////////////////////////////////////////////////////// + + //! Initial configuration for m_attachment + AttachmentConfiguration m_initialConfiguration; + + //! Implements actual attachment functionality + BoneFollower m_boneFollower; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp new file mode 100644 index 0000000000..3b50c0a48c --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp @@ -0,0 +1,242 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include "EditorAttachmentComponent.h" +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + void EditorAttachmentComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1) + ->Field("Target ID", &EditorAttachmentComponent::m_targetId) + ->Field("Target Bone Name", &EditorAttachmentComponent::m_targetBoneName) + ->Field("Position Offset", &EditorAttachmentComponent::m_positionOffset) + ->Field("Rotation Offset", &EditorAttachmentComponent::m_rotationOffset) + ->Field("Scale Offset", &EditorAttachmentComponent::m_scaleOffset) + ->Field("Attached Initially", &EditorAttachmentComponent::m_attachedInitially) + ->Field("Scale Source", &EditorAttachmentComponent::m_scaleSource); + + AZ::EditContext* editContext = serializeContext->GetEditContext(); + if (editContext) + { + editContext + ->Class( + "Attachment", "The Attachment component lets an entity attach to a bone on the skeleton of another entity") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Category, "Animation") + ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Attachment.svg") + ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Attachment.png") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute( + AZ::Edit::Attributes::HelpPageURL, + "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-attachment.html") + ->DataElement(0, &EditorAttachmentComponent::m_targetId, "Target entity", "Attach to this entity.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetIdChanged) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_targetBoneName, "Joint name", + "Attach to this joint on target entity.") + ->Attribute(AZ::Edit::Attributes::StringList, &EditorAttachmentComponent::GetTargetBoneOptions) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetBoneChanged) + ->DataElement( + 0, &EditorAttachmentComponent::m_positionOffset, "Position offset", "Local position offset from target bone") + ->Attribute(AZ::Edit::Attributes::Suffix, "m") + ->Attribute(AZ::Edit::Attributes::Step, 0.01f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) + ->DataElement( + 0, &EditorAttachmentComponent::m_rotationOffset, "Rotation offset", "Local rotation offset from target bone") + ->Attribute(AZ::Edit::Attributes::Suffix, "deg") + ->Attribute(AZ::Edit::Attributes::Step, 0.01f) + ->Attribute(AZ::Edit::Attributes::Min, -AZ::RadToDeg(AZ::Constants::TwoPi)) + ->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::TwoPi)) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) + ->DataElement(0, &EditorAttachmentComponent::m_scaleOffset, "Scale offset", "Local scale offset from target entity") + ->Attribute(AZ::Edit::Attributes::Step, 0.1f) + ->Attribute(AZ::Edit::Attributes::Min, 0.001f) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) + ->DataElement( + 0, &EditorAttachmentComponent::m_attachedInitially, "Attached initially", + "Whether to attach to target upon activation.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnAttachedInitiallyChanged) + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_scaleSource, "Scaling", + "How object scale should be determined. " + "Use world scale = Attached object is scaled in world space, Use target entity scale = Attached object adopts " + "scale of target entity., Use target bone scale = Attached object adopts scale of target entity/joint.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnScaleSourceChanged) + ->EnumAttribute(AttachmentConfiguration::ScaleSource::WorldScale, "Use world scale") + ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetEntityScale, "Use target entity scale") + ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetBoneScale, "Use target bone scale"); + } + } + } + + void EditorAttachmentComponent::Activate() + { + Base::Activate(); + m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), + false); // Entity's don't animate in Editor + } + + void EditorAttachmentComponent::Deactivate() + { + m_boneFollower.Deactivate(); + Base::Deactivate(); + } + + void EditorAttachmentComponent::BuildGameEntity(AZ::Entity* gameEntity) + { + AttachmentComponent* component = gameEntity->CreateComponent(); + if (component) + { + component->m_initialConfiguration = CreateAttachmentConfiguration(); + } + } + + AttachmentConfiguration EditorAttachmentComponent::CreateAttachmentConfiguration() const + { + AttachmentConfiguration configuration; + configuration.m_targetId = m_targetId; + configuration.m_targetBoneName = m_targetBoneName; + configuration.m_targetOffset = GetTargetOffset(); + configuration.m_attachedInitially = m_attachedInitially; + configuration.m_scaleSource = m_scaleSource; + return configuration; + } + + AZ::Transform EditorAttachmentComponent::GetTargetOffset() const + { + AZ::Transform offset = AZ::ConvertEulerDegreesToTransform(m_rotationOffset); + offset.SetTranslation(m_positionOffset); + offset.MultiplyByScale(m_scaleOffset); + return offset; + } + + AZStd::vector EditorAttachmentComponent::GetTargetBoneOptions() const + { + AZStd::vector names; + + // insert blank entry, so user may choose to bind to NO bone. + names.push_back(""); + + // track whether currently-set bone is found + bool currentTargetBoneFound = false; + + // Get character and iterate over bones + AZ::u32 jointCount = 0; + LmbrCentral::SkeletalHierarchyRequestBus::EventResult(jointCount, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointCount); + for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) + { + const char* name = nullptr; + LmbrCentral::SkeletalHierarchyRequestBus::EventResult(name, m_targetId, &LmbrCentral::SkeletalHierarchyRequests::GetJointNameByIndex, jointIndex); + if (name) + { + names.push_back(name); + + if (!currentTargetBoneFound) + { + currentTargetBoneFound = (m_targetBoneName == names.back()); + } + } + } + + // If we never found currently-set bone name, + // stick it at top of list, just in case user wants to keep it anyway + if (!currentTargetBoneFound && !m_targetBoneName.empty()) + { + names.insert(names.begin(), m_targetBoneName); + } + + return names; + } + + AZ::u32 EditorAttachmentComponent::OnTargetIdChanged() + { + // Warn about bad setups (it won't crash, but it's nice to handle this early) + if (m_targetId == GetEntityId()) + { + AZ_Warning(GetEntity()->GetName().c_str(), false, "AttachmentComponent cannot target self.") m_targetId.SetInvalid(); + } + + // Warn about children attaching to a parent + AZ::EntityId parentOfTarget; + AZ::TransformBus::EventResult(parentOfTarget, m_targetId, &AZ::TransformBus::Events::GetParentId); + while (parentOfTarget.IsValid()) + { + if (parentOfTarget == GetEntityId()) + { + AZ_Warning( + GetEntity()->GetName().c_str(), parentOfTarget != GetEntityId(), "AttachmentComponent cannot target child entity"); + m_targetId.SetInvalid(); + break; + } + + AZ::EntityId currentParentId = parentOfTarget; + parentOfTarget.SetInvalid(); + AZ::TransformBus::EventResult(parentOfTarget, currentParentId, &AZ::TransformBus::Events::GetParentId); + } + + AttachOrDetachAsNecessary(); + + return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; // refresh bone options + } + + AZ::u32 EditorAttachmentComponent::OnTargetBoneChanged() + { + AttachOrDetachAsNecessary(); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorAttachmentComponent::OnTargetOffsetChanged() + { + EBUS_EVENT_ID(GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, SetAttachmentOffset, GetTargetOffset()); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorAttachmentComponent::OnAttachedInitiallyChanged() + { + AttachOrDetachAsNecessary(); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorAttachmentComponent::OnScaleSourceChanged() + { + m_boneFollower.Deactivate(); + m_boneFollower.Activate(GetEntity(), CreateAttachmentConfiguration(), false); + return AZ::Edit::PropertyRefreshLevels::None; + } + + void EditorAttachmentComponent::AttachOrDetachAsNecessary() + { + if (m_attachedInitially && m_targetId.IsValid()) + { + EBUS_EVENT_ID( + GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, Attach, m_targetId, m_targetBoneName.c_str(), GetTargetOffset()); + } + else + { + EBUS_EVENT_ID(GetEntityId(), LmbrCentral::AttachmentComponentRequestBus, Detach); + } + } + } // namespace Render + } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.h new file mode 100644 index 0000000000..cac8a71a94 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.h @@ -0,0 +1,104 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include "AttachmentComponent.h" + +namespace AZ +{ + namespace Render + { + /*! + * In-editor attachment component. + * \ref AttachmentComponent + */ + class EditorAttachmentComponent + : public AzToolsFramework::Components::EditorComponentBase + { + private: + using Base = AzToolsFramework::Components::EditorComponentBase; + public: + AZ_COMPONENT(EditorAttachmentComponent, "{DA6072FD-E696-47D8-81D9-1F77D3464200}", Base); + static void Reflect(AZ::ReflectContext* context); + + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + AttachmentComponent::GetProvidedServices(provided); + } + + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + AttachmentComponent::GetIncompatibleServices(incompatible); + } + + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + AttachmentComponent::GetRequiredServices(required); + } + + ~EditorAttachmentComponent() override = default; + void BuildGameEntity(AZ::Entity* gameEntity) override; + + protected: + + ////////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Activate() override; + void Deactivate() override; + ////////////////////////////////////////////////////////////////////////// + + AZ::u32 OnTargetIdChanged(); + AZ::u32 OnTargetBoneChanged(); + AZ::u32 OnTargetOffsetChanged(); + AZ::u32 OnAttachedInitiallyChanged(); + AZ::u32 OnScaleSourceChanged(); + + //! Invoked when an attachment property changes + void AttachOrDetachAsNecessary(); + + //! For populating ComboBox + AZStd::vector GetTargetBoneOptions() const; + + //! Create runtime configuration from editor configuration + AttachmentConfiguration CreateAttachmentConfiguration() const; + + //! Create AZ::Transform from position and rotation + AZ::Transform GetTargetOffset() const; + + //! Attach to this entity. + AZ::EntityId m_targetId; + + //! Attach to this bone on target entity. + AZStd::string m_targetBoneName; + + //! Offset from target bone's position. + AZ::Vector3 m_positionOffset = AZ::Vector3::CreateZero(); + + //! Offset from target bone's rotation. + AZ::Vector3 m_rotationOffset = AZ::Vector3::CreateZero(); + + //! Offset from target entity's scale. + AZ::Vector3 m_scaleOffset = AZ::Vector3::CreateOne(); + + //! Observe scale information from the specified source. + AttachmentConfiguration::ScaleSource m_scaleSource = AttachmentConfiguration::ScaleSource::WorldScale; + + //! Whether to attach to target upon activation. + //! If false, the entity remains detached until Attach() is called. + bool m_attachedInitially = true; + + //! Implements actual attachment functionality + AZ::Render::BoneFollower m_boneFollower; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 8c5f6d6836..a77bcfdd12 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -336,6 +336,7 @@ namespace AZ bool needsFullRefresh = HandleLightTypeChange(); LmbrCentral::EditorShapeComponentRequestsBus::Event(GetEntityId(), &LmbrCentral::EditorShapeComponentRequests::SetShapeColor, m_controller.m_configuration.m_color); + LmbrCentral::EditorShapeComponentRequestsBus::Event(GetEntityId(), &LmbrCentral::EditorShapeComponentRequests::SetShapeWireframeColor, m_controller.m_configuration.m_color); // If photometric unit changes, convert the intensities so the actual intensity doesn't change. m_controller.ConvertToIntensityMode(m_controller.m_configuration.m_intensityMode); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index f7915bbff4..03533e142f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -245,9 +245,12 @@ namespace AZ for (const auto& propertyDefinition : propertyListItr->second) { AtomToolsFramework::DynamicPropertyConfig propertyConfig; + + // Assign id before conversion so it can be used in dynamic description + propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName(); + AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition); - propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName(); propertyConfig.m_groupName = groupDisplayName; const auto& propertyIndex = m_editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id); propertyConfig.m_showThumbnail = true; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp index 94dfb39419..e9a81f2e9f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include #include @@ -93,7 +95,6 @@ namespace AZ void EditorMaterialSystemComponent::Activate() { - AzFramework::TargetManagerClient::Bus::Handler::BusConnect(); EditorMaterialSystemComponentRequestBus::Handler::BusConnect(); AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusConnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); @@ -105,7 +106,6 @@ namespace AZ void EditorMaterialSystemComponent::Deactivate() { - AzFramework::TargetManagerClient::Bus::Handler::BusDisconnect(); EditorMaterialSystemComponentRequestBus::Handler::BusDisconnect(); AzFramework::ApplicationLifecycleEvents::Bus::Handler::BusDisconnect(); AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); @@ -123,36 +123,19 @@ namespace AZ void EditorMaterialSystemComponent::OpenInMaterialEditor(const AZStd::string& sourcePath) { - if (m_materialEditorTarget.IsValid()) - { - AzFramework::TmMsg openDocumentMsg(AZ_CRC("OpenInMaterialEditor", 0x9f92aac8)); - openDocumentMsg.AddCustomBlob(sourcePath.c_str(), sourcePath.size() + 1); - AzFramework::TargetManager::Bus::Broadcast(&AzFramework::TargetManager::SendTmMessage, m_materialEditorTarget, openDocumentMsg); - } - else - { - AZ_TracePrintf("MaterialComponent", "Launching Material Editor"); + AZ_TracePrintf("MaterialComponent", "Launching Material Editor"); - QStringList arguments; - arguments.append(sourcePath.c_str()); - AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments); - } - } + QStringList arguments; + arguments.append(sourcePath.c_str()); - void EditorMaterialSystemComponent::TargetJoinedNetwork(AzFramework::TargetInfo info) - { - if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor")) + // Use the same RHI as the main editor + AZ::Name apiName = AZ::RHI::Factory::Get().GetName(); + if (!apiName.IsEmpty()) { - m_materialEditorTarget = info; + arguments.append(QString("--rhi=%1").arg(apiName.GetCStr())); } - } - void EditorMaterialSystemComponent::TargetLeftNetwork(AzFramework::TargetInfo info) - { - if (AZ::StringFunc::Equal(info.GetDisplayName(), "MaterialEditor")) - { - m_materialEditorTarget = {}; - } + AtomToolsFramework::LaunchTool("MaterialEditor", ".exe", arguments); } void EditorMaterialSystemComponent::OnApplicationAboutToStop() @@ -166,7 +149,10 @@ namespace AZ { m_openMaterialEditorAction = new QAction("Material Editor"); m_openMaterialEditorAction->setShortcut(QKeySequence(Qt::Key_M)); - QObject::connect(m_openMaterialEditorAction, &QAction::triggered, m_openMaterialEditorAction, [this]() + m_openMaterialEditorAction->setCheckable(false); + m_openMaterialEditorAction->setChecked(false); + QObject::connect( + m_openMaterialEditorAction, &QAction::triggered, m_openMaterialEditorAction, [this]() { OpenInMaterialEditor(""); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h index 09ad1c1b9c..cb1aac9163 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h @@ -14,7 +14,6 @@ #include #include -#include #include #include @@ -32,7 +31,6 @@ namespace AZ class EditorMaterialSystemComponent : public AZ::Component , private EditorMaterialSystemComponentRequestBus::Handler - , private AzFramework::TargetManagerClient::Bus::Handler , private AzFramework::ApplicationLifecycleEvents::Bus::Handler , public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler , public AzToolsFramework::EditorMenuNotificationBus::Handler @@ -57,10 +55,6 @@ namespace AZ //! EditorMaterialSystemComponentRequestBus::Handler overrides... void OpenInMaterialEditor(const AZStd::string& sourcePath) override; - //! AzFramework::TargetManagerClient::Bus::Handler overrides... - void TargetJoinedNetwork(AzFramework::TargetInfo info) override; - void TargetLeftNetwork(AzFramework::TargetInfo info) override; - // AzFramework::ApplicationLifecycleEvents overrides... void OnApplicationAboutToStop() override; @@ -74,9 +68,6 @@ namespace AZ void SetupThumbnails(); void TeardownThumbnails(); - // Material Editor target for interprocess communication with MaterialEditor - AzFramework::TargetInfo m_materialEditorTarget; - QAction* m_openMaterialEditorAction = nullptr; AZStd::unique_ptr m_materialBrowserInteractions; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp index b33dd7f165..2ef4e1e229 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef ATOMLYINTEGRATION_FEATURE_COMMON_EDITOR #include @@ -69,6 +70,7 @@ #include #include #include +#include #endif namespace AZ @@ -111,6 +113,7 @@ namespace AZ DiffuseProbeGridComponent::CreateDescriptor(), DeferredFogComponent::CreateDescriptor(), SurfaceData::SurfaceDataMeshComponent::CreateDescriptor(), + AttachmentComponent::CreateDescriptor(), #ifdef ATOMLYINTEGRATION_FEATURE_COMMON_EDITOR EditorAreaLightComponent::CreateDescriptor(), @@ -141,6 +144,7 @@ namespace AZ EditorDiffuseProbeGridComponent::CreateDescriptor(), EditorDeferredFogComponent::CreateDescriptor(), SurfaceData::EditorSurfaceDataMeshComponent::CreateDescriptor(), + EditorAttachmentComponent::CreateDescriptor(), #endif }); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp index efefcc3dc6..735eab5368 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp @@ -133,23 +133,14 @@ namespace AZ AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); EditorReflectionProbeBus::Handler::BusConnect(GetEntityId()); + AZ::TickBus::Handler::BusConnect(); ReflectionProbeComponentConfig& configuration = m_controller.m_configuration; - // special handling is required if this component is being cloned in the editor: - // if the entityId in the configuration does not match this component's entityId it is being cloned - AZ::u64 entityId = (AZ::u64)GetEntityId(); - if (configuration.m_entityId != EntityId::InvalidEntityId - && configuration.m_entityId != entityId) - { - // clear the cubeMapRelativePath to prevent the newly cloned reflection probe - // from using the same cubemap path as the original reflection probe - configuration.m_bakedCubeMapRelativePath = ""; - } - // update UI cubemap path display m_bakedCubeMapRelativePath = configuration.m_bakedCubeMapRelativePath; + AZ::u64 entityId = (AZ::u64)GetEntityId(); configuration.m_entityId = entityId; } @@ -158,9 +149,55 @@ namespace AZ EditorReflectionProbeBus::Handler::BusDisconnect(GetEntityId()); AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); + AZ::TickBus::Handler::BusDisconnect(); BaseClass::Deactivate(); } + void EditorReflectionProbeComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) + { + if (!m_controller.m_featureProcessor) + { + return; + } + + if (m_controller.m_configuration.m_useBakedCubemap) + { + AZStd::string cubeMapRelativePath = m_controller.m_configuration.m_bakedCubeMapRelativePath + ".streamingimage"; + Data::Asset cubeMapAsset; + CubeMapAssetNotificationType notificationType = CubeMapAssetNotificationType::None; + if (m_controller.m_featureProcessor->CheckCubeMapAssetNotification(cubeMapRelativePath, cubeMapAsset, notificationType)) + { + // a cubemap bake is in progress for this entity component + if (notificationType == CubeMapAssetNotificationType::Ready) + { + // bake is complete, update configuration with the new baked cubemap asset + m_controller.m_configuration.m_bakedCubeMapAsset = { cubeMapAsset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; + + // refresh the currently rendered cubemap + m_controller.UpdateCubeMap(); + + // update the UI + AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); + } + else if (notificationType == CubeMapAssetNotificationType::Error) + { + // cubemap bake failed + QMessageBox::information( + QApplication::activeWindow(), + "Reflection Probe", + "Reflection Probe cubemap failed to bake, please check the Asset Processor for more information.", + QMessageBox::Ok); + + // clear relative path, this will allow the user to retry + m_controller.m_configuration.m_bakedCubeMapRelativePath.clear(); + + // update the UI + AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); + } + } + } + } + void EditorReflectionProbeComponent::DisplayEntityViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { // only draw the bounds if selected @@ -172,13 +209,19 @@ namespace AZ AZ::Vector3 position = AZ::Vector3::CreateZero(); AZ::TransformBus::EventResult(position, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); + AZ::Vector3 scale = AZ::Vector3::CreateOne(); + AZ::TransformBus::EventResult(scale, GetEntityId(), &AZ::TransformBus::Events::GetLocalScale); + // draw AABB at probe position using the inner dimensions Color color(0.0f, 0.0f, 1.0f, 1.0f); debugDisplay.SetColor(color); ReflectionProbeComponentConfig& configuration = m_controller.m_configuration; - AZ::Vector3 innerMin(position.GetX() - configuration.m_innerWidth / 2, position.GetY() - configuration.m_innerLength / 2, position.GetZ() - configuration.m_innerHeight / 2); - AZ::Vector3 innerMax(position.GetX() + configuration.m_innerWidth / 2, position.GetY() + configuration.m_innerLength / 2, position.GetZ() + configuration.m_innerHeight / 2); + AZ::Vector3 innerExtents(configuration.m_innerWidth, configuration.m_innerLength, configuration.m_innerHeight); + innerExtents *= scale; + + AZ::Vector3 innerMin(position.GetX() - innerExtents.GetX() / 2, position.GetY() - innerExtents.GetY() / 2, position.GetZ() - innerExtents.GetZ() / 2); + AZ::Vector3 innerMax(position.GetX() + innerExtents.GetX() / 2, position.GetY() + innerExtents.GetY() / 2, position.GetZ() + innerExtents.GetZ() / 2); debugDisplay.DrawWireBox(innerMin, innerMax); } @@ -270,122 +313,94 @@ namespace AZ return AZ::Edit::PropertyRefreshLevels::None; } - // callback from the EnvironmentCubeMapPass when the cubemap render is complete - BuildCubeMapCallback buildCubeMapCallback = [this](uint8_t* const* cubeMapFaceTextureData, const RHI::Format cubeMapTextureFormat) + char projectPath[AZ_MAX_PATH_LEN]; + AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN); + + // retrieve the source cubemap path from the configuration + // we need to make sure to use the same source cubemap for each bake + AZStd::string cubeMapRelativePath = m_controller.m_configuration.m_bakedCubeMapRelativePath; + AZStd::string cubeMapFullPath; + + if (!cubeMapRelativePath.empty()) { - if (!m_bakeInProgress) + // test to see if the cubemap file is actually there, if it was removed we need to + // generate a new filename, otherwise it will cause an error in the asset system + AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true); + + if (!AZ::IO::FileIOBase::GetInstance()->Exists(cubeMapFullPath.c_str())) { - // user canceled the bake - return; + // clear it to force the generation of a new filename + cubeMapRelativePath.clear(); } + } - char projectPath[AZ_MAX_PATH_LEN]; - AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", projectPath, AZ_MAX_PATH_LEN); + // build a new cubemap path if necessary + if (cubeMapRelativePath.empty()) + { + // the file name is a combination of the entity name, a UUID, and the filemask + Entity* entity = GetEntity(); + AZ_Assert(entity, "ReflectionProbe entity is null"); - // retrieve the source cubemap path from the configuration - // we need to make sure to use the same source cubemap for each bake - AZStd::string cubeMapRelativePath = m_controller.m_configuration.m_bakedCubeMapRelativePath; - AZStd::string cubeMapFullPath; + AZ::Uuid uuid = AZ::Uuid::CreateRandom(); + AZStd::string uuidString; + uuid.ToString(uuidString); - if (!cubeMapRelativePath.empty()) + cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + "_iblspecularcm.dds"; + + // replace any invalid filename characters + auto invalidCharacters = [](char letter) { - // test to see if the cubemap file is actually there, if it was removed we need to - // generate a new filename, otherwise it will cause an error in the asset system - AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true); + return + letter == ':' || letter == '"' || letter == '\'' || + letter == '{' || letter == '}' || + letter == '<' || letter == '>'; + }; + AZStd::replace_if(cubeMapRelativePath.begin(), cubeMapRelativePath.end(), invalidCharacters, '_'); - if (!AZ::IO::FileIOBase::GetInstance()->Exists(cubeMapFullPath.c_str())) - { - // clear it to force the generation of a new filename - cubeMapRelativePath.clear(); - } - } + // build the full source path + AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true); + } - // build a new cubemap path if necessary - if (cubeMapRelativePath.empty()) - { - // the file name is a combination of the entity name, a UUID, and the filemask - Entity* entity = GetEntity(); - AZ_Assert(entity, "ReflectionProbe entity is null"); + // make sure the folder is created + AZStd::string reflectionProbeFolder; + AzFramework::StringFunc::Path::GetFolderPath(cubeMapFullPath.data(), reflectionProbeFolder); + AZ::IO::SystemFile::CreateDir(reflectionProbeFolder.c_str()); - AZ::Uuid uuid = AZ::Uuid::CreateRandom(); - AZStd::string uuidString; - uuid.ToString(uuidString); + // check out the file in source control + bool checkedOutSuccessfully = false; + using ApplicationBus = AzToolsFramework::ToolsApplicationRequestBus; + ApplicationBus::BroadcastResult( + checkedOutSuccessfully, + &ApplicationBus::Events::RequestEditForFileBlocking, + cubeMapFullPath.c_str(), + "Checking out for edit...", + ApplicationBus::Events::RequestEditProgressCallback()); - cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + "_iblspecularcm.dds"; + if (!checkedOutSuccessfully) + { + AZ_Error("ReflectionProbe", false, "Failed to write \"%s\", source control checkout failed", cubeMapFullPath.c_str()); + } - // replace any invalid filename characters - auto invalidCharacters = [](char letter) - { - return - letter == ':' || letter == '"' || letter == '\'' || - letter == '{' || letter == '}' || - letter == '<' || letter == '>'; - }; - AZStd::replace_if(cubeMapRelativePath.begin(), cubeMapRelativePath.end(), invalidCharacters, '_'); + // save the relative source path in the configuration + AzToolsFramework::ScopedUndoBatch undoBatch("Cubemap path changed."); + m_controller.m_configuration.m_bakedCubeMapRelativePath = cubeMapRelativePath; + SetDirty(); - // build the full source path - AzFramework::StringFunc::Path::Join(projectPath, cubeMapRelativePath.c_str(), cubeMapFullPath, true, true); - } - - // make sure the folder is created - AZStd::string reflectionProbeFolder; - AzFramework::StringFunc::Path::GetFolderPath(cubeMapFullPath.data(), reflectionProbeFolder); - AZ::IO::SystemFile::CreateDir(reflectionProbeFolder.c_str()); - - // check out the file in source control - bool checkedOutSuccessfully = false; - using ApplicationBus = AzToolsFramework::ToolsApplicationRequestBus; - ApplicationBus::BroadcastResult( - checkedOutSuccessfully, - &ApplicationBus::Events::RequestEditForFileBlocking, - cubeMapFullPath.c_str(), - "Checking out for edit...", - ApplicationBus::Events::RequestEditProgressCallback()); - - if (!checkedOutSuccessfully) - { - AZ_Error("ReflectionProbe", false, "Failed to write \"%s\", source control checkout failed", cubeMapFullPath.c_str()); - } + // update UI cubemap path display + m_bakedCubeMapRelativePath = cubeMapRelativePath; + // callback from the EnvironmentCubeMapPass when the cubemap render is complete + BuildCubeMapCallback buildCubeMapCallback = [=](uint8_t* const* cubeMapFaceTextureData, const RHI::Format cubeMapTextureFormat) + { // write the cubemap data to the .dds file WriteOutputFile(cubeMapFullPath.c_str(), cubeMapFaceTextureData, cubeMapTextureFormat); - - // save the relative source path in the configuration - AzToolsFramework::ScopedUndoBatch undoBatch("Cubemap path changed."); - m_controller.m_configuration.m_bakedCubeMapRelativePath = cubeMapRelativePath; - SetDirty(); - - // update UI cubemap path display - m_bakedCubeMapRelativePath = cubeMapRelativePath; - - // call the feature processor to notify when the asset is created and ready - NotifyCubeMapAssetReadyCallback notifyCubeMapAssetReadyCallback = [this](const Data::Asset& cubeMapAsset, CubeMapAssetNotificationType notificationType) - { - // we only need to store the cubemap asset and update the cubemap image on the first bake of the probe, - // otherwise it is a hot-reload of an existing cubemap asset which is handled by the RPI - if (notificationType == CubeMapAssetNotificationType::Ready) - { - // update configuration with the new baked cubemap asset - m_controller.m_configuration.m_bakedCubeMapAsset = { cubeMapAsset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; - - // refresh the currently rendered cubemap - m_controller.UpdateCubeMap(); - - // update the UI - AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh, AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues); - } - - // signal completion - m_bakeInProgress = false; - }; - - AZStd::string cubeMapRelativeAssetPath = cubeMapRelativePath + ".streamingimage"; - m_controller.m_featureProcessor->NotifyCubeMapAssetReady(cubeMapRelativeAssetPath, notifyCubeMapAssetReadyCallback); + m_bakeInProgress = false; }; - // initiate the cubemap bake + // initiate the cubemap bake, this will invoke the buildCubeMapCallback when the cubemap data is ready m_bakeInProgress = true; - m_controller.BakeReflectionProbe(buildCubeMapCallback); + AZStd::string cubeMapRelativeAssetPath = cubeMapRelativePath + ".streamingimage"; + m_controller.BakeReflectionProbe(buildCubeMapCallback, cubeMapRelativeAssetPath); // show a dialog box letting the user know the probe is baking QProgressDialog bakeDialog; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h index eba9575ec4..23fd391818 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.h @@ -13,6 +13,7 @@ #pragma once #include +#include #include #include #include @@ -29,6 +30,7 @@ namespace AZ , public EditorReflectionProbeBus::Handler , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler , private AzFramework::EntityDebugDisplayEventBus::Handler + , private AZ::TickBus::Handler { public: using BaseClass = EditorRenderComponentAdapter; @@ -45,8 +47,12 @@ namespace AZ // AzFramework::EntityDebugDisplayEventBus::Handler overrides void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + private: + // AZ::TickBus overrides + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + // validation AZ::Outcome OnUseBakedCubemapValidate(void* newValue, const AZ::Uuid& valueType); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp index c7349adefa..59d1f7afa7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp @@ -111,6 +111,18 @@ namespace AZ m_boxShapeInterface = LmbrCentral::BoxShapeComponentRequestsBus::FindFirstHandler(m_entityId); AZ_Assert(m_boxShapeInterface, "ReflectionProbeComponentController was unable to find box shape component"); + // special handling is required if this component is being cloned in the editor: + // if this probe is using a baked cubemap, check to see if it is already referenced by another probe + if (m_configuration.m_useBakedCubemap) + { + if (m_featureProcessor->IsCubeMapReferenced(m_configuration.m_bakedCubeMapRelativePath)) + { + // clear the cubeMapRelativePath to prevent the newly cloned reflection probe + // from using the same cubemap path as the original reflection probe + m_configuration.m_bakedCubeMapRelativePath = ""; + } + } + // add this reflection probe to the feature processor const AZ::Transform& transform = m_transformInterface->GetWorldTM(); m_handle = m_featureProcessor->AddProbe(transform, m_configuration.m_useParallaxCorrection); @@ -130,12 +142,15 @@ namespace AZ m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapAsset : m_configuration.m_authoredCubeMapAsset; Data::AssetBus::MultiHandler::BusConnect(cubeMapAsset.GetId()); + const AZStd::string& relativePath = + m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapRelativePath : m_configuration.m_authoredCubeMapAsset.GetHint(); + if (cubeMapAsset.GetId().IsValid()) { if (cubeMapAsset.IsReady()) { Data::Instance image = RPI::StreamingImage::FindOrCreate(cubeMapAsset); - m_featureProcessor->SetProbeCubeMap(m_handle, image); + m_featureProcessor->SetProbeCubeMap(m_handle, image, relativePath); } else { @@ -169,8 +184,11 @@ namespace AZ return; } + const AZStd::string& relativePath = + m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapRelativePath : m_configuration.m_authoredCubeMapAsset.GetHint(); + Data::Instance image = RPI::StreamingImage::FindOrCreate(asset); - m_featureProcessor->SetProbeCubeMap(m_handle, image); + m_featureProcessor->SetProbeCubeMap(m_handle, image, relativePath); } void ReflectionProbeComponentController::SetConfiguration(const ReflectionProbeComponentConfig& config) @@ -188,8 +206,11 @@ namespace AZ Data::Asset& cubeMapAsset = m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapAsset : m_configuration.m_authoredCubeMapAsset; + const AZStd::string& relativePath = + m_configuration.m_useBakedCubemap ? m_configuration.m_bakedCubeMapRelativePath : m_configuration.m_authoredCubeMapAsset.GetHint(); + Data::Instance image = RPI::StreamingImage::FindOrCreate(cubeMapAsset); - m_featureProcessor->SetProbeCubeMap(m_handle, image); + m_featureProcessor->SetProbeCubeMap(m_handle, image, relativePath); } void ReflectionProbeComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world) @@ -240,14 +261,14 @@ namespace AZ m_configuration.m_innerHeight = AZStd::min(m_configuration.m_innerHeight, m_configuration.m_outerHeight); } - void ReflectionProbeComponentController::BakeReflectionProbe(BuildCubeMapCallback callback) + void ReflectionProbeComponentController::BakeReflectionProbe(BuildCubeMapCallback callback, const AZStd::string& relativePath) { if (!m_featureProcessor) { return; } - m_featureProcessor->BakeProbe(m_handle, callback); + m_featureProcessor->BakeProbe(m_handle, callback, relativePath); } AZ::Aabb ReflectionProbeComponentController::GetAabb() const diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h index 20d692145c..0a57fde882 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.h @@ -79,7 +79,7 @@ namespace AZ AZ::Aabb GetAabb() const; // initiate the reflection probe bake, invokes callback when complete - void BakeReflectionProbe(BuildCubeMapCallback callback); + void BakeReflectionProbe(BuildCubeMapCallback callback, const AZStd::string& relativePath); // update the currently rendering cubemap asset for this probe void UpdateCubeMap(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp index f3c74629c2..16baf16886 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/CaptureStep.cpp @@ -37,6 +37,15 @@ namespace AZ void CaptureStep::Start() { + if (!m_context->GetData()->m_materialAsset || + !m_context->GetData()->m_modelAsset) + { + AzToolsFramework::Thumbnailer::ThumbnailerRendererNotificationBus::Event( + m_context->GetData()->m_thumbnailKeyRendered, + &AzToolsFramework::Thumbnailer::ThumbnailerRendererNotifications::ThumbnailFailedToRender); + m_context->SetStep(Step::FindThumbnailToRender); + return; + } Render::MaterialComponentRequestBus::Event( m_context->GetData()->m_modelEntity->GetId(), &Render::MaterialComponentRequestBus::Events::SetDefaultMaterialOverride, diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp index 100b0f61cd..322c765f1b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Thumbnails/Rendering/ThumbnailRendererSteps/InitializeStep.cpp @@ -189,6 +189,7 @@ namespace AZ m_context->GetData()->DefaultModelPath, RPI::ModelAsset::RTTI_Type(), false); + AZ_Error("ThumbnailRenderer", defaultModelAssetId.IsValid(), "Default model asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultModelPath); if (m_context->GetData()->m_assetsToLoad.emplace(defaultModelAssetId).second) { data->m_defaultModelAsset.Create(defaultModelAssetId); @@ -203,6 +204,7 @@ namespace AZ m_context->GetData()->DefaultMaterialPath, RPI::MaterialAsset::RTTI_Type(), false); + AZ_Error("ThumbnailRenderer", defaultMaterialAssetId.IsValid(), "Default material asset is invalid. Verify the asset %s exists.", m_context->GetData()->DefaultMaterialPath); if (m_context->GetData()->m_assetsToLoad.emplace(defaultMaterialAssetId).second) { data->m_defaultMaterialAsset.Create(defaultMaterialAssetId); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index ff8f33e06e..e58f72a121 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -11,6 +11,8 @@ set(FILES Source/Module.cpp + Source/Animation/EditorAttachmentComponent.h + Source/Animation/EditorAttachmentComponent.cpp Include/AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h Include/AtomLyIntegration/CommonFeatures/ReflectionProbe/EditorReflectionProbeBus.h Source/EditorCommonFeaturesSystemComponent.h diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake index b26ebc60a6..e13d1d37d6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake @@ -10,6 +10,8 @@ # set(FILES + Source/Animation/AttachmentComponent.h + Source/Animation/AttachmentComponent.cpp Source/CoreLights/AreaLightComponent.h Source/CoreLights/AreaLightComponent.cpp Source/CoreLights/AreaLightComponentConfig.cpp diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h index b31091681e..1002fcbde1 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.h @@ -18,7 +18,7 @@ #include -#include +#include #include #include diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp index 49ed813ed8..8ae7c30c6a 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/DebugConsole.cpp @@ -126,7 +126,12 @@ namespace AZ SetFilter(inputFilter); // Bind our custom log handler. - AZ::Interface::Get()->BindLogHandler(m_logHandler); + AZ::ILogger* loggerInstance = AZ::Interface::Get(); + AZ_Assert(loggerInstance, "Failed to get ILogger instance. Log handler not bound.") + if (loggerInstance) + { + loggerInstance->BindLogHandler(m_logHandler); + } // Connect to receive render tick events. auto atomViewportRequests = AZ::Interface::Get(); diff --git a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp index 34e7af688c..8493b78171 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp +++ b/Gems/AtomLyIntegration/ImguiAtom/Code/Source/ImguiAtomSystemComponent.cpp @@ -99,7 +99,7 @@ namespace AZ #endif } - void ImguiAtomSystemComponent::OnViewportSizeChanged(AzFramework::WindowSize size) + void ImguiAtomSystemComponent::OnViewportSizeChanged([[maybe_unused]] AzFramework::WindowSize size) { #if defined(IMGUI_ENABLED) ImGui::ImGuiManagerBus::Broadcast([this, size](ImGui::ImGuiManagerBus::Events* imgui) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/main.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/main.py index 7fc7d49a40..8ffbee78d5 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/main.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/main.py @@ -29,7 +29,10 @@ import collections from collections import abc # import subprocess import logging as _logging -import pathlib +try: + import pathlib +except: + import pathlib2 as pathlib from pathlib import * import shelve # import socket diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/utilities.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/utilities.py index eb4974bd55..9fd031b106 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/utilities.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/utilities.py @@ -17,8 +17,14 @@ import logging as _logging + +try: + import pathlib +except: + import pathlib2 as pathlib + from pathlib import Path -import pathlib + from box import Box import os diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/set_callbacks.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/set_callbacks.py index 5d495d2dcd..4a1a7164d8 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/set_callbacks.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/set_callbacks.py @@ -62,15 +62,15 @@ _LOGGER.debug('Invoking:: {0}.'.format({_MODULENAME})) # To Do: move the callback key like 'NewSceneOpened' here (instead of None) # ^ this would provide ability to loop through and replace key with CB object -_G_callbacks = Box(box_dots=True) # global scope container -_G_masterkey = 'DCCsi_callbacks' -_G_callbacks[_G_masterkey] = True # required master key +_G_CALLBACKS = Box(box_dots=True) # global scope container +_G_PRIMEKEY = 'DCCsi_callbacks' +_G_CALLBACKS[_G_PRIMEKEY] = True # required prime key # ------------------------------------------------------------------------- -def init_callbacks(_callbacks=_G_callbacks): +def init_callbacks(_callbacks=_G_CALLBACKS): # store as a dict (Box is a fancy dict) - _callbacks[_G_masterkey] = True # required master key + _callbacks[_G_PRIMEKEY] = True # required prime key # signature dict['callback key'] = ('CallBack'(type), func, callbackObj) _callbacks['on_new_file'] = ['NewSceneOpened', set_defaults, None] @@ -96,24 +96,24 @@ def uninstall_callbacks(): """Bulk uninstalls hte globally defined set of callbacks: _G_callbacks""" - global _G_callbacks + global _G_CALLBACKS _LOGGER.debug('uninstall_callbacks() fired') - for key, value in _G_callbacks: + for key, value in _G_CALLBACKS: if value[2] is not None: # have a cb value[2].uninstall() # so uninstall it else: _LOGGER.warning('No callback in: key {0}, value:{1}' ''.format(key, value)) - _G_callbacks = None + _G_CALLBACKS = None _LOGGER.info('DCCSI CALLBACKS UNINSTALLED ... EXITING') - return _G_callbacks + return _G_CALLBACKS # ------------------------------------------------------------------------- # ------------------------------------------------------------------------- -def install_callbacks(_callbacks=_G_callbacks): +def install_callbacks(_callbacks=_G_CALLBACKS): """Bulk installs the globally defined set of callbacks: _G_callbacks""" @@ -126,15 +126,15 @@ def install_callbacks(_callbacks=_G_callbacks): _callbacks.pop('box_dots') # don't pass anything but carefully considered dict - if _G_masterkey in _callbacks: - _masterkey = _callbacks.pop(_G_masterkey) + if _G_PRIMEKEY in _callbacks: + _primekey = _callbacks.pop(_G_PRIMEKEY) else: - _LOGGER.error('No master key, use a correct dictionary') + _LOGGER.error('No prime key, use a correct dictionary') #To Do: implement error handling and return codes return _callbacks[None] - for key, value in _G_callbacks.items(): - # we popped the master key should the rest should be safe + for key, value in _G_CALLBACKS.items(): + # we popped the prime key should the rest should be safe if value[0] != 'nodeMessageType': # set callback up _cb = azEvCbH.EventCallbackHandler(value[0], @@ -195,10 +195,10 @@ def update_workspace(foo=None): # ------------------------------------------------------------------------- # install and init callbacks on an import obj -_G_callbacks = install_callbacks(_G_callbacks) +_G_CALLBACKS = install_callbacks(_G_CALLBACKS) # ========================================================================== # Module Tests #========================================================================== if __name__ == '__main__': - _G_callbacks = install_callbacks(_G_callbacks) + _G_CALLBACKS = install_callbacks(_G_CALLBACKS) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/userSetup.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/userSetup.py index 809cb97494..c615311f3c 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/userSetup.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/userSetup.py @@ -262,9 +262,9 @@ def post_startup(): # callbacks, To Do: these should also be moved to the bootstrapping config # Defered startup after the Ui is running. - _G_callbacks = Box(box_dots=True) # this just ensures a global scope container + _G_CALLBACKS = Box(box_dots=True) # this just ensures a global scope container if _G_LOAD_CALLBACKS: - from set_callbacks import _G_callbacks + from set_callbacks import _G_CALLBACKS # ^ need to hold on to this as the install repopulate set # this ensures the fixPaths callback is loaded diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/readme.txt b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/readme.txt index 5936b24632..cc090d922f 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/readme.txt +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/readme.txt @@ -74,7 +74,9 @@ Now your local maya install is all set up with pip so you can install additional Now you will want to run the following file to finish setup... We have a requirements.txt file with the extension packages we use in the DCCsi. -You'll need the repo/branch path of your Lumberyard(O3DE) install. -And you'll need to know where the DCCsi, we will install package dependancies there. +You'll need the repo/branch path of your O3DE (aka Lumberyard) install. +And you'll need to know where the DCCsi is located, we will install package dependancies there. -C:\Program Files\Autodesk\Maya2020\bin>mayapy -m pip install -r C:\Depot\Lumberyard\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\SDK\Maya\requirements.txt -t C:\Depot\Lumberyard\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\3rdParty\Python\Lib\2.x\2.7.x\site-packages +Note: you may need to update the paths below to match your local o3de engine install! + +C:\Program Files\Autodesk\Maya2020\bin>mayapy -m pip install -r C:\Depot\o3de\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\SDK\Maya\requirements.txt -t C:\Depot\o3de\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\3rdParty\Python\Lib\2.x\2.7.x\site-packages diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/requirements.txt b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/requirements.txt index 2d087be121..8fd084dac8 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/requirements.txt +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/requirements.txt @@ -4,12 +4,14 @@ # # pip-compile --generate-hashes requirements.txt # -typing==3.7.4.3 \ - --hash=sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9 \ - --hash=sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5 - # via - # -r requirements.txt - # dynaconf +cachetools==3.1.1 \ + --hash=sha256:428266a1c0d36dc5aca63a2d7c5942e88c2c898d72139fca0e97fdd2380517ae \ + --hash=sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a + # via -r requirements.txt +certifi==2020.6.20 \ + --hash=sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3 \ + --hash=sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41 + # via -r requirements.txt click==7.1.2 \ --hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a \ --hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc @@ -20,6 +22,14 @@ dynaconf==3.1.4 \ --hash=sha256:b2f472d83052f809c5925565b8a2ba76a103d5dc1dbb9748b693ed67212781b9 \ --hash=sha256:e6f383b84150b70fc439c8b2757581a38a58d07962aa14517292dcce1a77e160 # via -r requirements.txt +hashids==1.3.1 \ + --hash=sha256:6c3dc775e65efc2ce2c157a65acb776d634cb814598f406469abef00ae3f635c \ + --hash=sha256:8bddd1acba501bfc9306e7e5a99a1667f4f2cacdc20cbd70bcc5ddfa5147c94c + # via -r requirements.txt +pathlib2==2.3.5 \ + --hash=sha256:0ec8205a157c80d7acc301c0b18fbd5d44fe655968f5d947b6ecef5290fc35db \ + --hash=sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868 + # via -r requirements.txt pathlib==1.0.1 \ --hash=sha256:6940718dfc3eff4258203ad5021090933e5c04707d5ca8cc9e73c94a7894ea9f # via -r requirements.txt @@ -27,7 +37,38 @@ python-box==3.4.6 \ --hash=sha256:694a7555e3ff9fbbce734bbaef3aad92b8e4ed0659d3ed04d56b6a0a0eff26a9 \ --hash=sha256:a71d3dc9dbaa34c8597d3517c89a8041bd62fa875f23c0f3dad55e1958e3ce10 # via -r requirements.txt +scandir==1.10.0 \ + --hash=sha256:2586c94e907d99617887daed6c1d102b5ca28f1085f90446554abf1faf73123e \ + --hash=sha256:2ae41f43797ca0c11591c0c35f2f5875fa99f8797cb1a1fd440497ec0ae4b022 \ + --hash=sha256:2b8e3888b11abb2217a32af0766bc06b65cc4a928d8727828ee68af5a967fa6f \ + --hash=sha256:2c712840c2e2ee8dfaf36034080108d30060d759c7b73a01a52251cc8989f11f \ + --hash=sha256:4d4631f6062e658e9007ab3149a9b914f3548cb38bfb021c64f39a025ce578ae \ + --hash=sha256:67f15b6f83e6507fdc6fca22fedf6ef8b334b399ca27c6b568cbfaa82a364173 \ + --hash=sha256:7d2d7a06a252764061a020407b997dd036f7bd6a175a5ba2b345f0a357f0b3f4 \ + --hash=sha256:8c5922863e44ffc00c5c693190648daa6d15e7c1207ed02d6f46a8dcc2869d32 \ + --hash=sha256:92c85ac42f41ffdc35b6da57ed991575bdbe69db895507af88b9f499b701c188 \ + --hash=sha256:b24086f2375c4a094a6b51e78b4cf7ca16c721dcee2eddd7aa6494b42d6d519d \ + --hash=sha256:cb925555f43060a1745d0a321cca94bcea927c50114b623d73179189a4e100ac + # via + # -r requirements.txt + # pathlib2 +six==1.15.0 \ + --hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259 \ + --hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced + # via + # -r requirements.txt + # pathlib2 +typing==3.7.4.3 \ + --hash=sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9 \ + --hash=sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5 + # via + # -r requirements.txt + # dynaconf unipath==1.1 \ --hash=sha256:09839adcc72e8a24d4f76d63656f30b5a1f721fc40c9bcd79d8c67bdd8b47dae \ --hash=sha256:e6257e508d8abbfb6ddd8ec357e33589f1f48b1599127f23b017124d90b0fff7 # via -r requirements.txt +wincertstore==0.2 \ + --hash=sha256:22d5eebb52df88a8d4014d5cf6d1b6c3a5d469e6c3b2e2854f3a003e48872356 \ + --hash=sha256:780bd1557c9185c15d9f4221ea7f905cb20b93f7151ca8ccaed9714dce4b327a + # via -r requirements.txt diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/__init__.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/__init__.py index 57b97ad1cb..69e4543a59 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/__init__.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/__init__.py @@ -36,11 +36,10 @@ _TYPE_TAG = 'module' _PACKAGENAME = _TOOL_TAG -__all__ = ['initialize_logger', - 'config_utils', 'render', +__all__ = ['config_utils', 'render', 'constants', 'return_stub', 'synthetic_env', 'env_base', 'env_bool', 'test', 'dev', - 'lumberyard', 'marmoset'] #'blender', 'maya', 'substance', 'houdini'] + 'lumberyard', 'marmoset'] # 'blender', 'maya', 'substance', 'houdini'] # ------------------------------------------------------------------------- @@ -68,7 +67,10 @@ _DCCSI_DEV_MODE = env_bool.env_bool(constants.ENVAR_DCCSI_DEV_MODE, False) # for py2.7 (Maya) we provide this, so we must assume some bootstrapping # has occured, see DccScriptingInterface\\config.py (_DCCSI_PYTHON_LIB_PATH) -import pathlib +try: + import pathlib +except: + import pathlib2 as pathlib from pathlib import Path if _G_DEBUG: print('DCCsi debug breadcrumb, pathlib is: {}'.format(pathlib)) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py index dbc75212d4..9c920a871d 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/config_utils.py @@ -80,9 +80,9 @@ def return_stub_dir(stub_file='dccsi_stub'): # ------------------------------------------------------------------------- -def get_stub_check_path(in_path=os.getcwd(), check_stub='engineroot.txt'): +def get_stub_check_path(in_path=os.getcwd(), check_stub='engine.json'): ''' - Returns the branch root directory of the dev\\'engineroot.txt' + Returns the branch root directory of the dev\\'engine.json' (... or you can pass it another known stub) so we can safely build relative filepaths within that branch. @@ -158,7 +158,6 @@ def bootstrap_dccsi_py_libs(dccsi_dirpath=return_stub_dir()): """Builds and adds local site dir libs based on py version""" from azpy.constants import STR_DCCSI_PYTHON_LIB_PATH # a path string constructor - #_DCCSI_PYTHON_LIB_PATH = "E:\\P4\\jromnoa_spectra_atom_2\\dev\\Tools\\Python\\3.7.5\\windows\\Lib\\site-packages" _DCCSI_PYTHON_LIB_PATH = STR_DCCSI_PYTHON_LIB_PATH.format(dccsi_dirpath, sys.version_info[0], sys.version_info[1]) @@ -193,9 +192,9 @@ if __name__ == '__main__': _config = get_dccsi_config() _LOGGER.info('DCCSI_CONFIG_PATH: {}'.format(_config)) - _LOGGER.info('LY_DEV: {}'.format(get_stub_check_path('engineroot.txt'))) + _LOGGER.info('LY_DEV: {}'.format(get_stub_check_path('engine.json'))) - _LOGGER.info('LY_PROJECT: {}'.format(get_current_project(get_stub_check_path('engineroot.txt')))) + _LOGGER.info('LY_PROJECT: {}'.format(get_current_project(get_stub_check_path('bootstrap.cfg')))) _LOGGER.info('DCCSI_PYTHON_LIB_PATH: {}'.format(bootstrap_dccsi_py_libs(return_stub_dir('dccsi_stub')))) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py index 5ca0bc4a95..792f0faee6 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/constants.py @@ -92,7 +92,7 @@ TAG_DIR_LY_BUILD = str('build') TAG_QT_PLUGIN_PATH = str('QT_PLUGIN_PATH') # filesystem markers, stub file names. -STUB_LY_DEV = str('engineroot.txt') +STUB_LY_DEV = str('engine.json') STUB_LY_ROOT_PROJECT = str('ly_project_stub') STUB_LY_ROOT_DCCSI = str('dccsi_stub') STUB_LY_DCCSI_AZPY = str('dccsi_azpy_stub') diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/maya/utils/wing_to_maya.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/maya/utils/wing_to_maya.py index 9798f3f268..3d34aceb40 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/maya/utils/wing_to_maya.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/maya/utils/wing_to_maya.py @@ -36,7 +36,7 @@ _LOGGER.info('local_host: {}'.format(_LOCAL_HOST)) # ------------------------------------------------------------------------- def start_wing_to_maya(local_host=_LOCAL_HOST, - comman_port=6000, + command_port=6000, logger=_LOGGER, *args, **kwargs): """ @@ -58,7 +58,7 @@ def start_wing_to_maya(local_host=_LOCAL_HOST, except NameError: port = None - port_name = str('{0}:{1}'.format(local_host, comman_port)) + port_name = str('{0}:{1}'.format(local_host, command_port)) # should only be getting the port passed in _LOGGER.info('Attempting to open port:: {0}'.format(port_name)) @@ -145,10 +145,10 @@ def start_wing_to_maya_menu(): port = object() # init a dummy object # default name ... name is first arg, or a kwarg - portName, kwargs = setSynthArgKwarg(port, argPosIndex=0, argTag='portName', - inArgs=args, inKwargs=kwargs, - defaultValue="127.0.0.1:6000") + portName, kwargs = set_synth_arg_kwarg(port, arg_pos_index=0, arg_tag='portName', + in_args=args, in_kwargs=kwargs, + default_value="127.0.0.1:6000") - port = start_wing_to_maya(local_host=_LOCAL_HOST, comman_port=6000) + port = start_wing_to_maya(local_host=_LOCAL_HOST, command_port=6000) return # ------------------------------------------------------------------------- diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/__init__.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/__init__.py index 7d165916c5..b30fef72c8 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/__init__.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/__init__.py @@ -15,30 +15,118 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """azpy.shared.ui.__init__""" import os -import logging -import logging.config +from pathlib import Path +import logging as _logging -# global space debug flag -_G_DEBUG = os.getenv('DCCSI_GDEBUG', False) +from azpy.env_bool import env_bool +from azpy.constants import ENVAR_DCCSI_GDEBUG +from azpy.constants import ENVAR_DCCSI_DEV_MODE -# global space debug flag -_DCCSI_DEV_MODE = os.getenv('DCCSI_DEV_MODE', False) +# global space +_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False) +_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False) +_PACKAGENAME = __name__ +if _PACKAGENAME is '__main__': + _PACKAGENAME = 'azpy.shared.noodely' + +import azpy +_LOGGER = azpy.initialize_logger(_PACKAGENAME) +_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME})) +# ------------------------------------------------------------------------- +# +__all__ = ['find_arg', + 'helpers', + 'node', + 'synth', + 'synth_arg_kwarg', + 'test_foo'] +# +# ------------------------------------------------------------------------- + + +# -- Project Globals ------------------------------------------------------ +while 1: + # But if we want to change the prject root, we can set a new one here. + def set_G_DEFAULT_PROJECT_DIR(value): + global _G_DEFAULT_PROJECT_DIR + """Sets and returns the _G_DEFAULT_PROJECT_DIR""" + _G_DEFAULT_PROJECT_DIR = Path(value).resolve() + return Path(_G_DEFAULT_PROJECT_DIR) + + def get_G_DEFAULT_PROJECT_DIR(): + global _G_DEFAULT_PROJECT_DIR + """Returns the _G_DEFAULT_PROJECT_DIR""" + return Path(_G_DEFAULT_PROJECT_DIR) + + # if we are initializing everythin properly, we can assume the project + # variables are properly set + global _G_DEFAULT_PROJECT_DIR + _G_DEFAULT_PROJECT_DIR = Path(os.getcwd()).resolve() + + break +# ------------------------------------------------------------------------- + +# ------------------------------------------------------------------------- +while 1: + global _G_PRIME_ROOT_NODE + _G_PRIME_ROOT_NODE = None # <-- needs to be set up! + # But if we want to change the prject root, we can set a new one here. + + def set_G_PRIME_ROOT_NODE(node): + """Sets and returns the _G_PRIME_ROOT_NODE""" + global _G_PRIME_ROOT_NODE + if not isinstance(node, ProjectRootNode): + message = '_G_PRIME_ROOT_NODE: {}\r'.format(type(node)) + message += 'A project root node needs to be properly set\r' + raise TypeError(message) + _G_PRIME_ROOT_NODE = node + return _G_PRIME_ROOT_NODE + + def get_G_PRIME_ROOT_NODE(): + """Returns the _G_PRIME_ROOT_NODE""" + global _G_PRIME_ROOT_NODE + return _G_PRIME_ROOT_NODE + + break +# ------------------------------------------------------------------------- + + +########################################################################### +# tests(), code block for testing module +# ------------------------------------------------------------------------- +def tests(): + _G_DEFAULT_PROJECT_DIR = set_G_DEFAULT_PROJECT_DIR(os.getcwd()) + _LOGGER.info(_G_DEFAULT_PROJECT_DIR) + _LOGGER.info(_G_DEFAULT_PROJECT_DIR.parent) + _LOGGER.info(_G_DEFAULT_PROJECT_DIR.parts) + + # NOT implemented yet + # _G_PRIME_ROOT_NODE + + return +# ------------------------------------------------------------------------- + + +# ------------------------------------------------------------------------- if _DCCSI_DEV_MODE: - _PACKAGENAME = __name__ - if _PACKAGENAME is '__main__': - _PACKAGENAME = 'noodely' - -_PKG_PARENT_PATH = str('azpy.shared') -_PKG_PATH = str('{0}.{1}'.format(_PKG_PARENT_PATH, _PACKAGENAME)) -_LOGGER = logging.getLogger(_PACKAGENAME) -_LOGGER.debug('Invoking __init__.py for {0}.'.format({_PKG_PATH})) - -# ------------------------------------------------------------------------- -# -__all__ = ['config', 'find_arg', 'master', 'node', 'synth', - 'synth_arg_kwarg', 'test_foo'] -# + # If in dev mode this will test imports of __all__ + from azpy import test_imports + _LOGGER.debug('Testing Imports from {0}'.format(_PACKAGENAME)) + test_imports(__all__, + _pkg=_PACKAGENAME, + _logger=_LOGGER) # ------------------------------------------------------------------------- -del _LOGGER + +########################################################################### +# --call block------------------------------------------------------------- +if __name__ == "__main__": + _LOGGER.info("# {0} #".format('-' * 72)) + _LOGGER.info('~ noodely.prime ... Running script as __main__') + _LOGGER.info("# {0} #".format('-' * 72)) + + # run simple tests + tests() + +del _LOGGER \ No newline at end of file diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/find_arg.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/find_arg.py index 517064e57a..1ed217bc73 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/find_arg.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/find_arg.py @@ -23,8 +23,8 @@ __author__ = 'HogJonny' # ------------------------------------------------------------------------- -def find_arg(argPosIndex=None, argTag=None, removeKwarg=None, - inArgs=None, inKwargs=None, defaultValue=None): +def find_arg(arg_pos_index=None, arg_tag=None, remove_kwarg=None, + in_args=None, in_kwargs=None, default_value=None): """ # finds and returns an arg... # if a positional index is given argPosIndex=0, it checks args first @@ -41,31 +41,33 @@ def find_arg(argPosIndex=None, argTag=None, removeKwarg=None, # # foundArg, args, kwargs = find_arg(0, 'name',) """ - if argPosIndex != None: - if not isinstance(argPosIndex, int): + + found_arg = None + + if arg_pos_index != None: + if not isinstance(arg_pos_index, int): raise TypeError('argPosIndex: accepts a index integer!\r' - 'got: {0}'.format(argPosIndex)) + 'got: {0}'.format(arg_pos_index)) # positional args ... check the position - if len(inArgs) > 0: + if len(in_args) > 0: try: - foundArg = inArgs[argPosIndex] + found_arg = in_args[arg_pos_index] except: pass # check kwargs ... a set kwarg will ALWAYS take precident over # positional arg!!! - try: - foundArg - except: - foundArg = inKwargs.get(argTag, defaultValue) # defaults to None + if in_kwargs: + found_arg = in_kwargs.get(arg_tag, default_value) # defaults to None - if removeKwarg: - if argTag in inKwargs: - del inKwargs[argTag] + if remove_kwarg: + if in_kwargs: + if arg_tag in in_kwargs: + del in_kwargs[arg_tag] # if we didn't find the arg/kwarg, the defualt return will be None - return foundArg, inKwargs + return found_arg, in_kwargs # ------------------------------------------------------------------------- @@ -86,14 +88,14 @@ if __name__ == "__main__": class TestNode(Foo): def __init__(self, *args, **kwargs): super().__init__() - self._name, kwargs = find_arg(argTag='foo', removeKwarg=True, - inArgs=args, inKwargs=kwargs) - self._name, kwargs = find_arg(argPosIndex=0, argTag='name', - removeKwarg=True, - inArgs=args, inKwargs=kwargs) # <-- first positional OR kwarg - self._parent, kwargs = find_arg(argPosIndex=1, argTag='parent', - removeKwarg=True, - inArgs=args, inKwargs=kwargs) # <-- second positional OR kwarg + self._name, kwargs = find_arg(arg_tag='foo', remove_kwarg=True, + in_args=args, in_kwargs=kwargs) + self._name, kwargs = find_arg(arg_pos_index=0, arg_tag='name', + remove_kwarg=True, + in_args=args, in_kwargs=kwargs) # <-- first positional OR kwarg + self._parent, kwargs = find_arg(arg_pos_index=1, arg_tag='parent', + remove_kwarg=True, + in_args=args, in_kwargs=kwargs) # <-- second positional OR kwarg self._kwargsDict = {} @@ -117,7 +119,7 @@ if __name__ == "__main__": testNode2 = TestNode(name='fooey', parent=testNode) - testNode3 = TestNode('kablooey', testNode2, goober='dufus') + testNode3 = TestNode('kablooey', testNode2, gomer='pile') print ('testNode2, name: {0}, parent: {1}'.format(testNode2._name, testNode2._parent)) print (testNode3) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/master.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/master.py deleted file mode 100644 index d85ea48854..0000000000 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/master.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -its licensors. - -For complete copyright and license terms please see the LICENSE at the root of this -distribution (the "License"). All use of this software is governed by the License, -or, if provided, by the license below or the license accompanying this file. Do not -remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -""" -# ------------------------------------------------------------------------- - -# ------------------------------------------------------------------------- -# ------------------------------------------------------------------------- -# master.py -# Allows for project based setup to be used with noodly -# version: 0.1 -# author: Gallowj -# ------------------------------------------------------------------------- -# ------------------------------------------------------------------------- -import os - -from unipath import Path - -_G_DEFAULT_PROJECT_DIR = os.getcwd() -_G_MASTER_ROOT_NODE = None - - -@property -def _G_DEFAULT_PROJECT_DIR(value): - _G_DEFAULT_PROJECT_DIR = value - return _G_DEFAULT_PROJECT_DIR - - -def set_PROJECT_DIR(value): - """Sets and returns _G_DEFAULT_PROJECT_DIR""" - global _G_DEFAULT_PROJECT_DIR - _G_DEFAULT_PROJECT_DIR = Path(value).expand() - return Path(_G_DEFAULT_PROJECT_DIR) - - -@property -def _G_MASTER_ROOT_NODE(value): - _G_MASTER_ROOT_NODE = value - return _G_MASTER_ROOT_NODE - - -def set_MASTER_ROOT_NODE(value): - """Sets and returns _G_MASTER_ROOT_NODE""" - global _G_MASTER_ROOT_NODE - if not isinstance(inNode, ProjectRootNode): - raise TypeError('self._projectRootNode is: {0}\r' - 'A _projectRootNode, needs to be properly set\r' - 'So that we can acces:\r' - '\tself._projectRootNode._sourceRoot\r' - '\tself._projectRootNode._overrideRoot\r' - 'Use self.assignProjectRootNode()\r' - ''.format(type(inNode))) - - _G_MASTER_ROOT_NODE = inNode - return _G_MASTER_ROOT_NODE - - -########################################################################### -# tests(), code block for testing module -# ------------------------------------------------------------------------- -def tests(): - set_PROJECT_DIR(os.getcwd()) - print(_G_DEFAULT_PROJECT_DIR) - print(_G_DEFAULT_PROJECT_DIR.parent) - print(_G_DEFAULT_PROJECT_DIR.components()) - - # NOT implemented yet - # set_PROJECT_DIR - - return - - -########################################################################### -# --call block------------------------------------------------------------- -if __name__ == "__main__": - print ("# ----------------------------------------------------------------------- #") - print ('~ noodly.master ... Running script as __main__') - print ("# ----------------------------------------------------------------------- #\r") - - # run simple tests - tests() - - #_G_DEFAULT_PROJECT_DIR = Path(os.getcwd()) - print(_G_DEFAULT_PROJECT_DIR.components()) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/node.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/node.py index 4eca3b315d..950b8fcbec 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/node.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/node.py @@ -16,7 +16,7 @@ from __future__ import division # ------------------------------------------------------------------------- # ------------------------------------------------------------------------- # node.py -# simple base Node Class, for tool creation. +# simple base Node Class, useful in tool creation. # version: 0.1 # author: Gallowj # ------------------------------------------------------------------------- @@ -25,16 +25,8 @@ from __future__ import division Module docstring: A Simple Node Base Class Module, for creating basic nodes within a hierarchy. """ - __author__ = 'HogJonny' -_G_DEBUG = True # global state for debugging -_G_SETTINGS = None # global Settings storage -_G_LOG = None # global LOGger storage - -_G_MASTER_NODE = None # We intend to init a master node, unless provided - -# ------------------------------------------------------------------------- # built-ins import os import copy @@ -48,11 +40,32 @@ import cachetools from sched import scheduler # local imports -from LyPy.si_shared.noodly.helpers import display_cached_value -from LyPy.si_shared.noodly.find_arg import find_arg -from LyPy.si_shared.noodly.synth import synthesize +from azpy.shared.noodely.helpers import display_cached_value +from azpy.shared.noodely.find_arg import find_arg +from azpy.shared.noodely.synth import synthesize + +import azpy +from azpy.env_bool import env_bool +from azpy.constants import ENVAR_DCCSI_GDEBUG +from azpy.constants import ENVAR_DCCSI_DEV_MODE + +# global space +# To Do: update to dynaconf dynamic env and settings? +_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False) +_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False) + +_MODULENAME = 'azpy.shared.noodely.node' + +_log_level = int(20) +if _G_DEBUG: + _log_level = int(10) +_LOGGER = azpy.initialize_logger(_MODULENAME, + log_to_file=False, + default_log_level=_log_level) +_LOGGER.debug('Starting:: {}.'.format({_MODULENAME})) # ------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # quick test code (remove later) from hashids import Hashids @@ -79,8 +92,6 @@ if os.path.supports_unicode_filenames: ########################################################################### # HELPER method functions # ------------------------------------------------------------------------- - - def return_node_from_hashid(hashid): if not isinstance(hashid, str): raise TypeError("{0},{1}: Accepts hashids as str types!\r" @@ -95,6 +106,7 @@ def return_node_from_hashid(hashid): # ------------------------------------------------------------------------- +# ------------------------------------------------------------------------- class Node(object): """Class constructor: makes a node.""" @@ -131,9 +143,9 @@ class Node(object): # -- secret keyword ----------------------------------------------- self._temp_node = False - temp_node, kwargs = find_arg(argPosIndex=None, argTag='temp_node', - removeKwarg=True, inArgs=args, - inKwargs=kwargs) # <-- kwarg only + temp_node, kwargs = find_arg(arg_pos_index=None, arg_tag='temp_node', + remove_kwarg=True, in_args=args, + in_kwargs=kwargs) # <-- kwarg only self._temp_node = temp_node if self._temp_node: self._kwargs_dict['temp_node'] = self._temp_node @@ -141,9 +153,9 @@ class Node(object): # -- store message header ----------------------------------------- # setup the .message_header <-- kwarg only - message_header, kwargs = find_arg(argPosIndex=None, argTag='message_header', - removeKwarg=True, inArgs=args, inKwargs=kwargs, - defaultValue=('{0}(), Message' + message_header, kwargs = find_arg(arg_pos_index=None, arg_tag='message_header', + remove_kwarg=True, in_args=args, in_kwargs=kwargs, + default_value=('{0}(), Message' .format(self._node_type))) self._message_header = message_header # ----------------------------------------------------------------- @@ -165,7 +177,7 @@ class Node(object): # -- store the node name ------------------------------------------ self._node_name = node_name if (self._node_class_index == 0 and self._node_name == None): - self._node_name = 'MASTER' + self._node_name = 'PRIME' elif (self._node_class_index > 0 and self._node_name == None): # set a default node_name if none, based on the unihashid if not self._name_is_uni_hashid: @@ -325,7 +337,7 @@ class Node(object): @property def cls_node_dict(self): return Node._cls_node_dict - # ---------------------------------------------------------------------- + # --------------------------------------------------------------------- # --method-set--------------------------------------------------------- def cls_node_count_up(self): @@ -584,10 +596,10 @@ def tests(): print(default_node.hierarchy()) # retreive a node from it's known hashid - master_node = return_node_from_hashid('kxYLm0XQeXJ7jWaP') - print(master_node.uni_hashid) # verify hasid + prime_node = return_node_from_hashid('kxYLm0XQeXJ7jWaP') + print(prime_node.uni_hashid) # verify hasid # should return the same node as default_node - print(master_node.node_name) # should be 'MASTER' + print(prime_node.node_name) # should be 'PRIME' return # ------------------------------------------------------------------------- diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/pathnode.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/pathnode.py index f969e16fbe..5dee58b1c5 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/pathnode.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/pathnode.py @@ -27,12 +27,6 @@ A simple path objecy based Node Class, for creating path hierarchies. """ __author__ = 'HogJonny' -_G_DEBUG = True # global state for debugging -_G_SETTINGS = None # global Settings storage -_G_LOG = None # global LOGger storage - -_G_MASTER_NODE = None # We intend to init a master node - # ------------------------------------------------------------------------- # built-ins import os @@ -44,10 +38,31 @@ import logging from unipath import Path, AbstractPath # local ly imports -from LyPy.si_shared.noodly.helpers import istext -from LyPy.si_shared.noodly.find_arg import find_arg -from LyPy.si_shared.noodly.synth import synthesize -from LyPy.si_shared.noodly.node import Node +from azpy.shared.noodely.helpers import istext +from azpy.shared.noodely.find_arg import find_arg +from azpy.shared.noodely.synth import synthesize +from azpy.shared.noodely.node import Node + +import azpy +from azpy.env_bool import env_bool +from azpy.constants import ENVAR_DCCSI_GDEBUG +from azpy.constants import ENVAR_DCCSI_DEV_MODE + +# ------------------------------------------------------------------------- +# global space +# To Do: update to dynaconf dynamic env and settings? +_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False) +_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False) + +_MODULENAME = 'azpy.shared.noodely.pathnode' + +_log_level = int(20) +if _G_DEBUG: + _log_level = int(10) +_LOGGER = azpy.initialize_logger(_MODULENAME, + log_to_file=False, + default_log_level=_log_level) +_LOGGER.debug('Starting:: {}.'.format({_MODULENAME})) # ------------------------------------------------------------------------- @@ -63,20 +78,12 @@ if os.path.supports_unicode_filenames: # ------------------------------------------------------------------------- -# set up logger -_G_LOGGER = logging.getLogger(__name__) -# ------------------------------------------------------------------------- - - class PathNode(Node): """doc string""" # share the debug state _DEBUG = _G_DEBUG - # logger - _LOGGER = _G_LOGGER - # class header _message_header = 'noodly, PathNode(): Message' @@ -117,22 +124,22 @@ class PathNode(Node): # -- secret keyword ----------------------------------------------- self._temp_node = False - temp_node, kwargs = find_arg(argPosIndex=None, argTag='temp_node', - removeKwarg=True, inArgs=args, - inKwargs=kwargs) # <-- kwarg only + temp_node, kwargs = find_arg(arg_pos_index=None, arg_tag='temp_node', + remove_kwarg=True, in_args=args, + in_kwargs=kwargs) # <-- kwarg only self._temp_node = temp_node if self._temp_node: self.k_wargs_dict['temp_node'] = self._temp_node # -- Node class args/kwargs --------------------------------------- - node_name, kwargs = find_arg(argPosIndex=2, argTag='node_name', - removeKwarg=True, inArgs=args, - inKwargs=kwargs) # <-- third arg, kwarg + node_name, kwargs = find_arg(arg_pos_index=2, arg_tag='node_name', + remove_kwarg=True, in_args=args, + in_kwargs=kwargs) # <-- third arg, kwarg - parent_node, kwargs = find_arg(argPosIndex=3, argTag='parent_node', - removeKwarg=True, inArgs=args, - inKwargs=kwargs) # <-- fourth arg, kwarg + parent_node, kwargs = find_arg(arg_pos_index=3, arg_tag='parent_node', + remove_kwarg=True, in_args=args, + in_kwargs=kwargs) # <-- fourth arg, kwarg self._root_path = root_path @@ -344,12 +351,12 @@ class PathNode(Node): # ------------------------------------------------------------------------- def tests(): from node import Node - default_node = Node() # result: Node(node_name='MASTER') + default_node = Node() # result: Node(node_name='PRIME') print(default_node) first_child = PathNode(path=None, node_name='first_child', parent_node=default_node) print(first_child) - # result: PathNode(temp_node=True, parent_node=Node(node_name='MASTER')).siblingNodeFromHashid('WNPZoKBVpXV16QLz') + # result: PathNode(temp_node=True, parent_node=Node(node_name='PRIME')).siblingNodeFromHashid('WNPZoKBVpXV16QLz') # first_child.nodeType # first_child.parent_node # first_child.node_name diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/synth_arg_kwarg.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/synth_arg_kwarg.py index 3618ad67de..0f71439dae 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/synth_arg_kwarg.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/synth_arg_kwarg.py @@ -22,9 +22,9 @@ from synth import synthesize # ------------------------------------------------------------------------- -def setSynthArgKwarg(inst, argPosIndex=None, argTag=None, defaultValue=None, - inArgs=None, inKwargs=None, removeKwarg=True, - setAnyway=True): +def set_synth_arg_kwarg(inst, arg_pos_index=None, arg_tag=None, default_value=None, + in_args=None, in_kwargs=None, remove_kwarg=True, + set_anyway=True): """ Uses find_arg and sets a property on a object. @@ -34,44 +34,44 @@ def setSynthArgKwarg(inst, argPosIndex=None, argTag=None, defaultValue=None, If the arg/property doesn't exist we synthesize it """ - foundArg = None - argValueDict = {} + found_arg = None + arg_value_dict = {} # find the argument, or set to default value - foundArg, inKwargs = find_arg(argPosIndex, argTag, removeKwarg, - inArgs, inKwargs, - defaultValue) + found_arg, in_kwargs = find_arg(arg_pos_index, arg_tag, remove_kwarg, + in_args, in_kwargs, + default_value) - if foundArg: - argTag = foundArg + if found_arg: + arg_tag = found_arg # single arg first # make sure the object doesn't arealdy have this property try: - hasattr(inst, argTag) # check if property exists - if setAnyway: + hasattr(inst, arg_tag) # check if property exists + if set_anyway: try: - setattr(inst, argTag, defaultValue) # try to set + setattr(inst, arg_tag, default_value) # try to set except Exception as e: raise e except: pass # make it a synthetic property - if argTag: + if arg_tag: try: - argValue = synthesize(inst, argTag, defaultValue) - argValueDict[argTag] = argValue + arg_value = synthesize(inst, arg_tag, default_value) + arg_value_dict[arg_tag] = arg_value except Exception as e: raise e # multiple and/or remaining kwards next - if inKwargs: - if len(inKwargs) > 0: - for k, v in inKwargs.items(): + if in_kwargs: + if len(in_kwargs) > 0: + for k, v in in_kwargs.items(): try: hasattr(inst, k) # check if property exists - if setAnyway: + if set_anyway: try: setattr(inst, k, v) # try to set except Exception as e: @@ -81,12 +81,12 @@ def setSynthArgKwarg(inst, argPosIndex=None, argTag=None, defaultValue=None, if k: try: - argValue = synthesize(inst, k, v) - argValueDict[k] = argValue + arg_value = synthesize(inst, k, v) + arg_value_dict[k] = arg_value except Exception as e: raise e - return argValueDict + return arg_value_dict # -------------------------------------------------------------------------- @@ -98,28 +98,28 @@ if __name__ == '__main__': from test_foo import Foo # define a arg/property tag we know doesn't exist - synthArgTag = 'syntheticArg' + synth_arg_tag = 'synthetic_arg' # create a test object print('~ creating the test foo object...') - myFoo = Foo() + my_foo = Foo() print('~ Starting - single synthetic arg test...') # find and set existing, or create and set - argValueDict = setSynthArgKwarg(myFoo, - argTag=synthArgTag, - defaultValue='kablooey') + arg_value_dict = set_synth_arg_kwarg(my_foo, + arg_tag=synth_arg_tag, + default_value='kablooey') # what was returned print('~ single value returned...') - for k, v in argValueDict.items(): + for k, v in arg_value_dict.items(): print("Arg '{0}':'{1}'".format(k, v)) # attempt to access the new synthetic property directly print('~ direct property access test...') try: - myFoo.syntheticArg - print('myFoo.{0}: {1}'.format(synthArgTag, myFoo.syntheticArg)) + my_foo.synthetic_arg + print('myFoo.{0}: {1}'.format(synth_arg_tag, my_foo.synthetic_arg)) except Exception as e: raise e @@ -128,31 +128,31 @@ if __name__ == '__main__': newKwargs = {'fooey': 'chop suey', 'success': True} # find and set existing, or create and set - argValueDict = setSynthArgKwarg(myFoo, - inKwargs=newKwargs, - defaultValue='kablooey') + arg_value_dict = set_synth_arg_kwarg(my_foo, + in_kwargs=newKwargs, + default_value='kablooey') # what was returned print('~ multiple values returned...') - for k, v in argValueDict.items(): + for k, v in arg_value_dict.items(): print("Arg '{0}':'{1}'".format(k, v)) print('~ multiple direct property access test...') try: - myFoo.fooey - print('myFoo.{0}: {1}'.format('fooey', myFoo.fooey)) + my_foo.fooey + print('myFoo.{0}: {1}'.format('fooey', my_foo.fooey)) except Exception as e: raise e try: - myFoo.success - print('myFoo.{0}: {1}'.format('success', myFoo.success)) + my_foo.success + print('myFoo.{0}: {1}'.format('success', my_foo.success)) except Exception as e: raise e print('~ Starting - known failure test...') try: - myFoo.knownBad + my_foo.knownBad except Exception as e: print(e) print('Test failed as expected!!!') diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/test_foo.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/test_foo.py index ca652503d2..d1c535fe14 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/test_foo.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/noodely/test_foo.py @@ -25,13 +25,13 @@ class Foo(object): This is a Class, it creates a Foo object... which does nothing really """ - __propertyTag = 'fooProperty' + __property_tag = 'fooProperty' # ------------------------------------------------------------------ def __init__(self, name='Foo', value='defaultValue', *args, **kwargs): '''Class __init__''' synthesize(self, 'name', name) - synthesize(self, Foo.__propertyTag, value) + synthesize(self, Foo.__property_tag, value) synthesize(self, 'test', 'testValue') diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/custom_treemodel.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/custom_treemodel.py index cded8fec09..1ca3221508 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/custom_treemodel.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/custom_treemodel.py @@ -20,7 +20,10 @@ import os # from io import StringIO # for handling unicode strings # azpy -from azpy import initialize_logger +import azpy +from azpy.env_bool import env_bool +from azpy.constants import ENVAR_DCCSI_GDEBUG +from azpy.constants import ENVAR_DCCSI_DEV_MODE # 3rd Party from unipath import Path @@ -28,22 +31,22 @@ import PySide2.QtCore as QtCore import PySide2.QtWidgets as QtWidgets import PySide2.QtGui as QtGui # ------------------------------------------------------------------------- -# global space debug flag -_G_DEBUG = os.getenv('DCCSI_GDEBUG', False) - -# global space debug flag -_DCCSI_DEV_MODE = os.getenv('DCCSI_DEV_MODE', False) +# global space +# To Do: update to dynaconf dynamic env and settings? +_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False) +_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False) _MODULE_PATH = Path(__file__) -_ORG_TAG = 'Amazon_Lumberyard' -_APP_TAG = 'DCCsi' -_TOOL_TAG = 'azpy.shared.ui.custom_treemodel' -_TYPE_TAG = 'test' +_MODULENAME = 'azpy.shared.ui.custom_treemodel' -_MODULENAME = __name__ -if _MODULENAME is '__main__': - _MODULENAME = _TOOL_TAG +_log_level = int(20) +if _G_DEBUG: + _log_level = int(10) +_LOGGER = azpy.initialize_logger(_MODULENAME, + log_to_file=False, + default_log_level=_log_level) +_LOGGER.debug('Starting:: {}.'.format({_MODULENAME})) _UI_FILE = Path(_MODULE_PATH.parent, 'resources', 'example.ui') # ------------------------------------------------------------------------- @@ -75,15 +78,15 @@ class CustomFileTreeModel(QtCore.QAbstractItemModel): # TODO: need to make sure we are getting path objects # build the root node - self._root_node = self.buildRootNode('root', None, self._rootFilePath) + self._root_node = self.build_rootnode('root', None, self._root_filepath) - # master selection - self._masterSelection = masterSelection + # prime selection + self._prime_selection = prime_selection - # build the master selection node - self._masterNode = self.buildMasterNode('master', None, self._masterSelection, self._rootNode.path()) + # build the prime selection node + self._primenode = self.build_primenode('prime', None, self._prime_selection, self._rootnode.path()) # want to store off a couple lists in the model, for retreival later - self._nodeList = None - self._depNodesList = None + self._nodelist = None + self._dep_nodelist = None diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/help_menu.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/help_menu.py index 39f151cd2e..b261d4b0e1 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/help_menu.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/shared/ui/help_menu.py @@ -68,7 +68,7 @@ class HelpMenu(): INPUTS: main_window = the class instance of the QMainWindow tool_label = the menu label for the tool's help item - tool_help_page = the http:// path to the specific bpTool help page + tool_help_page = the http:// path to the tool specific help page Here's an example # self.help_menu = azpy.shared.ui.help_menu.setup(self, 'Help...', 'https://some.site.com/azpy') diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/synthetic_env.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/synthetic_env.py index 6186026852..86e4b68488 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/synthetic_env.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/synthetic_env.py @@ -667,7 +667,7 @@ if __name__ == '__main__': try: import azpy.test.entry_test print('SUCCESS: import azpy.test.entry_test') - azpy.test.entry_test.main(verbose=True, connectDebugger=True) + azpy.test.entry_test.main(verbose=True, connect_debugger=True) except ImportError as e: print('ERROR: {0}'.format(e)) raise e diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/test/entry_test.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/test/entry_test.py index 67dc3b60ad..46a852736e 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/test/entry_test.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/test/entry_test.py @@ -25,6 +25,7 @@ from pathlib import Path # ------------------------------------------------------------------------- _BOOT_CHECK = False # set true to test breakpoint in this module directly + import azpy from azpy.env_bool import env_bool from azpy.constants import ENVAR_DCCSI_GDEBUG @@ -48,13 +49,13 @@ _LOGGER.debug('Starting:: {}.'.format({_MODULENAME})) # ------------------------------------------------------------------------- -def main(verbose=_G_DEBUG, connectDebugger=True): +def main(verbose=_G_DEBUG, connect_debugger=True): _LOGGER.info('{}'.format('-' * 74)) _LOGGER.info('entry_test.main()') _LOGGER.info('Root test import successful:') _LOGGER.info('~ {}'.format(__file__)) - if connectDebugger: + if connect_debugger: status = connect_wing() _LOGGER.info(status) # ------------------------------------------------------------------------- @@ -137,4 +138,4 @@ def connect_wing(): # ------------------------------------------------------------------------- if __name__ == '__main__': _G_DEBUG = True - main(verbose=_G_DEBUG, connectDebugger=_G_DEBUG) + main(verbose=_G_DEBUG, connect_debugger=_G_DEBUG) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/config.py b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/config.py index 0068b4c766..c62571b2f5 100755 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/config.py +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/config.py @@ -26,7 +26,6 @@ import re # our framework for dcc tools need to run in apps like Maya that may still be # on py27 so we need to import and use after some boostrapping - # -------------------------------------------------------------------+------ #os.environ['PYTHONINSPECT'] = 'True' _MODULE_PATH = os.path.abspath(__file__) @@ -78,6 +77,10 @@ _DCCSI_PYTHON_LIB_PATH = azpy.config_utils.bootstrap_dccsi_py_libs(_DCCSIG_PATH) # Now we should be able to just carry on with pth lib and dynaconf from dynaconf import Dynaconf +try: + import pathlib +except: + import pathlib2 as pathlib from pathlib import Path _DCCSIG_PATH = Path(_DCCSIG_PATH).resolve() @@ -218,7 +221,7 @@ os.environ["DYNACONF_DCCSI_DEV_MODE"] = str(_DCCSI_DEV_MODE) # search up to get \dev _LY_DEV = azpy.config_utils.get_stub_check_path(in_path=_DCCSIG_PATH, - check_stub='engineroot.txt') + check_stub='engine.json') os.environ["DYNACONF_LY_DEV"] = str(_LY_DEV.resolve()) _LY_PROJECT = azpy.config_utils.get_current_project(_LY_DEV) os.environ["DYNACONF_LY_PROJECT"] = _LY_PROJECT diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/requirements.txt b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/requirements.txt index 05d47ea70c..2f7626addb 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/requirements.txt +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/requirements.txt @@ -4,34 +4,39 @@ # # pip-compile --generate-hashes requirements.txt # -typing==3.7.4.3 \ - --hash=sha256:1187fb9c82fd670d10aa07bbb6cfcfe4bdda42d6fab8d5134f04e8c4d0b71cc9 \ - --hash=sha256:283d868f5071ab9ad873e5e52268d611e851c870a2ba354193026f2dfb29d8b5 - # via - # -r requirements.txt - # dynaconf +cachetools==4.2.1 \ + --hash=sha256:1d9d5f567be80f7c07d765e21b814326d78c61eb0c3a637dffc0e5d1796cb2e2 \ + --hash=sha256:f469e29e7aa4cff64d8de4aad95ce76de8ea1125a16c68e0d93f65c3c3dc92e9 + # via -r requirements.txt +certifi==2020.12.5 \ + --hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c \ + --hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830 + # via -r requirements.txt click==7.1.2 \ --hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a \ --hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc # via # -r requirements.txt - # pip-tools dynaconf==3.1.4 \ --hash=sha256:b2f472d83052f809c5925565b8a2ba76a103d5dc1dbb9748b693ed67212781b9 \ --hash=sha256:e6f383b84150b70fc439c8b2757581a38a58d07962aa14517292dcce1a77e160 # via -r requirements.txt +hashids==1.3.1 \ + --hash=sha256:6c3dc775e65efc2ce2c157a65acb776d634cb814598f406469abef00ae3f635c \ + --hash=sha256:8bddd1acba501bfc9306e7e5a99a1667f4f2cacdc20cbd70bcc5ddfa5147c94c + # via -r requirements.txt pathlib==1.0.1 \ --hash=sha256:6940718dfc3eff4258203ad5021090933e5c04707d5ca8cc9e73c94a7894ea9f # via -r requirements.txt -python-box==3.4.6 \ - --hash=sha256:694a7555e3ff9fbbce734bbaef3aad92b8e4ed0659d3ed04d56b6a0a0eff26a9 \ - --hash=sha256:a71d3dc9dbaa34c8597d3517c89a8041bd62fa875f23c0f3dad55e1958e3ce10 +python-box==5.3.0 \ + --hash=sha256:4ed4ef5d34de505a65c01e3f1911de8cdb29484fcae0c035141dce535c6c194a \ + --hash=sha256:f2a531f9f5bbef078c175fad6abb31e9b59d40d121ea79993197e6bb221c6be6 # via -r requirements.txt unipath==1.1 \ --hash=sha256:09839adcc72e8a24d4f76d63656f30b5a1f721fc40c9bcd79d8c67bdd8b47dae \ --hash=sha256:e6257e508d8abbfb6ddd8ec357e33589f1f48b1599127f23b017124d90b0fff7 # via -r requirements.txt - -# WARNING: The following packages were not pinned, but pip requires them to be -# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag. -# pip +wincertstore==0.2 \ + --hash=sha256:22d5eebb52df88a8d4014d5cf6d1b6c3a5d469e6c3b2e2854f3a003e48872356 \ + --hash=sha256:780bd1557c9185c15d9f4221ea7f905cb20b93f7151ca8ccaed9714dce4b327a + # via -r requirements.txt \ No newline at end of file diff --git a/Gems/Blast/Code/Source/Family/ActorRenderManager.h b/Gems/Blast/Code/Source/Family/ActorRenderManager.h index 9512fba92d..3908ed5ecd 100644 --- a/Gems/Blast/Code/Source/Family/ActorRenderManager.h +++ b/Gems/Blast/Code/Source/Family/ActorRenderManager.h @@ -15,11 +15,6 @@ #include #include -namespace LmbrCentral -{ - class MeshComponentRequests; -} - namespace Blast { class BlastMeshData; diff --git a/Gems/CMakeLists.txt b/Gems/CMakeLists.txt index b6bda8c16e..3b630cfd2f 100644 --- a/Gems/CMakeLists.txt +++ b/Gems/CMakeLists.txt @@ -37,7 +37,6 @@ add_subdirectory(MessagePopup) add_subdirectory(PhysX) add_subdirectory(PhysXDebug) add_subdirectory(ScriptEvents) -add_subdirectory(Visibility) add_subdirectory(AssetValidation) add_subdirectory(VirtualGamepad) add_subdirectory(SaveData) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp index d57105a589..1327045806 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorBuilder.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index cfacdf9f09..ec1b00bda4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -360,7 +360,7 @@ namespace EMotionFX ApplyMorphSetup(); UpdateSkinningMatrices(); UpdateAttachments(); - } + } // update the bounds when needed if (GetBoundsUpdateEnabled() && mBoundsUpdateType != BOUNDS_MESH_BASED) @@ -418,7 +418,8 @@ namespace EMotionFX } // Update the bounds when we are set to use mesh based bounds. - if (GetBoundsUpdateEnabled() == BOUNDS_MESH_BASED) + if (GetBoundsUpdateEnabled() && + GetBoundsUpdateType() == BOUNDS_MESH_BASED) { mBoundsUpdatePassedTime += timePassedInSeconds; if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) @@ -449,7 +450,8 @@ namespace EMotionFX } // Update the bounds when we are set to use mesh based bounds. - if (GetBoundsUpdateEnabled() == BOUNDS_MESH_BASED) + if (GetBoundsUpdateEnabled() && + GetBoundsUpdateType() == BOUNDS_MESH_BASED) { mBoundsUpdatePassedTime += timePassedInSeconds; if (mBoundsUpdatePassedTime >= mBoundsUpdateFrequency) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp index 73cbad195a..27cf34961f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.cpp @@ -10,7 +10,8 @@ * */ -// include the required headers +#include +#include #include "EMotionFXConfig.h" #include "DualQuatSkinDeformer.h" #include "Mesh.h" @@ -23,138 +24,143 @@ #include #include - namespace EMotionFX { AZ_CLASS_ALLOCATOR_IMPL(DualQuatSkinDeformer, DeformerAllocator, 0) - // constructor DualQuatSkinDeformer::DualQuatSkinDeformer(Mesh* mesh) : MeshDeformer(mesh) { - mBones.SetMemoryCategory(EMFX_MEMCATEGORY_GEOMETRY_DEFORMERS); } - - // destructor DualQuatSkinDeformer::~DualQuatSkinDeformer() { - mBones.Clear(); } + AZ::Outcome DualQuatSkinDeformer::FindLocalBoneIndex(uint32 nodeIndex) const + { + const size_t numBones = m_bones.size(); + for (size_t i = 0; i < numBones; ++i) + { + if (m_bones[i].mNodeNr == nodeIndex) + { + return AZ::Success(i); + } + } + + return AZ::Failure(); + } - // creation DualQuatSkinDeformer* DualQuatSkinDeformer::Create(Mesh* mesh) { return aznew DualQuatSkinDeformer(mesh); } - - // get the type id uint32 DualQuatSkinDeformer::GetType() const { return TYPE_ID; } - - // get the subtype id uint32 DualQuatSkinDeformer::GetSubType() const { return SUBTYPE_ID; } - - // clone this class MeshDeformer* DualQuatSkinDeformer::Clone(Mesh* mesh) { // create the new cloned deformer DualQuatSkinDeformer* result = aznew DualQuatSkinDeformer(mesh); // copy the bone info (for precalc/optimization reasons) - result->mBones = mBones; + result->m_bones = m_bones; // return the result return result; } - // the main method where all calculations are done - void DualQuatSkinDeformer::Update(ActorInstance* actorInstance, Node* node, float timeDelta) + void DualQuatSkinDeformer::Update(ActorInstance* actorInstance, [[maybe_unused]] Node* node, [[maybe_unused]] float timeDelta) { - AZ_UNUSED(node); - MCORE_UNUSED(timeDelta); - const Actor* actor = actorInstance->GetActor(); const Pose* pose = actorInstance->GetTransformData()->GetCurrentPose(); + const uint32 numVertices = mMesh->GetNumVertices(); - AZ::Vector3 newPos, newNormal, newTangent, newBitangent; - AZ::Vector3 vtxPos, normal, tangent, bitangent; - AZ::Vector3* positions = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_POSITIONS)); - AZ::Vector3* normals = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_NORMALS)); - AZ::Vector4* tangents = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_TANGENTS)); - AZ::Vector3* bitangents = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_BITANGENTS)); - AZ::u32* orgVerts = static_cast(mMesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS)); - - // precalc the skinning matrices - const uint32 numBones = mBones.GetLength(); - for (uint32 i = 0; i < numBones; i++) + // pre-calculate the skinning matrices + for (BoneInfo& boneInfo : m_bones) { - const uint32 nodeIndex = mBones[i].mNodeNr; - Transform skinTransform = actor->GetInverseBindPoseTransform(nodeIndex); - skinTransform.Multiply(pose->GetModelSpaceTransform(nodeIndex)); - mBones[i].mDualQuat.FromRotationTranslation(skinTransform.mRotation, skinTransform.mPosition); + const uint32 nodeIndex = boneInfo.mNodeNr; + const Transform skinTransform = actor->GetInverseBindPoseTransform(nodeIndex) * pose->GetModelSpaceTransform(nodeIndex); + boneInfo.mDualQuat.FromRotationTranslation(skinTransform.mRotation, skinTransform.mPosition); } - // find the skinning layer - SkinningInfoVertexAttributeLayer* layer = (SkinningInfoVertexAttributeLayer*)mMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); - MCORE_ASSERT(layer); + AZ::JobCompletion jobCompletion; + + // Split up the skinned vertices into batches. + const AZ::u32 numBatches = aznumeric_caster(ceilf(aznumeric_cast(numVertices) / aznumeric_cast(s_numVerticesPerBatch))); + for (AZ::u32 batchIndex = 0; batchIndex < numBatches; ++batchIndex) + { + const AZ::u32 startVertex = batchIndex * s_numVerticesPerBatch; + const AZ::u32 endVertex = AZStd::min(startVertex + s_numVerticesPerBatch, numVertices); + + // Create a job for every batch and skin them simultaneously. + AZ::JobContext* jobContext = nullptr; + AZ::Job* job = AZ::CreateJobFunction([this, startVertex, endVertex]() + { + SkinRange(mMesh, startVertex, endVertex, m_bones); + }, /*isAutoDelete=*/true, jobContext); + + job->SetDependent(&jobCompletion); + job->Start(); + } + + jobCompletion.StartAndWaitForCompletion(); + } + + void DualQuatSkinDeformer::SkinRange(Mesh* mesh, AZ::u32 startVertex, AZ::u32 endVertex, const AZStd::vector& boneInfos) + { + SkinningInfoVertexAttributeLayer* layer = (SkinningInfoVertexAttributeLayer*)mesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); + AZ_Assert(layer, "Cannot find skinning layer."); + + AZ::Vector3 newTangent; + AZ::Vector3 vtxPos, normal, tangent, bitangent; + AZ::u32 orgVertex; + float weight; + + AZ::Vector3* positions = static_cast(mesh->FindVertexData(Mesh::ATTRIB_POSITIONS)); + AZ::Vector3* normals = static_cast(mesh->FindVertexData(Mesh::ATTRIB_NORMALS)); + AZ::Vector4* tangents = static_cast(mesh->FindVertexData(Mesh::ATTRIB_TANGENTS)); + AZ::Vector3* bitangents = static_cast(mesh->FindVertexData(Mesh::ATTRIB_BITANGENTS)); + AZ::u32* orgVerts = static_cast(mesh->FindVertexData(Mesh::ATTRIB_ORGVTXNUMBERS)); // if there are tangents and bitangents to skin if (tangents && bitangents) { - const uint32 numVertices = mMesh->GetNumVertices(); - uint32 v = 0; - uint32 orgVertex; - - SkinInfluence* influence; - BoneInfo* boneInfo; - float weight; - for (v = 0; v < numVertices; ++v) + for (AZ::u32 v = startVertex; v < endVertex; ++v) { - // get the original vertex number - orgVertex = *(orgVerts++); - - // reset the skinned position - newPos = AZ::Vector3::CreateZero(); - newNormal = AZ::Vector3::CreateZero(); - newTangent = AZ::Vector3::CreateZero(); - newBitangent = AZ::Vector3::CreateZero(); - - const float tangentW = tangents->GetW(); - vtxPos.Set (positions->GetX(), positions->GetY(), positions->GetZ()); - normal.Set (normals->GetX(), normals->GetY(), normals->GetZ()); - tangent.Set (tangents->GetX(), tangents->GetY(), tangents->GetZ()); - bitangent.Set(bitangents->GetX(), bitangents->GetY(), bitangents->GetZ()); + orgVertex = orgVerts[v]; + vtxPos = positions[v]; + normal = normals[v]; + const float tangentW = tangents[v].GetW(); + tangent.Set(tangents[v].GetX(), tangents[v].GetY(), tangents[v].GetZ()); + bitangent = bitangents[v]; // process the skin influences for this vertex const size_t numInfluences = layer->GetNumInfluences(orgVertex); if (numInfluences > 0) { // get the pivot quat, used for the dot product check - const MCore::DualQuaternion& pivotQuat = mBones[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; + const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; // our skinning dual quaternion MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0)); for (size_t i = 0; i < numInfluences; ++i) { - // get the influence - influence = layer->GetInfluence(orgVertex, i); - boneInfo = &mBones[ influence->GetBoneNr() ]; - weight = influence->GetWeight(); + SkinInfluence* influence = layer->GetInfluence(orgVertex, i); + weight = influence->GetWeight(); // check if we need to invert the dual quat - MCore::DualQuaternion& influenceQuat = mBones[ influence->GetBoneNr() ].mDualQuat; + MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat; if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f) { influenceQuat *= -1.0f; @@ -168,74 +174,50 @@ namespace EMotionFX skinQuat.Normalize(); // perform skinning - newPos = skinQuat.TransformPoint(vtxPos); - newNormal = skinQuat.TransformVector(normal); - newTangent = skinQuat.TransformVector(tangent); - newBitangent = skinQuat.TransformVector(bitangent); + positions[v] = skinQuat.TransformPoint(vtxPos); + normals[v] = skinQuat.TransformVector(normal); + newTangent = skinQuat.TransformVector(tangent); + tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW); + bitangents[v] = skinQuat.TransformVector(bitangent); } else { - // perform the skinning - newPos = vtxPos; - newNormal = normal; - newTangent = tangent; - newBitangent = bitangent; + // no skinning influences, just copy the values + positions[v] = vtxPos; + normals[v] = normal; + newTangent = tangent; + tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW); + bitangents[v] = bitangent; } - - // output the skinned values - positions->Set (newPos.GetX(), newPos.GetY(), newPos.GetZ()); - positions++; - normals->Set (newNormal.GetX(), newNormal.GetY(), newNormal.GetZ()); - normals++; - tangents->Set (newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW); - tangents++; - bitangents->Set (newBitangent.GetX(), newBitangent.GetY(), newBitangent.GetZ()); - bitangents++; } } else if (tangents && !bitangents) // tangents but no bitangents { - const uint32 numVertices = mMesh->GetNumVertices(); - uint32 v = 0; - uint32 orgVertex; - - SkinInfluence* influence; - BoneInfo* boneInfo; - float weight; - for (v = 0; v < numVertices; ++v) + for (AZ::u32 v = startVertex; v < endVertex; ++v) { - // get the original vertex number - orgVertex = *(orgVerts++); - - // reset the skinned position - newPos = AZ::Vector3::CreateZero(); - newNormal = AZ::Vector3::CreateZero(); - newTangent = AZ::Vector3::CreateZero(); - - const float tangentW = tangents->GetW(); - vtxPos.Set (positions->GetX(), positions->GetY(), positions->GetZ()); - normal.Set (normals->GetX(), normals->GetY(), normals->GetZ()); - tangent.Set (tangents->GetX(), tangents->GetY(), tangents->GetZ()); + orgVertex = orgVerts[v]; + vtxPos = positions[v]; + normal = normals[v]; + const float tangentW = tangents[v].GetW(); + tangent.Set(tangents[v].GetX(), tangents[v].GetY(), tangents[v].GetZ()); // process the skin influences for this vertex const size_t numInfluences = layer->GetNumInfluences(orgVertex); if (numInfluences > 0) { // get the pivot quat, used for the dot product check - const MCore::DualQuaternion& pivotQuat = mBones[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; + const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; // our skinning dual quaternion MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0)); for (size_t i = 0; i < numInfluences; ++i) { - // get the influence - influence = layer->GetInfluence(orgVertex, i); - boneInfo = &mBones[ influence->GetBoneNr() ]; - weight = influence->GetWeight(); + SkinInfluence* influence = layer->GetInfluence(orgVertex, i); + weight = influence->GetWeight(); // check if we need to invert the dual quat - MCore::DualQuaternion& influenceQuat = mBones[ influence->GetBoneNr() ].mDualQuat; + MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat; if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f) { influenceQuat *= -1.0f; @@ -249,68 +231,46 @@ namespace EMotionFX skinQuat.Normalize(); // perform skinning - newPos = skinQuat.TransformPoint(vtxPos); - newNormal = skinQuat.TransformVector(normal); - newTangent = skinQuat.TransformVector(tangent); + positions[v] = skinQuat.TransformPoint(vtxPos); + normals[v] = skinQuat.TransformVector(normal); + newTangent = skinQuat.TransformVector(tangent); + tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW); } else { - // perform the skinning - newPos = vtxPos; - newNormal = normal; - newTangent = tangent; + // no skinning influences, just copy the values + positions[v] = vtxPos; + normals[v] = normal; + newTangent = tangent; + tangents[v].Set(newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW); } - - // output the skinned values - positions->Set (newPos.GetX(), newPos.GetY(), newPos.GetZ()); - positions++; - normals->Set (newNormal.GetX(), newNormal.GetY(), newNormal.GetZ()); - normals++; - tangents->Set (newTangent.GetX(), newTangent.GetY(), newTangent.GetZ(), tangentW); - tangents++; } } else // there are no tangents and bitangents to skin { - const uint32 numVertices = mMesh->GetNumVertices(); - uint32 v = 0; - uint32 orgVertex; - - SkinInfluence* influence; - BoneInfo* boneInfo; - float weight; - - for (v = 0; v < numVertices; ++v) + for (AZ::u32 v = startVertex; v < endVertex; ++v) { - // get the original vertex number - orgVertex = *(orgVerts++); - - // reset the skinned position - newPos = AZ::Vector3::CreateZero(); - newNormal = AZ::Vector3::CreateZero(); - - vtxPos.Set(positions->GetX(), positions->GetY(), positions->GetZ()); - normal.Set(normals->GetX(), normals->GetY(), normals->GetZ()); + orgVertex = orgVerts[v]; + vtxPos = positions[v]; + normal = normals[v]; // process the skin influences for this vertex const size_t numInfluences = layer->GetNumInfluences(orgVertex); if (numInfluences > 0) { // get the pivot quat, used for the dot product check - const MCore::DualQuaternion& pivotQuat = mBones[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; + const MCore::DualQuaternion& pivotQuat = boneInfos[ layer->GetInfluence(orgVertex, 0)->GetBoneNr() ].mDualQuat; // our skinning dual quaternion MCore::DualQuaternion skinQuat(AZ::Quaternion(0, 0, 0, 0), AZ::Quaternion(0, 0, 0, 0)); for (size_t i = 0; i < numInfluences; ++i) { - // get the influence - influence = layer->GetInfluence(orgVertex, i); - boneInfo = &mBones[ influence->GetBoneNr() ]; - weight = influence->GetWeight(); + SkinInfluence* influence = layer->GetInfluence(orgVertex, i); + weight = influence->GetWeight(); // check if we need to invert the dual quat - MCore::DualQuaternion& influenceQuat = mBones[ influence->GetBoneNr() ].mDualQuat; + MCore::DualQuaternion influenceQuat = boneInfos[ influence->GetBoneNr() ].mDualQuat; if (influenceQuat.mReal.Dot(pivotQuat.mReal) < 0.0f) { influenceQuat *= -1.0f; @@ -324,26 +284,19 @@ namespace EMotionFX skinQuat.Normalize(); // perform skinning - newPos = skinQuat.TransformPoint(vtxPos); - newNormal = skinQuat.TransformVector(normal); + positions[v] = skinQuat.TransformPoint(vtxPos); + normals[v] = skinQuat.TransformVector(normal); } else { - // perform the skinning - newPos = vtxPos; - newNormal = normal; + // no skinning influences, just copy the values + positions[v] = vtxPos; + normals[v] = normal; } - - // output the skinned values - positions->Set(newPos.GetX(), newPos.GetY(), newPos.GetZ()); - positions++; - normals->Set(newNormal.GetX(), newNormal.GetY(), newNormal.GetZ()); - normals++; } } } - // initialize the mesh deformer void DualQuatSkinDeformer::Reinitialize(Actor* actor, Node* node, uint32 lodLevel) { @@ -352,7 +305,7 @@ namespace EMotionFX MCORE_UNUSED(lodLevel); // clear the bone information array, but don't free the currently allocated/reserved memory - mBones.Clear(false); + m_bones.clear(); // if there is no mesh if (mMesh == nullptr) @@ -360,13 +313,9 @@ namespace EMotionFX return; } - // get the attribute number SkinningInfoVertexAttributeLayer* skinningLayer = (SkinningInfoVertexAttributeLayer*)mMesh->FindSharedVertexAttributeLayer(SkinningInfoVertexAttributeLayer::TYPE_ID); MCORE_ASSERT(skinningLayer); - // reserve space for the bone array - //mBones.Reserve( actor->GetNumNodes() ); - // find out what bones this mesh uses const uint32 numOrgVerts = mMesh->GetNumOrgVertices(); for (uint32 i = 0; i < numOrgVerts; i++) @@ -379,26 +328,21 @@ namespace EMotionFX { SkinInfluence* influence = skinningLayer->GetInfluence(i, a); - // get the bone index in the array - uint32 boneIndex = FindLocalBoneIndex(influence->GetNodeNr()); - - // if the bone is not found in our array - if (boneIndex == MCORE_INVALIDINDEX32) + AZ::Outcome boneIndexOutcome = FindLocalBoneIndex(influence->GetNodeNr()); + if (boneIndexOutcome.IsSuccess()) + { + influence->SetBoneNr(boneIndexOutcome.GetValue()); + } + else { // add the bone to the array of bones in this deformer - mBones.AddEmptyExact(); - BoneInfo& lastBone = mBones.GetLast(); + BoneInfo lastBone; lastBone.mNodeNr = influence->GetNodeNr(); lastBone.mDualQuat.Identity(); - boneIndex = mBones.GetLength() - 1; + m_bones.emplace_back(lastBone); + influence->SetBoneNr(static_cast(m_bones.size() - 1)); } - - // set the bone number in the influence - influence->SetBoneNr(static_cast(boneIndex)); } } - - // get rid of all items in the used bones array - // mBones.Shrink(); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h index fc80256524..ec00f1186f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/DualQuatSkinDeformer.h @@ -12,13 +12,13 @@ #pragma once -// include the required headers +#include +#include #include "EMotionFXConfig.h" #include #include "Mesh.h" #include "MeshDeformer.h" - namespace EMotionFX { // forward declarations @@ -101,37 +101,47 @@ namespace EMotionFX * This is the number of different bones that the skinning information of the mesh where this deformer works on uses. * @result The number of bones. */ - MCORE_INLINE uint32 GetNumLocalBones() const { return mBones.GetLength(); } + MCORE_INLINE uint32 GetNumLocalBones() const { return static_cast(m_bones.size()); } /** * Get the node number of a given local bone. * @param index The local bone number, which must be in range of [0..GetNumLocalBones()-1]. * @result The node number, which is in range of [0..Actor::GetNumNodes()-1], depending on the actor where this deformer works on. */ - MCORE_INLINE uint32 GetLocalBone(uint32 index) const { return mBones[index].mNodeNr; } + MCORE_INLINE uint32 GetLocalBone(uint32 index) const { return m_bones[index].mNodeNr; } /** * Pre-allocate space for a given number of local bones. * This does not alter the value returned by GetNumLocalBones(). * @param numBones The number of bones to pre-allocate space for. */ - MCORE_INLINE void ReserveLocalBones(uint32 numBones) { mBones.Reserve(numBones); } - + MCORE_INLINE void ReserveLocalBones(uint32 numBones) { m_bones.reserve(numBones); } protected: /** - * Structure used for precalculating the skinning matrices. + * Structure used for pre-calculating the skinning matrices. */ struct EMFX_API BoneInfo { uint32 mNodeNr; /**< The node number. */ - MCore::DualQuaternion mDualQuat; /**< The dual quat of the precalculated matrix that contains the "globalMatrix * inverse(bindPoseMatrix)". */ + MCore::DualQuaternion mDualQuat; /**< The dual quat of the pre-calculated matrix that contains the "globalMatrix * inverse(bindPoseMatrix)". */ MCORE_INLINE BoneInfo() : mNodeNr(MCORE_INVALIDINDEX32) {} }; + AZStd::vector m_bones; /**< The array of bone information used for pre-calculation. */ - MCore::Array mBones; /**< The array of bone information used for precalculation. */ + /** + * Skin a part of the mesh. + * @param mesh The mesh to be skinned. + * @param startVertex The start vertex index to start skinning. + * @param endVertex The end vertex index for the range to be skinned. + * @param boneInfos The pre-calculated skinning matrices shared across the skinning process. + */ + static void SkinRange(Mesh* mesh, AZ::u32 startVertex, AZ::u32 endVertex, const AZStd::vector& boneInfos); + + //! Number of vertices per batch/job used for multi-threaded software skinning. + static constexpr AZ::u32 s_numVerticesPerBatch = 10000; /** * Default constructor. @@ -149,18 +159,6 @@ namespace EMotionFX * @param nodeIndex The node number to search for. * @result The index inside the mBones member array, which uses the given node. */ - MCORE_INLINE uint32 FindLocalBoneIndex(uint32 nodeIndex) const - { - const uint32 numBones = mBones.GetLength(); - for (uint32 i = 0; i < numBones; ++i) - { - if (mBones[i].mNodeNr == nodeIndex) - { - return i; - } - } - - return MCORE_INVALIDINDEX32; - } + AZ::Outcome FindLocalBoneIndex(uint32 nodeIndex) const; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp index cbe13308d9..d715fabd1c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionInstancePool.cpp @@ -220,7 +220,7 @@ namespace EMotionFX //mPool->mFreeList.Reserve( numInstances * 2 ); if (mPool->mFreeList.GetMaxLength() < mPool->mNumInstances) { - mPool->mFreeList.Reserve(mPool->mNumInstances); + mPool->mFreeList.Reserve(mPool->mNumInstances + mPool->mFreeList.GetMaxLength() / 2); } mPool->mFreeList.ResizeFast(startIndex + numInstances); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h index 85fc9c8d56..e33a5f3f51 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioPlugin.h @@ -78,8 +78,6 @@ namespace EMStudio virtual void OnBeforeRemovePlugin(uint32 classID) { MCORE_UNUSED(classID); } virtual void OnMainWindowClosed() {} - virtual void RegisterKeyboardShortcuts() {} - struct RenderInfo { MCORE_MEMORYOBJECTCATEGORY(EMStudioPlugin::RenderInfo, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp index b8093d2115..d6fdb9128b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.cpp @@ -116,14 +116,6 @@ namespace EMStudio } - void KeyboardShortcutsWindow::hideEvent(QHideEvent* event) - { - MCORE_UNUSED(event); - //if (mShortcutReceiverDialog) - // mShortcutReceiverDialog->reject(); - } - - // reconstruct the whole interface void KeyboardShortcutsWindow::ReInit() { @@ -138,11 +130,11 @@ namespace EMStudio // add the groups to the left list widget MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - const uint32 numGroups = shortcutManager->GetNumGroups(); + const size_t numGroups = shortcutManager->GetNumGroups(); for (uint32 i = 0; i < numGroups; ++i) { MysticQt::KeyboardShortcutManager::Group* group = shortcutManager->GetGroup(i); - mListWidget->addItem(group->GetName()); + mListWidget->addItem(FromStdString(group->GetName())); } mTableWidget->blockSignals(false); @@ -183,10 +175,10 @@ namespace EMStudio // get access to the shortcut group and some data MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); MysticQt::KeyboardShortcutManager::Group* group = shortcutManager->GetGroup(mSelectedGroup); - const uint32 numActions = group->GetNumActions(); + const size_t numActions = group->GetNumActions(); // set the row count - mTableWidget->setRowCount(numActions); + mTableWidget->setRowCount(aznumeric_caster(numActions)); // fill the table with the media root folders for (uint32 i = 0; i < numActions; ++i) @@ -195,11 +187,11 @@ namespace EMStudio MysticQt::KeyboardShortcutManager::Action* action = group->GetAction(i); // add the item to the table and set the row height - QTableWidgetItem* item = new QTableWidgetItem(action->mName.c_str()); + QTableWidgetItem* item = new QTableWidgetItem(action->m_qaction->text()); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); mTableWidget->setItem(i, 0, item); - const QString keyText = ConstructStringFromShortcut(action->mKey, action->mCtrl, action->mAlt); + const QString keyText = ConstructStringFromShortcut(action->m_qaction->shortcut()); item = new QTableWidgetItem(keyText); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); @@ -255,18 +247,14 @@ namespace EMStudio // handle conflicts if (shortcutWindow.mConflictDetected) { - shortcutWindow.mConflictAction->mKey = -1; - shortcutWindow.mConflictAction->mCtrl = false; - shortcutWindow.mConflictAction->mAlt = false; + shortcutWindow.mConflictAction->m_qaction->setShortcut({}); } // adjust the shortcut action - action->mKey = shortcutWindow.mKey; - action->mAlt = shortcutWindow.mAlt; - action->mCtrl = shortcutWindow.mCtrl; + action->m_qaction->setShortcut(shortcutWindow.mKey); // save the new shortcuts - QSettings settings(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioKeyboardShortcuts.cfg").c_str(), QSettings::IniFormat, this); + QSettings settings(FromStdString(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioKeyboardShortcuts.cfg")), QSettings::IniFormat, this); shortcutManager->Save(&settings); // reinit the window @@ -277,31 +265,14 @@ namespace EMStudio // construct a text version of a shortcut - QString KeyboardShortcutsWindow::ConstructStringFromShortcut(int key, bool ctrl, bool alt) + QString KeyboardShortcutsWindow::ConstructStringFromShortcut(QKeySequence key) { - if (key == -1) + if (key.isEmpty()) { return "not set"; } - QString keyText; - - if (ctrl) - { - #if AZ_TRAIT_OS_PLATFORM_APPLE - keyText += "COMMAND + "; - #else - keyText += "CTRL + "; - #endif - } - if (alt) - { - keyText += "ALT + "; - } - - keyText += QKeySequence(key).toString(QKeySequence::NativeText); - - return keyText; + return key.toString(QKeySequence::NativeText); } @@ -313,9 +284,7 @@ namespace EMStudio return; } - mContextMenuAction->mKey = mContextMenuAction->mDefaultKey; - mContextMenuAction->mCtrl = mContextMenuAction->mDefaultCtrl; - mContextMenuAction->mAlt = mContextMenuAction->mDefaultAlt; + mContextMenuAction->m_qaction->setShortcut(mContextMenuAction->m_defaultKeySequence); ReInit(); } @@ -378,19 +347,14 @@ namespace EMStudio setWindowTitle(" "); layout->addWidget(new QLabel("Press the new shortcut on the keyboard:")); - // find the initial shortcut - //MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - mOrgAction = action; mOrgGroup = group; mConflictAction = nullptr; mConflictDetected = false; - mKey = action->mKey; - mCtrl = action->mCtrl; - mAlt = action->mAlt; + mKey = action->m_qaction->shortcut(); - QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(mKey, mCtrl, mAlt); + QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(mKey); mLabel = new QLabel(keyText); mLabel->setAlignment(Qt::AlignHCenter); @@ -431,9 +395,7 @@ namespace EMStudio // reset the shortcut to its default value void ShortcutReceiverDialog::ResetToDefault() { - mKey = mOrgAction->mDefaultKey; - mCtrl = mOrgAction->mDefaultCtrl; - mAlt = mOrgAction->mDefaultAlt; + mKey = mOrgAction->m_defaultKeySequence; UpdateInterface(); } @@ -444,10 +406,8 @@ namespace EMStudio { MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(mKey, mCtrl, mAlt); - // check if the currently assigned shortcut is already taken by another shortcut - mConflictAction = shortcutManager->FindShortcut(mKey, mCtrl, mAlt, mOrgGroup); + mConflictAction = shortcutManager->FindShortcut(mKey, mOrgGroup); if (mConflictAction == nullptr || mConflictAction == mOrgAction) { mOKButton->setToolTip(""); @@ -465,39 +425,25 @@ namespace EMStudio if (mConflictAction) { - AZStd::string tempString; - - tempString = AZStd::string::format("Assigning new shortcut will unassign '%s' automatically.", mConflictAction->mName.c_str()); - mOKButton->setToolTip(tempString.c_str()); + mOKButton->setToolTip(QString("Assigning new shortcut will unassign '%1' automatically.").arg(mConflictAction->m_qaction->text())); MysticQt::KeyboardShortcutManager::Group* conflictGroup = shortcutManager->FindGroupForShortcut(mConflictAction); if (conflictGroup) { - tempString = AZStd::string::format("Conflicts with: %s -> %s", conflictGroup->GetName(), mConflictAction->mName.c_str()); + mConflictKeyLabel->setText(QString("Conflicts with: %1 -> %2").arg(FromStdString(conflictGroup->GetName())).arg(mConflictAction->m_qaction->text())); } else { - tempString = AZStd::string::format("Conflicts with: %s", mConflictAction->mName.c_str()); + mConflictKeyLabel->setText(QString("Conflicts with: %1").arg(mConflictAction->m_qaction->text())); } - - mConflictKeyLabel->setText(tempString.c_str()); } } // adjust the label text to the new shortcut + const QString keyText = KeyboardShortcutsWindow::ConstructStringFromShortcut(mKey); mLabel->setText(keyText); } - - // close dialog as soon as it lost focus - void ShortcutReceiverDialog::focusOutEvent(QFocusEvent* event) - { - MCORE_UNUSED(event); - // if (event->reason() == Qt::ActiveWindowFocusReason) - // reject(); - } - - // called when the user pressed a new shortcut void ShortcutReceiverDialog::keyPressEvent(QKeyEvent* event) { @@ -513,18 +459,12 @@ namespace EMStudio if (event->key() == Qt::Key_Escape) { - //mKey = mOrgAction->mKey; - //mCtrl = mOrgAction->mCtrl; - //mAlt = mOrgAction->mAlt; - // close the dialog when pressing ESC reject(); } else { - mKey = event->key(); - mCtrl = event->modifiers() & Qt::ControlModifier; - mAlt = event->modifiers() & Qt::AltModifier; + mKey = event->key() | event->modifiers(); } UpdateInterface(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h index 024479cc90..f6d4f43642 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/KeyboardShortcutsWindow.h @@ -41,12 +41,9 @@ namespace EMStudio virtual ~ShortcutReceiverDialog() {} void keyPressEvent(QKeyEvent* event) override; - void focusOutEvent(QFocusEvent* event) override; void UpdateInterface(); - int mKey; - bool mCtrl; - bool mAlt; + QKeySequence mKey; bool mConflictDetected; MysticQt::KeyboardShortcutManager::Action* mConflictAction; @@ -74,7 +71,7 @@ namespace EMStudio void Init(); void ReInit(); - static QString ConstructStringFromShortcut(int key, bool ctrl, bool alt); + static QString ConstructStringFromShortcut(QKeySequence key); MysticQt::KeyboardShortcutManager::Group* GetCurrentGroup() const; void setVisible(bool visible) override; @@ -95,6 +92,5 @@ namespace EMStudio ShortcutReceiverDialog* mShortcutReceiverDialog; void contextMenuEvent(QContextMenuEvent* event) override; - void hideEvent(QHideEvent* event) override; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index 496b6b8e94..950b63ff26 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -66,6 +66,7 @@ #include #include #include +#include AZ_PUSH_DISABLE_WARNING(4267, "-Wconversion") #include AZ_POP_DISABLE_WARNING @@ -508,14 +509,33 @@ namespace EMStudio mShortcutManager = new MysticQt::KeyboardShortcutManager(); // load the old shortcuts - QSettings shortcutSettings(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioKeyboardShortcuts.cfg").c_str(), QSettings::IniFormat, this); - mShortcutManager->Load(&shortcutSettings); + LoadKeyboardShortcuts(); // add the application mode group - const char* layoutGroupName = "Layouts"; - mShortcutManager->RegisterKeyboardShortcut("AnimGraph", layoutGroupName, Qt::Key_1, false, true, false); - mShortcutManager->RegisterKeyboardShortcut("Animation", layoutGroupName, Qt::Key_2, false, true, false); - mShortcutManager->RegisterKeyboardShortcut("Character", layoutGroupName, Qt::Key_3, false, true, false); + constexpr AZStd::string_view layoutGroupName = "Layouts"; + QAction* animGraphLayoutAction = new QAction( + "AnimGraph", + this); + animGraphLayoutAction->setShortcut(Qt::Key_1 | Qt::AltModifier); + mShortcutManager->RegisterKeyboardShortcut(animGraphLayoutAction, layoutGroupName, false); + connect(animGraphLayoutAction, &QAction::triggered, [this]{ mApplicationMode->setCurrentIndex(0); }); + addAction(animGraphLayoutAction); + + QAction* animationLayoutAction = new QAction( + "Animation", + this); + animationLayoutAction->setShortcut(Qt::Key_2 | Qt::AltModifier); + mShortcutManager->RegisterKeyboardShortcut(animationLayoutAction, layoutGroupName, false); + connect(animationLayoutAction, &QAction::triggered, [this]{ mApplicationMode->setCurrentIndex(1); }); + addAction(animationLayoutAction); + + QAction* characterLayoutAction = new QAction( + "Character", + this); + characterLayoutAction->setShortcut(Qt::Key_1 | Qt::AltModifier); + mShortcutManager->RegisterKeyboardShortcut(characterLayoutAction, layoutGroupName, false); + connect(characterLayoutAction, &QAction::triggered, [this]{ mApplicationMode->setCurrentIndex(2); }); + addAction(characterLayoutAction); EMotionFX::ActorEditorRequestBus::Handler::BusConnect(); @@ -1267,6 +1287,12 @@ namespace EMStudio mRecentActors.AddRecentFile(fileName.toUtf8().data()); } + void MainWindow::LoadKeyboardShortcuts() + { + QSettings shortcutSettings(AZStd::string(GetManager()->GetAppDataFolder() + "EMStudioKeyboardShortcuts.cfg").c_str(), QSettings::IniFormat, this); + mShortcutManager->Load(&shortcutSettings); + } + void MainWindow::LoadActor(const char* fileName, bool replaceCurrentScene) { // create the final command @@ -2577,41 +2603,6 @@ namespace EMStudio QTimer::singleShot(0, this, &MainWindow::RaiseFloatingWidgets); } - void MainWindow::keyPressEvent(QKeyEvent* event) - { - const char* layoutGroupName = "Layouts"; - const uint32 numLayouts = GetMainWindow()->GetNumLayouts(); - for (uint32 i = 0; i < numLayouts; ++i) - { - if (mShortcutManager->Check(event, GetLayoutName(i), layoutGroupName)) - { - mApplicationMode->setCurrentIndex(i); - event->accept(); - return; - } - } - - event->ignore(); - } - - - void MainWindow::keyReleaseEvent(QKeyEvent* event) - { - const char* layoutGroupName = "Layouts"; - const uint32 numLayouts = GetNumLayouts(); - for (uint32 i = 0; i < numLayouts; ++i) - { - if (mShortcutManager->Check(event, layoutGroupName, GetLayoutName(i))) - { - event->accept(); - return; - } - } - - event->ignore(); - } - - // get the name of the currently active layout const char* MainWindow::GetCurrentLayoutName() const { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h index 15edaef144..850715b23f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h @@ -152,9 +152,6 @@ namespace EMStudio FileManager* GetFileManager() const { return mFileManager; } PreferencesWindow* GetPreferencesWindow() const { return mPreferencesWindow; } - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent* event) override; - uint32 GetNumLayouts() const { return mLayoutNames.GetLength(); } const char* GetLayoutName(uint32 index) const { return mLayoutNames[index].c_str(); } const char* GetCurrentLayoutName() const; @@ -168,6 +165,8 @@ namespace EMStudio void AddRecentActorFile(const QString& fileName); + void LoadKeyboardShortcuts(); + public slots: void OnAutosaveTimeOut(); void LoadLayoutAfterShow(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp index 214ed68367..ffe29ed691 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/PluginManager.cpp @@ -136,7 +136,6 @@ namespace EMStudio mActivePlugins.push_back(newPlugin); newPlugin->Init(); - newPlugin->RegisterKeyboardShortcuts(); return newPlugin; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index 47b88b1fa2..8e4c1bce37 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -1020,17 +1020,6 @@ namespace EMStudio } - // register keyboard shortcuts used for the render plugin - void RenderPlugin::RegisterKeyboardShortcuts() - { - MysticQt::KeyboardShortcutManager* shortcutManger = GetMainWindow()->GetShortcutManager(); - - shortcutManger->RegisterKeyboardShortcut("Show Selected", "Render Window", Qt::Key_S, false, false, true); - shortcutManger->RegisterKeyboardShortcut("Show Entire Scene", "Render Window", Qt::Key_A, false, false, true); - shortcutManger->RegisterKeyboardShortcut("Toggle Selection Box Rendering", "Render Window", Qt::Key_J, false, false, true); - } - - // find the trajectory path for a given actor instance MCommon::RenderUtil::TrajectoryTracePath* RenderPlugin::FindTracePath(EMotionFX::ActorInstance* actorInstance) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h index 43f237b89e..7dab0a5f95 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.h @@ -124,9 +124,6 @@ namespace EMStudio void ViewCloseup(bool selectedInstancesOnly = true, RenderWidget* renderWidget = nullptr, float flightTime = DEFAULT_FLIGHT_TIME); void SetSkipFollowCalcs(bool skipFollowCalcs); - // keyboard shortcuts - void RegisterKeyboardShortcuts() override; - // manipulators void ReInitTransformationManipulators(); MCommon::TransformationManipulator* GetActiveManipulator(MCommon::Camera* camera, int32 mousePosX, int32 mousePosY); @@ -177,6 +174,11 @@ namespace EMStudio void SaveRenderOptions(); void LoadRenderOptions(); + inline static constexpr AZStd::string_view s_renderWindowShortcutGroupName = "Render Window"; + inline static constexpr AZStd::string_view s_showSelectedShortcutName = "Show Selected"; + inline static constexpr AZStd::string_view s_showEntireSceneShortcutName = "Show Entire Scene"; + inline static constexpr AZStd::string_view s_toggleSelectionBoxRenderingShortcutName = "Toggle Selection Box Rendering"; + public slots: void SetManipulatorMode(RenderOptions::ManipulatorMode mode); void SetSelectionMode() { SetManipulatorMode(RenderOptions::ManipulatorMode::SELECT); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp index f6c44980fe..9abb05ea2c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp @@ -16,7 +16,9 @@ #include "../PreferencesWindow.h" #include #include +#include #include +#include #include @@ -156,8 +158,17 @@ namespace EMStudio cameraMenu->addSeparator(); cameraMenu->addAction("Reset Camera", [this]() { this->OnResetCamera(); }); - cameraMenu->addAction("Show Selected", this, &RenderViewWidget::OnShowSelected); - cameraMenu->addAction("Show Entire Scene", this, &RenderViewWidget::OnShowEntireScene); + + QAction* showSelectedAction = cameraMenu->addAction("Show Selected", this, &RenderViewWidget::OnShowSelected); + showSelectedAction->setShortcut(Qt::Key_S); + GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(showSelectedAction, RenderPlugin::s_renderWindowShortcutGroupName, true); + addAction(showSelectedAction); + + QAction* showEntireSceneAction = cameraMenu->addAction("Show Entire Scene", this, &RenderViewWidget::OnShowEntireScene); + showEntireSceneAction->setShortcut(Qt::Key_A); + GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(showEntireSceneAction, RenderPlugin::s_renderWindowShortcutGroupName, true); + addAction(showEntireSceneAction); + cameraMenu->addSeparator(); mFollowCharacterAction = cameraMenu->addAction(tr("Follow Character")); @@ -181,8 +192,30 @@ namespace EMStudio connect(m_manipulatorModes[RenderOptions::ROTATE], &QAction::triggered, mPlugin, &RenderPlugin::SetRotationMode); connect(m_manipulatorModes[RenderOptions::SCALE], &QAction::triggered, mPlugin, &RenderPlugin::SetScaleMode); + QAction* toggleSelectionBoxRendering = new QAction( + "Toggle Selection Box Rendering", + this + ); + toggleSelectionBoxRendering->setShortcut(Qt::Key_J); + GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(toggleSelectionBoxRendering, RenderPlugin::s_renderWindowShortcutGroupName, true); + connect(toggleSelectionBoxRendering, &QAction::triggered, this, [this] + { + mPlugin->GetRenderOptions()->SetRenderSelectionBox(mPlugin->GetRenderOptions()->GetRenderSelectionBox() ^ true); + }); + addAction(toggleSelectionBoxRendering); + + QAction* deleteSelectedActorInstance = new QAction( + "Delete Selected Actor Instance", + this + ); + deleteSelectedActorInstance->setShortcut(Qt::Key_Delete); + connect(deleteSelectedActorInstance, &QAction::triggered, []{ CommandSystem::RemoveSelectedActorInstances(); }); + addAction(deleteSelectedActorInstance); + Reset(); UpdateInterface(); + + GetMainWindow()->LoadKeyboardShortcuts(); } void RenderViewWidget::SetManipulatorMode(RenderOptions::ManipulatorMode mode) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h index 33b648f9c9..3ef48d0749 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.h @@ -43,6 +43,8 @@ namespace EMStudio RenderViewWidget(RenderPlugin* parentPlugin, QWidget* parentWidget); virtual ~RenderViewWidget(); + void CreateActions(); + enum ERenderFlag { RENDER_SOLID = 0, diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp index 6218194fc6..5ca912ef71 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.cpp @@ -25,7 +25,6 @@ #include "../EMStudioManager.h" #include "../MainWindow.h" #include -#include namespace EMStudio @@ -76,7 +75,6 @@ namespace EMStudio delete mAxisFakeCamera; } - // start view closeup flight void RenderWidget::ViewCloseup(const MCore::AABB& aabb, float flightTime, uint32 viewCloseupWaiting) { @@ -726,72 +724,6 @@ namespace EMStudio } - // called when a key got pressed - void RenderWidget::OnKeyPressEvent(QWidget* renderWidget, QKeyEvent* event) - { - MCORE_UNUSED(renderWidget); - MysticQt::KeyboardShortcutManager* shortcutManger = GetMainWindow()->GetShortcutManager(); - - if (shortcutManger->Check(event, "Show Selected", "Render Window")) - { - mPlugin->ViewCloseup(true, this); - event->accept(); - return; - } - - if (shortcutManger->Check(event, "Show Entire Scene", "Render Window")) - { - mPlugin->ViewCloseup(false, this); - event->accept(); - return; - } - - if (shortcutManger->Check(event, "Toggle Selection Box Rendering", "Render Window")) - { - mPlugin->GetRenderOptions()->SetRenderSelectionBox(mPlugin->GetRenderOptions()->GetRenderSelectionBox() ^ true); - event->accept(); - return; - } - - if (event->key() == Qt::Key_Delete) - { - CommandSystem::RemoveSelectedActorInstances(); - event->accept(); - return; - } - - event->ignore(); - } - - - // called when a key got released - void RenderWidget::OnKeyReleaseEvent(QWidget* renderWidget, QKeyEvent* event) - { - MCORE_UNUSED(renderWidget); - MysticQt::KeyboardShortcutManager* shortcutManger = GetMainWindow()->GetShortcutManager(); - - if (shortcutManger->Check(event, "Show Selected", "Render Window")) - { - event->accept(); - return; - } - - if (shortcutManger->Check(event, "Show Entire Scene", "Render Window")) - { - event->accept(); - return; - } - - if (event->key() == Qt::Key_Delete) - { - event->accept(); - return; - } - - event->ignore(); - } - - // handles context menu events void RenderWidget::OnContextMenuEvent(QWidget* renderWidget, bool shiftPressed, bool altPressed, int32 localMouseX, int32 localMouseY, QPoint globalMousePos) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h index f376f10f84..99c1c38f70 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderWidget.h @@ -96,6 +96,8 @@ namespace EMStudio RenderWidget(RenderPlugin* renderPlugin, RenderViewWidget* viewWidget); virtual ~RenderWidget(); + void CreateActions(); + // main render callback virtual void Render() = 0; virtual void Update() = 0; @@ -132,8 +134,6 @@ namespace EMStudio void OnMousePressEvent(QWidget* renderWidget, QMouseEvent* event); void OnMouseReleaseEvent(QWidget* renderWidget, QMouseEvent* event); void OnWheelEvent(QWidget* renderWidget, QWheelEvent* event); - void OnKeyPressEvent(QWidget* renderWidget, QKeyEvent* event); - void OnKeyReleaseEvent(QWidget* renderWidget, QKeyEvent* event); void OnContextMenuEvent(QWidget* renderWidget, bool shiftPressed, bool altPressed, int32 localMouseX, int32 localMouseY, QPoint globalMousePos); protected: diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp index 4824821a61..28a4fb9c92 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/SaveChangedFilesManager.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -398,33 +399,49 @@ namespace EMStudio const size_t numDirtyFiles = dirtyFileNames.size(); mTableWidget->setRowCount(static_cast(numDirtyFiles)); - AZStd::string extension, typeString, filenameText, path, filenameOnly; for (size_t i = 0; i < numDirtyFiles; ++i) { SaveDirtyFilesCallback::ObjectPointer object = mObjects[i]; + QString labelText; if (dirtyFileNames[i].empty()) { - filenameText = ""; + labelText = ""; } else { - AzFramework::StringFunc::Path::GetFullPath(dirtyFileNames[i].c_str(), path); - AzFramework::StringFunc::Path::GetFullFileName(dirtyFileNames[i].c_str(), filenameOnly); + const AZStd::string& productFilename = dirtyFileNames[i]; - filenameText = AZStd::string::format("%s%s", path.c_str(), filenameOnly.c_str()); + // Get the asset source name from the product filename. + bool sourceAssetFound = false; + AZStd::string sourceAssetFilename; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(sourceAssetFound, + &AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, + productFilename, + sourceAssetFilename); + + const AZStd::string usedFilename = sourceAssetFound ? sourceAssetFilename : dirtyFileNames[i]; + + // Separate the path from the filename, so that we can display the filename in bold. + AZStd::string fullPath; + AzFramework::StringFunc::Path::GetFullPath(usedFilename.c_str(), fullPath); + AzFramework::StringFunc::RelativePath::Normalize(fullPath); // Add trailing slash in case it is missing + AZStd::string fullFilename; + AzFramework::StringFunc::Path::GetFullFileName(usedFilename.c_str(), fullFilename); + labelText = QString("%1%2").arg(fullPath.c_str(), fullFilename.c_str()); } // create the checkbox QCheckBox* checkbox = new QCheckBox(""); - checkbox->setStyleSheet("background: transparent; padding-left: 3px; max-width: 13px;"); + checkbox->setStyleSheet("background: transparent;"); checkbox->setChecked(true); // create the filename table item QLabel* filenameLabel = new QLabel(); - filenameLabel->setToolTip(filenameText.c_str()); - filenameLabel->setText(filenameText.c_str()); + filenameLabel->setToolTip(labelText); + filenameLabel->setText(labelText); + QString typeString; if (object.mMotion) { typeString = "Motion"; @@ -445,12 +462,8 @@ namespace EMStudio { typeString = "Workspace"; } - else - { - typeString = ""; - } - QTableWidgetItem* itemType = new QTableWidgetItem(typeString.c_str()); + QTableWidgetItem* itemType = new QTableWidgetItem(typeString); const int row = static_cast(i); itemType->setData(Qt::UserRole, row); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h index 107869de33..c81d7c61ae 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/OpenGLRender/GLWidget.h @@ -72,8 +72,6 @@ namespace EMStudio void mousePressEvent(QMouseEvent* event) { RenderWidget::OnMousePressEvent(this, event); } void mouseReleaseEvent(QMouseEvent* event) { RenderWidget::OnMouseReleaseEvent(this, event); } void wheelEvent(QWheelEvent* event) { RenderWidget::OnWheelEvent(this, event); } - void keyPressEvent(QKeyEvent* event) { RenderWidget::OnKeyPressEvent(this, event); } - void keyReleaseEvent(QKeyEvent* event) { RenderWidget::OnKeyReleaseEvent(this, event); } void focusInEvent(QFocusEvent* event); void focusOutEvent(QFocusEvent* event); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp index 9cbd654393..f76f684ea5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.cpp @@ -99,7 +99,7 @@ namespace EMStudio } if (!m_pasteItems.empty()) { - m_pasteOperation = PasteOperation::Copy; + SetPasteOperation(PasteOperation::Copy); } } @@ -126,7 +126,7 @@ namespace EMStudio } if (!m_pasteItems.empty()) { - m_pasteOperation = PasteOperation::Cut; + SetPasteOperation(PasteOperation::Cut); } } @@ -168,8 +168,8 @@ namespace EMStudio } } - m_pasteOperation = PasteOperation::None; m_pasteItems.clear(); + SetPasteOperation(PasteOperation::None); } void AnimGraphActionManager::SetEntryState() @@ -443,6 +443,18 @@ namespace EMStudio } } + void AnimGraphActionManager::NavigateToParent() + { + const QModelIndex parentFocus = m_plugin->GetAnimGraphModel().GetParentFocus(); + if (parentFocus.isValid()) + { + QModelIndex newParentFocus = parentFocus.model()->parent(parentFocus); + if (newParentFocus.isValid()) + { + m_plugin->GetAnimGraphModel().Focus(newParentFocus); + } + } + } void AnimGraphActionManager::OpenReferencedAnimGraph(EMotionFX::AnimGraphReferenceNode* referenceNode) { @@ -678,4 +690,10 @@ namespace EMStudio GetCommandManager()->ExecuteCommandGroup(commandGroup, outResult); } } + + void AnimGraphActionManager::SetPasteOperation(PasteOperation newOperation) + { + m_pasteOperation = newOperation; + emit PasteStateChanged(); + } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.h index 30b520d2a5..9182272875 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphActionManager.h @@ -72,6 +72,9 @@ namespace EMStudio Bottom }; + signals: + void PasteStateChanged(); + public slots: void Copy(); void Cut(); @@ -95,6 +98,7 @@ namespace EMStudio void DeleteSelectedNodes(); void NavigateToNode(); + void NavigateToParent(); void OpenReferencedAnimGraph(EMotionFX::AnimGraphReferenceNode* referenceNode); @@ -126,5 +130,7 @@ namespace EMStudio AnimGraphPlugin* m_plugin; AZStd::vector m_pasteItems; PasteOperation m_pasteOperation; + + void SetPasteOperation(PasteOperation newOperation); }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp index 2669153dfd..d9b77ccf89 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.cpp @@ -461,10 +461,7 @@ namespace EMStudio { m_actionFilter = actionFilter; - if (mViewWidget) - { - mViewWidget->UpdateSelection(); - } + emit ActionFilterChanged(); } const AnimGraphActionFilter& AnimGraphPlugin::GetActionFilter() const @@ -1408,33 +1405,6 @@ namespace EMStudio } - // register keyboard shortcuts used for the render plugin - void AnimGraphPlugin::RegisterKeyboardShortcuts() - { - MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - - shortcutManager->RegisterKeyboardShortcut("Fit Entire Graph", "Anim Graph Window", Qt::Key_A, false, false, true); - shortcutManager->RegisterKeyboardShortcut("Zoom On Selected Nodes", "Anim Graph Window", Qt::Key_Z, false, false, true); - - shortcutManager->RegisterKeyboardShortcut("Open Parent Node", "Anim Graph Window", Qt::Key_Up, false, false, true); - shortcutManager->RegisterKeyboardShortcut("Open Selected Node", "Anim Graph Window", Qt::Key_Down, false, false, true); - shortcutManager->RegisterKeyboardShortcut("History Back", "Anim Graph Window", Qt::Key_Left, false, false, true); - shortcutManager->RegisterKeyboardShortcut("History Forward", "Anim Graph Window", Qt::Key_Right, false, false, true); - - shortcutManager->RegisterKeyboardShortcut("Align Left", "Anim Graph Window", Qt::Key_L, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Align Right", "Anim Graph Window", Qt::Key_R, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Align Top", "Anim Graph Window", Qt::Key_T, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Align Bottom", "Anim Graph Window", Qt::Key_B, true, false, true); - - shortcutManager->RegisterKeyboardShortcut("Cut", "Anim Graph Window", Qt::Key_X, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Copy", "Anim Graph Window", Qt::Key_C, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Paste", "Anim Graph Window", Qt::Key_V, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Select All", "Anim Graph Window", Qt::Key_A, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Unselect All", "Anim Graph Window", Qt::Key_D, true, false, true); - shortcutManager->RegisterKeyboardShortcut("Delete Selected Nodes", "Anim Graph Window", Qt::Key_Delete, false, false, true); - } - - // double clicked a node history item in the timeview plugin void AnimGraphPlugin::OnDoubleClickedRecorderNodeHistoryItem(EMotionFX::Recorder::ActorInstanceData* actorInstanceData, EMotionFX::Recorder::NodeHistoryItem* historyItem) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h index c1e2004aae..cb8e015429 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/AnimGraphPlugin.h @@ -49,7 +49,6 @@ namespace EMotionFX class AnimGraphObjectFactory; } - namespace EMStudio { // forward declarations @@ -151,8 +150,6 @@ namespace EMStudio void LoadOptions(); void SaveOptions(); - void RegisterKeyboardShortcuts() override; - bool CheckIfCanCreateObject(EMotionFX::AnimGraphObject* parentObject, const EMotionFX::AnimGraphObject* object, EMotionFX::AnimGraphObject::ECategory category) const; void ProcessFrame(float timePassedInSeconds) override; @@ -171,6 +168,27 @@ namespace EMStudio /// Is the given anim graph running on any selected actor instance? bool IsAnimGraphActive(EMotionFX::AnimGraph* animGraph) const; + inline static constexpr AZStd::string_view s_animGraphWindowShortcutGroupName = "Anim Graph Window"; + inline static constexpr AZStd::string_view s_fitEntireGraphShortcutName = "Fit Entire Graph"; + inline static constexpr AZStd::string_view s_zoomOnSelectedNodesShortcutName = "Zoom On Selected Nodes"; + inline static constexpr AZStd::string_view s_openParentNodeShortcutName = "Open Parent Node"; + inline static constexpr AZStd::string_view s_openSelectedNodeShortcutName = "Open Selected Node"; + inline static constexpr AZStd::string_view s_historyBackShortcutName = "History Back"; + inline static constexpr AZStd::string_view s_historyForwardShortcutName = "History Forward"; + inline static constexpr AZStd::string_view s_alignLeftShortcutName = "Align Left"; + inline static constexpr AZStd::string_view s_alignRightShortcutName = "Align Right"; + inline static constexpr AZStd::string_view s_alignTopShortcutName = "Align Top"; + inline static constexpr AZStd::string_view s_alignBottomShortcutName = "Align Bottom"; + inline static constexpr AZStd::string_view s_cutShortcutName = "Cut"; + inline static constexpr AZStd::string_view s_copyShortcutName = "Copy"; + inline static constexpr AZStd::string_view s_pasteShortcutName = "Paste"; + inline static constexpr AZStd::string_view s_selectAllShortcutName = "Select All"; + inline static constexpr AZStd::string_view s_unselectAllShortcutName = "Unselect All"; + inline static constexpr AZStd::string_view s_deleteSelectedNodesShortcutName = "Delete Selected Nodes"; + + signals: + void ActionFilterChanged(); + public slots: void OnFileOpen(); void OnFileSave(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp index 4203271b58..eccabd37b5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -40,74 +41,298 @@ namespace EMStudio : QWidget(parentWidget) , m_parentPlugin(plugin) { - for (uint32 i = 0; i < NUM_OPTIONS; ++i) + EMotionFX::ActorEditorRequestBus::Handler::BusConnect(); + } + + void BlendGraphViewWidget::CreateActions() + { + MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); + + m_actions[SELECTION_ALIGNLEFT] = new QAction( + QIcon(":/EMotionFX/AlignLeft.svg"), + FromStdString(AnimGraphPlugin::s_alignLeftShortcutName), + this); + m_actions[SELECTION_ALIGNLEFT]->setShortcut(Qt::Key_L | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[SELECTION_ALIGNLEFT], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[SELECTION_ALIGNLEFT], &QAction::triggered, &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignLeft); + + m_actions[SELECTION_ALIGNRIGHT] = new QAction( + QIcon(":/EMotionFX/AlignRight.svg"), + FromStdString(AnimGraphPlugin::s_alignRightShortcutName), + this); + m_actions[SELECTION_ALIGNRIGHT]->setShortcut(Qt::Key_R | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[SELECTION_ALIGNRIGHT], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[SELECTION_ALIGNRIGHT], &QAction::triggered, &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignRight); + + m_actions[SELECTION_ALIGNTOP] = new QAction( + QIcon(":/EMotionFX/AlignTop.svg"), + FromStdString(AnimGraphPlugin::s_alignTopShortcutName), + this); + m_actions[SELECTION_ALIGNTOP]->setShortcut(Qt::Key_T | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[SELECTION_ALIGNTOP], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[SELECTION_ALIGNTOP], &QAction::triggered, &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignTop); + + m_actions[SELECTION_ALIGNBOTTOM] = new QAction( + QIcon(":/EMotionFX/AlignBottom.svg"), + FromStdString(AnimGraphPlugin::s_alignBottomShortcutName), + this); + m_actions[SELECTION_ALIGNBOTTOM]->setShortcut(Qt::Key_B | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[SELECTION_ALIGNBOTTOM], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[SELECTION_ALIGNBOTTOM], &QAction::triggered, &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignBottom); + + m_actions[SELECTION_SELECTALL] = new QAction( + FromStdString(AnimGraphPlugin::s_selectAllShortcutName), + this + ); + m_actions[SELECTION_SELECTALL]->setShortcut(Qt::Key_A | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[SELECTION_SELECTALL], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[SELECTION_SELECTALL], &QAction::triggered, [this] { - m_actions[i] = nullptr; + NodeGraph* activeGraph = m_parentPlugin->GetGraphWidget()->GetActiveGraph(); + if (activeGraph) + { + activeGraph->SelectAllNodes(); + } + }); + + m_actions[SELECTION_UNSELECTALL] = new QAction( + FromStdString(AnimGraphPlugin::s_unselectAllShortcutName), + this + ); + m_actions[SELECTION_UNSELECTALL]->setShortcut(Qt::Key_D | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[SELECTION_UNSELECTALL], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[SELECTION_UNSELECTALL], &QAction::triggered, [this] + { + NodeGraph* activeGraph = m_parentPlugin->GetGraphWidget()->GetActiveGraph(); + if (activeGraph) + { + activeGraph->UnselectAllNodes(); + } + }); + + m_actions[FILE_NEW] = new QAction( + QIcon(":/EMotionFX/Plus.svg"), + tr("Create a new anim graph"), + this); + m_actions[FILE_NEW]->setObjectName("EMFX.BlendGraphViewWidget.NewButton"); + connect(m_actions[FILE_NEW], &QAction::triggered, this, &BlendGraphViewWidget::OnCreateAnimGraph); + + m_actions[FILE_OPEN] = new QAction( + tr("Open..."), + this); + connect(m_actions[FILE_OPEN], &QAction::triggered, m_parentPlugin, &AnimGraphPlugin::OnFileOpen); + + m_actions[FILE_SAVE] = new QAction( + tr("Save"), + this); + connect(m_actions[FILE_SAVE], &QAction::triggered, m_parentPlugin, &AnimGraphPlugin::OnFileSave); + + m_actions[FILE_SAVEAS] = new QAction( + tr("Save as..."), + this); + connect(m_actions[FILE_SAVEAS], &QAction::triggered, m_parentPlugin, &AnimGraphPlugin::OnFileSaveAs); + + m_actions[NAVIGATION_FORWARD] = new QAction( + QIcon(":/EMotionFX/Forward.svg"), + FromStdString(AnimGraphPlugin::s_historyForwardShortcutName), + this); + m_actions[NAVIGATION_FORWARD]->setShortcut(Qt::Key_Right); + shortcutManager->RegisterKeyboardShortcut(m_actions[NAVIGATION_FORWARD], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[NAVIGATION_FORWARD], &QAction::triggered, [this] + { + m_parentPlugin->GetNavigationHistory()->StepForward(); + UpdateNavigation(); + }); + + m_actions[NAVIGATION_BACK] = new QAction( + QIcon(":/EMotionFX/Backward.svg"), + FromStdString(AnimGraphPlugin::s_historyBackShortcutName), + this); + m_actions[NAVIGATION_BACK]->setShortcut(Qt::Key_Left); + shortcutManager->RegisterKeyboardShortcut(m_actions[NAVIGATION_BACK], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[NAVIGATION_BACK], &QAction::triggered, [this] + { + m_parentPlugin->GetNavigationHistory()->StepBackward(); + UpdateNavigation(); + }); + + m_actions[NAVIGATION_NAVPANETOGGLE] = new QAction( + QIcon(":/EMotionFX/List.svg"), + tr("Show/hide navigation pane"), + this); + connect(m_actions[NAVIGATION_NAVPANETOGGLE], &QAction::triggered, this, &BlendGraphViewWidget::ToggleNavigationPane); + + m_actions[NAVIGATION_OPEN_SELECTED] = new QAction( + FromStdString(AnimGraphPlugin::s_openSelectedNodeShortcutName), + this); + m_actions[NAVIGATION_OPEN_SELECTED]->setShortcut(Qt::Key_Down); + shortcutManager->RegisterKeyboardShortcut(m_actions[NAVIGATION_OPEN_SELECTED], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[NAVIGATION_OPEN_SELECTED], &QAction::triggered, &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::NavigateToNode); + + m_actions[NAVIGATION_TO_PARENT] = new QAction( + FromStdString(AnimGraphPlugin::s_openParentNodeShortcutName), + this); + m_actions[NAVIGATION_TO_PARENT]->setShortcut(Qt::Key_Up); + shortcutManager->RegisterKeyboardShortcut(m_actions[NAVIGATION_TO_PARENT], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[NAVIGATION_TO_PARENT], &QAction::triggered, &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::NavigateToParent); + + m_actions[NAVIGATION_FRAME_ALL] = new QAction( + QIcon(":/EMotionFX/ZoomSelected.svg"), + FromStdString(AnimGraphPlugin::s_fitEntireGraphShortcutName), + this); + m_actions[NAVIGATION_FRAME_ALL]->setShortcut(Qt::Key_A); + shortcutManager->RegisterKeyboardShortcut(m_actions[NAVIGATION_FRAME_ALL], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[NAVIGATION_FRAME_ALL], &QAction::triggered, this, &BlendGraphViewWidget::ZoomToAll); + + m_actions[NAVIGATION_ZOOMSELECTION] = new QAction( + QIcon(":/EMotionFX/ZoomSelected.svg"), + FromStdString(AnimGraphPlugin::s_zoomOnSelectedNodesShortcutName), + this); + m_actions[NAVIGATION_ZOOMSELECTION]->setShortcut(Qt::Key_Z); + shortcutManager->RegisterKeyboardShortcut(m_actions[NAVIGATION_ZOOMSELECTION], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[NAVIGATION_ZOOMSELECTION], &QAction::triggered, this, &BlendGraphViewWidget::ZoomSelected); + + m_actions[ACTIVATE_ANIMGRAPH] = new QAction( + QIcon(":/EMotionFX/PlayForward.svg"), + tr("Activate Animgraph/State"), + this); + connect(m_actions[ACTIVATE_ANIMGRAPH], &QAction::triggered, &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::ActivateAnimGraph); + + m_actions[VISUALIZATION_PLAYSPEEDS] = new QAction( + tr("Display Play Speeds"), + this); + m_actions[VISUALIZATION_PLAYSPEEDS]->setCheckable(true); + connect(m_actions[VISUALIZATION_PLAYSPEEDS], &QAction::triggered, this, &BlendGraphViewWidget::OnDisplayPlaySpeeds); + + m_actions[VISUALIZATION_GLOBALWEIGHTS] = new QAction( + tr("Display Global Weights"), + this); + m_actions[VISUALIZATION_GLOBALWEIGHTS]->setCheckable(true); + connect(m_actions[VISUALIZATION_GLOBALWEIGHTS], &QAction::triggered, this, &BlendGraphViewWidget::OnDisplayGlobalWeights); + + m_actions[VISUALIZATION_SYNCSTATUS] = new QAction( + tr("Display Sync Status"), + this); + m_actions[VISUALIZATION_SYNCSTATUS]->setCheckable(true); + connect(m_actions[VISUALIZATION_SYNCSTATUS], &QAction::triggered, this, &BlendGraphViewWidget::OnDisplaySyncStatus); + + m_actions[VISUALIZATION_PLAYPOSITIONS] = new QAction( + tr("Display Play Positions"), + this); + m_actions[VISUALIZATION_PLAYPOSITIONS]->setCheckable(true); + connect(m_actions[VISUALIZATION_PLAYPOSITIONS], &QAction::triggered, this, &BlendGraphViewWidget::OnDisplayPlayPositions); + + m_actions[EDIT_CUT] = new QAction( + FromStdString(AnimGraphPlugin::s_cutShortcutName), + this + ); + m_actions[EDIT_CUT]->setShortcut(Qt::Key_X | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[EDIT_CUT], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[EDIT_CUT], &QAction::triggered, this, [this] + { + m_parentPlugin->GetActionManager().Cut(); + }); + + m_actions[EDIT_COPY] = new QAction( + FromStdString(AnimGraphPlugin::s_copyShortcutName), + this + ); + m_actions[EDIT_COPY]->setShortcut(Qt::Key_C | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[EDIT_COPY], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[EDIT_COPY], &QAction::triggered, this, [this] + { + m_parentPlugin->GetActionManager().Copy(); + }); + + m_actions[EDIT_PASTE] = new QAction( + FromStdString(AnimGraphPlugin::s_pasteShortcutName), + this + ); + m_actions[EDIT_PASTE]->setShortcut(Qt::Key_V | Qt::ControlModifier); + shortcutManager->RegisterKeyboardShortcut(m_actions[EDIT_PASTE], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[EDIT_PASTE], &QAction::triggered, this, [this] + { + const BlendGraphWidget* graphWidget = m_parentPlugin->GetGraphWidget(); + const NodeGraph* activeGraph = graphWidget->GetActiveGraph(); + if (!activeGraph) + { + return; + } + const QPoint pastePosition = graphWidget->underMouse() + ? graphWidget->SnapLocalToGrid(graphWidget->LocalToGlobal(graphWidget->mapFromGlobal(QCursor::pos()))) + : graphWidget->SnapLocalToGrid(graphWidget->LocalToGlobal(graphWidget->rect().center())); + m_parentPlugin->GetActionManager().Paste(activeGraph->GetModelIndex(), pastePosition); + }); + + m_actions[EDIT_DELETE] = new QAction( + FromStdString(AnimGraphPlugin::s_deleteSelectedNodesShortcutName), + this + ); + m_actions[EDIT_DELETE]->setShortcut(Qt::Key_Delete); + shortcutManager->RegisterKeyboardShortcut(m_actions[EDIT_DELETE], AnimGraphPlugin::s_animGraphWindowShortcutGroupName, true); + connect(m_actions[EDIT_DELETE], &QAction::triggered, this, [this] + { + m_parentPlugin->GetGraphWidget()->DeleteSelectedItems(); + }); + + for (QAction* action : m_actions) + { + addAction(action); } - EMotionFX::ActorEditorRequestBus::Handler::BusConnect(); + GetMainWindow()->LoadKeyboardShortcuts(); } QToolBar* BlendGraphViewWidget::CreateTopToolBar() { QToolBar* toolBar = new QToolBar(this); toolBar->setObjectName("EMFX.BlendGraphViewWidget.TopToolBar"); - // Create new anim graph - { - QAction* action = toolBar->addAction(QIcon(":/EMotionFX/Plus.svg"), - tr("Create a new anim graph"), - this, &BlendGraphViewWidget::OnCreateAnimGraph); - action->setObjectName("EMFX.BlendGraphViewWidget.NewButton"); - - //action->setShortcut(QKeySequence::New); - m_actions[FILE_NEW] = action; - } + + toolBar->addAction(m_actions[FILE_NEW]); // Open anim graph { - QAction* action = toolBar->addAction( - QIcon(":/EMotionFX/Open.svg"), - tr("Open anim graph asset")); - m_actions[FILE_OPEN] = action; - - QToolButton* toolButton = qobject_cast(toolBar->widgetForAction(action)); - AZ_Assert(toolButton, "The action widget must be a tool button."); - toolButton->setPopupMode(QToolButton::InstantPopup); - - m_openMenu = new QMenu(toolBar); - action->setMenu(m_openMenu); - BuildOpenMenu(); + m_openMenu = new QMenu(this); connect(m_openMenu, &QMenu::aboutToShow, this, &BlendGraphViewWidget::BuildOpenMenu); + + QAction* action = new QAction( + QIcon(":/EMotionFX/Open.svg"), + tr("Open")); + action->setMenu(m_openMenu); + + QToolButton* button = new QToolButton(); + button->setDefaultAction(action); + button->setPopupMode(QToolButton::InstantPopup); + + toolBar->addWidget(button); } + // Save anim graph { - QAction* saveMenuAction = toolBar->addAction( + QMenu* contextMenu = new QMenu(toolBar); + contextMenu->addAction(m_actions[FILE_SAVE]); + contextMenu->addAction(m_actions[FILE_SAVEAS]); + + QAction* saveMenuAction = new QAction( QIcon(":/EMotionFX/Save.svg"), tr("Save anim graph")); - - QToolButton* toolButton = qobject_cast(toolBar->widgetForAction(saveMenuAction)); - AZ_Assert(toolButton, "The action widget must be a tool button."); - toolButton->setPopupMode(QToolButton::InstantPopup); - - QMenu* contextMenu = new QMenu(toolBar); - - m_actions[FILE_SAVE] = contextMenu->addAction(tr("Save"), m_parentPlugin, &AnimGraphPlugin::OnFileSave); - m_actions[FILE_SAVEAS] = contextMenu->addAction(tr("Save as..."), m_parentPlugin, &AnimGraphPlugin::OnFileSaveAs); - saveMenuAction->setMenu(contextMenu); + + QToolButton* button = new QToolButton(); + button->setDefaultAction(saveMenuAction); + button->setPopupMode(QToolButton::InstantPopup); + + toolBar->addWidget(button); } toolBar->addSeparator(); - m_actions[ACTIVATE_ANIMGRAPH] = toolBar->addAction(QIcon(":/EMotionFX/PlayForward.svg"), - tr("Activate Animgraph/State"), - &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::ActivateAnimGraph); + toolBar->addAction(m_actions[ACTIVATE_ANIMGRAPH]); + toolBar->addSeparator(); - m_actions[SELECTION_ZOOMSELECTION] = toolBar->addAction(QIcon(":/EMotionFX/ZoomSelected.svg"), - tr("Zoom Selection"), - this, &BlendGraphViewWidget::ZoomSelected); + toolBar->addAction(m_actions[NAVIGATION_ZOOMSELECTION]); // Visualization options { @@ -121,15 +346,10 @@ namespace EMStudio QMenu* contextMenu = new QMenu(toolBar); - m_actions[VISUALIZATION_PLAYSPEEDS] = contextMenu->addAction(tr("Display Play Speeds"), this, &BlendGraphViewWidget::OnDisplayPlaySpeeds); - m_actions[VISUALIZATION_GLOBALWEIGHTS] = contextMenu->addAction(tr("Display Global Weights"), this, &BlendGraphViewWidget::OnDisplayGlobalWeights); - m_actions[VISUALIZATION_SYNCSTATUS] = contextMenu->addAction(tr("Display Sync Status"), this, &BlendGraphViewWidget::OnDisplaySyncStatus); - m_actions[VISUALIZATION_PLAYPOSITIONS] = contextMenu->addAction(tr("Display Play Positions"), this, &BlendGraphViewWidget::OnDisplayPlayPositions); - - m_actions[VISUALIZATION_PLAYSPEEDS]->setCheckable(true); - m_actions[VISUALIZATION_GLOBALWEIGHTS]->setCheckable(true); - m_actions[VISUALIZATION_SYNCSTATUS]->setCheckable(true); - m_actions[VISUALIZATION_PLAYPOSITIONS]->setCheckable(true); + contextMenu->addAction(m_actions[VISUALIZATION_PLAYSPEEDS]); + contextMenu->addAction(m_actions[VISUALIZATION_GLOBALWEIGHTS]); + contextMenu->addAction(m_actions[VISUALIZATION_SYNCSTATUS]); + contextMenu->addAction(m_actions[VISUALIZATION_PLAYPOSITIONS]); menuAction->setMenu(contextMenu); } @@ -137,21 +357,10 @@ namespace EMStudio toolBar->addSeparator(); // Alignment Options - m_actions[SELECTION_ALIGNLEFT] = toolBar->addAction(QIcon(":/EMotionFX/AlignLeft.svg"), - tr("Align left"), - &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignLeft); - - m_actions[SELECTION_ALIGNRIGHT] = toolBar->addAction(QIcon(":/EMotionFX/AlignRight.svg"), - tr("Align right"), - &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignRight); - - m_actions[SELECTION_ALIGNTOP] = toolBar->addAction(QIcon(":/EMotionFX/AlignTop.svg"), - tr("Align top"), - &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignTop); - - m_actions[SELECTION_ALIGNBOTTOM] = toolBar->addAction(QIcon(":/EMotionFX/AlignBottom.svg"), - tr("Align bottom"), - &m_parentPlugin->GetActionManager(), &AnimGraphActionManager::AlignBottom); + toolBar->addAction(m_actions[SELECTION_ALIGNLEFT]); + toolBar->addAction(m_actions[SELECTION_ALIGNRIGHT]); + toolBar->addAction(m_actions[SELECTION_ALIGNTOP]); + toolBar->addAction(m_actions[SELECTION_ALIGNBOTTOM]); return toolBar; } @@ -160,27 +369,15 @@ namespace EMStudio { QToolBar* toolBar = new QToolBar(this); - m_actions[NAVIGATION_BACK] = toolBar->addAction(QIcon(":/EMotionFX/Backward.svg"), - tr("Back"), - this, [=] { - m_parentPlugin->GetNavigationHistory()->StepBackward(); - UpdateNavigation(); - }); + toolBar->addAction(m_actions[NAVIGATION_BACK]); - m_actions[NAVIGATION_FORWARD] = toolBar->addAction(QIcon(":/EMotionFX/Forward.svg"), - tr("Forward"), - this, [=] { - m_parentPlugin->GetNavigationHistory()->StepForward(); - UpdateNavigation(); - }); + toolBar->addAction(m_actions[NAVIGATION_FORWARD]); mNavigationLink = new NavigationLinkWidget(m_parentPlugin, this); mNavigationLink->setMinimumHeight(28); toolBar->addWidget(mNavigationLink); - m_actions[NAVIGATION_NAVPANETOGGLE] = toolBar->addAction(QIcon(":/EMotionFX/List.svg"), - tr("Show/hide navigation pane"), - this, &BlendGraphViewWidget::ToggleNavigationPane); + toolBar->addAction(m_actions[NAVIGATION_NAVPANETOGGLE]); return toolBar; } @@ -188,8 +385,11 @@ namespace EMStudio void BlendGraphViewWidget::Init(BlendGraphWidget* blendGraphWidget) { connect(&m_parentPlugin->GetAnimGraphModel(), &AnimGraphModel::FocusChanged, this, &BlendGraphViewWidget::OnFocusChanged); - connect(&m_parentPlugin->GetAnimGraphModel().GetSelectionModel(), &QItemSelectionModel::selectionChanged, this, &BlendGraphViewWidget::UpdateSelection); + connect(&m_parentPlugin->GetAnimGraphModel().GetSelectionModel(), &QItemSelectionModel::selectionChanged, this, &BlendGraphViewWidget::UpdateEnabledActions); connect(m_parentPlugin->GetNavigationHistory(), &NavigationHistory::ChangedSteppingLimits, this, &BlendGraphViewWidget::UpdateNavigation); + connect(m_parentPlugin->GetGraphWidget(), &NodeGraphWidget::ActiveGraphChanged, this, &BlendGraphViewWidget::UpdateEnabledActions); + connect(m_parentPlugin, &AnimGraphPlugin::ActionFilterChanged, this, &BlendGraphViewWidget::UpdateEnabledActions); + connect(&m_parentPlugin->GetActionManager(), &AnimGraphActionManager::PasteStateChanged, this, &BlendGraphViewWidget::UpdateEnabledActions); // create the vertical layout with the menu and the graph widget as entries QVBoxLayout* verticalLayout = new QVBoxLayout(this); @@ -198,6 +398,7 @@ namespace EMStudio verticalLayout->setMargin(2); // Create toolbars + CreateActions(); verticalLayout->addWidget(CreateTopToolBar()); verticalLayout->addWidget(CreateNavigationToolBar()); @@ -217,7 +418,7 @@ namespace EMStudio UpdateNavigation(); UpdateAnimGraphOptions(); - UpdateSelection(); + UpdateEnabledActions(); } BlendGraphViewWidget::~BlendGraphViewWidget() @@ -252,47 +453,35 @@ namespace EMStudio } } - void BlendGraphViewWidget::UpdateSelection() + void BlendGraphViewWidget::UpdateEnabledActions() { // do we have any selection? const bool anySelection = m_parentPlugin->GetAnimGraphModel().GetSelectionModel().hasSelection(); - SetOptionEnabled(SELECTION_ZOOMSELECTION, anySelection); + SetOptionEnabled(NAVIGATION_ZOOMSELECTION, anySelection); - QModelIndex firstSelectedNode; - bool atLeastTwoNodes = false; + const auto isNodeSelected = [](const QModelIndex& index) + { + return index.isValid() + && index.data(AnimGraphModel::ROLE_MODEL_ITEM_TYPE).value() == AnimGraphModel::ModelItemType::NODE; + }; const QModelIndexList selectedIndexes = m_parentPlugin->GetAnimGraphModel().GetSelectionModel().selectedRows(); - for (const QModelIndex& selected : selectedIndexes) - { - const AnimGraphModel::ModelItemType itemType = selected.data(AnimGraphModel::ROLE_MODEL_ITEM_TYPE).value(); - if (itemType == AnimGraphModel::ModelItemType::NODE) - { - if (firstSelectedNode.isValid()) - { - atLeastTwoNodes = true; - break; - } - else - { - firstSelectedNode = selected; - } - } - } + const auto firstSelectedNode = AZStd::find_if(selectedIndexes.begin(), selectedIndexes.end(), isNodeSelected); + const auto secondSelectedNode = AZStd::find_if(firstSelectedNode, selectedIndexes.end(), isNodeSelected); + const bool atLeastTwoNodes = secondSelectedNode != selectedIndexes.end(); - if (m_parentPlugin->GetActionFilter().m_editNodes && - atLeastTwoNodes) - { - SetOptionEnabled(SELECTION_ALIGNLEFT, true); - SetOptionEnabled(SELECTION_ALIGNRIGHT, true); - SetOptionEnabled(SELECTION_ALIGNTOP, true); - SetOptionEnabled(SELECTION_ALIGNBOTTOM, true); - } - else - { - SetOptionEnabled(SELECTION_ALIGNLEFT, false); - SetOptionEnabled(SELECTION_ALIGNRIGHT, false); - SetOptionEnabled(SELECTION_ALIGNTOP, false); - SetOptionEnabled(SELECTION_ALIGNBOTTOM, false); - } + const bool enableAlignActions = m_parentPlugin->GetActionFilter().m_editNodes && atLeastTwoNodes; + SetOptionEnabled(SELECTION_ALIGNLEFT, enableAlignActions); + SetOptionEnabled(SELECTION_ALIGNRIGHT, enableAlignActions); + SetOptionEnabled(SELECTION_ALIGNTOP, enableAlignActions); + SetOptionEnabled(SELECTION_ALIGNBOTTOM, enableAlignActions); + + const bool isEditable = m_parentPlugin->GetGraphWidget()->GetActiveGraph() && !m_parentPlugin->GetGraphWidget()->GetActiveGraph()->IsInReferencedGraph(); + const AnimGraphActionFilter& actionFilter = m_parentPlugin->GetActionFilter(); + + SetOptionEnabled(EDIT_CUT, actionFilter.m_copyAndPaste && anySelection && isEditable); + SetOptionEnabled(EDIT_COPY, actionFilter.m_copyAndPaste && anySelection); + SetOptionEnabled(EDIT_PASTE, actionFilter.m_copyAndPaste && isEditable && m_parentPlugin->GetActionManager().GetIsReadyForPaste()); + SetOptionEnabled(EDIT_DELETE, actionFilter.m_copyAndPaste && anySelection && isEditable); } AnimGraphNodeWidget* BlendGraphViewWidget::GetWidgetForNode(const EMotionFX::AnimGraphNode* node) @@ -375,19 +564,17 @@ namespace EMStudio void BlendGraphViewWidget::SetOptionFlag(EOptionFlag option, bool isEnabled) { - const uint32 optionIndex = (uint32)option; - if (m_actions[optionIndex]) + if (m_actions[option]) { - m_actions[optionIndex]->setChecked(isEnabled); + m_actions[option]->setChecked(isEnabled); } } void BlendGraphViewWidget::SetOptionEnabled(EOptionFlag option, bool isEnabled) { - const uint32 optionIndex = (uint32)option; - if (m_actions[optionIndex]) + if (m_actions[option]) { - m_actions[optionIndex]->setEnabled(isEnabled); + m_actions[option]->setEnabled(isEnabled); } } @@ -395,8 +582,7 @@ namespace EMStudio { m_openMenu->clear(); - m_actions[FILE_OPEN] = m_openMenu->addAction(tr("Open...")); - connect(m_actions[FILE_OPEN], &QAction::triggered, m_parentPlugin, &AnimGraphPlugin::OnFileOpen); + m_openMenu->addAction(m_actions[FILE_OPEN]); const uint32 numAnimGraphs = EMotionFX::GetAnimGraphManager().GetNumAnimGraphs(); if (numAnimGraphs > 0) @@ -521,6 +707,19 @@ namespace EMStudio } } + void BlendGraphViewWidget::ZoomToAll() + { + BlendGraphWidget* blendGraphWidget = m_parentPlugin->GetGraphWidget(); + if (blendGraphWidget) + { + NodeGraph* nodeGraph = blendGraphWidget->GetActiveGraph(); + if (nodeGraph) + { + nodeGraph->FitGraphOnScreen(geometry().width(), geometry().height(), blendGraphWidget->GetMousePos()); + } + } + } + void BlendGraphViewWidget::OnActivateState() { // Transition to the selected state. @@ -546,7 +745,6 @@ namespace EMStudio } } - void BlendGraphViewWidget::NavigateToRoot() { const QModelIndex nodeModelIndex = m_parentPlugin->GetGraphWidget()->GetActiveGraph()->GetModelIndex(); @@ -556,20 +754,6 @@ namespace EMStudio } } - - void BlendGraphViewWidget::NavigateToParent() - { - const QModelIndex parentFocus = m_parentPlugin->GetAnimGraphModel().GetParentFocus(); - if (parentFocus.isValid()) - { - QModelIndex newParentFocus = parentFocus.model()->parent(parentFocus); - if (newParentFocus.isValid()) - { - m_parentPlugin->GetAnimGraphModel().Focus(newParentFocus); - } - } - } - void BlendGraphViewWidget::ToggleNavigationPane() { QList sizes = m_viewportSplitter->sizes(); @@ -588,16 +772,6 @@ namespace EMStudio m_viewportSplitter->setSizes(sizes); } - void BlendGraphViewWidget::NavigateToNode() - { - const QModelIndexList currentModelIndexes = m_parentPlugin->GetAnimGraphModel().GetSelectionModel().selectedRows(); - if (!currentModelIndexes.empty()) - { - const QModelIndex currentModelIndex = currentModelIndexes.front(); - m_parentPlugin->GetAnimGraphModel().Focus(currentModelIndex); - } - } - // toggle playspeed viz void BlendGraphViewWidget::OnDisplayPlaySpeeds() { @@ -638,36 +812,4 @@ namespace EMStudio EMotionFX::AnimGraphEditorNotificationBus::Broadcast(&EMotionFX::AnimGraphEditorNotificationBus::Events::OnShow); } - void BlendGraphViewWidget::keyPressEvent(QKeyEvent* event) - { - switch (event->key()) - { - case Qt::Key_Backspace: - { - m_parentPlugin->GetNavigationHistory()->StepBackward(); - event->accept(); - break; - } - - default: - event->ignore(); - } - } - - - // on key release - void BlendGraphViewWidget::keyReleaseEvent(QKeyEvent* event) - { - switch (event->key()) - { - case Qt::Key_Backspace: - { - event->accept(); - break; - } - - default: - event->ignore(); - } - } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h index dbc200856a..196fadb115 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphViewWidget.h @@ -53,25 +53,32 @@ namespace EMStudio public: enum EOptionFlag { - SELECTION_ALIGNLEFT = 0, - SELECTION_ALIGNRIGHT = 1, - SELECTION_ALIGNTOP = 2, - SELECTION_ALIGNBOTTOM = 3, - FILE_NEW = 4, - FILE_OPENFILE = 5, - FILE_OPEN = 6, - FILE_SAVE = 7, - FILE_SAVEAS = 8, - NAVIGATION_FORWARD = 9, - NAVIGATION_BACK = 10, - NAVIGATION_NAVPANETOGGLE = 11, - SELECTION_ZOOMSELECTION = 12, - ACTIVATE_ANIMGRAPH = 13, - WINDOWS_NODEGROUPWINDOW = 14, - VISUALIZATION_PLAYSPEEDS = 15, - VISUALIZATION_GLOBALWEIGHTS = 16, - VISUALIZATION_SYNCSTATUS = 17, - VISUALIZATION_PLAYPOSITIONS = 18, + SELECTION_ALIGNLEFT, + SELECTION_ALIGNRIGHT, + SELECTION_ALIGNTOP, + SELECTION_ALIGNBOTTOM, + SELECTION_SELECTALL, + SELECTION_UNSELECTALL, + FILE_NEW, + FILE_OPEN, + FILE_SAVE, + FILE_SAVEAS, + NAVIGATION_FORWARD, + NAVIGATION_BACK, + NAVIGATION_NAVPANETOGGLE, + NAVIGATION_OPEN_SELECTED, + NAVIGATION_TO_PARENT, + NAVIGATION_FRAME_ALL, + NAVIGATION_ZOOMSELECTION, + ACTIVATE_ANIMGRAPH, + VISUALIZATION_PLAYSPEEDS, + VISUALIZATION_GLOBALWEIGHTS, + VISUALIZATION_SYNCSTATUS, + VISUALIZATION_PLAYPOSITIONS, + EDIT_CUT, + EDIT_COPY, + EDIT_PASTE, + EDIT_DELETE, NUM_OPTIONS //automatically gets the next number assigned }; @@ -85,13 +92,12 @@ namespace EMStudio void Init(BlendGraphWidget* blendGraphWidget); void UpdateAnimGraphOptions(); - void UpdateSelection(); + void UpdateEnabledActions(); // If there is a specific widget to handle this node returns that. // Else, returns nullptr. AnimGraphNodeWidget* GetWidgetForNode(const EMotionFX::AnimGraphNode* node); - // Get Actions (used for testing purposes) QAction* GetAction(EOptionFlag option) const { return m_actions[option]; } public slots: @@ -100,11 +106,10 @@ namespace EMStudio void OnCreateAnimGraph(); void NavigateToRoot(); - void NavigateToNode(); - void NavigateToParent(); void ToggleNavigationPane(); void ZoomSelected(); + void ZoomToAll(); void OnActivateState(); @@ -122,17 +127,15 @@ namespace EMStudio void showEvent(QShowEvent* showEvent); - void keyReleaseEvent(QKeyEvent* event) override; - void keyPressEvent(QKeyEvent* event) override; - private: + void CreateActions(); QToolBar* CreateTopToolBar(); QToolBar* CreateNavigationToolBar(); QMenuBar* m_menu = nullptr; QMenu* m_openMenu = nullptr; QHBoxLayout* m_toolbarLayout = nullptr; - QAction* m_actions[NUM_OPTIONS]; + AZStd::array m_actions{}; AnimGraphPlugin* m_parentPlugin = nullptr; NavigationLinkWidget* mNavigationLink = nullptr; QStackedWidget m_viewportStack; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp index 7cd5a2d849..623f9f94a9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.cpp @@ -71,12 +71,6 @@ namespace EMStudio } - // destructor - BlendGraphWidget::~BlendGraphWidget() - { - } - - // when dropping stuff in our window void BlendGraphWidget::dropEvent(QDropEvent* event) { @@ -1555,254 +1549,6 @@ namespace EMStudio } - // on keypress - void BlendGraphWidget::keyPressEvent(QKeyEvent* event) - { - MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - const AnimGraphActionFilter& actionFilter = mPlugin->GetActionFilter(); - - if (shortcutManager->Check(event, "Open Parent Node", "Anim Graph Window")) - { - const QModelIndex parentFocus = mPlugin->GetAnimGraphModel().GetParentFocus(); - if (parentFocus.isValid()) - { - QModelIndex newParentFocus = parentFocus.model()->parent(parentFocus); - if (newParentFocus.isValid()) - { - mPlugin->GetAnimGraphModel().Focus(newParentFocus); - } - } - event->accept(); - return; - } - - if (shortcutManager->Check(event, "Open Selected Node", "Anim Graph Window")) - { - mPlugin->GetActionManager().NavigateToNode(); - event->accept(); - return; - } - - if (shortcutManager->Check(event, "History Back", "Anim Graph Window")) - { - mPlugin->GetNavigationHistory()->StepBackward(); - event->accept(); - return; - } - - if (shortcutManager->Check(event, "History Forward", "Anim Graph Window")) - { - mPlugin->GetNavigationHistory()->StepForward(); - event->accept(); - return; - } - - if (mActiveGraph && - !mActiveGraph->IsInReferencedGraph()) - { - if (actionFilter.m_editNodes) - { - if (shortcutManager->Check(event, "Align Left", "Anim Graph Window")) - { - mPlugin->GetActionManager().AlignLeft(); - event->accept(); - return; - } - - if (shortcutManager->Check(event, "Align Right", "Anim Graph Window")) - { - mPlugin->GetActionManager().AlignRight(); - event->accept(); - return; - } - - if (shortcutManager->Check(event, "Align Top", "Anim Graph Window")) - { - mPlugin->GetActionManager().AlignTop(); - event->accept(); - return; - } - - if (shortcutManager->Check(event, "Align Bottom", "Anim Graph Window")) - { - mPlugin->GetActionManager().AlignBottom(); - event->accept(); - return; - } - } - - if (actionFilter.m_copyAndPaste && - shortcutManager->Check(event, "Cut", "Anim Graph Window")) - { - mPlugin->GetActionManager().Cut(); - event->accept(); - return; - } - } - - if (actionFilter.m_copyAndPaste) - { - if (shortcutManager->Check(event, "Copy", "Anim Graph Window")) - { - mPlugin->GetActionManager().Copy(); - event->accept(); - return; - } - - if (shortcutManager->Check(event, "Paste", "Anim Graph Window")) - { - if (mActiveGraph && !mActiveGraph->IsInReferencedGraph()) - { - if (mPlugin->GetActionManager().GetIsReadyForPaste()) - { - QModelIndex modelIndex = GetActiveGraph()->GetModelIndex(); - if (modelIndex.isValid()) - { - if (rect().contains(mapFromGlobal(QCursor::pos())) == false) - { - mPlugin->GetActionManager().Paste(modelIndex, GetMousePos()); - event->accept(); - } - } - } - } - return; - } - } - - if (shortcutManager->Check(event, "Select All", "Anim Graph Window")) - { - if (mActiveGraph) - { - mActiveGraph->SelectAllNodes(); - event->accept(); - } - return; - } - - if (shortcutManager->Check(event, "Unselect All", "Anim Graph Window")) - { - if (mActiveGraph) - { - mActiveGraph->UnselectAllNodes(); - event->accept(); - } - return; - } - - if (mActiveGraph && - actionFilter.m_delete && - !mActiveGraph->IsInReferencedGraph() && - shortcutManager->Check(event, "Delete Selected Nodes", "Anim Graph Window")) - { - DeleteSelectedItems(); - event->accept(); - return; - } - - return NodeGraphWidget::keyPressEvent(event); - } - - - // on key release - void BlendGraphWidget::keyReleaseEvent(QKeyEvent* event) - { - MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - const AnimGraphActionFilter& actionFilter = mPlugin->GetActionFilter(); - - if (shortcutManager->Check(event, "Open Parent Node", "Anim Graph Window")) - { - event->accept(); - return; - } - if (shortcutManager->Check(event, "Open Selected Node", "Anim Graph Window")) - { - event->accept(); - return; - } - if (shortcutManager->Check(event, "History Back", "Anim Graph Window")) - { - event->accept(); - return; - } - if (shortcutManager->Check(event, "History Forward", "Anim Graph Window")) - { - event->accept(); - return; - } - - if (mActiveGraph && !mActiveGraph->IsInReferencedGraph()) - { - if (actionFilter.m_editNodes) - { - if (shortcutManager->Check(event, "Align Left", "Anim Graph Window")) - { - event->accept(); - return; - } - if (shortcutManager->Check(event, "Align Right", "Anim Graph Window")) - { - event->accept(); - return; - } - if (shortcutManager->Check(event, "Align Top", "Anim Graph Window")) - { - event->accept(); - return; - } - if (shortcutManager->Check(event, "Align Bottom", "Anim Graph Window")) - { - event->accept(); - return; - } - } - - if (actionFilter.m_copyAndPaste && - shortcutManager->Check(event, "Cut", "Anim Graph Window")) - { - event->accept(); - return; - } - } - - if (actionFilter.m_copyAndPaste) - { - if (shortcutManager->Check(event, "Copy", "Anim Graph Window")) - { - event->accept(); - return; - } - if (mActiveGraph && !mActiveGraph->IsInReferencedGraph() && shortcutManager->Check(event, "Paste", "Anim Graph Window")) - { - event->accept(); - return; - } - } - - if (shortcutManager->Check(event, "Select All", "Anim Graph Window")) - { - event->accept(); - return; - } - if (shortcutManager->Check(event, "Unselect All", "Anim Graph Window")) - { - event->accept(); - return; - } - - if (mActiveGraph && - actionFilter.m_delete && - !mActiveGraph->IsInReferencedGraph() && - shortcutManager->Check(event, "Delete Selected Nodes", "Anim Graph Window")) - { - event->accept(); - return; - } - - return NodeGraphWidget::keyReleaseEvent(event); - } - - void BlendGraphWidget::OnRowsInserted(const QModelIndex& parent, int first, int last) { // Here we could be receiving connections, transitions or nodes being inserted into diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h index f5c5d4a5ea..7453e4cc53 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/BlendGraphWidget.h @@ -45,7 +45,6 @@ namespace EMStudio public: BlendGraphWidget(AnimGraphPlugin* plugin, QWidget* parent); - ~BlendGraphWidget(); // overloaded bool CheckIfIsCreateConnectionValid(uint32 portNr, GraphNode* portNode, NodePort* port, bool isInputPort) override; @@ -120,8 +119,6 @@ namespace EMStudio void OnSelectionModelChanged(const QItemSelection& selected, const QItemSelection& deselected); private: - void keyReleaseEvent(QKeyEvent* event) override; - void keyPressEvent(QKeyEvent* event) override; EMotionFX::AnimGraphStateTransition* FindTransitionForConnection(NodeConnection* connection) const; EMotionFX::BlendTreeConnection* FindBlendTreeConnection(NodeConnection* connection) const; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp index 8866ec678e..80603c37bf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/ContextMenu.cpp @@ -183,17 +183,11 @@ namespace EMStudio if (graphNode == nullptr) { QMenu* menu = new QMenu(parentWidget); - if (actionFilter.m_copyAndPaste && actionManager.GetIsReadyForPaste()) - { - const QModelIndex modelIndex = nodeGraph->GetModelIndex(); - if (modelIndex.isValid()) - { - localMousePos = SnapLocalToGrid(LocalToGlobal(localMousePos)); - QAction* pasteAction = menu->addAction("Paste"); - connect(pasteAction, &QAction::triggered, [&actionManager, modelIndex, localMousePos]() { actionManager.Paste(modelIndex, localMousePos); }); - menu->addSeparator(); - } + if (actionFilter.m_copyAndPaste && actionManager.GetIsReadyForPaste() && nodeGraph->GetModelIndex().isValid()) + { + menu->addAction(viewWidget->GetAction(BlendGraphViewWidget::EDIT_PASTE)); + menu->addSeparator(); } if (actionFilter.m_createNodes) @@ -324,8 +318,7 @@ namespace EMStudio // we can only go to the selected node in case the selected node has a visual graph (state machine / blend tree) if (animGraphNode->GetHasVisualGraph()) { - QAction* goToNodeAction = menu->addAction("Open Selected Node"); - connect(goToNodeAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::NavigateToNode); + menu->addAction(viewWidget->GetAction(BlendGraphViewWidget::NAVIGATION_OPEN_SELECTED)); menu->addSeparator(); } @@ -360,20 +353,17 @@ namespace EMStudio if (!inReferenceGraph) { // cut and copy actions - QAction* cutAction = menu->addAction("Cut"); - connect(cutAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::Cut); + menu->addAction(viewWidget->GetAction(BlendGraphViewWidget::EDIT_CUT)); } - QAction* ccopyAction = menu->addAction("Copy"); - connect(ccopyAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::Copy); + menu->addAction(viewWidget->GetAction(BlendGraphViewWidget::EDIT_COPY)); menu->addSeparator(); } if (actionFilter.m_delete && !inReferenceGraph) { - QAction* removeNodeAction = menu->addAction("Delete Node"); - connect(removeNodeAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::DeleteSelectedNodes); + menu->addAction(viewWidget->GetAction(BlendGraphViewWidget::EDIT_DELETE)); menu->addSeparator(); } } @@ -403,22 +393,14 @@ namespace EMStudio if (actionFilter.m_editNodes && !inReferenceGraph) { - QAction* alignLeftAction = menu.addAction("Align Left"); - QAction* alignRightAction = menu.addAction("Align Right"); - QAction* alignTopAction = menu.addAction("Align Top"); - QAction* alignBottomAction = menu.addAction("Align Bottom"); - - - connect(alignLeftAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::AlignLeft); - connect(alignRightAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::AlignRight); - connect(alignTopAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::AlignTop); - connect(alignBottomAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::AlignBottom); - + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::SELECTION_ALIGNLEFT)); + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::SELECTION_ALIGNRIGHT)); + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::SELECTION_ALIGNTOP)); + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::SELECTION_ALIGNBOTTOM)); menu.addSeparator(); } - QAction* zoomSelectionAction = menu.addAction("Zoom Selection"); - connect(zoomSelectionAction, &QAction::triggered, viewWidget, &BlendGraphViewWidget::ZoomSelected); + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::NAVIGATION_ZOOMSELECTION)); menu.addSeparator(); @@ -494,12 +476,10 @@ namespace EMStudio if (!inReferenceGraph) { - QAction* cutAction = menu.addAction("Cut"); - connect(cutAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::Cut); + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::EDIT_CUT)); } - QAction* ccopyAction = menu.addAction("Copy"); - connect(ccopyAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::Copy); + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::EDIT_COPY)); } menu.addSeparator(); @@ -507,8 +487,7 @@ namespace EMStudio if (actionFilter.m_delete && !inReferenceGraph) { - QAction* removeNodesAction = menu.addAction("Delete Nodes"); - connect(removeNodesAction, &QAction::triggered, &actionManager, &AnimGraphActionManager::DeleteSelectedNodes); + menu.addAction(viewWidget->GetAction(BlendGraphViewWidget::EDIT_DELETE)); menu.addSeparator(); } @@ -526,4 +505,4 @@ namespace EMStudio } } } -} +} // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp index eae890c69d..f102cc5d96 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -155,6 +154,11 @@ namespace EMStudio // set the active graph void NodeGraphWidget::SetActiveGraph(NodeGraph* graph) { + if (mActiveGraph == graph) + { + return; + } + if (mActiveGraph) { mActiveGraph->StopCreateConnection(); @@ -165,6 +169,8 @@ namespace EMStudio mActiveGraph = graph; mMoveNode = nullptr; + + emit ActiveGraphChanged(); } @@ -322,7 +328,7 @@ namespace EMStudio // convert to a global position - QPoint NodeGraphWidget::LocalToGlobal(const QPoint& inPoint) + QPoint NodeGraphWidget::LocalToGlobal(const QPoint& inPoint) const { if (mActiveGraph) { @@ -334,7 +340,7 @@ namespace EMStudio // convert to a local position - QPoint NodeGraphWidget::GlobalToLocal(const QPoint& inPoint) + QPoint NodeGraphWidget::GlobalToLocal(const QPoint& inPoint) const { if (mActiveGraph) { @@ -345,7 +351,7 @@ namespace EMStudio } - QPoint NodeGraphWidget::SnapLocalToGrid(const QPoint& inPoint, uint32 cellSize) + QPoint NodeGraphWidget::SnapLocalToGrid(const QPoint& inPoint, uint32 cellSize) const { MCORE_UNUSED(cellSize); @@ -1491,45 +1497,9 @@ namespace EMStudio } } - MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - - if (shortcutManager->Check(event, "Fit Entire Graph", "Anim Graph Window")) - { - // zoom to fit the entire graph in view - if (mActiveGraph) - { - mActiveGraph->FitGraphOnScreen(geometry().width(), geometry().height(), GetMousePos()); - } - - event->accept(); - return; - } - - if (shortcutManager->Check(event, "Zoom On Selected Nodes", "Anim Graph Window")) - { - if (mActiveGraph) - { - // try zooming on the selection rect - QRect selectionRect = mActiveGraph->CalcRectFromSelection(true); - if (selectionRect.isEmpty() == false) - { - mActiveGraph->ZoomOnRect(selectionRect, geometry().width(), geometry().height()); - //update(); - } - else // zoom on the full scene - { - mActiveGraph->FitGraphOnScreen(geometry().width(), geometry().height(), GetMousePos()); - } - } - - event->accept(); - return; - } - event->ignore(); } - // on key release void NodeGraphWidget::keyReleaseEvent(QKeyEvent* event) { @@ -1552,20 +1522,6 @@ namespace EMStudio } } - MysticQt::KeyboardShortcutManager* shortcutManager = GetMainWindow()->GetShortcutManager(); - - if (shortcutManager->Check(event, "Fit Entire Graph", "Anim Graph Window")) - { - event->accept(); - return; - } - - if (shortcutManager->Check(event, "Zoom On Selected Nodes", "Anim Graph Window")) - { - event->accept(); - return; - } - event->ignore(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h index 68e9f72209..9b8d8c6ace 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/AnimGraph/NodeGraphWidget.h @@ -65,9 +65,9 @@ namespace EMStudio uint32 CalcNumSelectedNodes() const; - QPoint LocalToGlobal(const QPoint& inPoint); - QPoint GlobalToLocal(const QPoint& inPoint); - QPoint SnapLocalToGrid(const QPoint& inPoint, uint32 cellSize = 10); + QPoint LocalToGlobal(const QPoint& inPoint) const; + QPoint GlobalToLocal(const QPoint& inPoint) const; + QPoint SnapLocalToGrid(const QPoint& inPoint, uint32 cellSize = 10) const; void CalcSelectRect(QRect& outRect); @@ -106,6 +106,9 @@ namespace EMStudio const QString& GetTitleBarText() const { return m_titleBarText; } void SetTitleBarText(const QString& text) { m_titleBarText = text; } + signals: + void ActiveGraphChanged(); + protected: //virtual void paintEvent(QPaintEvent* event); void mouseMoveEvent(QMouseEvent* event) override; @@ -160,4 +163,4 @@ namespace EMStudio float m_borderOverwriteWidth; QString m_titleBarText; }; -} // namespace EMStudio +} // namespace EMStudio diff --git a/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp b/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp index 202feb3d18..0d44330b34 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp +++ b/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.cpp @@ -12,6 +12,8 @@ // include required headers #include "KeyboardShortcutManager.h" +#include +#include #include #include @@ -19,52 +21,27 @@ #include #include - namespace MysticQt { - // find action by name - KeyboardShortcutManager::Action* KeyboardShortcutManager::Group::FindActionByName(const char* actionName, bool local) const + void KeyboardShortcutManager::Group::RemoveAction(QAction* qaction, bool local) { - const uint32 numActions = mActions.GetLength(); - for (uint32 i = 0; i < numActions; ++i) + m_actions.erase(AZStd::find_if(begin(m_actions), end(m_actions), [&qaction, local](const AZStd::unique_ptr& action) { - if (mActions[i]->mLocal == local && mActions[i]->mName == actionName) - { - return mActions[i]; - } - } - - return nullptr; + return action->m_local == local && action->m_qaction == qaction; + })); } - // constructor - KeyboardShortcutManager::KeyboardShortcutManager() + KeyboardShortcutManager::Action* KeyboardShortcutManager::Group::FindActionByName(const QString& actionName, bool local) const { - } - - - // destructor - KeyboardShortcutManager::~KeyboardShortcutManager() - { - Clear(); - } - - - // get rid of all groups including their actions - void KeyboardShortcutManager::Clear() - { - // get rid of the groups - const uint32 numGroups = mGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + const auto found = AZStd::find_if(begin(m_actions), end(m_actions), [&actionName, local](const AZStd::unique_ptr& action) { - delete mGroups[i]; - } + return action->m_local == local && action->m_qaction->text() == actionName; + }); - mGroups.Clear(); + return found != end(m_actions) ? found->get() : nullptr; } - - void KeyboardShortcutManager::RegisterKeyboardShortcut(const char* actionName, const char* groupName, int defaultKey, bool defaultCtrl, bool defaultAlt, bool local) + void KeyboardShortcutManager::RegisterKeyboardShortcut(QAction* qaction, AZStd::string_view groupName, bool local) { // find the group with the given name Group* group = FindGroupByName(groupName); @@ -72,188 +49,112 @@ namespace MysticQt // if there is no group with the given name, create it if (group == nullptr) { - group = new Group(groupName); - mGroups.Add(group); + m_groups.emplace_back(AZStd::make_unique(groupName)); + group = m_groups.back().get(); } // check if the action is already there to avoid adding it twice - Action* action = group->FindActionByName(actionName, local); + Action* action = group->FindActionByName(qaction->text(), local); if (action) { - action->mDefaultKey = defaultKey; - action->mDefaultCtrl = defaultCtrl; - action->mDefaultAlt = defaultAlt; + action->m_defaultKeySequence = qaction->shortcut(); return; } // create the new action and add it to the group - action = new Action(actionName, defaultKey, defaultCtrl, defaultAlt, local); - group->AddAction(action); + group->AddAction(AZStd::make_unique(qaction, local)); + + QAction::connect(qaction, &QAction::destroyed, this, [this, groupName = AZStd::string(groupName), local](QObject* qaction) + { + UnregisterKeyboardShortcut(static_cast(qaction), groupName, local); + }); + } + + void KeyboardShortcutManager::UnregisterKeyboardShortcut(QAction* qaction, AZStd::string_view groupName, bool local) + { + Group* group = FindGroupByName(groupName); + + if (!group) + { + return; + } + + group->RemoveAction(qaction, local); } // find the action with the given name in the given group - KeyboardShortcutManager::Action* KeyboardShortcutManager::FindAction(const char* actionName, const char* groupName) + KeyboardShortcutManager::Action* KeyboardShortcutManager::FindAction(const QString& actionName, AZStd::string_view groupName) const { - const uint32 numGroups = mGroups.GetLength(); - - // first search global shortcuts - for (uint32 i = 0; i < numGroups; ++i) + const Group* group = FindGroupByName(groupName); + if (!group) { - if (mGroups[i]->GetNameString() == groupName) - { - Action* action = mGroups[i]->FindActionByName(actionName, false); - if (action) - { - return action; - } - } + return nullptr; } - // then local shortcuts - for (uint32 i = 0; i < numGroups; ++i) + Action* action = group->FindActionByName(actionName, false); + if (action) { - if (mGroups[i]->GetNameString() == groupName) - { - Action* action = mGroups[i]->FindActionByName(actionName, true); - if (action) - { - return action; - } - } + return action; } - - // failure, not found - return nullptr; + return group->FindActionByName(actionName, true); } // find a group by name - KeyboardShortcutManager::Group* KeyboardShortcutManager::FindGroupByName(const char* groupName) const + KeyboardShortcutManager::Group* KeyboardShortcutManager::FindGroupByName(AZStd::string_view groupName) const { - // iterate through the groups and find the one with the given name - const uint32 numGroups = mGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + const auto found = AZStd::find_if(begin(m_groups), end(m_groups), [&groupName](const AZStd::unique_ptr& group) { - if (mGroups[i]->GetNameString() == groupName) - { - return mGroups[i]; - } - } - - // failure, a group with the given name hasn't been found - return nullptr; - } - - - bool KeyboardShortcutManager::Check(QKeyEvent* event, const char* actionName, const char* groupName) - { - // find the corresponding action for the given strings - Action* action = FindAction(actionName, groupName); - if (action == nullptr) - { - //MCore::LogError("Action named '%s' in group '%s' not registered. Please register the shortcut before using it.", actionName, groupName); - return false; - } - - const bool ctrlPressed = event->modifiers() & Qt::ControlModifier; - //const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; - const bool altPressed = event->modifiers() & Qt::AltModifier; - - Group* group = FindGroupByName(groupName); - Action* conflictAction = FindShortcut(event->key(), ctrlPressed, altPressed, group); - - // check if they are equal, if yes this means they match - if (action == conflictAction) - { - return true; - } - - // check if the action and the key event are the same shortcut - /*if (event->key() == action->mKey && - ctrlPressed == action->mCtrl && - altPressed == action->mAlt) - return true;*/ - - return false; + return group->GetName() == groupName; + }); + return found != end(m_groups) ? found->get() : nullptr; } // find the correspondng group for the given action - KeyboardShortcutManager::Group* KeyboardShortcutManager::FindGroupForShortcut(Action* action) + KeyboardShortcutManager::Group* KeyboardShortcutManager::FindGroupForShortcut(Action* action) const { - // get the number of available groups - const uint32 numGroups = mGroups.GetLength(); - - // first check the global shortcuts - for (uint32 i = 0; i < numGroups; ++i) + const auto foundGroup = AZStd::find_if(begin(m_groups), end(m_groups), [action](const AZStd::unique_ptr& group) { - Group* group = mGroups[i]; - - // iterate through the actions and save them - const uint32 numActions = group->GetNumActions(); - for (uint32 j = 0; j < numActions; ++j) + const auto foundAction = AZStd::find_if(begin(group->GetActions()), end(group->GetActions()), [action](const AZStd::unique_ptr& actionInGroup) { - if (group->GetAction(j) == action) - { - return group; - } - } - } - - // failure, not found - return nullptr; + return action == actionInGroup.get(); + }); + return foundAction != end(group->GetActions()) ? foundAction->get() : nullptr; + }); + return foundGroup != end(m_groups) ? foundGroup->get() : nullptr; } - KeyboardShortcutManager::Action* KeyboardShortcutManager::FindShortcut(int key, bool ctrl, bool alt, Group* group) + KeyboardShortcutManager::Action* KeyboardShortcutManager::FindShortcut(QKeySequence keySequence, Group* group) const { - // get the number of available groups - const uint32 numGroups = mGroups.GetLength(); + const auto findMatchingAction = [keySequence] (const Group* group, const bool local) + { + return AZStd::find_if(begin(group->GetActions()), end(group->GetActions()), [keySequence, local] (const AZStd::unique_ptr& action) + { + if (action->m_local != local) + { + return false; + } + + return action->m_qaction->shortcut().matches(keySequence) == QKeySequence::ExactMatch; + }); + }; // first check the global shortcuts - for (uint32 i = 0; i < numGroups; ++i) + const auto globalAction = findMatchingAction(group, false); + if (globalAction != end(group->GetActions())) { - Group* currentGroup = mGroups[i]; - - // iterate through the actions and save them - const uint32 numActions = currentGroup->GetNumActions(); - for (uint32 j = 0; j < numActions; ++j) - { - // get the shortcut action - KeyboardShortcutManager::Action* action = currentGroup->GetAction(j); - if (action->mLocal) - { - continue; - } - - // check if the action and shortcut are the same - if (key == action->mKey && - ctrl == action->mCtrl && - alt == action->mAlt) - { - return action; - } - } + return globalAction->get(); } - // iterate through the actions and save them - const uint32 numActions = group->GetNumActions(); - for (uint32 j = 0; j < numActions; ++j) + const auto localAction = findMatchingAction(group, true); + if (localAction != end(group->GetActions())) { - // get the shortcut action - KeyboardShortcutManager::Action* action = group->GetAction(j); - - // check if the action and shortcut are the same - if (key == action->mKey && - ctrl == action->mCtrl && - alt == action->mAlt) - { - return action; - } + return localAction->get(); } - // failure, shortcut not found return nullptr; } @@ -264,24 +165,16 @@ namespace MysticQt settings->clear(); // iterate through the groups and save all actions for them - const uint32 numGroups = mGroups.GetLength(); - for (uint32 i = 0; i < numGroups; ++i) + for (const AZStd::unique_ptr& group : m_groups) { - Group* group = mGroups[i]; - settings->beginGroup(group->GetName()); + settings->beginGroup(QString::fromUtf8(group->GetName().data(), group->GetName().size())); // iterate through the actions and save them - const uint32 numActions = group->GetNumActions(); - for (uint32 j = 0; j < numActions; ++j) + for (const AZStd::unique_ptr& action : group->GetActions()) { - // get the shortcut action - KeyboardShortcutManager::Action* action = group->GetAction(j); - - settings->beginGroup(action->mName.c_str()); - settings->setValue("Key", action->mKey); - settings->setValue("Ctrl", action->mCtrl); - settings->setValue("Alt", action->mAlt); - settings->setValue("Local", action->mLocal); + settings->beginGroup(action->m_qaction->text()); + settings->setValue("Key", action->m_qaction->shortcut()); + settings->setValue("Local", action->m_local); settings->endGroup(); } @@ -292,33 +185,49 @@ namespace MysticQt void KeyboardShortcutManager::Load(QSettings* settings) { - // clear the shortcut manager before loading - Clear(); - // iterate through the groups and load all actions - QStringList groupNames = settings->childGroups(); - const uint32 numGroups = groupNames.count(); - for (uint32 i = 0; i < numGroups; ++i) + const QStringList groupNames = settings->childGroups(); + for (const QString& groupName : groupNames) { - QString groupName = groupNames[i]; - settings->beginGroup(groupNames[i]); - QStringList actionNames = settings->childGroups(); + Group* group = FindGroupByName(FromQtString(groupName)); + if (!group) + { + continue; + } + + settings->beginGroup(groupName); + const QStringList actionNames = settings->childGroups(); // iterate through the actions and save them - const uint32 numActions = actionNames.count(); - for (uint32 j = 0; j < numActions; ++j) + for (const QString& actionName : actionNames) { - QString actionName = actionNames[j]; settings->beginGroup(actionName); - int key = settings->value("Key", "").toInt(); - bool ctrlPressed = settings->value("Ctrl", false).toBool(); - bool altPressed = settings->value("Alt", false).toBool(); - bool local = settings->value("Local", false).toBool(); - RegisterKeyboardShortcut(FromQtString(actionName).c_str(), FromQtString(groupName).c_str(), key, ctrlPressed, altPressed, local); + const bool local = settings->value("Local", false).toBool(); + + Action* action = group->FindActionByName(actionName, local); + if (!action) + { + continue; + } + + const QVariant keyValue = settings->value("Key", ""); + if (keyValue.canConvert()) + { + const QKeySequence key = keyValue.value(); + action->m_qaction->setShortcut(key); + } + else if (keyValue.canConvert()) + { + const int key = keyValue.value(); + const bool ctrlModifier = settings->value("Ctrl", false).value(); + const bool altModifier = settings->value("Alt", false).value(); + action->m_qaction->setShortcut(key | (ctrlModifier ? Qt::ControlModifier : 0) | (altModifier ? Qt::AltModifier : 0)); + } + settings->endGroup(); } settings->endGroup(); } } -} // namespace MysticQt +} // namespace MysticQt diff --git a/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.h b/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.h index 9bd1b58812..ce989767e0 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.h +++ b/Gems/EMotionFX/Code/MysticQt/Source/KeyboardShortcutManager.h @@ -10,12 +10,14 @@ * */ -#ifndef __MYSTICQT_KEYBOARDSHORTCUTMANAGER_H -#define __MYSTICQT_KEYBOARDSHORTCUTMANAGER_H +#pragma once #if !defined(Q_MOC_RUN) +#include +#include +#include #include -#include +#include #include #include "MysticQtConfig.h" #endif @@ -26,86 +28,58 @@ class QSettings; namespace MysticQt { class MYSTICQT_API KeyboardShortcutManager + : public QObject { - MCORE_MEMORYOBJECTCATEGORY(KeyboardShortcutManager, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MYSTICQT); - public: - KeyboardShortcutManager(); - virtual ~KeyboardShortcutManager(); - struct Action { - MCORE_MEMORYOBJECTCATEGORY(KeyboardShortcutManager::Action, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MYSTICQT); + QAction* m_qaction; + QKeySequence m_defaultKeySequence; + bool m_local; - AZStd::string mName; - int mKey; - bool mCtrl; - bool mAlt; - bool mLocal; - - int mDefaultKey; - bool mDefaultCtrl; - bool mDefaultAlt; - - Action(const char* name, int defaultKey, bool defaultCtrl, bool defaultAlt, bool local) + Action(QAction* qaction, bool local) + : m_qaction(qaction) + , m_defaultKeySequence(qaction->shortcut()) + , m_local(local) { - mName = name; - mLocal = local; - - mKey = defaultKey; - mCtrl = defaultCtrl; - mAlt = defaultAlt; - - mDefaultKey = defaultKey; - mDefaultCtrl = defaultCtrl; - mDefaultAlt = defaultAlt; } }; class Group { - MCORE_MEMORYOBJECTCATEGORY(KeyboardShortcutManager::Group, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_MYSTICQT); public: - Group(const char* groupName) { mName = groupName; } - virtual ~Group() + Group(AZStd::string_view groupName) + : m_name(groupName) { - const uint32 numActions = mActions.GetLength(); - for (uint32 i = 0; i < numActions; ++i) - { - delete mActions[i]; - } - mActions.Clear(); } - void AddAction(Action* action) { mActions.Add(action); } - uint32 GetNumActions() const { return mActions.GetLength(); } - Action* GetAction(uint32 index) { return mActions[index]; } - const char* GetName() const { return mName.c_str(); } - const AZStd::string& GetNameString() const { return mName; } - Action* FindActionByName(const char* actionName, bool local) const; + + void AddAction(AZStd::unique_ptr action) { m_actions.emplace_back(AZStd::move(action)); } + void RemoveAction(QAction* action, bool local); + size_t GetNumActions() const { return m_actions.size(); } + Action* GetAction(size_t index) { return m_actions[index].get(); } + const AZStd::vector>& GetActions() const { return m_actions; } + const AZStd::string& GetName() const { return m_name; } + Action* FindActionByName(const QString& actionName, bool local) const; private: - AZStd::string mName; - MCore::Array mActions; + AZStd::string m_name; + AZStd::vector> m_actions; }; - void RegisterKeyboardShortcut(const char* actionName, const char* groupName, int defaultKey, bool defaultCtrl, bool defaultAlt, bool local); - bool Check(QKeyEvent* event, const char* actionName, const char* groupName); - Action* FindShortcut(int key, bool ctrl, bool alt, Group* group); - Action* FindAction(const char* actionName, const char* groupName); - Group* FindGroupForShortcut(Action* action); - uint32 GetNumGroups() const { return mGroups.GetLength(); } - Group* GetGroup(uint32 index) const { return mGroups[index]; } - void Clear(); + void RegisterKeyboardShortcut(QAction* qaction, AZStd::string_view groupName, bool local); + void UnregisterKeyboardShortcut(QAction* qaction, AZStd::string_view groupName, bool local); + Action* FindShortcut(QKeySequence keySequence, Group* group) const; + Action* FindAction(const QString& actionName, AZStd::string_view groupName) const; + Group* FindGroupForShortcut(Action* action) const; + size_t GetNumGroups() const { return m_groups.size(); } + Group* GetGroup(size_t index) const { return m_groups[index].get(); } void Save(QSettings* settings); void Load(QSettings* settings); private: - MCore::Array mGroups; + AZStd::vector> m_groups; - Group* FindGroupByName(const char* groupName) const; + Group* FindGroupByName(AZStd::string_view groupName) const; }; } // namespace MysticQt - - -#endif diff --git a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtConfig.h b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtConfig.h index 54d2fddb54..90df0bf418 100644 --- a/Gems/EMotionFX/Code/MysticQt/Source/MysticQtConfig.h +++ b/Gems/EMotionFX/Code/MysticQt/Source/MysticQtConfig.h @@ -39,14 +39,19 @@ enum // convert from a QString into an AZStd::string MCORE_INLINE AZStd::string FromQtString(const QString& s) { - return s.toUtf8().data(); + return {s.toUtf8().data(), static_cast(s.size())}; } // convert from a QString into an AZStd::string MCORE_INLINE void FromQtString(const QString& s, AZStd::string* result) { - *result = s.toUtf8().data(); + *result = AZStd::string{s.toUtf8().data(), static_cast(s.size())}; +} + +inline QString FromStdString(AZStd::string_view s) +{ + return QString::fromUtf8(s.data(), static_cast(s.size())); } // forward declare a MysticQt class diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp index e3de713b3c..8ef87af9a7 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -414,9 +413,6 @@ namespace EMotionFX CheckAttachToEntity(); - // Send general mesh creation notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event(entityId, &LmbrCentral::MeshComponentNotifications::OnMeshCreated, m_configuration.m_actorAsset); - Physics::RagdollConfiguration ragdollConfiguration; [[maybe_unused]] bool ragdollConfigValid = GetRagdollConfiguration(ragdollConfiguration); AZ_Assert(ragdollConfigValid, "Ragdoll Configuration is not valid"); @@ -460,11 +456,6 @@ namespace EMotionFX m_attachmentTargetActor = nullptr; - // Send general mesh destruction notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event( - GetEntityId(), - &LmbrCentral::MeshComponentNotifications::OnMeshDestroyed); - ActorComponentNotificationBus::Event( GetEntityId(), &ActorComponentNotificationBus::Events::OnActorInstanceDestroyed, diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h index 1a185edccc..416705bff4 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -130,11 +129,7 @@ namespace EMotionFX provided.push_back(AZ_CRC("EMotionFXActorService", 0xd6e8f48d)); provided.push_back(AZ_CRC("MeshService", 0x71d8a455)); provided.push_back(AZ_CRC("CharacterPhysicsDataService", 0x34757927)); - - if (AZ::Interface::Get()) - { - provided.push_back(AZ_CRC("MaterialReceiverService", 0x0d1a6a74)); - } + provided.push_back(AZ_CRC("MaterialReceiverService", 0x0d1a6a74)); } static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp index 6958710b1a..eee9896dee 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/AnimAudioComponent.cpp @@ -22,7 +22,7 @@ #include #include -#include // for SkeletalHierarchyRequestBus +#include #include diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index 3aa281c4c2..d22bb0007f 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -26,8 +26,6 @@ #include #include -#include - #include #include #include @@ -255,11 +253,6 @@ namespace EMotionFX { if (m_actorInstance) { - // Send general mesh destruction notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event( - GetEntityId(), - &LmbrCentral::MeshComponentNotifications::OnMeshDestroyed); - ActorComponentNotificationBus::Event( GetEntityId(), &ActorComponentNotificationBus::Events::OnActorInstanceDestroyed, @@ -650,7 +643,6 @@ namespace EMotionFX } distance = std::numeric_limits::max(); - bool isHit = false; // Get the MCore::Ray used by Mesh::Intersects // Convert the input source position and direction to a line segment by using the frustum depth as line length. @@ -659,12 +651,13 @@ namespace EMotionFX const AZ::Vector3 dest = src + dir * frustumDepth; const MCore::Ray ray(src, dest); - // Update the mesh deformers so the intersection test will hit the actor if it is being - // animated by a motion component that is previewing the animation in the editor + // Update the mesh deformers (apply software skinning and morphing) so the intersection test will hit the actor + // if it is being animated by a motion component that is previewing the animation in the editor. m_actorInstance->UpdateMeshDeformers(0.0f, true); const TransformData* transformData = m_actorInstance->GetTransformData(); const Pose* currentPose = transformData->GetCurrentPose(); + bool isHit = false; // Iterate through the meshes in the actor, looking for the closest hit const AZ::u32 lodLevel = m_actorInstance->GetLODLevel(); @@ -822,7 +815,7 @@ namespace EMotionFX bool EditorActorComponent::IsAtomDisabled() const { - return !AZ::Interface::Get(); + return false; } void EditorActorComponent::OnActorReady(Actor* actor) @@ -848,11 +841,6 @@ namespace EMotionFX if (m_actorInstance) { - // Send general mesh destruction notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event( - GetEntityId(), - &LmbrCentral::MeshComponentNotifications::OnMeshDestroyed); - ActorComponentNotificationBus::Event( GetEntityId(), &ActorComponentNotificationBus::Events::OnActorInstanceDestroyed, @@ -941,9 +929,6 @@ namespace EMotionFX { LmbrCentral::AttachmentComponentRequestBus::Event(attachment, &LmbrCentral::AttachmentComponentRequestBus::Events::Reattach, true); } - - // Send general mesh creation notification to interested parties. - LmbrCentral::MeshComponentNotificationBus::Event(GetEntityId(), &LmbrCentral::MeshComponentNotifications::OnMeshCreated, m_actorAsset); } } //namespace Integration } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanDeleteAnimGraphNode.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanDeleteAnimGraphNode.cpp index a7f9ae228f..c7b2363ad4 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanDeleteAnimGraphNode.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/CanDeleteAnimGraphNode.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -64,8 +65,10 @@ namespace EMotionFX { m_blendGraphWidget->OnContextMenuEvent(m_blendGraphWidget, localPoint, m_blendGraphWidget->LocalToGlobal(localPoint), m_animGraphPlugin, m_blendGraphWidget->GetActiveGraph()->GetSelectedAnimGraphNodes(), true, false, m_animGraphPlugin->GetActionFilter()); // Find Action for deleting node - QAction* deleteAction = GetNamedAction(m_blendGraphWidget, "Delete Node"); - ASSERT_TRUE(deleteAction) << "Could not find the 'Delete Node' action in the context menu"; + QAction* deleteAction = GetNamedAction(m_animGraphPlugin->GetViewWidget(), FromStdString(EMStudio::AnimGraphPlugin::s_deleteSelectedNodesShortcutName)); + ASSERT_TRUE(deleteAction) << "Could not find the '" << + std::string(EMStudio::AnimGraphPlugin::s_deleteSelectedNodesShortcutName.data(), EMStudio::AnimGraphPlugin::s_deleteSelectedNodesShortcutName.size()) + << "' action in the context menu"; // Trigger delete const size_t nodeCount = activeAnimGraph->GetNumNodes(); diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/Transitions/RemoveTransition.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/Transitions/RemoveTransition.cpp index 819c24baa7..98fec0fe13 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/Transitions/RemoveTransition.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/Transitions/RemoveTransition.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include "qtestsystem.h" @@ -80,9 +81,8 @@ namespace EMotionFX ASSERT_TRUE(modelIndex.isValid()) << "Anim graph transition has an invalid model index."; animGraphModel.GetSelectionModel().select(QItemSelection(modelIndex, modelIndex), QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - // Delete key pressed. - EMStudio::BlendGraphWidget* blendGraphWidget = animGraphPlugin->GetGraphWidget(); - QTest::keyClick((QWidget*)blendGraphWidget, Qt::Key_Delete); + EMStudio::BlendGraphViewWidget* blendGraphViewWidget = animGraphPlugin->GetViewWidget(); + blendGraphViewWidget->GetAction(EMStudio::BlendGraphViewWidget::EDIT_DELETE)->trigger(); // Check if the transition get deleted. ASSERT_EQ(0, m_animGraph->GetRootStateMachine()->GetNumTransitions()) << " Anim Graph transition should be removed"; diff --git a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp index 2b7676e4db..a22064cfe2 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.cpp @@ -161,7 +161,7 @@ namespace EditorPythonBindings bufferArg = *name; } - AZStd::string_view type = FetchPythonType(*behaviorMethod.GetArgument(argIndex)); + AZStd::string type = FetchPythonTypeName(*behaviorMethod.GetArgument(argIndex)); if (!type.empty()) { AzFramework::StringFunc::Append(bufferArg, ": "); @@ -289,7 +289,7 @@ namespace EditorPythonBindings bool isBroadcast = false; if (sender.m_event) { - AZStd::string_view addressType = FetchPythonType(behaviorEBus->m_idParam); + AZStd::string addressType = FetchPythonTypeName(behaviorEBus->m_idParam); if (addressType.empty()) { AzFramework::StringFunc::Append(buffer, "(busCallType: int, busEventName: str, address: Any, args: Tuple[Any])"); @@ -338,7 +338,7 @@ namespace EditorPythonBindings } const AZ::BehaviorParameter* resultParam = behaviorMethod->GetResult(); - AZStd::string_view returnType = FetchPythonType(*resultParam); + AZStd::string returnType = FetchPythonTypeName(*resultParam); AZStd::string returnTypeStr = AZStd::string::format(") -> " AZ_STRING_FORMAT" \n", AZ_STRING_ARG(returnType)); AzFramework::StringFunc::Append(inOutStrBuffer, returnTypeStr.c_str()); }; @@ -664,9 +664,9 @@ namespace EditorPythonBindings return m_typeCache[typeId]; } - AZStd::string_view PythonLogSymbolsComponent::FetchPythonType(const AZ::BehaviorParameter& param) + AZStd::string PythonLogSymbolsComponent::FetchPythonTypeName(const AZ::BehaviorParameter& param) { - AZStd::string_view pythonType = FetchPythonTypeAndTraits(param.m_typeId, param.m_traits); + AZStd::string pythonType = FetchPythonTypeAndTraits(param.m_typeId, param.m_traits); if (pythonType.empty()) { diff --git a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h index 2972e3c9e0..e52cb00570 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h +++ b/Gems/EditorPythonBindings/Code/Source/PythonLogSymbolsComponent.h @@ -62,6 +62,7 @@ namespace EditorPythonBindings void LogGlobalMethod(AZStd::string_view moduleName, AZStd::string_view methodName, AZ::BehaviorMethod* behaviorMethod) override; void LogGlobalProperty(AZStd::string_view moduleName, AZStd::string_view propertyName, AZ::BehaviorProperty* behaviorProperty) override; void Finalize() override; + AZStd::string FetchPythonTypeName(const AZ::BehaviorParameter& param) override; //////////////////////////////////////////////////////////////////////// // EditorPythonConsoleInterface @@ -71,7 +72,6 @@ namespace EditorPythonBindings //////////////////////////////////////////////////////////////////////// // Python type deduction AZStd::string_view FetchPythonTypeAndTraits(const AZ::TypeId& typeId, AZ::u32 traits); - AZStd::string_view FetchPythonType(const AZ::BehaviorParameter& param); private: using ModuleSet = AZStd::unordered_set; diff --git a/Gems/EditorPythonBindings/Code/Tests/PythonLogSymbolsComponentTests.cpp b/Gems/EditorPythonBindings/Code/Tests/PythonLogSymbolsComponentTests.cpp index 97f4dd02d0..8297bad094 100644 --- a/Gems/EditorPythonBindings/Code/Tests/PythonLogSymbolsComponentTests.cpp +++ b/Gems/EditorPythonBindings/Code/Tests/PythonLogSymbolsComponentTests.cpp @@ -41,9 +41,9 @@ namespace UnitTest return FetchPythonTypeAndTraits(typeId, traits); } - AZStd::string_view FetchPythonTypeWrapper(const AZ::BehaviorParameter& param) + AZStd::string FetchPythonTypeWrapper(const AZ::BehaviorParameter& param) { - return FetchPythonType(param); + return FetchPythonTypeName(param); } }; diff --git a/Gems/GradientSignal/Code/Source/Editor/EditorImageBuilderComponent.cpp b/Gems/GradientSignal/Code/Source/Editor/EditorImageBuilderComponent.cpp index bd1fbfb464..cc207b59a3 100644 --- a/Gems/GradientSignal/Code/Source/Editor/EditorImageBuilderComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Editor/EditorImageBuilderComponent.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -258,39 +257,6 @@ namespace GradientSignal return AZ::Uuid::CreateString("{7520DF20-16CA-4CF6-A6DB-D96759A09EE4}"); } - static AZStd::unique_ptr LegacyLoadImageFromPath(const AZStd::string& fullPath) - { - ImageProcessing::IImageObjectPtr imageObject; - ImageProcessing::ImageProcessingRequestBus::BroadcastResult(imageObject, &ImageProcessing::ImageProcessingRequests::LoadImage, - fullPath); - - if (!imageObject) - { - return {}; - } - - //create a new image asset - auto imageAsset = AZStd::make_unique(); - - if (!imageAsset) - { - return {}; - } - - imageAsset->m_imageWidth = imageObject->GetWidth(0); - imageAsset->m_imageHeight = imageObject->GetHeight(0); - imageAsset->m_imageFormat = imageObject->GetPixelFormat(); - - AZ::u8* mem = nullptr; - AZ::u32 pitch = 0; - AZ::u32 mipBufferSize = imageObject->GetMipBufSize(0); - imageObject->GetImagePointer(0, mem, pitch); - - imageAsset->m_imageData = { mem, mem + mipBufferSize }; - - return imageAsset; - } - static ImageProcessing::EPixelFormat AtomPixelFormatToLegacyPixelFormat(ImageProcessingAtom::EPixelFormat atomPixFormat) { // This could be dangerous to do if these enums have differences in the middle. @@ -334,14 +300,7 @@ namespace GradientSignal AZStd::unique_ptr EditorImageBuilderWorker::LoadImageFromPath(const AZStd::string& fullPath) { - if (AZ::Interface::Get()) - { - return AtomLoadImageFromPath(fullPath); - } - else - { - return LegacyLoadImageFromPath(fullPath); - } + return AtomLoadImageFromPath(fullPath); } AZStd::unique_ptr EditorImageBuilderWorker::LoadImageSettingsFromPath(const AZStd::string& fullPath) diff --git a/Gems/ImGui/Code/Editor/ImGuiEditorWindowSystemComponent.cpp b/Gems/ImGui/Code/Editor/ImGuiEditorWindowSystemComponent.cpp index 6c370e091c..07ab3b0a42 100644 --- a/Gems/ImGui/Code/Editor/ImGuiEditorWindowSystemComponent.cpp +++ b/Gems/ImGui/Code/Editor/ImGuiEditorWindowSystemComponent.cpp @@ -18,7 +18,6 @@ #include "ImGuiEditorWindowSystemComponent.h" #include "ImGuiMainWindow.h" #include -#include static const char* s_ImGuiQtViewPaneName = "ImGui Editor"; @@ -60,19 +59,5 @@ namespace ImGui void ImGuiEditorWindowSystemComponent::NotifyRegisterViews() { - if (!AZ::Interface::Get()) - { - // The Tools->ImGui menu currently crashes trying to enable a render pipeline when this is invoked - // Disable this menu item for now - // [GFX TODO][ATOM-4607] - QtViewOptions options; - options.canHaveMultipleInstances = false; - AzToolsFramework::EditorRequests::Bus::Broadcast( - &AzToolsFramework::EditorRequests::RegisterViewPane, - s_ImGuiQtViewPaneName, - "Tools", - options, - [](QWidget* parent = nullptr) { return new ImGui::ImGuiMainWindow(parent); }); - } } } diff --git a/Gems/ImGui/Code/Source/ImGuiManager.cpp b/Gems/ImGui/Code/Source/ImGuiManager.cpp index e10a59bde1..c9b32ac692 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.cpp +++ b/Gems/ImGui/Code/Source/ImGuiManager.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -380,14 +379,8 @@ void ImGuiManager::Render() TransformationMatrices backupSceneMatrices; - AZ::u32 backBufferWidth = 0; - AZ::u32 backBufferHeight = 0; - - if (AZ::Interface::Get()) - { - backBufferWidth = m_windowSize.m_width; - backBufferHeight = m_windowSize.m_height; - } + AZ::u32 backBufferWidth = m_windowSize.m_width; + AZ::u32 backBufferHeight = m_windowSize.m_height; // Find ImGui Render Resolution. int renderRes[2]; @@ -759,10 +752,7 @@ void ImGuiManager::RenderImGuiBuffers(const ImVec2& scaleRects) //@rky: Only render the main ImGui if it is visible if (m_clientMenuBarState != DisplayState::Hidden) { - if (AZ::Interface::Get()) - { - OtherActiveImGuiRequestBus::Broadcast(&OtherActiveImGuiRequestBus::Events::RenderImGuiBuffers, *drawData); - } + OtherActiveImGuiRequestBus::Broadcast(&OtherActiveImGuiRequestBus::Events::RenderImGuiBuffers, *drawData); } } diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp index 770e1190be..7b15d6680d 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -518,18 +517,6 @@ namespace ImGui ImGui::EndChild(); // End the "Meshes in Scene" Child } } - - // Check to make sure the Tick Bus Connection status matches the debug enabled flag - if (m_meshDebugEnabled && !AZ::TickBus::Handler::BusIsConnected()) - { - // Connect to the Tick Bus - AZ::TickBus::Handler::BusConnect(); - } - else if (!m_meshDebugEnabled && AZ::TickBus::Handler::BusIsConnected()) - { - // Disconnect from the Tick Bus - AZ::TickBus::Handler::BusDisconnect(); - } } // Mesh Mouse Over Helper function @@ -597,81 +584,6 @@ namespace ImGui instanceOptions.m_mousedOverForDraw |= ImGui::IsItemHovered(); } - void ImGuiLYAssetExplorer::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) - { - // Search through all entities for Asset Components - OnTick_FindAssets(); - - // Check for all relevant pointers here. ( Actually requires checking all of these for different edge cases! :( - if (gEnv && gEnv->pRenderer && gEnv->pSystem && - gEnv->pSystem->GetIViewSystem() && gEnv->pSystem->GetIViewSystem()->GetActiveView() && - gEnv->pSystem->GetIViewSystem()->GetActiveView()->GetCurrentParams()) - { - // Get the Camera View Position from the view system. - const Vec3& cameraPosVec3 = gEnv->pSystem->GetIViewSystem()->GetActiveView()->GetCurrentParams()->position; - const AZ::Vector3 cameraPos(cameraPosVec3.x, cameraPosVec3.y, cameraPosVec3.z); - - // Loop through all Meshes to draw the appropriate ones! - for (const MeshInstanceDisplayList& meshInstanceList : m_meshInstanceDisplayList) - { - // bunch of different ways to filter results. First check for Mesh and Instance Name Filters... - bool displayMesh = true; - if (m_meshNameFilter) - { - displayMesh &= meshInstanceList.m_passesFilter; - } - if (m_entityNameFilter) - { - displayMesh &= meshInstanceList.m_childrenPassFilter; - } - - // ..Mouse Overs and Selection Filters should override other filters, so do it after.. Mouse Over THEN Selection Filter for precedence. - if (m_anyMousedOverForDraw) - { - displayMesh = meshInstanceList.m_mousedOverForDraw || meshInstanceList.m_childMousedOverForDraw; - } - else if (m_selectionFilter) - { - displayMesh = meshInstanceList.m_selectedForDraw; - for (const auto& meshInstance : meshInstanceList.m_instanceOptionMap) - { - displayMesh |= meshInstance.second.m_selectedForDraw; - } - } - - if (displayMesh) - { - for (const auto& meshInstance : meshInstanceList.m_instanceOptionMap) - { - AZ::Data::Asset meshAsset; - LmbrCentral::MeshComponentRequestBus::EventResult(meshAsset, meshInstance.first, &LmbrCentral::MeshComponentRequests::GetMeshAsset); - // See if we pass name filter first.. - bool displayEntity = true; - if (m_entityNameFilter) - { - displayEntity = meshInstance.second.m_passesFilter; - } - - // ..Mouse Overs and Selection Filters should override other filters, so do it after.. Mouse Over THEN Selection Filter for precedence. - if (m_anyMousedOverForDraw) - { - displayEntity = meshInstance.second.m_mousedOverForDraw || meshInstanceList.m_mousedOverForDraw; - } - else if (m_selectionFilter) - { - displayEntity = meshInstance.second.m_selectedForDraw | meshInstanceList.m_selectedForDraw; - } - - if (displayEntity) - { - OnTick_DrawEntity(meshInstance.first, meshAsset.GetId(), gEnv->pRenderer, cameraPos); - } - } - } - } - } - } - MeshInstanceDisplayList& ImGuiLYAssetExplorer::FindOrCreateMeshInstanceList(const char* meshName) { // Walk the list and see if an entry for this mesh exists already. If we find one, return it! @@ -696,250 +608,6 @@ namespace ImGui m_meshInstanceDisplayList.push_back(meshList); return m_meshInstanceDisplayList.back(); } - - // Scan the scene for Meshes! - void ImGuiLYAssetExplorer::OnTick_FindAssets() - { - // Retrieve Id map from game entity context (editor->runtime). - AzFramework::EntityContextId gameContextId = AzFramework::EntityContextId::CreateNull(); - AzFramework::GameEntityContextRequestBus::BroadcastResult(gameContextId, &AzFramework::GameEntityContextRequests::GetGameEntityContextId); - - // Get the Root Slice Component - AZ::SliceComponent* rootSliceComponent; - AzFramework::SliceEntityOwnershipServiceRequestBus::EventResult(rootSliceComponent, gameContextId, - &AzFramework::SliceEntityOwnershipServiceRequests::GetRootSlice); - - if (rootSliceComponent) - { - // Get an unordered_set of all EntityIds in the slice - AZ::SliceComponent::EntityIdSet entityIds; - rootSliceComponent->GetEntityIds(entityIds); - - // Loop through Mesh Map and "un-verify" them - for (MeshInstanceDisplayList& meshInstanceList : m_meshInstanceDisplayList) - { - for (auto& meshInstance : meshInstanceList.m_instanceOptionMap) - { - meshInstance.second.m_verifiedThisFrame = false; - } - } - - for (auto it = entityIds.begin(); it != entityIds.end(); it++) - { - AZ::Data::Asset meshAsset; - LmbrCentral::MeshComponentRequestBus::EventResult(meshAsset, *it, &LmbrCentral::MeshComponentRequests::GetMeshAsset); - - if (meshAsset.IsReady()) - { - // Get the Asset Info so we can get the mesh path - AZ::Data::AssetInfo assetInfo; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, meshAsset.GetId()); - - AZStd::string meshPath = assetInfo.m_relativePath; - AZStd::to_lower(meshPath.begin(), meshPath.end()); - // Save off this mesh instance into the instance map - MeshInstanceDisplayList& displayList = FindOrCreateMeshInstanceList(meshPath.c_str()); - if (!displayList.m_instanceOptionMap.count(*it)) - { - // Get the Entity Name, for easy searching later - AZStd::string entityName; - AZ::ComponentApplicationBus::BroadcastResult(entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, *it); - - // Init the instance entry and options - MeshInstanceOptions& meshOptions = displayList.m_instanceOptionMap[*it]; - meshOptions.m_verifiedThisFrame = true; - meshOptions.m_passesFilter = true; - meshOptions.m_selectedForDraw = false; - meshOptions.m_mousedOverForDraw = false; - meshOptions.m_instanceLabel = AZStd::string::format("%s%s", (*it).ToString().c_str(), entityName.c_str()); - AZStd::to_lower(meshOptions.m_instanceLabel.begin(), meshOptions.m_instanceLabel.end()); - } - else - { - displayList.m_instanceOptionMap[*it].m_verifiedThisFrame = true; - } - } - } - - // Loop through Mesh Map again and remove any "un-verify"-ed entries! - for (auto meshInstanceListIter = m_meshInstanceDisplayList.begin(); meshInstanceListIter != m_meshInstanceDisplayList.end();) - { - for (auto meshInstanceIter = (*meshInstanceListIter).m_instanceOptionMap.begin(); meshInstanceIter != (*meshInstanceListIter).m_instanceOptionMap.end();) - { - if (!(*meshInstanceIter).second.m_verifiedThisFrame) - { - // erase this instance from the map and set the iterator correctly. - meshInstanceIter = (*meshInstanceListIter).m_instanceOptionMap.erase(meshInstanceIter); - } - else - { - // increment the iterator - meshInstanceIter++; - } - } - - // Remove the Mesh Entry if there are no instances remaining - if ((*meshInstanceListIter).m_instanceOptionMap.empty()) - { - meshInstanceListIter = m_meshInstanceDisplayList.erase(meshInstanceListIter); - } - else - { - // increment the iterator - meshInstanceListIter++; - } - } - } - } - - // We know we want to draw this Entity/Mesh ( depending on distance from Cam ).. so draw! - void ImGuiLYAssetExplorer::OnTick_DrawEntity(const AZ::EntityId& entity, const AZ::Data::AssetId& assetId, IRenderer* renderer, const AZ::Vector3& cameraPos) - { - // Get the Entity Position so we can see how far from the camera we are. - AZ::Vector3 worldPos = AZ::Vector3::CreateZero(); - AZ::TransformBus::EventResult(worldPos, entity, &AZ::TransformBus::Events::GetWorldTranslation); - - // Get Our Distance From The Camera! ( Used just for draw alpha value ) - float distFromCamera = m_distanceFilter_far + 1.0f; // Default to just outside camera view ( i.e. Don't draw ) - if (m_anyMousedOverForDraw || m_selectionFilter || !m_distanceFilter) - { - // If we have either the Selection Filter or Mouse Over state on or the distance filter is off, and we made it this far, we are the lucky selected one! Draw ourselves by setting dist to 0.0f - distFromCamera = 0.0; - } - else if (m_distanceFilter) - { - // Distance filter is on and we aren't selected, so actually find the distance from the camera - distFromCamera = worldPos.GetDistance(cameraPos); - } - - // Only draw things within view distance ( cheese it to zero above to force drawing far things ) - if (distFromCamera <= m_distanceFilter_far) - { - // Find an interpolated Alpha.. 1.0f while inside near radius, interp 1.0 -> 0.0 while heading toward far radius - float alpha = (distFromCamera <= m_distanceFilter_near) ? 1.0f : (1.0f - ((distFromCamera - m_distanceFilter_near) / (m_distanceFilter_far - m_distanceFilter_near))); - - // The string to hold label text we will build. - AZStd::string entityLabel; - - // Grab the Asset Info to get the mesh path name. - AZ::Data::AssetInfo assetInfo; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, assetId); - - // Start the label with either the EntName and Mesh, or just Mesh - if (m_inWorld_label_entityName) - { - AZ::ComponentApplicationBus::BroadcastResult(entityLabel, &AZ::ComponentApplicationBus::Events::GetEntityName, entity); - entityLabel = AZStd::string::format("Entity: %s %s\nMesh: %s", entity.ToString().c_str(), entityLabel.c_str(), assetInfo.m_relativePath.c_str()); - } - else - { - entityLabel = AZStd::string::format("Mesh: %s", assetInfo.m_relativePath.c_str()); - } - - // See if we should add the Material! - if (m_inWorld_label_materialName) - { - _smart_ptr material; - LmbrCentral::MaterialOwnerRequestBus::EventResult(material, entity, &LmbrCentral::MaterialOwnerRequests::GetMaterial); - if (material) - { - entityLabel.append(AZStd::string::format("\nMaterial: %s", material->GetName())); - } - } - - // Get The Render Node for mesh debug draw and Lod Info - IRenderNode* renderNode = nullptr; - LmbrCentral::RenderNodeRequestBus::EventResult(renderNode, entity, &LmbrCentral::RenderNodeRequests::GetRenderNode); - - if (renderNode != nullptr && renderNode->GetEntityStatObj()) - { - // Debug Draw Mesh - if (m_inWorld_debugDrawMesh) - { - SGeometryDebugDrawInfo dd; - dd.color.Set(0.0f, 0.0f, 255.0f, 0.5f * alpha); - dd.lineColor.Set(255.0f, 0.0f, 0.0f, 0.75f * alpha); - renderNode->GetEntityStatObj()->DebugDraw(dd, 0.2f); - } - // Draw Total Lods info - if (m_inWorld_label_totalLods) - { - entityLabel.append(AZStd::string::format("\nTotal Lods: %d", renderNode->GetEntityStatObj()->GetLoadedLodsNum())); - } - // Draw Misc Lod Info - if (m_inWorld_label_miscLod) - { - entityLabel.append(AZStd::string::format("\nFirst Lod Distance: %f", renderNode->GetFirstLodDistance())); - float distances[SMeshLodInfo::s_nMaxLodCount]; - renderNode->GetLodDistances(gEnv->p3DEngine->GetFrameLodInfo(), distances); - for (int i = 0; i < SMeshLodInfo::s_nMaxLodCount; i++) - { - entityLabel.append(AZStd::string::format("\n frameLod: %d - %f", i, distances[i])); - } - } - } - - // Draw the label in the world - if (m_inWorld_drawLabel) - { - SDrawTextInfo ti; - ti.xscale = ti.yscale = m_inWorld_labelTextSize * alpha; - ti.flags = eDrawText_FixedSize | eDrawText_Center | eDrawText_800x600; - if (m_inWorld_label_framed) - { - ti.flags |= eDrawText_Framed; - } - if (m_inWorld_label_monoSpace) - { - ti.flags |= eDrawText_Monospace; - } - - { - ti.color[0] = m_inWorld_label_textColor.Value.x; - ti.color[1] = m_inWorld_label_textColor.Value.y; - ti.color[2] = m_inWorld_label_textColor.Value.z; - ti.color[3] = alpha; - } - Vec3 labelPos(worldPos.GetX(), worldPos.GetY(), worldPos.GetZ() - m_inWorld_originSphereRadius); - renderer->DrawTextQueued(labelPos, ti, entityLabel.c_str()); - } - - // Draw the sphere and/or AABB in the world - if (m_inWorld_drawOriginSphere || m_inWorld_drawAABB) - { - IRenderAuxGeom* pAuxGeom = renderer->GetIRenderAuxGeom(); - if (pAuxGeom) - { - const ColorF sphereColor(m_inWorld_label_textColor.Value.x, m_inWorld_label_textColor.Value.y, m_inWorld_label_textColor.Value.z, alpha); - Vec3 spherePos(worldPos.GetX(), worldPos.GetY(), worldPos.GetZ()); - - // draw a sample sphere - SAuxGeomRenderFlags oldFlags = pAuxGeom->GetRenderFlags(); - SAuxGeomRenderFlags flags = oldFlags; - flags.SetDepthWriteFlag(e_DepthWriteOff); - flags.SetDepthTestFlag(e_DepthTestOff); - flags.SetDrawInFrontMode(e_DrawInFrontOn); - flags.SetFillMode(e_FillModeSolid); - flags.SetCullMode(e_CullModeNone); - pAuxGeom->SetRenderFlags(flags); - - if ( m_inWorld_drawOriginSphere) - { - pAuxGeom->DrawSphere(spherePos, m_inWorld_originSphereRadius, sphereColor, false); - } - - if (m_inWorld_drawAABB && renderNode) - { - pAuxGeom->DrawAABB(renderNode->GetBBox(), false, sphereColor, EBoundingBoxDrawStyle::eBBD_Extremes_Color_Encoded); - } - - // Restore rendering state - pAuxGeom->SetRenderFlags(oldFlags); - } - } - } - } - -} // namespace ImGui + } // namespace ImGui #endif // IMGUI_ENABLED diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h index 29584c84d3..b5f8ea576c 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYAssetExplorer.h @@ -43,7 +43,6 @@ namespace ImGui class ImGuiLYAssetExplorer : public ImGuiAssetExplorerRequestBus::Handler - , public AZ::TickBus::Handler { public: @@ -61,10 +60,6 @@ namespace ImGui void SetEnabled(bool enabled) override { m_enabled = enabled; m_meshDebugEnabled = enabled; } // -- ImGuiAssetExplorerRequestBus::Handler Interface ---------------------- - // -- AZ::TickBus::Handler Interface --------------------------------------- - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - // -- AZ::TickBus::Handler Interface --------------------------------------- - // Toggle the menu on and off void ToggleEnabled() { m_enabled = !m_enabled; } @@ -117,9 +112,6 @@ namespace ImGui void ImGuiUpdate_DrawMeshMouseOver(MeshInstanceDisplayList& meshDisplayList); void ImGuiUpdate_DrawEntityInstanceMouseOver(MeshInstanceDisplayList& meshDisplayList, AZ::EntityId& entityInstance, AZStd::string& entityName, MeshInstanceOptions& instanceOptions); - // Helper functions for the OnTick callback - void OnTick_DrawEntity(const AZ::EntityId& entity, const AZ::Data::AssetId& assetId, IRenderer* renderer, const AZ::Vector3& cameraPos); - void OnTick_FindAssets(); }; } #endif // IMGUI_ENABLED diff --git a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.cpp b/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.cpp deleted file mode 100644 index 537585f48c..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "LmbrCentral_precompiled.h" -#include "AttachmentComponent.h" -#include -#include -#include -#include -#include -#include - -namespace LmbrCentral -{ - /// Behavior Context handler for AttachmentComponentNotificationBus - class BehaviorAttachmentComponentNotificationBusHandler : public AttachmentComponentNotificationBus::Handler, public AZ::BehaviorEBusHandler - { - public: - AZ_EBUS_BEHAVIOR_BINDER(BehaviorAttachmentComponentNotificationBusHandler, "{636B95A0-5C7D-4EE7-8645-955665315451}", AZ::SystemAllocator - , OnAttached, OnDetached); - - void OnAttached(AZ::EntityId id) override - { - Call(FN_OnAttached, id); - } - - void OnDetached(AZ::EntityId id) override - { - Call(FN_OnDetached, id); - } - }; - - void AttachmentConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Target ID", &AttachmentConfiguration::m_targetId) - ->Field("Target Bone Name", &AttachmentConfiguration::m_targetBoneName) - ->Field("Target Offset", &AttachmentConfiguration::m_targetOffset) - ->Field("Attached Initially", &AttachmentConfiguration::m_attachedInitially) - ->Field("Scale Source", &AttachmentConfiguration::m_scaleSource) - ; - } - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->EBus("AttachmentComponentRequestBus") - ->Event("Attach", &AttachmentComponentRequestBus::Events::Attach) - ->Event("Detach", &AttachmentComponentRequestBus::Events::Detach) - ->Event("SetAttachmentOffset", &AttachmentComponentRequestBus::Events::SetAttachmentOffset); - - behaviorContext->EBus("AttachmentComponentNotificationBus") - ->Handler(); - } - } - - void AttachmentComponent::Reflect(AZ::ReflectContext* context) - { - AttachmentConfiguration::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Configuration", &AttachmentComponent::m_initialConfiguration) - ; - } - } - - //========================================================================= - // BoneFollower - //========================================================================= - - void BoneFollower::Activate(AZ::Entity* owner, const AttachmentConfiguration& configuration, bool targetCanAnimate) - { - AZ_Assert(owner, "owner is required"); - AZ_Assert(!m_ownerId.IsValid(), "BoneFollower is already Activated"); - - m_ownerId = owner->GetId(); - m_targetCanAnimate = targetCanAnimate; - m_isUpdatingOwnerTransform = false; - m_scaleSource = configuration.m_scaleSource; - - m_cachedOwnerTransform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(m_cachedOwnerTransform, m_ownerId, AZ::TransformBus, GetWorldTM); - - if (configuration.m_attachedInitially) - { - Attach(configuration.m_targetId, configuration.m_targetBoneName.c_str(), configuration.m_targetOffset); - } - - AttachmentComponentRequestBus::Handler::BusConnect(m_ownerId); - } - - void BoneFollower::Deactivate() - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower was never Activated"); - - AttachmentComponentRequestBus::Handler::BusDisconnect(); - Detach(); - m_ownerId.SetInvalid(); - } - - AZ::EntityId BoneFollower::GetTargetEntityId() - { - return m_targetId; - } - - AZ::Transform BoneFollower::GetOffset() - { - return m_targetOffset; - } - - void BoneFollower::Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use.") - - // safe to try and detach, even if we weren't attached - Detach(); - - if (!targetId.IsValid()) - { - return; - } - - if (targetId == m_ownerId) - { - AZ_Error("Attachment Component", false, "AttachmentComponent cannot target itself"); - return; - } - - // Note: the target entity may not be activated yet. That's ok. - // When mesh is ready we are notified via MeshComponentEvents::OnMeshCreated - // When transform is ready we are notified via TransformNotificationBus::OnTransformChanged - - m_targetId = targetId; - m_targetBoneName = targetBoneName; - m_targetOffset = offset; - - BindTargetBone(); - - m_targetBoneTransform = AZ::Transform::Identity(); - - m_isTargetEntityTransformKnown = false; // target's transform may not be available yet - - AZ::TransformBus::EventResult(m_cachedOwnerTransform, m_ownerId, &AZ::TransformBus::Events::GetWorldTM); // owner query will always succeed - - MeshComponentNotificationBus::Handler::BusConnect(m_targetId); // fires OnMeshCreated if asset is already ready - AZ::TransformNotificationBus::Handler::BusConnect(m_targetId); - if (m_targetCanAnimate) - { - // Only register for per-frame updates when target can animate - AZ::TickBus::Handler::BusConnect(); - } - - // update owner's transform - UpdateOwnerTransformIfNecessary(); - - // alert others that we've attached - AttachmentComponentNotificationBus::Event(m_targetId, &AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); - } - - void BoneFollower::Detach() - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); - - if (m_targetId.IsValid()) - { - // alert others that we're detaching - EBUS_EVENT_ID(m_targetId, AttachmentComponentNotificationBus, OnDetached, m_ownerId); - - MeshComponentNotificationBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(m_targetId); - AZ::TickBus::Handler::BusDisconnect(); - - m_targetId.SetInvalid(); - } - } - - const char* BoneFollower::GetJointName() - { - return m_targetBoneName.c_str(); - } - - void BoneFollower::SetAttachmentOffset(const AZ::Transform& offset) - { - AZ_Assert(m_ownerId.IsValid(), "BoneFollower must be Activated to use."); - - if (m_targetId.IsValid()) - { - m_targetOffset = offset; - UpdateOwnerTransformIfNecessary(); - } - } - - void BoneFollower::OnMeshCreated(const AZ::Data::Asset& asset) - { - (void)asset; - - // reset character values - BindTargetBone(); - m_targetBoneTransform = QueryBoneTransform(); - - // move owner if necessary - UpdateOwnerTransformIfNecessary(); - } - - void BoneFollower::BindTargetBone() - { - m_targetBoneId = -1; - SkeletalHierarchyRequestBus::EventResult(m_targetBoneId, m_targetId, &SkeletalHierarchyRequests::GetJointIndexByName, m_targetBoneName.c_str()); - } - - void BoneFollower::UpdateOwnerTransformIfNecessary() - { - // Can't update until target entity's transform is known - if (!m_isTargetEntityTransformKnown) - { - if (AZ::TransformBus::GetNumOfEventHandlers(m_targetId) == 0) - { - return; - } - - AZ::TransformBus::EventResult(m_targetEntityTransform, m_targetId, &AZ::TransformBus::Events::GetWorldTM); - m_isTargetEntityTransformKnown = true; - } - - AZ::Transform finalTransform; - if (m_scaleSource == AttachmentConfiguration::ScaleSource::WorldScale) - { - // apply offset in world-space - finalTransform = m_targetEntityTransform * m_targetBoneTransform; - finalTransform.SetScale(AZ::Vector3::CreateOne()); - finalTransform *= m_targetOffset; - } - else if (m_scaleSource == AttachmentConfiguration::ScaleSource::TargetEntityScale) - { - // apply offset in target-entity-space (ignoring bone scale) - AZ::Transform boneNoScale = m_targetBoneTransform; - boneNoScale.SetScale(AZ::Vector3::CreateOne()); - - finalTransform = m_targetEntityTransform * boneNoScale * m_targetOffset; - } - else // AttachmentConfiguration::ScaleSource::TargetEntityScale - { - // apply offset in target-bone-space - finalTransform = m_targetEntityTransform * m_targetBoneTransform * m_targetOffset; - } - - if (m_cachedOwnerTransform != finalTransform) - { - AZ_Warning("Attachment Component", !m_isUpdatingOwnerTransform, "AttachmentComponent detected a cycle when updating transform, do not target child entities."); - if (!m_isUpdatingOwnerTransform) - { - m_cachedOwnerTransform = finalTransform; - m_isUpdatingOwnerTransform = true; - EBUS_EVENT_ID(m_ownerId, AZ::TransformBus, SetWorldTM, finalTransform); - m_isUpdatingOwnerTransform = false; - } - } - } - - AZ::Transform BoneFollower::QueryBoneTransform() const - { - AZ::Transform boneTransform = AZ::Transform::CreateIdentity(); - - if (m_targetBoneId >= 0) - { - SkeletalHierarchyRequestBus::EventResult(boneTransform, m_targetId, &SkeletalHierarchyRequests::GetJointTransformCharacterRelative, m_targetBoneId); - } - - return boneTransform; - } - - // fires when target's transform changes - void BoneFollower::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_targetEntityTransform = world; - m_isTargetEntityTransformKnown = true; - UpdateOwnerTransformIfNecessary(); - } - - void BoneFollower::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/) - { - m_targetBoneTransform = QueryBoneTransform(); - UpdateOwnerTransformIfNecessary(); - } - - int BoneFollower::GetTickOrder() - { - return AZ::TICK_ATTACHMENT; - } - - void BoneFollower::Reattach(bool detachFirst) - { -#ifdef AZ_ENABLE_TRACING - AZ::Entity* ownerEntity = nullptr; - AZ::Entity* targetEntity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(ownerEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_ownerId); - AZ::ComponentApplicationBus::BroadcastResult(targetEntity, &AZ::ComponentApplicationBus::Events::FindEntity, m_targetId); - AZ_TracePrintf("BoneFollower", "Reattaching entity '%s' to entity '%s'", ownerEntity ? ownerEntity->GetName().c_str() : "", - targetEntity ? targetEntity->GetName().c_str() : ""); -#endif - - if (m_targetId.IsValid() && detachFirst) - { - AttachmentComponentNotificationBus::Event(m_targetId, &AttachmentComponentNotificationBus::Events::OnDetached, m_ownerId); - } - - if (m_targetId != m_ownerId) - { - AttachmentComponentNotificationBus::Event(m_targetId, &AttachmentComponentNotificationBus::Events::OnAttached, m_ownerId); - } - } - - //========================================================================= - // AttachmentComponent - //========================================================================= - - void AttachmentComponent::Activate() - { -#ifdef AZ_ENABLE_TRACING - bool isStaticTransform = false; - AZ::TransformBus::EventResult(isStaticTransform, GetEntityId(), &AZ::TransformBus::Events::IsStaticTransform); - AZ_Warning("Attachment Component", !isStaticTransform, - "Attachment needs to move, but entity '%s' %s has a static transform.", GetEntity()->GetName().c_str(), GetEntityId().ToString().c_str()); -#endif - - m_boneFollower.Activate(GetEntity(), m_initialConfiguration, true); - } - - - void AttachmentComponent::Deactivate() - { - m_boneFollower.Deactivate(); - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.h b/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.h deleted file mode 100644 index f2ef428ac2..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/AttachmentComponent.h +++ /dev/null @@ -1,186 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include - -struct ISkeletonPose; - -namespace LmbrCentral -{ - /*! - * Configuration data for AttachmentComponent. - */ - struct AttachmentConfiguration - { - AZ_TYPE_INFO(AttachmentConfiguration, "{74B5DC69-DE44-4640-836A-55339E116795}"); - - virtual ~AttachmentConfiguration() = default; - - static void Reflect(AZ::ReflectContext* context); - - //! Attach to this entity. - AZ::EntityId m_targetId; - - //! Attach to this bone on target entity. - AZStd::string m_targetBoneName; - - //! Offset from target. - AZ::Transform m_targetOffset = AZ::Transform::Identity(); - - //! Whether to attach to target upon activation. - //! If false, the entity remains detached until Attach() is called. - bool m_attachedInitially = true; - - //! Source from which to retrieve scale information. - enum class ScaleSource : AZ::u8 - { - WorldScale, // Scaled in world space. - TargetEntityScale, // Adopt scaling of attachment target entity. - TargetBoneScale, // Adopt scaling of attachment target entity/joint. - }; - ScaleSource m_scaleSource = ScaleSource::WorldScale; - }; - - /* - * Common functionality for game and editor attachment components. - * The BoneFollower tracks movement of the target's bone and - * updates the owning entity's TransformComponent to follow. - * This class should be a member within the attachment component - * and be activated/deactivated along with the component. - * \ref AttachmentComponent - */ - class BoneFollower - : public AttachmentComponentRequestBus::Handler - , public AZ::TransformNotificationBus::Handler - , public MeshComponentNotificationBus::Handler - , public AZ::Data::AssetBus::Handler - , public AZ::TickBus::Handler - { - public: - void Activate(AZ::Entity* owner, const AttachmentConfiguration& initialConfiguration, bool targetCanAnimate); - void Deactivate(); - - //////////////////////////////////////////////////////////////////////// - // AttachmentComponentRequests - void Reattach(bool detachFirst); - void Attach(AZ::EntityId targetId, const char* targetBoneName, const AZ::Transform& offset) override; - void Detach() override; - void SetAttachmentOffset(const AZ::Transform& offset) override; - const char* GetJointName() override; - AZ::EntityId GetTargetEntityId() override; - AZ::Transform GetOffset() override; - //////////////////////////////////////////////////////////////////////// - - private: - - //////////////////////////////////////////////////////////////////////// - // AZ::TickBus - //! Check target bone transform every frame. - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - //! Make sure target bone transform updates after animation update. - int GetTickOrder() override; - //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // AZ::TransformNotificationBus - //! When target's transform changes - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - //////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////////////////// - // MeshComponentEvents - //! When target's mesh changes - void OnMeshCreated(const AZ::Data::Asset& asset) override; - //////////////////////////////////////////////////////////////////////// - - void BindTargetBone(); - - AZ::Transform QueryBoneTransform() const; - - void UpdateOwnerTransformIfNecessary(); - - //! Entity which which is being attached. - AZ::EntityId m_ownerId; - - //! Whether to query bone position per-frame (false while in editor) - bool m_targetCanAnimate = false; - - AZ::EntityId m_targetId; - AZStd::string m_targetBoneName; - AZ::Transform m_targetOffset; //!< local transform - AZ::Transform m_targetBoneTransform; //!< local transform of bone - AZ::Transform m_targetEntityTransform; //!< world transform of target - bool m_isTargetEntityTransformKnown = false; - - //! Cached value, so we don't update owner's position unnecessarily. - AZ::Transform m_cachedOwnerTransform; - bool m_isUpdatingOwnerTransform = false; //!< detect infinite loops when updating owner's transform - - // Cached character values to avoid repeated lookup. - // These are set by calling ResetCharacter() - int m_targetBoneId; //!< negative when bone not found - - AttachmentConfiguration::ScaleSource m_scaleSource; - }; - - /*! - * The AttachmentComponent lets an entity stick to a particular bone on - * a target entity. This is achieved by tracking movement of the target's - * bone and updating the entity's TransformComponent accordingly. - */ - class AttachmentComponent - : public AZ::Component - { - public: - AZ_COMPONENT(AttachmentComponent, "{2D17A64A-7AC5-4C02-AC36-C5E8141FFDDF}"); - - friend class EditorAttachmentComponent; - - static void Reflect(AZ::ReflectContext* context); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("AttachmentService", 0x5aaa7b63)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - ~AttachmentComponent() override = default; - - private: - //////////////////////////////////////////////////////////////////////// - // AZ::Component - void Activate() override; - void Deactivate() override; - //////////////////////////////////////////////////////////////////////// - - //! Initial configuration for m_attachment - AttachmentConfiguration m_initialConfiguration; - - //! Implements actual attachment functionality - BoneFollower m_boneFollower; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.cpp b/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.cpp deleted file mode 100644 index 265f4ad864..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" -#include "EditorAttachmentComponent.h" -#include -#include -#include -#include - -namespace LmbrCentral -{ - void EditorAttachmentComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Target ID", &EditorAttachmentComponent::m_targetId) - ->Field("Target Bone Name", &EditorAttachmentComponent::m_targetBoneName) - ->Field("Position Offset", &EditorAttachmentComponent::m_positionOffset) - ->Field("Rotation Offset", &EditorAttachmentComponent::m_rotationOffset) - ->Field("Scale Offset", &EditorAttachmentComponent::m_scaleOffset) - ->Field("Attached Initially", &EditorAttachmentComponent::m_attachedInitially) - ->Field("Scale Source", &EditorAttachmentComponent::m_scaleSource) - ; - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Attachment", "The Attachment component lets an entity attach to a bone on the skeleton of another entity") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Animation") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Attachment.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Attachment.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-attachment.html") - ->DataElement(0, &EditorAttachmentComponent::m_targetId, - "Target entity", "Attach to this entity.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetIdChanged) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_targetBoneName, - "Joint name", "Attach to this joint on target entity.") - ->Attribute(AZ::Edit::Attributes::StringList, &EditorAttachmentComponent::GetTargetBoneOptions) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetBoneChanged) - ->DataElement(0, &EditorAttachmentComponent::m_positionOffset, - "Position offset", "Local position offset from target bone") - ->Attribute(AZ::Edit::Attributes::Suffix, "m") - ->Attribute(AZ::Edit::Attributes::Step, 0.01f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) - ->DataElement(0, &EditorAttachmentComponent::m_rotationOffset, - "Rotation offset", "Local rotation offset from target bone") - ->Attribute(AZ::Edit::Attributes::Suffix, "deg") - ->Attribute(AZ::Edit::Attributes::Step, 0.01f) - ->Attribute(AZ::Edit::Attributes::Min, -AZ::RadToDeg(AZ::Constants::TwoPi)) - ->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::TwoPi)) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) - ->DataElement(0, &EditorAttachmentComponent::m_scaleOffset, - "Scale offset", "Local scale offset from target entity") - ->Attribute(AZ::Edit::Attributes::Step, 0.1f) - ->Attribute(AZ::Edit::Attributes::Min, 0.001f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetOffsetChanged) - ->DataElement(0, &EditorAttachmentComponent::m_attachedInitially, - "Attached initially", "Whether to attach to target upon activation.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnAttachedInitiallyChanged) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorAttachmentComponent::m_scaleSource, - "Scaling", "How object scale should be determined. " - "Use world scale = Attached object is scaled in world space, Use target entity scale = Attached object adopts scale of target entity., Use target bone scale = Attached object adopts scale of target entity/joint.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnScaleSourceChanged) - ->EnumAttribute(AttachmentConfiguration::ScaleSource::WorldScale, "Use world scale") - ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetEntityScale, "Use target entity scale") - ->EnumAttribute(AttachmentConfiguration::ScaleSource::TargetBoneScale, "Use target bone scale") - ; - } - } - } - - void EditorAttachmentComponent::Activate() - { - Base::Activate(); - m_boneFollower.Activate(GetEntity(), - CreateAttachmentConfiguration(), - false); // Entity's don't animate in Editor - } - - void EditorAttachmentComponent::Deactivate() - { - m_boneFollower.Deactivate(); - Base::Deactivate(); - } - - void EditorAttachmentComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - AttachmentComponent* component = gameEntity->CreateComponent(); - if (component) - { - component->m_initialConfiguration = CreateAttachmentConfiguration(); - } - } - - AttachmentConfiguration EditorAttachmentComponent::CreateAttachmentConfiguration() const - { - AttachmentConfiguration configuration; - configuration.m_targetId = m_targetId; - configuration.m_targetBoneName = m_targetBoneName; - configuration.m_targetOffset = GetTargetOffset(); - configuration.m_attachedInitially = m_attachedInitially; - configuration.m_scaleSource = m_scaleSource; - return configuration; - } - - AZ::Transform EditorAttachmentComponent::GetTargetOffset() const - { - AZ::Transform offset = AZ::ConvertEulerDegreesToTransform(m_rotationOffset); - offset.SetTranslation(m_positionOffset); - offset.MultiplyByScale(m_scaleOffset); - return offset; - } - - AZStd::vector EditorAttachmentComponent::GetTargetBoneOptions() const - { - AZStd::vector names; - - // insert blank entry, so user may choose to bind to NO bone. - names.push_back(""); - - // track whether currently-set bone is found - bool currentTargetBoneFound = false; - - // Get character and iterate over bones - AZ::u32 jointCount = 0; - SkeletalHierarchyRequestBus::EventResult(jointCount, m_targetId, &SkeletalHierarchyRequests::GetJointCount); - for (AZ::u32 jointIndex = 0; jointIndex < jointCount; ++jointIndex) - { - const char* name = nullptr; - SkeletalHierarchyRequestBus::EventResult(name, m_targetId, &SkeletalHierarchyRequests::GetJointNameByIndex, jointIndex); - if (name) - { - names.push_back(name); - - if (!currentTargetBoneFound) - { - currentTargetBoneFound = (m_targetBoneName == names.back()); - } - } - } - - // If we never found currently-set bone name, - // stick it at top of list, just in case user wants to keep it anyway - if (!currentTargetBoneFound && !m_targetBoneName.empty()) - { - names.insert(names.begin(), m_targetBoneName); - } - - return names; - } - - AZ::u32 EditorAttachmentComponent::OnTargetIdChanged() - { - // Warn about bad setups (it won't crash, but it's nice to handle this early) - if (m_targetId == GetEntityId()) - { - AZ_Warning(GetEntity()->GetName().c_str(), false, "AttachmentComponent cannot target self.") - m_targetId.SetInvalid(); - } - - // Warn about children attaching to a parent - AZ::EntityId parentOfTarget; - AZ::TransformBus::EventResult(parentOfTarget, m_targetId, &AZ::TransformBus::Events::GetParentId); - while (parentOfTarget.IsValid()) - { - if (parentOfTarget == GetEntityId()) - { - AZ_Warning(GetEntity()->GetName().c_str(), parentOfTarget != GetEntityId(), "AttachmentComponent cannot target child entity"); - m_targetId.SetInvalid(); - break; - } - - AZ::EntityId currentParentId = parentOfTarget; - parentOfTarget.SetInvalid(); - AZ::TransformBus::EventResult(parentOfTarget, currentParentId, &AZ::TransformBus::Events::GetParentId); - } - - AttachOrDetachAsNecessary(); - - return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; // refresh bone options - } - - AZ::u32 EditorAttachmentComponent::OnTargetBoneChanged() - { - AttachOrDetachAsNecessary(); - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 EditorAttachmentComponent::OnTargetOffsetChanged() - { - EBUS_EVENT_ID(GetEntityId(), AttachmentComponentRequestBus, SetAttachmentOffset, GetTargetOffset()); - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 EditorAttachmentComponent::OnAttachedInitiallyChanged() - { - AttachOrDetachAsNecessary(); - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 EditorAttachmentComponent::OnScaleSourceChanged() - { - m_boneFollower.Deactivate(); - m_boneFollower.Activate(GetEntity(), - CreateAttachmentConfiguration(), - false); - return AZ::Edit::PropertyRefreshLevels::None; - } - - void EditorAttachmentComponent::AttachOrDetachAsNecessary() - { - if (m_attachedInitially && m_targetId.IsValid()) - { - EBUS_EVENT_ID(GetEntityId(), AttachmentComponentRequestBus, Attach, m_targetId, m_targetBoneName.c_str(), GetTargetOffset()); - } - else - { - EBUS_EVENT_ID(GetEntityId(), AttachmentComponentRequestBus, Detach); - } - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.h b/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.h deleted file mode 100644 index 808ffd393e..0000000000 --- a/Gems/LmbrCentral/Code/Source/Animation/EditorAttachmentComponent.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include "AttachmentComponent.h" - -namespace LmbrCentral -{ - /*! - * In-editor attachment component. - * \ref AttachmentComponent - */ - class EditorAttachmentComponent - : public AzToolsFramework::Components::EditorComponentBase - { - private: - using Base = AzToolsFramework::Components::EditorComponentBase; - public: - AZ_COMPONENT(EditorAttachmentComponent, "{DA6072FD-E696-47D8-81D9-1F77D3464200}", Base); - static void Reflect(AZ::ReflectContext* context); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - AttachmentComponent::GetProvidedServices(provided); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - AttachmentComponent::GetIncompatibleServices(incompatible); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - AttachmentComponent::GetRequiredServices(required); - } - - ~EditorAttachmentComponent() override = default; - void BuildGameEntity(AZ::Entity* gameEntity) override; - - protected: - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - AZ::u32 OnTargetIdChanged(); - AZ::u32 OnTargetBoneChanged(); - AZ::u32 OnTargetOffsetChanged(); - AZ::u32 OnAttachedInitiallyChanged(); - AZ::u32 OnScaleSourceChanged(); - - //! Invoked when an attachment property changes - void AttachOrDetachAsNecessary(); - - //! For populating ComboBox - AZStd::vector GetTargetBoneOptions() const; - - //! Create runtime configuration from editor configuration - AttachmentConfiguration CreateAttachmentConfiguration() const; - - //! Create AZ::Transform from position and rotation - AZ::Transform GetTargetOffset() const; - - //! Attach to this entity. - AZ::EntityId m_targetId; - - //! Attach to this bone on target entity. - AZStd::string m_targetBoneName; - - //! Offset from target bone's position. - AZ::Vector3 m_positionOffset = AZ::Vector3::CreateZero(); - - //! Offset from target bone's rotation. - AZ::Vector3 m_rotationOffset = AZ::Vector3::CreateZero(); - - //! Offset from target entity's scale. - AZ::Vector3 m_scaleOffset = AZ::Vector3::CreateOne(); - - //! Observe scale information from the specified source. - AttachmentConfiguration::ScaleSource m_scaleSource = AttachmentConfiguration::ScaleSource::WorldScale; - - //! Whether to attach to target upon activation. - //! If false, the entity remains detached until Attach() is called. - bool m_attachedInitially = true; - - //! Implements actual attachment functionality - LmbrCentral::BoneFollower m_boneFollower; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp index 0f6b084201..ceac768e79 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentral.cpp @@ -21,7 +21,6 @@ #include // Component descriptors -#include "Animation/AttachmentComponent.h" #include "Audio/AudioAreaEnvironmentComponent.h" #include "Audio/AudioEnvironmentComponent.h" #include "Audio/AudioListenerComponent.h" @@ -33,13 +32,6 @@ #include "Audio/AudioSystemComponent.h" #include "Audio/AudioTriggerComponent.h" #include "Bundling/BundlingSystemComponent.h" -#include "Rendering/DecalComponent.h" -#include "Rendering/StereoRendererComponent.h" -#include "Rendering/LensFlareComponent.h" -#include "Rendering/LightComponent.h" -#include "Rendering/HighQualityShadowComponent.h" -#include "Rendering/MeshComponent.h" -#include "Rendering/GeomCacheComponent.h" #include "Ai/NavigationComponent.h" #include "Scripting/TagComponent.h" #include "Scripting/SimpleStateComponent.h" @@ -77,14 +69,9 @@ #include #include #include -#include #include #include -// Asset handlers -#include -#include - // Scriptable Ebus Registration #include "Events/ReflectScriptableEvents.h" @@ -202,7 +189,6 @@ namespace LmbrCentral : AZ::Module() { m_descriptors.insert(m_descriptors.end(), { - AttachmentComponent::CreateDescriptor(), AudioAreaEnvironmentComponent::CreateDescriptor(), AudioEnvironmentComponent::CreateDescriptor(), AudioListenerComponent::CreateDescriptor(), @@ -214,14 +200,9 @@ namespace LmbrCentral AudioSystemComponent::CreateDescriptor(), AudioTriggerComponent::CreateDescriptor(), BundlingSystemComponent::CreateDescriptor(), - DecalComponent::CreateDescriptor(), - LensFlareComponent::CreateDescriptor(), - LightComponent::CreateDescriptor(), LmbrCentralAllocatorComponent::CreateDescriptor(), LmbrCentralAssetBuilderAllocatorComponent::CreateDescriptor(), LmbrCentralSystemComponent::CreateDescriptor(), - HighQualityShadowComponent::CreateDescriptor(), - MeshComponent::CreateDescriptor(), NavigationComponent::CreateDescriptor(), SimpleStateComponent::CreateDescriptor(), SpawnerComponent::CreateDescriptor(), @@ -237,11 +218,9 @@ namespace LmbrCentral CompoundShapeComponent::CreateDescriptor(), SplineComponent::CreateDescriptor(), PolygonPrismShapeComponent::CreateDescriptor(), - StereoRendererComponent::CreateDescriptor(), NavigationSystemComponent::CreateDescriptor(), GeometrySystemComponent::CreateDescriptor(), RandomTimedSpawnerComponent::CreateDescriptor(), - GeometryCacheComponent::CreateDescriptor(), SphereShapeDebugDisplayComponent::CreateDescriptor(), DiskShapeDebugDisplayComponent::CreateDescriptor(), BoxShapeDebugDisplayComponent::CreateDescriptor(), @@ -275,7 +254,6 @@ namespace LmbrCentral azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), @@ -344,13 +322,6 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b)) ; } - - MaterialHandle::Reflect(serializeContext); - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - MaterialHandle::Reflect(behaviorContext); } ReflectScriptableEvents::Reflect(context); @@ -394,24 +365,11 @@ namespace LmbrCentral // Register asset handlers. Requires "AssetDatabaseService" AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!"); - auto lensFlareAssetHandler = aznew LensFlareAssetHandler; - lensFlareAssetHandler->Register(); // registers self with AssetManager - m_assetHandlers.emplace_back(lensFlareAssetHandler); - - auto meshAssetHandler = aznew MeshAssetHandler(); - meshAssetHandler->Register(); // registers self with AssetManager - m_assetHandlers.emplace_back(meshAssetHandler); - - auto geomCacheAssetHandler = aznew GeomCacheAssetHandler(); - geomCacheAssetHandler->Register(); // registers self with AssetManager - m_assetHandlers.emplace_back(geomCacheAssetHandler); - // Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService". auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler(); if (assetCatalog) { assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); - assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo::Uuid()); @@ -542,8 +500,6 @@ namespace LmbrCentral gEnv = system.GetGlobalEnvironment(); #endif - REGISTER_INT(s_meshAssetHandler_AsyncCvar, 1, 0, "Enables asynchronous loading of legacy mesh formats"); - // Enable catalog now that application's asset root is set. if (system.GetGlobalEnvironment()->IsEditor()) { @@ -560,11 +516,6 @@ namespace LmbrCentral void LmbrCentralSystemComponent::OnCrySystemShutdown([[maybe_unused]] ISystem& system) { - if (gEnv->pConsole) - { - gEnv->pConsole->UnregisterVariable(s_meshAssetHandler_AsyncCvar, true); - } - EBUS_EVENT(AZ::Data::AssetCatalogRequestBus, StopMonitoringAssets); #if !defined(AZ_MONOLITHIC_BUILD) diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp index b20ce12f35..8536733b01 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp +++ b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.cpp @@ -16,7 +16,6 @@ #include "Ai/EditorNavigationAreaComponent.h" #include "Ai/EditorNavigationSeedComponent.h" -#include "Animation/EditorAttachmentComponent.h" #include "Audio/EditorAudioAreaEnvironmentComponent.h" #include "Audio/EditorAudioEnvironmentComponent.h" #include "Audio/EditorAudioListenerComponent.h" @@ -25,16 +24,6 @@ #include "Audio/EditorAudioRtpcComponent.h" #include "Audio/EditorAudioSwitchComponent.h" #include "Audio/EditorAudioTriggerComponent.h" -#include "Rendering/EditorDecalComponent.h" -#include "Rendering/EditorLensFlareComponent.h" -#include "Rendering/EditorLightComponent.h" -#include "Rendering/EditorPointLightComponent.h" -#include "Rendering/EditorAreaLightComponent.h" -#include "Rendering/EditorProjectorLightComponent.h" -#include "Rendering/EditorEnvProbeComponent.h" -#include "Rendering/EditorHighQualityShadowComponent.h" -#include "Rendering/EditorMeshComponent.h" -#include "Rendering/EditorGeomCacheComponent.h" #include "Scripting/EditorLookAtComponent.h" #include "Scripting/EditorRandomTimedSpawnerComponent.h" #include "Scripting/EditorSpawnerComponent.h" @@ -70,7 +59,6 @@ namespace LmbrCentral : LmbrCentralModule() { m_descriptors.insert(m_descriptors.end(), { - EditorAttachmentComponent::CreateDescriptor(), EditorAudioAreaEnvironmentComponent::CreateDescriptor(), EditorAudioEnvironmentComponent::CreateDescriptor(), EditorAudioListenerComponent::CreateDescriptor(), @@ -79,15 +67,6 @@ namespace LmbrCentral EditorAudioRtpcComponent::CreateDescriptor(), EditorAudioSwitchComponent::CreateDescriptor(), EditorAudioTriggerComponent::CreateDescriptor(), - EditorDecalComponent::CreateDescriptor(), - EditorLensFlareComponent::CreateDescriptor(), - EditorLightComponent::CreateDescriptor(), - EditorPointLightComponent::CreateDescriptor(), - EditorAreaLightComponent::CreateDescriptor(), - EditorProjectorLightComponent::CreateDescriptor(), - EditorEnvProbeComponent::CreateDescriptor(), - EditorHighQualityShadowComponent::CreateDescriptor(), - EditorMeshComponent::CreateDescriptor(), EditorTagComponent::CreateDescriptor(), EditorSphereShapeComponent::CreateDescriptor(), EditorDiskShapeComponent::CreateDescriptor(), @@ -104,7 +83,6 @@ namespace LmbrCentral EditorNavigationAreaComponent::CreateDescriptor(), EditorNavigationSeedComponent::CreateDescriptor(), EditorRandomTimedSpawnerComponent::CreateDescriptor(), - EditorGeometryCacheComponent::CreateDescriptor(), EditorSpawnerComponent::CreateDescriptor(), CopyDependencyBuilder::CopyDependencyBuilderComponent::CreateDescriptor(), DependencyBuilder::DependencyBuilderComponent::CreateDescriptor(), @@ -125,8 +103,6 @@ namespace LmbrCentral typeIds.emplace_back(descriptor->GetUuid()); } EBUS_EVENT(AzFramework::MetricsPlainTextNameRegistrationBus, RegisterForNameSending, typeIds); - - EditorMeshBus::Handler::BusConnect(); } LmbrCentralEditorModule::~LmbrCentralEditorModule() @@ -141,11 +117,6 @@ namespace LmbrCentral return requiredComponents; } - - bool LmbrCentralEditorModule::AddMeshComponentWithAssetId(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) - { - return AddMeshComponentWithMesh(targetEntity, meshAssetId); - } } // namespace LmbrCentral AZ_DECLARE_MODULE_CLASS(Gem_LmbrCentralEditor, LmbrCentral::LmbrCentralEditorModule) diff --git a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h index f180c21d8d..7a9dbd01ba 100644 --- a/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h +++ b/Gems/LmbrCentral/Code/Source/LmbrCentralEditor.h @@ -13,13 +13,6 @@ #include "LmbrCentral.h" -#include - -namespace Water -{ - class WaterVolumeConverter; -} - namespace LmbrCentral { /** @@ -31,7 +24,6 @@ namespace LmbrCentral */ class LmbrCentralEditorModule : public LmbrCentralModule - , public EditorMeshBus::Handler { public: AZ_RTTI(LmbrCentralEditorModule, "{1BF648D7-3703-4B52-A688-67C253A059F2}", LmbrCentralModule); @@ -39,7 +31,5 @@ namespace LmbrCentral LmbrCentralEditorModule(); ~LmbrCentralEditorModule(); AZ::ComponentTypeList GetRequiredSystemComponents() const override; - - bool AddMeshComponentWithAssetId(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) override; }; } // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/DecalComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/DecalComponent.cpp deleted file mode 100644 index 1892b930b7..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/DecalComponent.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "LmbrCentral_precompiled.h" -#include "DecalComponent.h" -#include -#include -#include -#include -#include - -namespace LmbrCentral -{ - void DecalConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(2, &VersionConverter)-> - Field("Visible", &DecalConfiguration::m_visible)-> - Field("ProjectionType", &DecalConfiguration::m_projectionType)-> - Field("Material", &DecalConfiguration::m_material)-> - Field("SortPriority", &DecalConfiguration::m_sortPriority)-> - Field("Depth", &DecalConfiguration::m_depth)-> - Field("Offset", &DecalConfiguration::m_position)-> - Field("Opacity", &DecalConfiguration::m_opacity)-> - Field("Angle Attenuation", &DecalConfiguration::m_angleAttenuation)-> - Field("Deferred", &DecalConfiguration::m_deferred)-> - Field("DeferredString", &DecalConfiguration::m_deferredString)-> - Field("Max View Distance", &DecalConfiguration::m_maxViewDist)-> - Field("View Distance Multiplier", &DecalConfiguration::m_viewDistanceMultiplier)-> - Field("Min Spec", &DecalConfiguration::m_minSpec) - ; - } - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->EBus("DecalComponentRequestBus") - ->Event("SetVisibility", &DecalComponentRequestBus::Events::SetVisibility) - ->Event("Show", &DecalComponentRequestBus::Events::Show) - ->Event("Hide", &DecalComponentRequestBus::Events::Hide) - ; - } - } - - // Private Static - bool DecalConfiguration::VersionConverter([[maybe_unused]] AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement) - { - // conversion from version 1: - // - Remove Normal - if (classElement.GetVersion() <= 1) - { - classElement.RemoveElementByName(AZ_CRC_CE("Normal")); - } - - return true; - } - - ////////////////////////////////////////////////////////////////////////// - - void DecalComponent::Reflect(AZ::ReflectContext* context) - { - DecalConfiguration::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1)-> - Field("DecalConfiguration", &DecalComponent::m_configuration); - ; - } - } - - ////////////////////////////////////////////////////////////////////////// - - DecalComponent::DecalComponent() - : m_decalRenderNode(nullptr) - { - m_materialBusHandler = aznew MaterialOwnerRequestBusHandlerImpl; - } - - DecalComponent::~DecalComponent() - { - delete m_materialBusHandler; - } - - - void DecalComponent::Activate() - { - } - - void DecalComponent::Deactivate() - { - } - - void DecalComponent::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world) - { - SDecalProperties decalProperties = m_configuration.GetDecalProperties(world); - if (m_decalRenderNode) - { - m_decalRenderNode->SetDecalProperties(decalProperties); - m_decalRenderNode->SetMatrix(AZTransformToLYTransform(world)); - } - } - - void DecalComponent::Show() - { - if (!m_decalRenderNode) - { - return; - } - - m_decalRenderNode->Hide(false); - } - - void DecalComponent::Hide() - { - if (!m_decalRenderNode) - { - return; - } - - m_decalRenderNode->Hide(true); - } - - void DecalComponent::SetVisibility(bool show) - { - if (show) - { - Show(); - } - else - { - Hide(); - } - } - - IRenderNode* DecalComponent::GetRenderNode() - { - return m_decalRenderNode; - } - - float DecalComponent::GetRenderNodeRequestBusOrder() const - { - return s_renderNodeRequestBusOrder; - } - - - bool DecalComponent::IsMaterialOwnerReady() - { - return m_materialBusHandler->IsMaterialOwnerReady(); - } - - void DecalComponent::SetMaterial(_smart_ptr material) - { - m_materialBusHandler->SetMaterial(material); - } - - _smart_ptr DecalComponent::GetMaterial() - { - return m_materialBusHandler->GetMaterial(); - } - - void DecalComponent::SetMaterialHandle(const MaterialHandle& materialHandle) - { - m_materialBusHandler->SetMaterialHandle(materialHandle); - } - - MaterialHandle DecalComponent::GetMaterialHandle() - { - return m_materialBusHandler->GetMaterialHandle(); - } - - void DecalComponent::SetMaterialParamVector4(const AZStd::string& name, const AZ::Vector4& value, int materialId) - { - m_materialBusHandler->SetMaterialParamVector4(name, value, materialId); - } - - void DecalComponent::SetMaterialParamVector3(const AZStd::string& name, const AZ::Vector3& value, int materialId) - { - m_materialBusHandler->SetMaterialParamVector3(name, value, materialId); - } - - void DecalComponent::SetMaterialParamColor(const AZStd::string& name, const AZ::Color& value, int materialId) - { - m_materialBusHandler->SetMaterialParamColor(name, value, materialId); - } - - void DecalComponent::SetMaterialParamFloat(const AZStd::string& name, float value, int materialId) - { - m_materialBusHandler->SetMaterialParamFloat(name, value, materialId); - } - - AZ::Vector4 DecalComponent::GetMaterialParamVector4(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamVector4(name, materialId); - } - - AZ::Vector3 DecalComponent::GetMaterialParamVector3(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamVector3(name, materialId); - } - - AZ::Color DecalComponent::GetMaterialParamColor(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamColor(name, materialId); - } - - float DecalComponent::GetMaterialParamFloat(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamFloat(name, materialId); - } - - - const float DecalComponent::s_renderNodeRequestBusOrder = 900.f; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/DecalComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/DecalComponent.h deleted file mode 100644 index 177e2075f8..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/DecalComponent.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -namespace LmbrCentral -{ - class MaterialOwnerRequestBusHandlerImpl; - - /*! - * Contains properties used to create decals, these properties are later propagated to the - * 3D engine decal system. - */ - class DecalConfiguration - { - public: - AZ_TYPE_INFO(DecalConfiguration, "{47082F75-428F-4353-AC82-FAE8AB017F3B}"); - - virtual ~DecalConfiguration() {} - - virtual AZ::u32 MajorPropertyChanged() { return AZ_CRC("RefreshNone", 0x98a5045b); } - virtual AZ::u32 MinorPropertyChanged() { return AZ_CRC("RefreshNone", 0x98a5045b); } - - SDecalProperties::EProjectionType m_projectionType = SDecalProperties::EProjectionType::ePlanar; - AZ::Vector3 m_position = AZ::Vector3::CreateZero(); - AZ::Transform m_explicitRightUpFront = AZ::Transform::CreateIdentity(); - AZ::u32 m_sortPriority = 16; - float m_depth = 1.f; - float m_viewDistanceMultiplier = 1.f; - bool m_visible = true; - bool m_deferred = false; - AZStd::string m_deferredString = ""; - float m_opacity = 1.0f; - float m_angleAttenuation = 1.0f; - float m_maxViewDist = 8000.0f; - EngineSpec m_minSpec = EngineSpec::Low; - - //! User-specified material override. - AzFramework::SimpleAssetReference m_material; - - AZ::EntityId m_editorEntityId; // Editor-only, not reflected. - - static void Reflect(AZ::ReflectContext* context); - - SDecalProperties GetDecalProperties(const AZ::Transform& transform) - { - SDecalProperties decalProperties; - decalProperties.m_projectionType = m_projectionType; - decalProperties.m_radius = 1.f; - - if (m_projectionType != SDecalProperties::ePlanar) - { - decalProperties.m_radius = decalProperties.m_normal.GetLength(); - } - - Matrix34 wtm = AZTransformToLYTransform(transform); - Matrix33 rotation(wtm); - decalProperties.m_explicitRightUpFront = rotation; - decalProperties.m_pos = wtm.TransformPoint(AZVec3ToLYVec3(m_position)); - decalProperties.m_normal = Vec3(0, 0, 1); - decalProperties.m_pMaterialName = m_material.GetAssetPath().c_str(); - decalProperties.m_sortPrio = m_sortPriority; - decalProperties.m_deferred = m_deferred; - decalProperties.m_opacity = m_opacity; - decalProperties.m_angleAttenuation = m_angleAttenuation; - decalProperties.m_depth = m_depth; - decalProperties.m_maxViewDist = m_maxViewDist; - decalProperties.m_minSpec = m_minSpec; - - return decalProperties; - } - - private: - - static bool VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement); - }; - - /*! - * Spawns decals as setup during edit time. - */ - class DecalComponent - : public AZ::Component - , public DecalComponentRequestBus::Handler - , public RenderNodeRequestBus::Handler - , public AZ::TransformNotificationBus::Handler - , public MaterialOwnerRequestBus::Handler - { - public: - - AZ_COMPONENT(DecalComponent, "{1C2CEAA8-786F-4684-8202-CA7D940D627B}"); - - DecalComponent(); - ~DecalComponent() override; - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component implementation. - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // DecalComponentRequests implementation. - void Show() override; - void Hide() override; - void SetVisibility(bool visible) override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // RenderNodeRequests implementation - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - static const float s_renderNodeRequestBusOrder; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AZ::TransformNotificationBus implementation. - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // MaterialOwnerRequestBus interface implementation - bool IsMaterialOwnerReady() override; - void SetMaterial(_smart_ptr) override; - _smart_ptr GetMaterial() override; - void SetMaterialHandle(const MaterialHandle& materialHandle) override; - MaterialHandle GetMaterialHandle() override; - void SetMaterialParamVector4( const AZStd::string& /*name*/, const AZ::Vector4& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamVector3( const AZStd::string& /*name*/, const AZ::Vector3& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamColor( const AZStd::string& /*name*/, const AZ::Color& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamFloat( const AZStd::string& /*name*/, float /*value*/, int /*materialId = 1*/) override; - AZ::Vector4 GetMaterialParamVector4( const AZStd::string& /*name*/, int /*materialId = 1*/) override; - AZ::Vector3 GetMaterialParamVector3( const AZStd::string& /*name*/, int /*materialId = 1*/) override; - AZ::Color GetMaterialParamColor( const AZStd::string& /*name*/, int /*materialId = 1*/) override; - float GetMaterialParamFloat( const AZStd::string& /*name*/, int /*materialId = 1*/) override; - /////////////////////////////////// - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("DecalService", 0xfb7f71ae)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& /*dependent*/) - { - } - - static void Reflect(AZ::ReflectContext* context); - - void SetConfiguration(const DecalConfiguration& configuration) - { - m_configuration = configuration; - } - - protected: - - IDecalRenderNode* m_decalRenderNode; - DecalConfiguration m_configuration; - MaterialOwnerRequestBusHandlerImpl* m_materialBusHandler; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorAreaLightComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorAreaLightComponent.cpp deleted file mode 100644 index 00c314400e..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorAreaLightComponent.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include "EditorAreaLightComponent.h" - -namespace LmbrCentral -{ - void EditorAreaLightComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Area Light", "The Area Light component allows an entity to light a defined area") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/AreaLight.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AreaLight.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-area-light.html") - ->Attribute(AZ::Edit::Attributes::ExportIfAllPlatformTags, AZStd::vector{AZ_CRC("renderer", 0xf199a19c)}) // Only export on platforms that render - ->Attribute(AZ::Edit::Attributes::RuntimeExportCallback, &EditorLightComponent::ExportLightComponent) - ; - } - } - - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class()->RequestBus("EditorAreaLightComponentBus"); - } - } - - void EditorAreaLightComponent::Init() - { - SetLightType(EditorLightConfiguration::LightType::Area); - EditorLightComponent::Init(); - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorAreaLightComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorAreaLightComponent.h deleted file mode 100644 index ec9bb594d5..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorAreaLightComponent.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include "EditorLightComponent.h" - -namespace LmbrCentral -{ - /*! - * In-editor point light component. - * Handles previewing and activating lights in the editor. - */ - class EditorAreaLightComponent - : public EditorLightComponent - { - public: - AZ_COMPONENT(EditorAreaLightComponent, "{1DE624B1-876F-4E0A-96A6-7B248FA2076F}", EditorLightComponent); - - static void Reflect(AZ::ReflectContext* context); - - void Init() override; - - protected: - const char* GetLightTypeText() const override - { - return "Area Light"; - } - }; -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorDecalComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorDecalComponent.cpp deleted file mode 100644 index a1803afb23..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorDecalComponent.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" -#include "EditorDecalComponent.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace LmbrCentral -{ - void EditorDecalComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - EditorDecalConfiguration::Reflect(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1)-> - Field("EditorDecalConfiguration", &EditorDecalComponent::m_configuration) - ; - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Decal", "The Decal component allows an entity to project a texture or material onto a mesh")-> - ClassElement(AZ::Edit::ClassElements::EditorData, "")-> - Attribute(AZ::Edit::Attributes::Category, "Rendering")-> - Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Decal.svg")-> - Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid())-> - Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Decal.png")-> - Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-decal.html")-> - DataElement(0, &EditorDecalComponent::m_configuration, "Settings", "Decal configuration")-> - Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) - ; - } - } - } - - ////////////////////////////////////////////////////////////////////////// - - void EditorDecalConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - - if (editContext) - { - editContext->Class( - "Render Settings", "Rendering options for the decal.")-> - ClassElement(AZ::Edit::ClassElements::EditorData, "")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))-> - - ClassElement(AZ::Edit::ClassElements::Group, "Decal Settings")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(0, &DecalConfiguration::m_position, "Offset", "")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - - DataElement(0, &DecalConfiguration::m_visible, "Visible", "")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - - DataElement(AZ::Edit::UIHandlers::ComboBox, &DecalConfiguration::m_projectionType, "Projection type", "")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MajorPropertyChanged)-> - EnumAttribute(SDecalProperties::EProjectionType::ePlanar, "Planar")-> - EnumAttribute(SDecalProperties::EProjectionType::eProjectOnTerrain, "On Terrain")-> - EnumAttribute(SDecalProperties::EProjectionType::eProjectOnTerrainAndStaticObjects, "On Terrain and Static Objects")-> - - DataElement(AZ::Edit::UIHandlers::Default, &DecalConfiguration::m_deferredString, "Deferred", "")-> - Attribute(AZ::Edit::Attributes::ReadOnly, true)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MajorPropertyChanged)-> - - DataElement(AZ::Edit::UIHandlers::SpinBox, &DecalConfiguration::m_sortPriority, "Sort priority", "Higher priority renders decals on top.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0)-> - Attribute(AZ::Edit::Attributes::Max, 255)-> - Attribute(AZ::Edit::Attributes::Step, 1)-> - - DataElement(AZ::Edit::UIHandlers::SpinBox, &DecalConfiguration::m_depth, "Depth", "")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.0001f)-> - Attribute(AZ::Edit::Attributes::Max, 10.f)-> - Attribute(AZ::Edit::Attributes::Step, 1.f / 255.f)-> - - DataElement(0, &DecalConfiguration::m_material, "Material", "")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MajorPropertyChanged)-> - - DataElement(AZ::Edit::UIHandlers::Slider, &DecalConfiguration::m_opacity, "Opacity", "Additional opacity setting on top of the distance from the decal to the surface")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 1.f)-> - Attribute(AZ::Edit::Attributes::Visibility, &DecalConfiguration::m_deferred)-> - - DataElement(AZ::Edit::UIHandlers::Slider, &DecalConfiguration::m_angleAttenuation, "Angle Attenuation", "amount of angle attenuation computation taken into account")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 1.f)-> - Attribute(AZ::Edit::Attributes::Visibility, &DecalConfiguration::m_deferred)-> - - ClassElement(AZ::Edit::ClassElements::Group, "Options")-> - - DataElement(AZ::Edit::UIHandlers::Default, &DecalConfiguration::m_maxViewDist, "Max view distance", "The furthest distance this decal can be seen from")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 8000.0f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - - DataElement(AZ::Edit::UIHandlers::SpinBox, &DecalConfiguration::m_viewDistanceMultiplier, "View distance multiplier", "")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, IRenderNode::VIEW_DISTANCE_MULTIPLIER_MAX)-> - - DataElement(AZ::Edit::UIHandlers::ComboBox, &DecalConfiguration::m_minSpec, "Minimum spec", "Min spec for light to be active.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &DecalConfiguration::MinorPropertyChanged)-> - EnumAttribute(EngineSpec::Never, "Never")-> - EnumAttribute(EngineSpec::VeryHigh, "Very high")-> - EnumAttribute(EngineSpec::High, "High")-> - EnumAttribute(EngineSpec::Medium, "Medium")-> - EnumAttribute(EngineSpec::Low, "Low") - ; - } - } - } - - ////////////////////////////////////////////////////////////////////////// - - AZ::u32 EditorDecalConfiguration::MajorPropertyChanged() - { - if (m_editorEntityId.IsValid()) - { - EBUS_EVENT_ID(m_editorEntityId, DecalComponentEditorRequests::Bus, RefreshDecal); - } - - return AZ::Edit::PropertyRefreshLevels::EntireTree; - } - - AZ::u32 EditorDecalConfiguration::MinorPropertyChanged() - { - if (m_editorEntityId.IsValid()) - { - EBUS_EVENT_ID(m_editorEntityId, DecalComponentEditorRequests::Bus, RefreshDecal); - } - - return AZ::Edit::PropertyRefreshLevels::None; - } - - ////////////////////////////////////////////////////////////////////////// - - EditorDecalComponent::EditorDecalComponent() - : m_materialLayersMask(0) - { - } - - EditorDecalComponent::~EditorDecalComponent() - { - } - - void EditorDecalComponent::Activate() - { - Base::Activate(); - } - - void EditorDecalComponent::Deactivate() - { - Base::Deactivate(); - } - - void EditorDecalComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - DecalComponent* decalComponent = gameEntity->CreateComponent(); - - if (decalComponent) - { - decalComponent->SetConfiguration(m_configuration); - } - } - - void EditorDecalComponent::OnEditorSpecChange() - { - RefreshDecal(); - } - - void EditorDecalComponent::RefreshDecal() - { - if (!m_decalRenderNode) - { - return; - } - - if (m_configuration.m_projectionType == SDecalProperties::EProjectionType::eProjectOnTerrainAndStaticObjects) - { - m_configuration.m_deferred = true; - m_configuration.m_deferredString = "Yes"; - } - else - { - m_configuration.m_deferred = false; - m_configuration.m_deferredString = "No"; - } - - m_renderFlags = 0; - - if (IsSelected()) - { - m_renderFlags |= ERF_SELECTED; - } - - // take the entity's visibility into account - bool visible = false; - AzToolsFramework::EditorEntityInfoRequestBus::EventResult( - visible, GetEntityId(), &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); - - const int configSpec = gEnv->pSystem->GetConfigSpec(true); - if (!visible || !m_configuration.m_visible || static_cast(configSpec) < static_cast(m_configuration.m_minSpec)) - { - m_renderFlags |= ERF_HIDDEN; - } - - //Set default material - if (m_configuration.m_material.GetAssetPath().empty()) - { - m_configuration.m_material.SetAssetPath("engineassets/materials/decals/default.mtl"); - } - - AZ::Transform transform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(transform, GetEntityId(), AZ::TransformBus, GetWorldTM); - - SDecalProperties decalProperties = m_configuration.GetDecalProperties(transform); - m_decalRenderNode->SetDecalProperties(decalProperties); - - m_renderFlags |= ERF_COMPONENT_ENTITY; - m_decalRenderNode->SetRndFlags(m_renderFlags); - m_decalRenderNode->SetMatrix(AZTransformToLYTransform(transform)); - m_decalRenderNode->SetMinSpec(static_cast(decalProperties.m_minSpec)); - m_decalRenderNode->SetMaterialLayers(m_materialLayersMask); - m_decalRenderNode->SetViewDistanceMultiplier(m_configuration.m_viewDistanceMultiplier); - } - - void EditorDecalComponent::SetPrimaryAsset(const AZ::Data::AssetId& id) - { - AZStd::string assetPath; - EBUS_EVENT_RESULT(assetPath, AZ::Data::AssetCatalogRequestBus, GetAssetPathById, id); - m_configuration.m_material.SetAssetPath(assetPath.c_str()); - RefreshDecal(); - EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, AddDirtyEntity, GetEntityId()); - } - - void EditorDecalComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - // Displays a small grid over the area where the decal will be applied. - if (!IsSelected()) - { - return; - } - - AZ::Transform transform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(transform, GetEntityId(), AZ::TransformBus, GetWorldTM); - - AZ::Vector3 x1 = transform.TransformPoint(AZ::Vector3(-1, 0, 0)); - AZ::Vector3 x2 = transform.TransformPoint(AZ::Vector3(1, 0, 0)); - AZ::Vector3 y1 = transform.TransformPoint(AZ::Vector3(0, -1, 0)); - AZ::Vector3 y2 = transform.TransformPoint(AZ::Vector3(0, 1, 0)); - AZ::Vector3 p = transform.TransformPoint(AZ::Vector3(0, 0, 0)); - AZ::Vector3 n = transform.TransformPoint(AZ::Vector3(0, 0, 1)); - - debugDisplay.SetColor(AZ::Vector4(1, 0, 0, 1)); - - debugDisplay.DrawLine(p, n); - debugDisplay.DrawLine(x1, x2); - debugDisplay.DrawLine(y1, y2); - - AZ::Vector3 p0 = transform.TransformPoint(AZ::Vector3(-1, -1, 0)); - AZ::Vector3 p1 = transform.TransformPoint(AZ::Vector3(-1, 1, 0)); - AZ::Vector3 p2 = transform.TransformPoint(AZ::Vector3(1, 1, 0)); - AZ::Vector3 p3 = transform.TransformPoint(AZ::Vector3(1, -1, 0)); - - debugDisplay.DrawLine(p0, p1); - debugDisplay.DrawLine(p1, p2); - debugDisplay.DrawLine(p2, p3); - debugDisplay.DrawLine(p3, p0); - debugDisplay.DrawLine(p0, p2); - debugDisplay.DrawLine(p1, p3); - } - - void EditorDecalComponent::OnEntityVisibilityChanged(bool /*visibility*/) - { - RefreshDecal(); - } - - IRenderNode* EditorDecalComponent::GetRenderNode() - { - return m_decalRenderNode; - } - - float EditorDecalComponent::GetRenderNodeRequestBusOrder() const - { - return DecalComponent::s_renderNodeRequestBusOrder; - } - - void EditorDecalComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& /*world*/) - { - RefreshDecal(); - } - - void EditorDecalComponent::SetMaterial(_smart_ptr material) - { - if (material) - { - m_configuration.m_material.SetAssetPath(material->GetName()); - } - else - { - m_configuration.m_material.SetAssetPath(""); - } - - RefreshDecal(); - - EBUS_EVENT(AzToolsFramework::ToolsApplicationEvents::Bus, InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); - } - - _smart_ptr EditorDecalComponent::GetMaterial() - { - return m_decalRenderNode->GetMaterial(); - } - - AZ::Aabb EditorDecalComponent::GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& /*viewportInfo*/) - { - return GetWorldBounds(); - } - - AZ::Aabb EditorDecalComponent::GetWorldBounds() - { - AZ::Transform transform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - - return GetLocalBounds().GetTransformedAabb(transform); - } - - AZ::Aabb EditorDecalComponent::GetLocalBounds() - { - AZ::Aabb bbox = AZ::Aabb::CreateNull(); - - bbox.AddPoint(AZ::Vector3(-1, -1, 0)); - bbox.AddPoint(AZ::Vector3(-1, 1, 0)); - bbox.AddPoint(AZ::Vector3(1, 1, 0)); - bbox.AddPoint(AZ::Vector3(1, -1, 0)); - - return bbox; - } - - bool EditorDecalComponent::EditorSelectionIntersectRayViewport(const AzFramework::ViewportInfo& /*viewportInfo*/, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) - { - AZ::Transform transform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - - AZ::Vector3 p0 = transform.TransformPoint(AZ::Vector3(-1, -1, 0)); - AZ::Vector3 p1 = transform.TransformPoint(AZ::Vector3(-1, 1, 0)); - AZ::Vector3 p2 = transform.TransformPoint(AZ::Vector3(1, 1, 0)); - AZ::Vector3 p3 = transform.TransformPoint(AZ::Vector3(1, -1, 0)); - float t{ 0.0f }; - - bool hitResult = AZ::Intersect::IntersectRayQuad(src, dir, p0, p1, p2, p3, t) != 0; - distance = t; - - return hitResult; - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorDecalComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorDecalComponent.h deleted file mode 100644 index f4b25f4a9a..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorDecalComponent.h +++ /dev/null @@ -1,145 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include "DecalComponent.h" - -namespace LmbrCentral -{ - /*! - * Extends DecalConfiguration structure to add editor functionality - * such as property handlers and visibility filters, as well as - * reflection for editing. - */ - class EditorDecalConfiguration - : public DecalConfiguration - { - public: - - AZ_TYPE_INFO(EditorDecalConfiguration, "{559556BE-F41E-43C0-9EE6-7048D84D7952}"); - - ~EditorDecalConfiguration() override {} - - static void Reflect(AZ::ReflectContext* context); - - AZ::u32 MajorPropertyChanged() override; - AZ::u32 MinorPropertyChanged() override; - }; - - /*! - * In-editor decal component. - * Handles placement of decals in editor. - */ - class EditorDecalComponent - : public AzToolsFramework::Components::EditorComponentBase - , private DecalComponentEditorRequests::Bus::Handler - , private MaterialOwnerRequestBus::Handler - , private RenderNodeRequestBus::Handler - , private AZ::TransformNotificationBus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private AzToolsFramework::EditorVisibilityNotificationBus::Handler - , private AzToolsFramework::EditorEvents::Bus::Handler - , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - , public AzFramework::BoundsRequestBus::Handler - { - private: - using Base = AzToolsFramework::Components::EditorComponentBase; - - public: - AZ_COMPONENT(EditorDecalComponent, "{BA3890BD-D2E7-4DB6-95CD-7E7D5525567A}", AzToolsFramework::Components::EditorComponentBase); - - EditorDecalComponent(); - ~EditorDecalComponent() override; - - // AZ::Component interface implementation - void Activate() override; - void Deactivate() override; - - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // AzToolsFramework::EditorVisibilityNotificationBus interface implementation - void OnEntityVisibilityChanged(bool visibility) override; - - // DecalComponentEditorRequests::Bus::Handler interface implementation - void RefreshDecal() override; - - // MaterialOwnerRequestBus interface implementation - void SetMaterial(_smart_ptr) override; - _smart_ptr GetMaterial() override; - - // RenderNodeRequestBus::Handler interface implementation - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - - // TransformNotificationBus::Handler interface implementation - void OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& /*world*/) override; - - // EditorComponentSelectionRequestsBus::Handler interface implementation - AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo&) override; - bool SupportsEditorRayIntersect() override { return true; }; - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, - float& distance) override; - - // BoundsRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - void BuildGameEntity(AZ::Entity* gameEntity) override; - - //! Called when you want to change the game asset through code (like when creating components based on assets). - void SetPrimaryAsset(const AZ::Data::AssetId& assetId) override; - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - DecalComponent::GetProvidedServices(provided); - } - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - DecalComponent::GetDependentServices(dependent); - dependent.push_back(AZ_CRC_CE("EditorVisibilityService")); - } - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - DecalComponent::GetRequiredServices(required); - } - - static void Reflect(AZ::ReflectContext* context); - - protected: - - EditorDecalConfiguration m_configuration; - - IDecalRenderNode* m_decalRenderNode; - uint32 m_renderFlags; - - uint8 m_materialLayersMask; - - private: - // AzToolsFramework::EditorEvents interface implementation - void OnEditorSpecChange() override; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorEnvProbeComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorEnvProbeComponent.cpp deleted file mode 100644 index 98327471e5..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorEnvProbeComponent.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include - -#include "EditorEnvProbeComponent.h" - -namespace LmbrCentral -{ - void EditorEnvProbeComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Environment Probe", "The Environment Probe component is used to achieve the right visual quality for a space and help determine proper reflections, ambient diffuse values, particle diffuse values, and shadow colors") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/EnvironmentProbe.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/EnvironmentProbe.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-environment-probe.html") - ->Attribute(AZ::Edit::Attributes::RuntimeExportCallback, &EditorLightComponent::ExportLightComponent) - ; - } - } - - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class()->RequestBus("EditorProbeLightComponentBus"); - } - } - - void EditorEnvProbeComponent::Init() - { - SetLightType(EditorLightConfiguration::LightType::Probe); - EditorLightComponent::Init(); - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorEnvProbeComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorEnvProbeComponent.h deleted file mode 100644 index 5336546caa..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorEnvProbeComponent.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include "EditorLightComponent.h" - -namespace LmbrCentral -{ - /*! - * In-editor point light component. - * Handles previewing and activating lights in the editor. - */ - class EditorEnvProbeComponent - : public EditorLightComponent - { - public: - AZ_COMPONENT(EditorEnvProbeComponent, "{8DBD6035-583E-409F-AFD9-F36829A0655D}", EditorLightComponent); - - static void Reflect(AZ::ReflectContext* context); - - void Init() override; - - protected: - const char* GetLightTypeText() const override - { - return "Environment Probe"; - } - }; -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorGeomCacheComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorGeomCacheComponent.cpp deleted file mode 100644 index 37d04b94ba..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorGeomCacheComponent.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" -#include "EditorGeomCacheComponent.h" - -#include -#include - -namespace LmbrCentral -{ - void EditorGeometryCacheCommon::Reflect(AZ::ReflectContext* context) - { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ; - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("Editor Geom Cache Common Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; - - editContext->Class("Geom Cache Common Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_visible, "Visible", "Should the GeomCache be rendered.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnRenderOptionsChanged) - - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &GeometryCacheCommon::m_minSpec, "Min Spec", "The minimum graphics spec where this GeomCache will be rendered.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnRenderOptionsChanged) - ->EnumAttribute(EngineSpec::Never, "Never") - ->EnumAttribute(EngineSpec::VeryHigh, "Very high") - ->EnumAttribute(EngineSpec::High, "High") - ->EnumAttribute(EngineSpec::Medium, "Medium") - ->EnumAttribute(EngineSpec::Low, "Low") - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_geomCacheAsset, "Geom Cache", "The Alembic Geometry Cache asset.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnGeomCacheAssetChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_materialOverrideAsset, "Material Override", "Optional material override asset.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnMaterialOverrideChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_loop, "Loop", "Should the animation loop.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnLoopChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_playOnStart, "Play on Start", "Should the alembic animation play when the component activates.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnPlayOnStartChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_startTime, "Start Time", "The time point that the animation should start at.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnStartTimeChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_streamInDistance, "Stream In Distance", "How close does the viewer need to be for the GeomCache to begin streaming into memory.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnStreamInDistanceChanged) - - ->ClassElement(AZ::Edit::ClassElements::Group, "Stand-in Settings") - ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_firstFrameStandin, "First Frame Stand-in", "The entity that should stand in for this GeomCache before playback begins.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnFirstFrameStandinChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_lastFrameStandin, "Last Frame Stand-in", "The entity that should stand in for this GeomCache after playback has ended.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnLastFrameStandinChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_standin, "Stand-in", "The entity that should stand in for this GeomCache when the viewer is past the Stand-in Distance.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnStandinChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_standinDistance, "Stand-in Distance", "How close does the viewer need to be before the GeomCache replaces the Stand-in.") - - ->ClassElement(AZ::Edit::ClassElements::Group, "Options") - ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_maxViewDistance, "Max View Distance", "That maximum distance that this GeomCache can be viewed from.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnMaxViewDistanceChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_viewDistanceMultiplier, "View Distance Multiplier", "Multiplied to the Max View Distance to get the final max view distance.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnViewDistanceMultiplierChanged) - - ->DataElement(AZ::Edit::UIHandlers::Slider, &GeometryCacheCommon::m_lodDistanceRatio, "LOD Distance Ratio", "Controls LOD ratio over distance.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnLODDistanceRatioChanged) - ->Attribute(AZ::Edit::Attributes::Min, 0) - ->Attribute(AZ::Edit::Attributes::Max, 255) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_castShadows, "Cast Shadows", "Should the GeomCache cast shadows.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnRenderOptionsChanged) - - ->DataElement(AZ::Edit::UIHandlers::Default, &GeometryCacheCommon::m_useVisAreas, "Use Vis Areas", "Should the GeomCache be affected by VisAreas.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GeometryCacheCommon::OnRenderOptionsChanged) - ; - } - } - } - - void EditorGeometryCacheCommon::Activate() - { - GeometryCacheCommon::Activate(); - EditorGeometryCacheComponentRequestBus::Handler::BusConnect(m_entityId); - - //Store the serialized results here so that we can properly react to stand-in changes after level load - m_prevFirstFrameStandin = m_firstFrameStandin; - m_prevLastFrameStandin = m_lastFrameStandin; - m_prevStandin = m_standin; - } - - void EditorGeometryCacheCommon::Deactivate() - { - EditorGeometryCacheComponentRequestBus::Handler::BusDisconnect(m_entityId); - GeometryCacheCommon::Deactivate(); - } - - void EditorGeometryCacheCommon::SetMinSpec(EngineSpec minSpec) - { - m_minSpec = minSpec; - OnRenderOptionsChanged(); - } - - void EditorGeometryCacheCommon::SetPlayOnStart(bool playOnStart) - { - m_playOnStart = playOnStart; - OnPlayOnStartChanged(); - } - - void EditorGeometryCacheCommon::SetMaxViewDistance(float maxViewDistance) - { - m_maxViewDistance = maxViewDistance; - OnMaxViewDistanceChanged(); - } - - void EditorGeometryCacheCommon::SetViewDistanceMultiplier(float viewDistanceMultiplier) - { - m_viewDistanceMultiplier = viewDistanceMultiplier; - OnViewDistanceMultiplierChanged(); - } - - void EditorGeometryCacheCommon::SetLODDistanceRatio(AZ::u32 lodDistanceRatio) - { - m_lodDistanceRatio = lodDistanceRatio; - OnLODDistanceRatioChanged(); - } - - void EditorGeometryCacheCommon::SetCastShadows(bool castShadows) - { - m_castShadows = castShadows; - OnRenderOptionsChanged(); - } - - void EditorGeometryCacheCommon::SetUseVisAreas(bool useVisAreas) - { - m_useVisAreas = useVisAreas; - OnRenderOptionsChanged(); - } - - void EditorGeometryCacheCommon::OnFirstFrameStandinChanged() - { - //We only need to remove the prev stand-in from the geom cache's hierarchy if it's not used anywhere else - bool removePrevFirstFrameStandinTransform = false; - if (m_prevFirstFrameStandin != m_prevStandin && m_prevFirstFrameStandin != m_prevLastFrameStandin) - { - removePrevFirstFrameStandinTransform = true; - } - HandleStandinChanged(m_prevFirstFrameStandin, m_firstFrameStandin, removePrevFirstFrameStandinTransform); - - m_prevFirstFrameStandin = m_firstFrameStandin; - } - - void EditorGeometryCacheCommon::OnLastFrameStandinChanged() - { - //We only need to remove the prev stand-in from the geom cache's hierarchy if it's not used anywhere else - bool removePrevLastFrameStandinTransform = false; - if (m_prevLastFrameStandin != m_prevStandin && m_prevLastFrameStandin != m_prevFirstFrameStandin) - { - removePrevLastFrameStandinTransform = true; - } - HandleStandinChanged(m_prevLastFrameStandin, m_lastFrameStandin, removePrevLastFrameStandinTransform); - - m_prevLastFrameStandin = m_lastFrameStandin; - } - - void EditorGeometryCacheCommon::OnStandinChanged() - { - //We only need to remove the prev stand-in from the geom cache's hierarchy if it's not used anywhere else - bool removePrevStandinTransform = false; - if (m_prevStandin != m_prevLastFrameStandin && m_prevStandin != m_prevFirstFrameStandin) - { - removePrevStandinTransform = true; - } - HandleStandinChanged(m_prevStandin, m_standin, removePrevStandinTransform); - m_prevStandin = m_standin; - } - - void EditorGeometryCacheCommon::HandleStandinChanged(const AZ::EntityId& prevStandinId, const AZ::EntityId& newStandinId, bool evictPrevStandinTransform) - { - //Undo modifications we've made to the stand-in entity - if (prevStandinId.IsValid() && evictPrevStandinTransform) - { - //If this stand-in isn't currently active it may be set to invisible. If it's not going to be a stand-in anymore we want it to be visible - MeshComponentRequestBus::Event(prevStandinId, &MeshComponentRequestBus::Events::SetVisibility, true); - //If it's not going to be a stand-in anymore it also doesn't need to be parented. User can re-parent if needed - AZ::TransformBus::Event(prevStandinId, &AZ::TransformBus::Events::SetParent, AZ::EntityId()); - } - - //Parent new stand-in to geometry cache transform - AZ::TransformBus::Event(newStandinId, &AZ::TransformBus::Events::SetParent, m_entityId); - - //Standin will be made visible if necessary in GeomCacheCommon::OnTick - MeshComponentRequestBus::Event(m_standin, &MeshComponentRequestBus::Events::SetVisibility, false); - MeshComponentRequestBus::Event(m_firstFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, false); - MeshComponentRequestBus::Event(m_lastFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, false); - - //Force stand-in logic to refresh - m_currentStandinType = StandinType::None; - } - - void EditorGeometryCacheCommon::SetMaterial(_smart_ptr material) - { - GeometryCacheCommon::SetMaterial(material); - - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); - } - - void EditorGeometryCacheComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides) - { - provides.push_back(AZ_CRC("GeomCacheService", 0x3d2bc48c)); - } - - void EditorGeometryCacheComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires) - { - requires.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - void EditorGeometryCacheComponent::Reflect(AZ::ReflectContext* context) - { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("Common", &EditorGeometryCacheComponent::m_common) - ; - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("Geometry Cache", "Controls playback of baked vertex animations.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/GeometryCache.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/GeometryCache.png") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "http://docs.aws.amazon.com/console/lumberyard/userguide/geom-cache-component") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorGeometryCacheComponent::m_common, "Common", "No Description") - ; - } - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class() - ->RequestBus("GeometryCacheComponentRequestBus") - ->RequestBus("GeometryCacheComponentNotificationBus") - ; - } - - EditorGeometryCacheCommon::Reflect(context); - } - - void EditorGeometryCacheComponent::Init() - { - m_common.Init(GetEntityId()); - } - - void EditorGeometryCacheComponent::Activate() - { - m_common.Activate(); - - AzToolsFramework::Components::EditorComponentBase::Activate(); - - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); - AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId()); - - //Get initial world transform for debug rendering - m_currentWorldTransform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(m_currentWorldTransform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - } - - void EditorGeometryCacheComponent::Deactivate() - { - AzToolsFramework::Components::EditorComponentBase::Deactivate(); - - AZ::TransformNotificationBus::Handler::BusDisconnect(GetEntityId()); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(GetEntityId()); - - m_common.Deactivate(); - } - - void EditorGeometryCacheComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId) - { - m_common.SetGeomCacheAsset(assetId); - } - - void EditorGeometryCacheComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - gameEntity->CreateComponent(&m_common); - } - - void EditorGeometryCacheComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - // Don't draw extra visualization unless selected. - if (!IsSelected()) - { - return; - } - - debugDisplay.PushMatrix(m_currentWorldTransform); - - debugDisplay.SetColor(AZ::Vector4(1.0f, 1.0f, 1.0f, 1.0f)); - - debugDisplay.DrawWireSphere(AZ::Vector3::CreateZero(), m_common.GetStandInDistance()); - debugDisplay.DrawWireSphere(AZ::Vector3::CreateZero(), m_common.GetStreamInDistance()); - - debugDisplay.PopMatrix(); - } - - void EditorGeometryCacheComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_currentWorldTransform = world; - } - -} //namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorGeomCacheComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorGeomCacheComponent.h deleted file mode 100644 index 9fd64750a2..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorGeomCacheComponent.h +++ /dev/null @@ -1,133 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include - -#include -#include - -#include "GeomCacheComponent.h" - -namespace LmbrCentral -{ - /** - * Editor extensions for the GeometryCacheCommon - * - * Some parameters of the GeometryCache we only care - * about being able to edit on a bus at edit time. Mostly - * for legacy conversion. Also this class handles the - * PlayOnStart parameter differently. - */ - class EditorGeometryCacheCommon - : public GeometryCacheCommon - , public EditorGeometryCacheComponentRequestBus::Handler - { - public: - AZ_TYPE_INFO_LEGACY(EditorGeometryCacheCommon, "{ACE31D8E-F7BC-48B9-950E-AE191E50A80F}", GeometryCacheCommon); - AZ_CLASS_ALLOCATOR(EditorGeometryCacheCommon, AZ::SystemAllocator, 0); - - static void Reflect(AZ::ReflectContext* context); - - void Activate() override; - void Deactivate() override; - - void SetMinSpec(EngineSpec minSpec) override; - EngineSpec GetMinSpec() override { return m_minSpec; } - - void SetPlayOnStart(bool playOnStart) override; - bool GetPlayOnStart() override { return m_playOnStart; } - - void SetMaxViewDistance(float maxViewDistance) override; - float GetMaxViewDistance() override { return m_maxViewDistance; } - - void SetViewDistanceMultiplier(float viewDistanceMultiplier) override; - float GetViewDistanceMultiplier() override { return m_viewDistanceMultiplier; } - - void SetLODDistanceRatio(AZ::u32 lodDistanceRatio) override; - AZ::u32 GetLODDistanceRatio() override { return m_lodDistanceRatio; } - - void SetCastShadows(bool castShadows) override; - bool GetCastShadows() override { return m_castShadows; } - - void SetUseVisAreas(bool useVisAreas) override; - bool GetUseVisAreas() override { return m_useVisAreas; } - void SetMaterial(_smart_ptr material) override; - private: - - //We want the playOnStart param to reflect playing immediately in the editor - void OnPlayOnStartChanged() override - { - m_playing = m_playOnStart; - m_currentTime = m_startTime; - - //As in GeomCacheCommon::Activate we reset m_currentTime to m_startTime so - //that animations begin at the requested time. - } - - void OnFirstFrameStandinChanged() override; - void OnLastFrameStandinChanged() override; - void OnStandinChanged() override; - - void HandleStandinChanged(const AZ::EntityId& prevStandinId, const AZ::EntityId& newStandinId, bool evictPrevStandinTransform); //Handles the common logic for OnStandinXChanged events - - AZ::EntityId m_prevFirstFrameStandin; - AZ::EntityId m_prevLastFrameStandin; - AZ::EntityId m_prevStandin; - - }; - - /** - * The Edit-time implementation of the GeometryCache component - */ - class EditorGeometryCacheComponent - : public AzToolsFramework::Components::EditorComponentBase - , public AzFramework::EntityDebugDisplayEventBus::Handler - , public AZ::TransformNotificationBus::Handler - { - public: - friend class GeomCacheConverter; - - AZ_COMPONENT(EditorGeometryCacheComponent, "{045C0C58-C13E-49B0-A471-D4AC5D3FC6BD}", AzToolsFramework::Components::EditorComponentBase); - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires); - static void Reflect(AZ::ReflectContext* context); - - ~EditorGeometryCacheComponent() = default; - - // EditorComponentBase - void Init() override; - void Activate() override; - void Deactivate() override; - - void SetPrimaryAsset(const AZ::Data::AssetId& assetId) override; - - void BuildGameEntity(AZ::Entity* gameEntity) override; - - private: - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // AZ::TransformNotificationBus - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - //Reflected members - EditorGeometryCacheCommon m_common; - - //Unreflected members - AZ::Transform m_currentWorldTransform; - }; - -} //namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorHighQualityShadowComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorHighQualityShadowComponent.cpp deleted file mode 100644 index 30cea4619f..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorHighQualityShadowComponent.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include "EditorHighQualityShadowComponent.h" -#include -#include - - - -namespace LmbrCentral -{ - void EditorHighQualityShadowConfig::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - - if (editContext) - { - editContext->Class( - "Shadow Map Settings", "Settings for the entity's shadow map") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->DataElement(AZ::Edit::UIHandlers::Default, &HighQualityShadowConfig::m_enabled, "Enabled", "Enable the shadow map") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &HighQualityShadowConfig::EditorRefresh) - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &HighQualityShadowConfig::m_constBias, "Const Bias", "Constant bias") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 1.f) - ->Attribute(AZ::Edit::Attributes::Step, 0.001f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &HighQualityShadowConfig::EditorRefresh) - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &HighQualityShadowConfig::m_slopeBias, "Slope Bias", "Slope bias") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 1.f) - ->Attribute(AZ::Edit::Attributes::Step, 0.01f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &HighQualityShadowConfig::EditorRefresh) - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &HighQualityShadowConfig::m_jitter, "Jitter", "Jitter") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 1.f) - ->Attribute(AZ::Edit::Attributes::Step, 0.01f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &HighQualityShadowConfig::EditorRefresh) - ->DataElement(AZ::Edit::UIHandlers::Vector3, &HighQualityShadowConfig::m_bboxScale, "Bounding Box Scale", "Scale applied to the shadow frustum") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &HighQualityShadowConfig::EditorRefresh) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &HighQualityShadowConfig::m_shadowMapSize, "Shadow Map Size", "Shadow map size") - ->Attribute(AZ::Edit::Attributes::EnumValues, AZStd::vector > { - AZ::Edit::EnumConstant(256, "256"), - AZ::Edit::EnumConstant(512, "512"), - AZ::Edit::EnumConstant(1024, "1024"), - AZ::Edit::EnumConstant(2048, "2048"), - AZ::Edit::EnumConstant(8192, "8192") - }) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &HighQualityShadowConfig::EditorRefresh) - ; - } - } - } - - void EditorHighQualityShadowConfig::EditorRefresh() - { - if (m_entityId.IsValid()) - { - EditorHighQualityShadowComponentRequestBus::Event(m_entityId, &EditorHighQualityShadowComponentRequests::RefreshProperties); - } - } - - void EditorHighQualityShadowComponent::Reflect(AZ::ReflectContext* context) - { - EditorHighQualityShadowConfig::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("EditorHighQualityShadowConfig", &EditorHighQualityShadowComponent::m_config); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - - if (editContext) - { - editContext->Class("High Quality Shadow", "Assigns a unique shadow map to the entity to provide higher quality shadows. Has performance and memory impact so use sparingly.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Shadow.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Shadow.png") - ->Attribute(AZ::Edit::Attributes::PreferNoViewportIcon, true) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-high-quality-shadow.html") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorHighQualityShadowComponent::m_config, "Shadow Map Settings", "Settings for the entity's unique shadow map") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ; - } - } - } - - void EditorHighQualityShadowComponent::Activate() - { - m_config.m_entityId = GetEntityId(); - EditorHighQualityShadowComponentRequestBus::Handler::BusConnect(GetEntityId()); - MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); - } - - void EditorHighQualityShadowComponent::Deactivate() - { - HighQualityShadowComponentUtils::RemoveShadow(GetEntityId()); - EditorHighQualityShadowComponentRequestBus::Handler::BusDisconnect(); - MeshComponentNotificationBus::Handler::BusDisconnect(GetEntityId()); - } - - void EditorHighQualityShadowComponent::RefreshProperties() - { - HighQualityShadowComponentUtils::ApplyShadowSettings(GetEntityId(), m_config); - } - - void EditorHighQualityShadowComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - if (HighQualityShadowComponent* runtimeComponent = gameEntity->CreateComponent()) - { - runtimeComponent->m_config = m_config; - } - } - - void EditorHighQualityShadowComponent::OnMeshCreated([[maybe_unused]] const AZ::Data::Asset& asset) - { - HighQualityShadowComponentUtils::ApplyShadowSettings(GetEntityId(), m_config); - } - - void EditorHighQualityShadowComponent::OnMeshDestroyed() - { - HighQualityShadowComponentUtils::RemoveShadow(GetEntityId()); - } - - -} // namespace LmbrCentral - - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorHighQualityShadowComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorHighQualityShadowComponent.h deleted file mode 100644 index 82ba0f1514..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorHighQualityShadowComponent.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include "HighQualityShadowComponent.h" - -namespace LmbrCentral -{ - /** - * Extends HighQualityShadowConfig structure for editor functionality. - */ - class EditorHighQualityShadowConfig - : public HighQualityShadowConfig - { - public: - AZ_TYPE_INFO(EditorHighQualityShadowConfig, "{4A7D67C6-E689-427A-B126-A71A4BF8A2C7}"); - - static void Reflect(AZ::ReflectContext* context); - - AZ::EntityId m_entityId; // Editor-only, not reflected. - - void EditorRefresh() override; - }; - - /*! - * In-editor high quality shadow component. - */ - class EditorHighQualityShadowComponent - : public AzToolsFramework::Components::EditorComponentBase - , public EditorHighQualityShadowComponentRequestBus::Handler - , public MeshComponentNotificationBus::Handler - { - public: - - AZ_COMPONENT(EditorHighQualityShadowComponent, "{9C86E09D-0727-476E-A4A1-25989CDBF9C6}", AzToolsFramework::Components::EditorComponentBase); - - void BuildGameEntity(AZ::Entity* gameEntity) override; - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // MeshComponentNotificationBus interface implementation - void OnMeshCreated(const AZ::Data::Asset& asset) override; - void OnMeshDestroyed() override; - /////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // EditorHighQualityShadowComponentRequestBus interface implementation - void RefreshProperties() override; - /////////////////////////////////// - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("HighQualityShadowService", 0x43dea981)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("HighQualityShadowService", 0x43dea981)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - // HighQualityShadowComponent is only applicable to Entities that cast and/or receive shadows. - required.push_back(AZ_CRC("MeshService", 0x71d8a455)); - } - - static void Reflect(AZ::ReflectContext* context); - - protected: - - EditorHighQualityShadowConfig m_config; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorLensFlareComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorLensFlareComponent.cpp deleted file mode 100644 index 20e6799df6..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorLensFlareComponent.cpp +++ /dev/null @@ -1,564 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include "EditorLensFlareComponent.h" -#include "LightComponent.h" - -namespace LmbrCentral -{ - void EditorLensFlareComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - EditorLensFlareConfiguration::Reflect(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1)-> - Field("Visible", &EditorLensFlareComponent::m_visible)-> - Field("LensFlareLibrary", &EditorLensFlareComponent::m_asset)-> - Field("SelectedLensFlare", &EditorLensFlareComponent::m_selectedLensFlareName)-> - Field("EditorLensFlareConfiguration", &EditorLensFlareComponent::m_configuration) - ; - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Lens Flare", "The Lens Flare component allows the placement of a lens flare on an entity") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/LensFlare.svg") - ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/LensFlare.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-lens-flare.html") - - ->DataElement(0, &EditorLensFlareComponent::m_configuration, "Settings", "Lens flare configuration") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &EditorLensFlareComponent::m_visible, "Visible", "The current visibility status of this lens flare") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorLensFlareComponent::OnVisibleChanged) - - ->DataElement(0, &EditorLensFlareComponent::m_asset, "Library", "The selected library of lens flares.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorLensFlareComponent::OnAssetChanged) - - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorLensFlareComponent::m_selectedLensFlareName, "Lens flare", "The selected lens flare in this library.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorLensFlareComponent::OnLensFlareSelected) - ->Attribute(AZ::Edit::Attributes::StringList, &EditorLensFlareComponent::GetLensFlarePaths) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; - } - } - } - - void EditorLensFlareConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Configuration", "Lens Flare configuration")-> - - ClassElement(AZ::Edit::ClassElements::EditorData, "")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))-> - - ClassElement(AZ::Edit::ClassElements::Group, "Flare Settings")-> - - DataElement(AZ::Edit::UIHandlers::ComboBox, &LensFlareConfiguration::m_minSpec, "Minimum spec", "Min spec for light to be active.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - EnumAttribute(EngineSpec::Never, "Never")-> - EnumAttribute(EngineSpec::VeryHigh, "Very high")-> - EnumAttribute(EngineSpec::High, "High")-> - EnumAttribute(EngineSpec::Medium, "Medium")-> - EnumAttribute(EngineSpec::Low, "Low")-> - - DataElement(0, &LensFlareConfiguration::m_lensFlareFrustumAngle, "FOV", "The lens flare FOV angle")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 1.f)-> - Attribute(AZ::Edit::Attributes::Max, 360.f)-> - Attribute(AZ::Edit::Attributes::Suffix, " degrees")-> - - DataElement(AZ::Edit::UIHandlers::Default, &LensFlareConfiguration::m_size, "Size", "The size of the lens flare")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - - DataElement(0, &LensFlareConfiguration::m_attachToSun, "Attach to sun", "Attach this flare to the sun")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::AttachToSunChanged)-> - - DataElement(0, &LensFlareConfiguration::m_useVisAreas, "Use VisAreas", "Lens Flares is affected by VisAreas")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - - DataElement(0, &LensFlareConfiguration::m_indoorOnly, "Indoor only", "Indoor only")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - - DataElement(0, &LensFlareConfiguration::m_onInitially, "On initially", "The lens flare is initially turned on.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - - DataElement(0, &LensFlareConfiguration::m_viewDistMultiplier, "View distance multiplier", "Adjusts max view distance. If 1.0 then default is used. 1.1 would be 10% further than default.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - // Will be visible if attach to sun is false. - Attribute(AZ::Edit::Attributes::Visibility, &LensFlareConfiguration::ShouldViewDistanceMultiplier)-> - Attribute(AZ::Edit::Attributes::Suffix, "x")-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - - ClassElement(AZ::Edit::ClassElements::Group, "Color Settings")-> - - DataElement(AZ::Edit::UIHandlers::Color, &LensFlareConfiguration::m_tint, "Tint", "Lens flare color tint")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - - DataElement(AZ::Edit::UIHandlers::Color, &LensFlareConfiguration::m_tintAlpha, "Tint [alpha]", "Lens flare alpha tint")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0)-> - Attribute(AZ::Edit::Attributes::Max, 255)-> - Attribute(AZ::Edit::Attributes::Step, 1)-> - - DataElement(0, &LensFlareConfiguration::m_brightness, "Brightness", "Lens flare brightness")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, "x")-> - - ClassElement(AZ::Edit::ClassElements::Group, "Animation")-> - - DataElement(0, &LensFlareConfiguration::m_syncAnimWithLight, "Sync with light", "When checked uses the animation settings of a provided light")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::SyncAnimationChanged)-> - - DataElement(0, &LensFlareConfiguration::m_lightEntity, "Light", "Entity that has a light component to sync with")-> - Attribute(AZ::Edit::Attributes::Visibility, &LensFlareConfiguration::m_syncAnimWithLight)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - - DataElement(0, &LensFlareConfiguration::m_animIndex, "Style", "Light animation curve ID (\"style\") as it corresponds to values in Light.cfx")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - Attribute(AZ::Edit::Attributes::Max, 255)-> - Attribute(AZ::Edit::Attributes::Visibility, &LensFlareConfiguration::ShouldShowAnimationSettings)-> - - DataElement(0, &LensFlareConfiguration::m_animSpeed, "Speed", "Multiple of the base animation rate")-> - Attribute(AZ::Edit::Attributes::Visibility, &LensFlareConfiguration::ShouldShowAnimationSettings)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Max, 4.f)-> - Attribute(AZ::Edit::Attributes::Suffix, "x")-> - - DataElement(0, &LensFlareConfiguration::m_animPhase, "Phase", "Animation start offset from 0 to 1. 0.1 would be 10% into the animation")-> - Attribute(AZ::Edit::Attributes::Visibility, &LensFlareConfiguration::ShouldShowAnimationSettings)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LensFlareConfiguration::PropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Max, 1.f) - ; - } - } - } - - AZ::u32 EditorLensFlareConfiguration::PropertyChanged() - { - if (m_editorEntityId.IsValid()) - { - if (m_syncAnimWithLight && m_lightEntity.IsValid()) - { - //Get the config of the light we want to sync with - LmbrCentral::LightConfiguration lightConfig; - - EBUS_EVENT_ID_RESULT(lightConfig, m_lightEntity, EditorLightComponentRequestBus, GetConfiguration); - - m_syncAnimIndex = lightConfig.m_animIndex; - m_syncAnimSpeed = lightConfig.m_animSpeed; - m_syncAnimPhase = lightConfig.m_animPhase; - } - - EBUS_EVENT_ID(m_editorEntityId, EditorLensFlareComponentRequestBus, RefreshLensFlare); - } - - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 EditorLensFlareConfiguration::SyncAnimationChanged() - { - if (m_syncAnimWithLight) - { - LightSettingsNotificationsBus::Handler::BusConnect(m_editorEntityId); - } - else - { - LightSettingsNotificationsBus::Handler::BusDisconnect(); - } - - PropertyChanged(); - - return AZ_CRC("RefreshEntireTree", 0xefbc823c); - } - - AZ::u32 EditorLensFlareConfiguration::AttachToSunChanged() - { - // if attached to the sun , then use VIEW_DISTANCE_MULTIPLIER_MAX value - // else use the value set by user. - if (m_attachToSun) - { - m_viewDistMultiplierUser = m_viewDistMultiplier; - m_viewDistMultiplier = static_cast(IRenderNode::VIEW_DISTANCE_MULTIPLIER_MAX); - } - else - { - // We restore the cache user set value when it is not attached to the sun. - m_viewDistMultiplier = m_viewDistMultiplierUser; - } - - PropertyChanged(); - - return AZ_CRC("RefreshEntireTree", 0xefbc823c); - } - void EditorLensFlareConfiguration::AnimationSettingsChanged() - { - PropertyChanged(); - } - - void EditorLensFlareComponent::Init() - { - Base::Init(); - - //Set this in Init because it will never change and doesn't need to be reset if the component re-activates - m_configuration.m_material.SetAssetPath("EngineAssets/Materials/lens_optics"); - } - - void EditorLensFlareComponent::Activate() - { - Base::Activate(); - - //Trigger asset loading so the the editor could show right content for the dropdown. - //Don't call OnAssetChanged because we don't need to clear any serialized data - //nor do we need to check for bus connection. - if (m_asset.GetId().IsValid()) - { - //load LensFlare asset - AZ::Data::AssetBus::Handler::BusConnect(m_asset.GetId()); - m_asset.QueueLoad(); - } - - m_selectedLensFlareLibrary = GetLibraryNameFromAsset(); - m_selectedLensFlareName = GetFlareNameFromPath(m_configuration.m_lensFlare); - - const AZ::EntityId entityId = GetEntityId(); - m_configuration.m_editorEntityId = entityId; - - m_light.SetEntity(entityId); - RefreshLensFlare(); - - //Check to see if we need to start connected to the LightSettingsNotificationBus - m_configuration.SyncAnimationChanged(); - // We call this one in order to cache the user set value. - m_configuration.m_viewDistMultiplierUser = m_configuration.m_viewDistMultiplier; - - m_configuration.AttachToSunChanged(); - - EditorLensFlareComponentRequestBus::Handler::BusConnect(entityId); - RenderNodeRequestBus::Handler::BusConnect(entityId); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusConnect(entityId); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(entityId); - AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); - } - - void EditorLensFlareComponent::Deactivate() - { - //Check to see if we need to disconnect from the LightSettingsNotificationBus - m_configuration.SyncAnimationChanged(); - - AZ::Data::AssetBus::Handler::BusDisconnect(); - EditorLensFlareComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusDisconnect(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); - - m_light.DestroyRenderLight(); - m_light.SetEntity(AZ::EntityId()); - - m_configuration.m_editorEntityId.SetInvalid(); - - m_selectedLensFlareLibrary.clear(); - - Base::Deactivate(); - } - - void EditorLensFlareComponent::OnEntityVisibilityChanged(bool /*visibility*/) - { - RefreshLensFlare(); - } - - void EditorLensFlareComponent::OnEditorSpecChange() - { - RefreshLensFlare(); - } - - void EditorLensFlareComponent::RefreshLensFlare() - { - m_light.UpdateRenderLight(GetEditorLensFlareConfiguration()); - } - - EditorLensFlareConfiguration EditorLensFlareComponent::GetEditorLensFlareConfiguration() const - { - EditorLensFlareConfiguration configuration = m_configuration; - - // take the entity's visibility into account - bool visible = false; - AzToolsFramework::EditorEntityInfoRequestBus::EventResult( - visible, GetEntityId(), &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); - - configuration.m_visible = visible && configuration.m_visible; - configuration.m_asset = m_asset; - - return configuration; - } - - void EditorLensFlareComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - LensFlareComponent* lensFlareComponent = gameEntity->CreateComponent(); - - if (lensFlareComponent) - { - lensFlareComponent->m_configuration = m_configuration; - lensFlareComponent->m_configuration.m_asset = m_asset; - } - } - - void EditorLensFlareComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - // Don't draw extra visualization unless selected. - if (!IsSelected()) - { - return; - } - - AZ::Transform transform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(transform, GetEntityId(), AZ::TransformBus, GetWorldTM); - - debugDisplay.PushMatrix(transform); - - { - const AZ::Vector3& color = m_configuration.m_tint; - debugDisplay.SetColor(AZ::Vector4(color.GetX(), color.GetY(), color.GetZ(), 1.f)); - debugDisplay.DrawWireSphere(AZ::Vector3::CreateZero(), 1.0f); - } - - debugDisplay.PopMatrix(); - } - - AZ::u32 EditorLensFlareComponent::OnLensFlareSelected() - { - m_configuration.m_lensFlare = GetSelectedLensFlareFullName(); - - //If the flare we've selected is valid we need to parse a couple of parameters from it to make sure - //that we display the flare as it's seen in the lens flare editor - if (!m_configuration.m_lensFlare.empty()) - { - int lensOpticsID = 0; - if (gEnv->pOpticsManager->Load(m_configuration.m_lensFlare.c_str(), lensOpticsID)) - { - IOpticsElementBase* flare = gEnv->pOpticsManager->GetOptics(lensOpticsID); - - AZStd::vector varGroups = flare->GetEditorParamGroups(); - - for (size_t i = 0; i < varGroups.size(); ++i) - { - if (strcmp(varGroups[i].GetName(), "Common") == 0) - { - IFuncVariable* var = varGroups[i].FindVariable("Size"); - if (var) - { - m_configuration.m_size = var->GetFloat(); - } - - var = varGroups[i].FindVariable("Tint"); - if (var) - { - ColorF color = var->GetColorF(); - m_configuration.m_tint = AZ::Vector3(color.r, color.g, color.b); - m_configuration.m_tintAlpha = static_cast(color.a * 255.0f); - } - - var = varGroups[i].FindVariable("Brightness"); - if (var) - { - m_configuration.m_brightness = var->GetFloat(); - } - - } - } - } - } - - m_configuration.PropertyChanged(); // Update the render light - - return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; - } - - void EditorLensFlareComponent::OnVisibleChanged() - { - m_configuration.m_visible = m_visible; - - m_configuration.PropertyChanged(); - } - - void EditorLensFlareComponent::OnAssetReady(AZ::Data::Asset asset) - { - if (asset.GetId() == m_asset.GetId()) - { - // Grab the lens flare list list from the Asset and refresh - const AZStd::vector& paths = static_cast(asset.Get())->GetPaths(); - - if (!paths.empty()) - { - //Store the name of the library retrieved from the filepath - m_selectedLensFlareLibrary = GetLibraryNameFromAsset(); - - // No selected lens flare, so automatically select the first one to ensure we see something right away. - if (m_selectedLensFlareName.empty()) - { - m_selectedLensFlareName = GetFlareNameFromPath(paths[0]); - OnLensFlareSelected(); - } - } - - EBUS_EVENT(AzToolsFramework::ToolsApplicationEvents::Bus, InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); - } - } - - AZStd::vector EditorLensFlareComponent::GetLensFlarePaths() const - { - if (m_asset.IsReady()) - { - AZStd::vector paths = m_asset.Get()->GetPaths(); - - //Remove the library name from the path as it's redundant to display it - for (size_t i = 0; i < paths.size(); i++) - { - paths[i] = GetFlareNameFromPath(paths[i]); - } - - return paths; - } - else - { - return AZStd::vector(); - } - } - - IRenderNode* EditorLensFlareComponent::GetRenderNode() - { - return m_light.GetRenderNode(); - } - - float EditorLensFlareComponent::GetRenderNodeRequestBusOrder() const - { - return LensFlareComponent::s_renderNodeRequestBusOrder; - } - - void EditorLensFlareComponent::OnAssetReloaded(AZ::Data::Asset asset) - { - m_asset = asset; - - // Force the optics manager to reload the library. Otherwise, it will keep returning the old version of the lens flare - // each time Load() is called. - int unusedOutIndex = 0; - const bool forceReload = true; - gEnv->pOpticsManager->Load(GetSelectedLensFlareFullName().c_str(), unusedOutIndex, forceReload); - - RefreshLensFlare(); - } - - void EditorLensFlareComponent::OnAssetChanged() - { - m_selectedLensFlareLibrary.clear(); - m_selectedLensFlareName.clear(); //Clear this so that when the asset is ready we will always pull a new flare from the new library - - if (AZ::Data::AssetBus::Handler::BusIsConnected()) - { - AZ::Data::AssetBus::Handler::BusDisconnect(); - } - - if (m_asset.GetId().IsValid()) - { - //load LensFlare asset - AZ::Data::AssetBus::Handler::BusConnect(m_asset.GetId()); - m_asset.QueueLoad(); - m_asset.BlockUntilLoadComplete(); - } - - EBUS_EVENT(AzToolsFramework::ToolsApplicationEvents::Bus, InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); - } - - void EditorLensFlareComponent::SetPrimaryAsset(const AZ::Data::AssetId& id) - { - m_asset.Create(id, true); - EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, AddDirtyEntity, GetEntityId()); - OnAssetChanged(); - } - - AZStd::string EditorLensFlareComponent::GetFlareNameFromPath(const AZStd::string& path) const - { - //Trim the library name from the beginning of the path to get the flare's name - if (!m_selectedLensFlareLibrary.empty() && m_selectedLensFlareLibrary.size() < path.size()) - { - return path.substr(m_selectedLensFlareLibrary.size() + 1); - } - - return AZStd::string(); - } - - AZStd::string EditorLensFlareComponent::GetLibraryNameFromAsset() const - { - AZStd::string filePath; - EBUS_EVENT_RESULT(filePath, AZ::Data::AssetCatalogRequestBus, GetAssetPathById, m_asset.GetId()); - if (!filePath.empty()) - { - filePath = filePath.substr(filePath.find_last_of('/') + 1); - return filePath.substr(0, filePath.find_last_of('.')); - } - - return AZStd::string(); - } - - AZStd::string EditorLensFlareComponent::GetSelectedLensFlareFullName() const - { - return m_selectedLensFlareLibrary + "." + m_selectedLensFlareName; - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorLensFlareComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorLensFlareComponent.h deleted file mode 100644 index 116e2e3392..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorLensFlareComponent.h +++ /dev/null @@ -1,167 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include -#include - -#include - -#include -#include - -#include "LensFlareComponent.h" - -namespace LmbrCentral -{ - /** - * Extends LightConfiguration structure to add editor functionality - * such as property handlers and visibility filters, as well as - * reflection for editing. - */ - class EditorLensFlareConfiguration - : public LensFlareConfiguration - , private LightSettingsNotificationsBus::Handler - { - public: - AZ_TYPE_INFO(EditorLightConfiguration, "{B7E8C0BF-A7B6-4414-90FF-6E21B32E5E16}"); - - ~EditorLensFlareConfiguration() override {} - - static void Reflect(AZ::ReflectContext* context); - - // Overrides from LensFlareConfiguration - AZ::u32 PropertyChanged() override; - AZ::u32 SyncAnimationChanged() override; - AZ::u32 AttachToSunChanged() override; - - // Overrides from LightSettingsNotificationBus - void AnimationSettingsChanged() override; - - AZ::EntityId m_editorEntityId; // Not reflected. - }; - - /*! - * In-editor light component. - * Handles previewing and activating lights in the editor. - */ - class EditorLensFlareComponent - : public AzToolsFramework::Components::EditorComponentBase - , private AzToolsFramework::EditorVisibilityNotificationBus::Handler - , private AzToolsFramework::EditorEvents::Bus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private EditorLensFlareComponentRequestBus::Handler - , private RenderNodeRequestBus::Handler - , private AZ::Data::AssetBus::Handler - { - private: - using Base = AzToolsFramework::Components::EditorComponentBase; - public: - AZ_COMPONENT(EditorLensFlareComponent, "{4B85E77D-91F9-40C5-8FCB-B494000A9E69}", AzToolsFramework::Components::EditorComponentBase); - - EditorLensFlareComponent() {} - ~EditorLensFlareComponent() override {} - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Init() override; - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AzToolsFramework::EditorVisibilityNotificationBus interface implementation - void OnEntityVisibilityChanged(bool visibility) override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // LensFlareComponentEditorRequestBus::Handler interface implementation - virtual void RefreshLensFlare() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // RenderNodeRequestBus::Handler interface implementation - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AssetEventHandler - void OnAssetReady(AZ::Data::Asset asset) override; - void OnAssetReloaded(AZ::Data::Asset asset) override; - ////////////////////////////////////////////////////////////////////////// - - //! Called when you want to change the game asset through code (like when creating components based on assets). - void BuildGameEntity(AZ::Entity* gameEntity) override; - - //! Called when you want to change the game asset through code (like when creating components based on assets). - void SetPrimaryAsset(const AZ::Data::AssetId& assetId) override; - - //! Invoked in the editor when the user assigns a new lens flare. - void OnAssetChanged(); - - //! Invoked in the editor when the user selects a lens flare from the combo box. - AZ::u32 OnLensFlareSelected(); - - //! Invoked in the editor when the user changes the visibility setting from the check box - void OnVisibleChanged(); - - //! Used to populate the lens flare combo box. - AZStd::vector GetLensFlarePaths() const; - - //! Get a copy of configuration appropriate for use with the lens flare - EditorLensFlareConfiguration GetEditorLensFlareConfiguration() const; - - ////////////////////////////////////////////////////////////////////////// - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - LensFlareComponent::GetProvidedServices(provided); - } - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - LensFlareComponent::GetDependentServices(dependent); - dependent.push_back(AZ_CRC("EditorVisibilityService", 0x90888caf)); - } - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - LensFlareComponent::GetRequiredServices(required); - } - - static void Reflect(AZ::ReflectContext* context); - ////////////////////////////////////////////////////////////////////////// - - private: - ////////////////////////////////////////////////////////////////////////// - // AzToolsFramework::EditorEvents::Bus::Handler interface implementation - void OnEditorSpecChange() override; - ////////////////////////////////////////////////////////////////////////// - - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - AZStd::string GetSelectedLensFlareFullName() const; - AZStd::string GetFlareNameFromPath(const AZStd::string& path) const; - AZStd::string GetLibraryNameFromAsset() const; - - EditorLensFlareConfiguration m_configuration; - LightInstance m_light; - AZStd::string m_selectedLensFlareName; - AZStd::string m_selectedLensFlareLibrary; - AZ::Data::Asset m_asset; - bool m_visible = true; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorLightComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorLightComponent.cpp deleted file mode 100644 index cbef043f17..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorLightComponent.cpp +++ /dev/null @@ -1,2102 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include "EditorLightComponent.h" -#include "EditorAreaLightComponent.h" -#include "EditorPointLightComponent.h" -#include "EditorEnvProbeComponent.h" -#include "EditorProjectorLightComponent.h" - - -namespace LmbrCentral -{ - // private statics - IEditor* EditorLightComponent::m_editor = nullptr; - IMaterialManager* EditorLightComponent::m_materialManager = nullptr; - - const char* EditorLightComponent::BUTTON_GENERATE = "Generate"; - const char* EditorLightComponent::BUTTON_ADDBOUNCE = "Add Bounce"; - - // class converter. Convert EditorLightComponent to one of four above components - namespace ClassConverters - { - static bool ConvertEditorLightComponent(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) - { - // extract light type - bool isFound = false; - LightConfiguration::LightType lightType; - - int lightConfigIndex = classElement.FindElement(AZ_CRC("EditorLightConfiguration", 0xe4cf6af9)); - if (lightConfigIndex != -1) - { - AZ::SerializeContext::DataElementNode configElement = classElement.GetSubElement(lightConfigIndex); - int baseClassIndex = configElement.FindElement(AZ_CRC("BaseClass1", 0xd4925735)); - if (baseClassIndex != -1) - { - AZ::SerializeContext::DataElementNode baseConfig = configElement.GetSubElement(baseClassIndex); - - int lightTypeIndex = baseConfig.FindElement(AZ_CRC("LightType", 0x9884ece8)); - if (lightTypeIndex != -1) - { - AZ::SerializeContext::DataElementNode lightTypeNode = baseConfig.GetSubElement(lightTypeIndex); - lightTypeNode.GetData< LightConfiguration::LightType>(lightType); - isFound = true; - } - } - } - - if (!isFound) - { - return false; - } - - //save all the sub elements for old EditorLightComponent - typedef AZStd::vector NodeArray; - NodeArray subElements; - for (int i = 0; i < classElement.GetNumSubElements(); i++) - { - subElements.push_back(classElement.GetSubElement(i)); - } - - // Convert to specific editor light component. - bool result = true; - switch (lightType) - { - case LightConfiguration::LightType::Point: - result = classElement.Convert(context); - break; - case LightConfiguration::LightType::Area: - result = classElement.Convert(context); - break; - case LightConfiguration::LightType::Projector: - result = classElement.Convert(context); - break; - case LightConfiguration::LightType::Probe: - result = classElement.Convert(context); - break; - default: - result = false; - break; - } - - if (result) - { - //add base class for the new specific light component - int baseClass = classElement.AddElement(context, "BaseClass1"); - AZ::SerializeContext::DataElementNode& baseClassNode = classElement.GetSubElement(baseClass); - - //then add all the sub elements to this base class. it's because we didn't introduce any other new element to specific light components. - for (int i = 0; i < subElements.size(); i++) - { - baseClassNode.AddElement(subElements[i]); - } - } - - return result; - } - } - - AZ::ExportedComponent EditorLightComponent::ExportLightComponent(AZ::Component* thisComponent, const AZ::PlatformTagSet& /*platformTags*/) - { - EditorLightComponent* editorLightComponent = static_cast(thisComponent); - - LightComponent* lightComponent = aznew LightComponent(); - lightComponent->m_configuration = editorLightComponent->m_configuration; - - return AZ::ExportedComponent(lightComponent, true); - } - - void EditorLightComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - EditorLightConfiguration::Reflect(context); - - if (serializeContext) - { - //any data using old UUID of EditorLightComponent will be send to converter - serializeContext->ClassDeprecate("EditorLightComponent", "{33BB1CD4-6A33-46AA-87ED-8BBB40D94B0D}", &ClassConverters::ConvertEditorLightComponent); - - serializeContext->Class() - ->Version(2, &EditorLightComponent::VersionConverter) - ->Field("EditorLightConfiguration", &EditorLightComponent::m_configuration) - ->Field("CubemapRegen", &EditorLightComponent::m_cubemapRegen) - ->Field("CubemapClear", &EditorLightComponent::m_cubemapClear) - ->Field("ViewCubemap", &EditorLightComponent::m_viewCubemap) - ->Field("UseCustomizedCubemap", &EditorLightComponent::m_useCustomizedCubemap) - ; - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Light", "Attach lighting to an entity.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, &EditorLightComponent::GetLightTypeText) - ->DataElement(0, &EditorLightComponent::m_configuration, "Settings", "Light configuration") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) - - ->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap generation") - ->Attribute(AZ::Edit::Attributes::Visibility, &EditorLightComponent::IsProbe) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &EditorLightComponent::m_useCustomizedCubemap, "Use customized cubemap", "Check to enable usage of customized cubemap") - ->Attribute(AZ::Edit::Attributes::Visibility, &EditorLightComponent::IsProbe) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorLightComponent::OnCustomizedCubemapChanged) - - ->DataElement("Button", &EditorLightComponent::m_cubemapRegen, "Cubemap", "Generate the associated cubemap") - ->Attribute(AZ::Edit::Attributes::ButtonText, &EditorLightComponent::GetGenerateCubemapButtonName) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorLightComponent::GenerateCubemap) - ->Attribute(AZ::Edit::Attributes::Visibility, &EditorLightComponent::CanGenerateCubemap) - - ->DataElement("Button", &EditorLightComponent::m_cubemapClear, "Cubemap", "Clear the associated cubemap.") - ->Attribute(AZ::Edit::Attributes::ButtonText, "Reset") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorLightComponent::ClearCubemap) - ->Attribute(AZ::Edit::Attributes::Visibility, &EditorLightComponent::CanGenerateCubemap) - - ->DataElement(0, &EditorLightComponent::m_viewCubemap, "View cubemap", "Preview the cubemap in scene") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorLightComponent::OnViewCubemapChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &EditorLightComponent::IsProbe) - ; - } - } - - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - // In the editor we reflect a separate EBus per light type (e.g. Point, Area, Projector). At run-time, we only use a single - // "LightComponentBus" which is the intersection of the separate buses reflected here. - - // Point Light EBus reflection and VirtualProperties - behaviorContext->EBus("EditorPointLightComponentBus") - ->Event("GetVisible", &EditorLightComponentRequestBus::Events::GetVisible) - ->Event("SetVisible", &EditorLightComponentRequestBus::Events::SetVisible) - ->VirtualProperty("Visible", "GetVisible", "SetVisible") - ->Event("GetColor", &EditorLightComponentRequestBus::Events::GetColor) - ->Event("SetColor", &EditorLightComponentRequestBus::Events::SetColor) - ->VirtualProperty("Color", "GetColor", "SetColor") - ->Event("GetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::GetDiffuseMultiplier) - ->Event("SetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::SetDiffuseMultiplier) - ->VirtualProperty("DiffuseMultiplier", "GetDiffuseMultiplier", "SetDiffuseMultiplier") - ->Event("GetSpecularMultiplier", &EditorLightComponentRequestBus::Events::GetSpecularMultiplier) - ->Event("SetSpecularMultiplier", &EditorLightComponentRequestBus::Events::SetSpecularMultiplier) - ->VirtualProperty("SpecularMultiplier", "GetSpecularMultiplier", "SetSpecularMultiplier") - ->Event("GetAmbient", &EditorLightComponentRequestBus::Events::GetAmbient) - ->Event("SetAmbient", &EditorLightComponentRequestBus::Events::SetAmbient) - ->VirtualProperty("Ambient", "GetAmbient", "SetAmbient") - ->Event("GetPointMaxDistance", &EditorLightComponentRequestBus::Events::GetPointMaxDistance) - ->Event("SetPointMaxDistance", &EditorLightComponentRequestBus::Events::SetPointMaxDistance) - ->VirtualProperty("PointMaxDistance", "GetPointMaxDistance", "SetPointMaxDistance") - ->Event("GetPointAttenuationBulbSize", &EditorLightComponentRequestBus::Events::GetPointAttenuationBulbSize) - ->Event("SetPointAttenuationBulbSize", &EditorLightComponentRequestBus::Events::SetPointAttenuationBulbSize) - ->VirtualProperty("PointAttenuationBulbSize", "GetPointAttenuationBulbSize", "SetPointAttenuationBulbSize") - ; - - // Area Light EBus reflection and VirtualProperties - behaviorContext->EBus("EditorAreaLightComponentBus") - ->Event("GetVisible", &EditorLightComponentRequestBus::Events::GetVisible) - ->Event("SetVisible", &EditorLightComponentRequestBus::Events::SetVisible) - ->VirtualProperty("Visible", "GetVisible", "SetVisible") - ->Event("GetColor", &EditorLightComponentRequestBus::Events::GetColor) - ->Event("SetColor", &EditorLightComponentRequestBus::Events::SetColor) - ->VirtualProperty("Color", "GetColor", "SetColor") - ->Event("GetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::GetDiffuseMultiplier) - ->Event("SetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::SetDiffuseMultiplier) - ->VirtualProperty("DiffuseMultiplier", "GetDiffuseMultiplier", "SetDiffuseMultiplier") - ->Event("GetSpecularMultiplier", &EditorLightComponentRequestBus::Events::GetSpecularMultiplier) - ->Event("SetSpecularMultiplier", &EditorLightComponentRequestBus::Events::SetSpecularMultiplier) - ->VirtualProperty("SpecularMultiplier", "GetSpecularMultiplier", "SetSpecularMultiplier") - ->Event("GetAmbient", &EditorLightComponentRequestBus::Events::GetAmbient) - ->Event("SetAmbient", &EditorLightComponentRequestBus::Events::SetAmbient) - ->VirtualProperty("Ambient", "GetAmbient", "SetAmbient") - ->Event("GetAreaMaxDistance", &EditorLightComponentRequestBus::Events::GetAreaMaxDistance) - ->Event("SetAreaMaxDistance", &EditorLightComponentRequestBus::Events::SetAreaMaxDistance) - ->VirtualProperty("AreaMaxDistance", "GetAreaMaxDistance", "SetAreaMaxDistance") - ->Event("GetAreaWidth", &EditorLightComponentRequestBus::Events::GetAreaWidth) - ->Event("SetAreaWidth", &EditorLightComponentRequestBus::Events::SetAreaWidth) - ->VirtualProperty("AreaWidth", "GetAreaWidth", "SetAreaWidth") - ->Event("GetAreaHeight", &EditorLightComponentRequestBus::Events::GetAreaHeight) - ->Event("SetAreaHeight", &EditorLightComponentRequestBus::Events::SetAreaHeight) - ->VirtualProperty("AreaHeight", "GetAreaHeight", "SetAreaHeight") - ->Event("GetAreaFOV", &EditorLightComponentRequestBus::Events::GetAreaFOV) - ->Event("SetAreaFOV", &EditorLightComponentRequestBus::Events::SetAreaFOV) - ->VirtualProperty("AreaFOV", "GetAreaFOV", "SetAreaFOV") - ; - - // Projector Light Ebus reflection and VirtualProperties - behaviorContext->EBus("EditorProjectorLightComponentBus") - ->Event("GetVisible", &EditorLightComponentRequestBus::Events::GetVisible) - ->Event("SetVisible", &EditorLightComponentRequestBus::Events::SetVisible) - ->VirtualProperty("Visible", "GetVisible", "SetVisible") - ->Event("GetColor", &EditorLightComponentRequestBus::Events::GetColor) - ->Event("SetColor", &EditorLightComponentRequestBus::Events::SetColor) - ->VirtualProperty("Color", "GetColor", "SetColor") - ->Event("GetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::GetDiffuseMultiplier) - ->Event("SetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::SetDiffuseMultiplier) - ->VirtualProperty("DiffuseMultiplier", "GetDiffuseMultiplier", "SetDiffuseMultiplier") - ->Event("GetSpecularMultiplier", &EditorLightComponentRequestBus::Events::GetSpecularMultiplier) - ->Event("SetSpecularMultiplier", &EditorLightComponentRequestBus::Events::SetSpecularMultiplier) - ->VirtualProperty("SpecularMultiplier", "GetSpecularMultiplier", "SetSpecularMultiplier") - ->Event("GetAmbient", &EditorLightComponentRequestBus::Events::GetAmbient) - ->Event("SetAmbient", &EditorLightComponentRequestBus::Events::SetAmbient) - ->VirtualProperty("Ambient", "GetAmbient", "SetAmbient") - ->Event("GetProjectorMaxDistance", &EditorLightComponentRequestBus::Events::GetProjectorMaxDistance) - ->Event("SetProjectorMaxDistance", &EditorLightComponentRequestBus::Events::SetProjectorMaxDistance) - ->VirtualProperty("ProjectorMaxDistance", "GetProjectorMaxDistance", "SetProjectorMaxDistance") - ->Event("GetProjectorAttenuationBulbSize", &EditorLightComponentRequestBus::Events::GetProjectorAttenuationBulbSize) - ->Event("SetProjectorAttenuationBulbSize", &EditorLightComponentRequestBus::Events::SetProjectorAttenuationBulbSize) - ->VirtualProperty("ProjectorAttenuationBulbSize", "GetProjectorAttenuationBulbSize", "SetProjectorAttenuationBulbSize") - ->Event("GetProjectorFOV", &EditorLightComponentRequestBus::Events::GetProjectorFOV) - ->Event("SetProjectorFOV", &EditorLightComponentRequestBus::Events::SetProjectorFOV) - ->VirtualProperty("ProjectorFOV", "GetProjectorFOV", "SetProjectorFOV") - ->Event("GetProjectorNearPlane", &EditorLightComponentRequestBus::Events::GetProjectorNearPlane) - ->Event("SetProjectorNearPlane", &EditorLightComponentRequestBus::Events::SetProjectorNearPlane) - ->VirtualProperty("ProjectorNearPlane", "GetProjectorNearPlane", "SetProjectorNearPlane") - ; - - // Environment Probe Light Ebus reflection and VirtualProperties - behaviorContext->EBus("EditorProbeLightComponentBus") - ->Event("GetVisible", &EditorLightComponentRequestBus::Events::GetVisible) - ->Event("SetVisible", &EditorLightComponentRequestBus::Events::SetVisible) - ->VirtualProperty("Visible", "GetVisible", "SetVisible") - ->Event("GetColor", &EditorLightComponentRequestBus::Events::GetColor) - ->Event("SetColor", &EditorLightComponentRequestBus::Events::SetColor) - ->VirtualProperty("Color", "GetColor", "SetColor") - ->Event("GetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::GetDiffuseMultiplier) - ->Event("SetDiffuseMultiplier", &EditorLightComponentRequestBus::Events::SetDiffuseMultiplier) - ->VirtualProperty("DiffuseMultiplier", "GetDiffuseMultiplier", "SetDiffuseMultiplier") - ->Event("GetSpecularMultiplier", &EditorLightComponentRequestBus::Events::GetSpecularMultiplier) - ->Event("SetSpecularMultiplier", &EditorLightComponentRequestBus::Events::SetSpecularMultiplier) - ->VirtualProperty("SpecularMultiplier", "GetSpecularMultiplier", "SetSpecularMultiplier") - ->Event("GetProbeAreaDimensions", &EditorLightComponentRequestBus::Events::GetProbeAreaDimensions) - ->Event("SetProbeAreaDimensions", &EditorLightComponentRequestBus::Events::SetProbeAreaDimensions) - ->VirtualProperty("ProbeAreaDimensions", "GetProbeAreaDimensions", "SetProbeAreaDimensions") - ->Event("GetProbeSortPriority", &EditorLightComponentRequestBus::Events::GetProbeSortPriority) - ->Event("SetProbeSortPriority", &EditorLightComponentRequestBus::Events::SetProbeSortPriority) - ->VirtualProperty("ProbeSortPriority", "GetProbeSortPriority", "SetProbeSortPriority") - ->Event("GetProbeBoxProjected", &EditorLightComponentRequestBus::Events::GetProbeBoxProjected) - ->Event("SetProbeBoxProjected", &EditorLightComponentRequestBus::Events::SetProbeBoxProjected) - ->VirtualProperty("ProbeBoxProjected", "GetProbeBoxProjected", "SetProbeBoxProjected") - ->Event("GetProbeBoxHeight", &EditorLightComponentRequestBus::Events::GetProbeBoxHeight) - ->Event("SetProbeBoxHeight", &EditorLightComponentRequestBus::Events::SetProbeBoxHeight) - ->VirtualProperty("ProbeBoxHeight", "GetProbeBoxHeight", "SetProbeBoxHeight") - ->Event("GetProbeBoxLength", &EditorLightComponentRequestBus::Events::GetProbeBoxLength) - ->Event("SetProbeBoxLength", &EditorLightComponentRequestBus::Events::SetProbeBoxLength) - ->VirtualProperty("ProbeBoxLength", "GetProbeBoxLength", "SetProbeBoxLength") - ->Event("GetProbeBoxWidth", &EditorLightComponentRequestBus::Events::GetProbeBoxWidth) - ->Event("SetProbeBoxWidth", &EditorLightComponentRequestBus::Events::SetProbeBoxWidth) - ->VirtualProperty("ProbeBoxWidth", "GetProbeBoxWidth", "SetProbeBoxWidth") - ->Event("GetProbeAttenuationFalloff", &EditorLightComponentRequestBus::Events::GetProbeAttenuationFalloff) - ->Event("SetProbeAttenuationFalloff", &EditorLightComponentRequestBus::Events::SetProbeAttenuationFalloff) - ->VirtualProperty("ProbeAttenuationFalloff", "GetProbeAttenuationFalloff", "SetProbeAttenuationFalloff") - ->Event("GetProbeFade", &EditorLightComponentRequestBus::Events::GetProbeFade) - ->Event("SetProbeFade", &EditorLightComponentRequestBus::Events::SetProbeFade) - ->VirtualProperty("ProbeFade", "GetProbeFade", "SetProbeFade") - ; - } - } - - bool EditorLightComponent::VersionConverter([[maybe_unused]] AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) - { - if (classElement.GetVersion() <= 1) - { - if (!classElement.RemoveElementByName(AZ_CRC("cubemapAsset", 0xc10ac43b))) - { - return false; - } - } - - return true; - } - void EditorLightConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Configuration", "Light configuration")-> - - ClassElement(AZ::Edit::ClassElements::EditorData, "")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)-> - - ClassElement(AZ::Edit::ClassElements::Group, "General Settings")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(AZ::Edit::UIHandlers::CheckBox, &LightConfiguration::m_visible, "Visible", "The current visibility status of this flare")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MajorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_onInitially, "On initially", "The light is initially turned on.")-> - - DataElement(AZ::Edit::UIHandlers::Color, &LightConfiguration::m_color, "Color", "Light color")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_diffuseMultiplier, "Diffuse multiplier", "Diffuse color multiplier")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, "x")-> - - DataElement(0, &LightConfiguration::m_specMultiplier, "Specular multiplier", "Specular multiplier")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, "x")-> - - DataElement(0, &LightConfiguration::m_ambient, "Ambient", "Ambient light")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetAmbientLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - // Point Light Settings - ClassElement(AZ::Edit::ClassElements::Group, "Point Light Settings")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(0, &LightConfiguration::m_pointMaxDistance, "Max distance", "Point light radius")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetPointLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - Attribute(AZ::Edit::Attributes::Min, 0.1f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - - DataElement(0, &LightConfiguration::m_pointAttenuationBulbSize, "Attenuation bulb size", "Radius of area inside falloff.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetPointLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - - // Area Light Settings - ClassElement(AZ::Edit::ClassElements::Group, "Area Light Settings")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(0, &LightConfiguration::m_areaWidth, "Area width", "Area light width.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetAreaSettingVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.1f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - - DataElement(0, &LightConfiguration::m_areaHeight, "Area height", "Area light height.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetAreaSettingVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.1f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - - DataElement(0, &LightConfiguration::m_areaMaxDistance, "Max distance", "Area light max distance.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetAreaSettingVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.1f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, " _")-> - - DataElement(0, &LightConfiguration::m_areaFOV, "FOV", "Area light field of view.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetAreaSettingVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.0f)-> - Attribute(AZ::Edit::Attributes::Max, 90.0f)-> - Attribute(AZ::Edit::Attributes::Step, 1.0f)-> - Attribute(AZ::Edit::Attributes::Suffix, " degrees")-> - - // Projector settings. - ClassElement(AZ::Edit::ClassElements::Group, "Projector Light Settings")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(0, &LightConfiguration::m_projectorRange, "Max distance", "Projector light range")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProjectorLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.1f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - - DataElement(0, &LightConfiguration::m_projectorAttenuationBulbSize, "Attenuation bulb size", "Radius of area inside falloff.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProjectorLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - - DataElement(AZ::Edit::UIHandlers::Slider, &LightConfiguration::m_projectorFOV, "FOV", "Projector light FOV")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProjectorLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 1.f)-> - Attribute(AZ::Edit::Attributes::Max, 180.0f)-> //Projector will start shrinking if FOV goes above 180 degrees - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Suffix, " degrees")-> - - DataElement(0, &LightConfiguration::m_projectorNearPlane, "Near plane", "Projector light near plane")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProjectorLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 100.f)-> - Attribute(AZ::Edit::Attributes::Step, 1.f)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - - DataElement(0, &LightConfiguration::m_projectorTexture, "Texture", "Projector light texture")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProjectorLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MajorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_material, "Material", "Projector light material")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProjectorLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MajorPropertyChanged)-> - - //environment probe settings - ClassElement(AZ::Edit::ClassElements::Group, "Environment Probe Settings")-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(0, &LightConfiguration::m_probeArea, "Area dimensions", "Probe area")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(AZ::Edit::UIHandlers::CheckBox, &LightConfiguration::m_isBoxProjected, "Box projected", "Check to enable box projection during runtime")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_boxHeight, "Box height", "Height of box projection area")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_boxWidth, "Box width", "Width of box projection area")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_boxLength, "Box length", "Length of box projection area")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_attenFalloffMax, "Attenuation falloff", "Attenuation falloff value.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 1.0f)-> - Attribute(AZ::Edit::Attributes::Step, 0.02f)-> - - DataElement(0, &LightConfiguration::m_probeSortPriority, "Sort priority", "Sort priority")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(AZ::Edit::UIHandlers::ComboBox, &LightConfiguration::m_probeCubemapResolution, "Resolution", "Cubemap resolution")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MajorPropertyChanged)-> - EnumAttribute(ResolutionSetting::ResDefault, "Default (256)")-> - EnumAttribute(ResolutionSetting::Res32, "32")-> - EnumAttribute(ResolutionSetting::Res64, "64")-> - EnumAttribute(ResolutionSetting::Res128, "128")-> - EnumAttribute(ResolutionSetting::Res256, "256")-> - EnumAttribute(ResolutionSetting::Res512, "512")-> - - ClassElement(AZ::Edit::ClassElements::Group, "Cubemap Generation")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(AZ::Edit::UIHandlers::Default, &LightConfiguration::m_probeCubemap, "Cubemap asset", "Cubemap file path")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetProbeLightVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::OnCubemapAssetChanged)-> - Attribute(AZ::Edit::Attributes::ReadOnly,&LightConfiguration::CanGenerateCubemap)-> - - ClassElement(AZ::Edit::ClassElements::Group, "Animation")-> - - DataElement(0, &LightConfiguration::m_animIndex, "Style", "Light animation curve ID (\"style\") as it corresponds to values in Light.cfx")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::OnAnimationSettingChanged)-> - Attribute(AZ::Edit::Attributes::Max, 255)-> - - DataElement(0, &LightConfiguration::m_animSpeed, "Speed", "Multiple of the base animation rate")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::OnAnimationSettingChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Max, 4.f)-> - Attribute(AZ::Edit::Attributes::Suffix, "x")-> - - DataElement(0, &LightConfiguration::m_animPhase, "Phase", "Animation start offset from 0 to 1. 0.1 would be 10% into the animation")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::OnAnimationSettingChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - Attribute(AZ::Edit::Attributes::Max, 1.f)-> - - ClassElement(AZ::Edit::ClassElements::Group, "Options")-> - - DataElement(0, &LightConfiguration::m_viewDistMultiplier, "View distance multiplier", "Adjusts max view distance. If 1.0 then default is used. 1.1 would be 10% further than default.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Suffix, "x")-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - - DataElement(AZ::Edit::UIHandlers::ComboBox, &LightConfiguration::m_minSpec, "Minimum spec", "Min spec for light to be active.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - EnumAttribute(EngineSpec::Never, "Never")-> - EnumAttribute(EngineSpec::VeryHigh, "Very high")-> - EnumAttribute(EngineSpec::High, "High")-> - EnumAttribute(EngineSpec::Medium, "Medium")-> - EnumAttribute(EngineSpec::Low, "Low")-> - - DataElement(AZ::Edit::UIHandlers::ComboBox, &LightConfiguration::m_voxelGIMode, "Voxel GI mode", "Mode for light interaction with voxel GI.")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MajorPropertyChanged)-> - EnumAttribute(IRenderNode::VM_None, "None")-> - EnumAttribute(IRenderNode::VM_Static, "Static")-> - EnumAttribute(IRenderNode::VM_Dynamic, "Dynamic")-> - - DataElement(0, &LightConfiguration::m_useVisAreas, "Use VisAreas", "Light is affected by VisAreas")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_volumetricFog, "Volumetric fog", "Affects volumetric fog")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_volumetricFogOnly, "Volumetric fog only", "Only affects volumetric fog")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_indoorOnly, "Indoor only", "Indoor only")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - DataElement(0, &LightConfiguration::m_affectsThisAreaOnly, "Affects this area only", "Light only affects this area")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - ClassElement(AZ::Edit::ClassElements::Group, "Advanced")-> - - DataElement(0, &LightConfiguration::m_deferred, "Deferred", "Deferred light")-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_Hide", 0x32ab90f7))-> // Deprecated on non mobile platforms - hidden until we have a platform to use this - - ClassElement(AZ::Edit::ClassElements::Group, "Shadow Settings")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSpecVisibility)-> - Attribute(AZ::Edit::Attributes::AutoExpand, true)-> - - DataElement(AZ::Edit::UIHandlers::ComboBox, &LightConfiguration::m_castShadowsSpec, "Cast shadow spec", "Min spec for shadow casting.")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSpecVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MajorPropertyChanged)-> - EnumAttribute(EngineSpec::Never, "Never")-> - EnumAttribute(EngineSpec::VeryHigh, "Very high")-> - EnumAttribute(EngineSpec::High, "High")-> - EnumAttribute(EngineSpec::Medium, "Medium")-> - EnumAttribute(EngineSpec::Low, "Low")-> - - DataElement(0, &LightConfiguration::m_castTerrainShadows, "Terrain Shadows", "Include the terrain in the shadow casters for this light")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSettingsVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - - - DataElement(0, &LightConfiguration::m_shadowBias, "Shadow bias", "Shadow bias")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSettingsVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 100.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.5f)-> - - DataElement(0, &LightConfiguration::m_shadowSlopeBias, "Shadow slope bias", "Shadow slope bias")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSettingsVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 100.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.5f)-> - - DataElement(0, &LightConfiguration::m_shadowResScale, "Shadow resolution scale", "Shadow res scale")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSettingsVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 10.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f)-> - - DataElement(0, &LightConfiguration::m_shadowUpdateMinRadius, "Shadow update radius", "Shadow update min radius")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSettingsVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 100.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.5f)-> - Attribute(AZ::Edit::Attributes::Suffix, " m")-> - - DataElement(0, &LightConfiguration::m_shadowUpdateRatio, "Shadow update ratio", "Shadow update ratio")-> - Attribute(AZ::Edit::Attributes::Visibility, &LightConfiguration::GetShadowSettingsVisibility)-> - Attribute(AZ::Edit::Attributes::ChangeNotify, &LightConfiguration::MinorPropertyChanged)-> - Attribute(AZ::Edit::Attributes::Min, 0.f)-> - Attribute(AZ::Edit::Attributes::Max, 10.f)-> - Attribute(AZ::Edit::Attributes::Step, 0.1f) - ; - } - } - } - - AZ::Crc32 EditorLightConfiguration::GetAmbientLightVisibility() const - { - return m_lightType != LightType::Probe ? - AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - AZ::Crc32 EditorLightConfiguration::GetPointLightVisibility() const - { - return m_lightType == LightType::Point ? - AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - AZ::Crc32 EditorLightConfiguration::GetProjectorLightVisibility() const - { - return m_lightType == LightType::Projector ? - AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - AZ::Crc32 EditorLightConfiguration::GetProbeLightVisibility() const - { - return m_lightType == LightType::Probe ? - AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - AZ::Crc32 EditorLightConfiguration::GetShadowSpecVisibility() const - { - return m_lightType != LightType::Probe ? - AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - AZ::Crc32 EditorLightConfiguration::GetShadowSettingsVisibility() const - { - return m_castShadowsSpec != EngineSpec::Never ? - AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - AZ::Crc32 EditorLightConfiguration::GetAreaSettingVisibility() const - { - return m_lightType == LightType::Area ? - AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - AZ::Crc32 EditorLightConfiguration::MajorPropertyChanged() - { - if (m_editorEntityId.IsValid()) - { - EditorLightComponentRequestBus::Event(m_editorEntityId, &EditorLightComponentRequests::RefreshLight); - } - - return AZ::Edit::PropertyRefreshLevels::EntireTree; - } - - AZ::Crc32 EditorLightConfiguration::MinorPropertyChanged() - { - if (m_editorEntityId.IsValid()) - { - EditorLightComponentRequestBus::Event(m_editorEntityId, &EditorLightComponentRequests::RefreshLight); - } - - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::Crc32 EditorLightConfiguration::OnAnimationSettingChanged() - { - if (m_editorEntityId.IsValid()) - { - EditorLightComponentRequestBus::Event(m_editorEntityId, &EditorLightComponentRequests::RefreshLight); - LightSettingsNotificationsBus::Broadcast(&LightSettingsNotifications::AnimationSettingsChanged); - } - - return AZ_CRC("RefreshNone", 0x98a5045b); - } - - AZ::Crc32 EditorLightConfiguration::OnCubemapAssetChanged() - { - if (!m_component) - { - AZ_Error("Lighting", false, "Lighting configuration has a null component, unable to change CubemapAsset"); - return 0; - } - - return m_component->OnCubemapAssetChanged(); - } - - bool EditorLightConfiguration::CanGenerateCubemap() const - { - if (!m_component) - { - AZ_Error("Lighting", false, "Lighting configuration has a null component, unable to generate Cubemap"); - return false; - } - - return m_component->CanGenerateCubemap(); - } - - EditorLightComponent::EditorLightComponent() - : m_useCustomizedCubemap(false) - , m_viewCubemap(false) - , m_cubemapRegen(false) - , m_cubemapClear(false) - { - m_configuration.m_projectorTexture.SetAssetPath("engineassets/textures/defaults/spot_default.dds"); - m_configuration.SetComponent(nullptr); - } - - EditorLightComponent::~EditorLightComponent() - { - } - - void EditorLightComponent::Init() - { - Base::Init(); - } - - void EditorLightComponent::Activate() - { - Base::Activate(); - - m_configuration.SetComponent(this); - m_configuration.m_editorEntityId = GetEntityId(); - - m_light.SetEntity(GetEntityId()); - RefreshLight(); - - if (m_configuration.m_lightType == LightConfiguration::LightType::Probe) - { - m_cubemapPreview.Setup(m_configuration.m_probeCubemap.GetAssetPath().c_str()); - - AZ::Transform transform = AZ::Transform::Identity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformInterface::GetWorldTM); - m_cubemapPreview.SetTransform(AZTransformToLYTransform(transform)); - - OnViewCubemapChanged(); // Check to see if it should be displayed now. - } - - EditorCameraCorrectionRequestBus::Handler::BusConnect(GetEntityId()); - EditorLightComponentRequestBus::Handler::BusConnect(GetEntityId()); - RenderNodeRequestBus::Handler::BusConnect(GetEntityId()); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); - AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId()); - } - - void EditorLightComponent::Deactivate() - { - EditorCameraCorrectionRequestBus::Handler::BusDisconnect(); - EditorLightComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusDisconnect(); - AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - - if (gEnv->p3DEngine) - { - gEnv->p3DEngine->FreeRenderNodeState(&m_cubemapPreview); - } - - m_light.DestroyRenderLight(); - m_light.SetEntity(AZ::EntityId()); - - m_configuration.m_editorEntityId.SetInvalid(); - - Base::Deactivate(); - } - - void EditorLightComponent::OnEntityVisibilityChanged(bool /*visibility*/) - { - RefreshLight(); - } - - void EditorLightComponent::OnEditorSpecChange() - { - RefreshLight(); - } - - void EditorLightComponent::RefreshLight() - { - EditorLightConfiguration configuration = m_configuration; - - // take the entity's visibility into account - bool visible = false; - AzToolsFramework::EditorEntityInfoRequestBus::EventResult( - visible, GetEntityId(), &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); - - configuration.m_visible = visible && configuration.m_visible; - - m_light.UpdateRenderLight(configuration); - } - - IRenderNode* EditorLightComponent::GetRenderNode() - { - return m_light.GetRenderNode(); - } - - float EditorLightComponent::GetRenderNodeRequestBusOrder() const - { - return LightComponent::s_renderNodeRequestBusOrder; - } - - bool EditorLightComponent::IsProbe() const - { - return (m_configuration.m_lightType == LightConfiguration::LightType::Probe); - } - - bool EditorLightComponent::HasCubemap() const - { - return !m_configuration.m_probeCubemap.GetAssetPath().empty(); - } - - const char* EditorLightComponent::GetCubemapAssetName() const - { - return m_configuration.m_probeCubemap.GetAssetPath().c_str(); - } - - - bool EditorLightComponent::CanGenerateCubemap() const - { - return (m_configuration.m_lightType == LightConfiguration::LightType::Probe) && (!m_useCustomizedCubemap); - } - - const char* EditorLightComponent::GetGenerateCubemapButtonName() const - { - if (HasCubemap()) - { - return BUTTON_ADDBOUNCE; - } - else - { - return BUTTON_GENERATE; - } - } - - void EditorLightComponent::GenerateCubemap() - { - if (CanGenerateCubemap()) - { - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, - GenerateCubemapWithIDForEntity, - GetEntityId(), - GetCubemapId(), - nullptr, - false, - true); - } - } - - void EditorLightComponent::ClearCubemap() - { - SetCubemap(""); - } - - void EditorLightComponent::OnViewCubemapChanged() - { - if (!gEnv->p3DEngine) - { - return; - } - - if (m_viewCubemap) - { - gEnv->p3DEngine->RegisterEntity(&m_cubemapPreview); - } - else - { - gEnv->p3DEngine->FreeRenderNodeState(&m_cubemapPreview); - } - } - - void EditorLightComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - LightComponent* lightComponent = gameEntity->CreateComponent(); - - if (lightComponent) - { - lightComponent->m_configuration = m_configuration; - } - } - - void EditorLightComponent::SetCubemap(const AZStd::string& cubemap) - { - if (cubemap != m_configuration.m_probeCubemap.GetAssetPath()) - { - AzToolsFramework::ScopedUndoBatch undo("Cubemap Assignment"); - - m_configuration.m_probeCubemap.SetAssetPath(cubemap.c_str()); - m_cubemapPreview.UpdateTexture(m_configuration.m_probeCubemap.GetAssetPath().c_str()); - - AzToolsFramework::ToolsApplicationRequestBus::Broadcast( - &AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, GetEntityId()); - } - - if (m_configuration.m_probeCubemap.GetAssetPath().empty()) - { - // Since the cubemap was simply cleared, there is no need to wait for an asset to be processed. - // Instead, refresh the light now so the output will be cleared immediately. - - if (IsSelected()) - { - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); - - } - - if (EditorLightConfiguration::LightType::Probe == m_configuration.m_lightType) - { - RefreshLight(); - } - } - else - { - // Get the notice when the dds is generated by AP. We will only refresh the m_cubemapAsset and the PropertyDisplay when the dds is generated. - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - } - } - - void EditorLightComponent::SetProjectorTexture(const AZStd::string& projectorTexture) - { - if (projectorTexture != m_configuration.m_projectorTexture.GetAssetPath()) - { - m_configuration.m_projectorTexture.SetAssetPath(projectorTexture.c_str()); - RefreshLight(); - } - } - - void EditorLightComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) - { - AZ::Data::AssetId cmAssetId; - AZ::Data::AssetCatalogRequestBus::BroadcastResult( - cmAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, - m_configuration.m_probeCubemap.GetAssetPath().c_str(), - m_configuration.m_probeCubemap.GetAssetType(), true); - - if (cmAssetId == assetId) - { - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); - //refresh the tree since we don't need to wait for the asset imported - if (IsSelected()) - { - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); - } - - // We wait to refresh the light until after the new asset has finished loading to avoid showing old data; for example, when you - // Generate, Clear, and then Generate again. - if (EditorLightConfiguration::LightType::Probe == m_configuration.m_lightType) - { - RefreshLight(); - } - } - } - - void EditorLightComponent::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) - { - OnCatalogAssetAdded(assetId); - } - - AZ::Crc32 EditorLightComponent::OnCubemapAssetChanged() - { - //in case user select a "_diff" texture file. remove it and generate specular file name - static const char* diffExt = "_diff"; - static const int diffStrSize = 5; //string len of "_diff" - - const char* specularCubemap = 0; - string specularName(m_configuration.m_probeCubemap.GetAssetPath().c_str()); - - int strIndex = specularName.find(diffExt); - if (strIndex >= 0) - { - specularName = specularName.substr(0, strIndex) + specularName.substr(strIndex + diffStrSize, specularName.length()); - specularCubemap = specularName.c_str(); - m_configuration.m_probeCubemap.SetAssetPath(specularName); - } - - m_cubemapPreview.UpdateTexture(m_configuration.m_probeCubemap.GetAssetPath().c_str()); - - RefreshLight(); - - return AZ::Edit::PropertyRefreshLevels::ValuesOnly; - } - - void EditorLightConfiguration::SetComponent(EditorLightComponent* component) - { - m_component = component; - } - - AZ::Crc32 EditorLightComponent::OnCustomizedCubemapChanged() - { - //clean assets - m_configuration.m_probeCubemap.SetAssetPath(""); - m_cubemapPreview.UpdateTexture(m_configuration.m_probeCubemap.GetAssetPath().c_str()); - - RefreshLight(); - - return AZ::Edit::PropertyRefreshLevels::EntireTree; - } - - AZ::u32 EditorLightComponent::GetCubemapResolution() - { - return static_cast(m_configuration.m_probeCubemapResolution); - } - void EditorLightComponent::SetCubemapResolution(AZ::u32 newResolution) - { - AZ_Assert(newResolution > 0, "Invalid resolution"); - - LightConfiguration::ResolutionSetting cubemapResolution = static_cast(newResolution); - if (m_configuration.m_probeCubemapResolution != cubemapResolution) - { - m_configuration.m_probeCubemapResolution = cubemapResolution; - m_configuration.MinorPropertyChanged(); - } - } - - bool EditorLightComponent::UseCustomizedCubemap() const - { - return m_useCustomizedCubemap; - } - - const LightConfiguration& EditorLightComponent::GetConfiguration() const - { - return m_configuration; - } - - //////////////////////////////////////////////////////////// - // Modifiers - void EditorLightComponent::SetVisible(bool isVisible) - { - if (m_configuration.m_visible != isVisible) - { - m_configuration.m_visible = isVisible; - m_configuration.MajorPropertyChanged(); - } - } - - bool EditorLightComponent::GetVisible() - { - return m_configuration.m_visible; - } - - void EditorLightComponent::SetOnInitially(bool onInitially) - { - if (m_configuration.m_onInitially != onInitially) - { - m_configuration.m_onInitially = onInitially; - m_configuration.MajorPropertyChanged(); - } - } - bool EditorLightComponent::GetOnInitially() - { - return m_configuration.m_onInitially; - } - - void EditorLightComponent::SetColor(const AZ::Color& newColor) - { - if (m_configuration.m_color != newColor) - { - m_configuration.m_color = newColor; - m_configuration.MinorPropertyChanged(); - } - } - - const AZ::Color EditorLightComponent::GetColor() - { - return m_configuration.m_color; - } - - void EditorLightComponent::SetDiffuseMultiplier(float newMultiplier) - { - if (newMultiplier != m_configuration.m_diffuseMultiplier) - { - m_configuration.m_diffuseMultiplier = newMultiplier; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetDiffuseMultiplier() - { - return m_configuration.m_diffuseMultiplier; - } - - void EditorLightComponent::SetSpecularMultiplier(float newMultiplier) - { - if (newMultiplier != m_configuration.m_specMultiplier) - { - m_configuration.m_specMultiplier = newMultiplier; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetSpecularMultiplier() - { - return m_configuration.m_specMultiplier; - } - - void EditorLightComponent::SetAmbient(bool isAmbient) - { - if (isAmbient != m_configuration.m_ambient) - { - m_configuration.m_ambient = isAmbient; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetAmbient() - { - return m_configuration.m_ambient; - } - - void EditorLightComponent::SetPointMaxDistance(float newMaxDistance) - { - if (newMaxDistance != m_configuration.m_pointMaxDistance) - { - m_configuration.m_pointMaxDistance = newMaxDistance; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetPointMaxDistance() - { - return m_configuration.m_pointMaxDistance; - } - - void EditorLightComponent::SetPointAttenuationBulbSize(float newAttenuationBulbSize) - { - if (newAttenuationBulbSize != m_configuration.m_pointAttenuationBulbSize) - { - m_configuration.m_pointAttenuationBulbSize = newAttenuationBulbSize; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetPointAttenuationBulbSize() - { - return m_configuration.m_pointAttenuationBulbSize; - } - - void EditorLightComponent::SetAreaMaxDistance(float newMaxDistance) - { - if (newMaxDistance != m_configuration.m_areaMaxDistance) - { - m_configuration.m_areaMaxDistance = newMaxDistance; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetAreaMaxDistance() - { - return m_configuration.m_areaMaxDistance; - } - - void EditorLightComponent::SetAreaWidth(float newWidth) - { - if (newWidth != m_configuration.m_areaWidth) - { - m_configuration.m_areaWidth = newWidth; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetAreaWidth() - { - return m_configuration.m_areaWidth; - } - - void EditorLightComponent::SetAreaHeight(float newHeight) - { - if (newHeight != m_configuration.m_areaHeight) - { - m_configuration.m_areaHeight = newHeight; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetAreaHeight() - { - return m_configuration.m_areaHeight; - } - - void EditorLightComponent::SetAreaFOV(float newFOV) - { - if (newFOV != m_configuration.m_areaFOV) - { - m_configuration.m_areaFOV = newFOV; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetAreaFOV() - { - return m_configuration.m_areaFOV; - } - - void EditorLightComponent::SetProjectorMaxDistance(float newMaxDistance) - { - if (newMaxDistance != m_configuration.m_projectorRange) - { - m_configuration.m_projectorRange = newMaxDistance; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetProjectorMaxDistance() - { - return m_configuration.m_projectorRange; - } - - void EditorLightComponent::SetProjectorAttenuationBulbSize(float newAttenuationBulbSize) - { - if (newAttenuationBulbSize != m_configuration.m_projectorAttenuationBulbSize) - { - m_configuration.m_projectorAttenuationBulbSize = newAttenuationBulbSize; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetProjectorAttenuationBulbSize() - { - return m_configuration.m_projectorAttenuationBulbSize; - } - - void EditorLightComponent::SetProjectorFOV(float newFOV) - { - if (newFOV != m_configuration.m_projectorFOV) - { - m_configuration.m_projectorFOV = newFOV; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetProjectorFOV() - { - return m_configuration.m_projectorFOV; - } - - void EditorLightComponent::SetProjectorNearPlane(float newNearPlane) - { - if (newNearPlane != m_configuration.m_projectorNearPlane) - { - m_configuration.m_projectorNearPlane = newNearPlane; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetProjectorNearPlane() - { - return m_configuration.m_projectorNearPlane; - } - - void EditorLightComponent::SetProbeAreaDimensions(const AZ::Vector3& newDimensions) - { - if (newDimensions != m_configuration.m_probeArea) - { - m_configuration.m_probeArea = newDimensions; - m_configuration.MinorPropertyChanged(); - } - } - const AZ::Vector3 EditorLightComponent::GetProbeAreaDimensions() - { - return m_configuration.m_probeArea; - } - - void EditorLightComponent::SetProbeBoxProjected(bool isProbeBoxProjected) - { - if (isProbeBoxProjected != m_configuration.m_isBoxProjected) - { - m_configuration.m_isBoxProjected = isProbeBoxProjected; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetProbeBoxProjected() - { - return m_configuration.m_isBoxProjected; - } - - void EditorLightComponent::SetProbeBoxHeight(float newHeight) - { - if (newHeight != m_configuration.m_boxHeight) - { - m_configuration.m_boxHeight = newHeight; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetProbeBoxHeight() - { - return m_configuration.m_boxHeight; - } - - void EditorLightComponent::SetProbeBoxLength(float newLength) - { - if (newLength != m_configuration.m_boxLength) - { - m_configuration.m_boxLength = newLength; - m_configuration.MinorPropertyChanged(); - } - } - - float EditorLightComponent::GetProbeBoxLength() - { - return m_configuration.m_boxLength; - } - - void EditorLightComponent::SetProbeBoxWidth(float newWidth) - { - if (newWidth != m_configuration.m_boxWidth) - { - m_configuration.m_boxWidth = newWidth; - m_configuration.MinorPropertyChanged(); - } - } - - float EditorLightComponent::GetProbeBoxWidth() - { - return m_configuration.m_boxWidth; - } - - void EditorLightComponent::SetProbeAttenuationFalloff(float newAttenuationFalloff) - { - if (newAttenuationFalloff != m_configuration.m_attenFalloffMax) - { - m_configuration.m_attenFalloffMax = newAttenuationFalloff; - m_configuration.MinorPropertyChanged(); - } - } - - float EditorLightComponent::GetProbeAttenuationFalloff() - { - return m_configuration.m_attenFalloffMax; - } - - void EditorLightComponent::SetProbeFade(float fade) - { - AZ_Warning("Lighting", 0.0f <= fade && fade <= 1.0f, "SetProbeFade value %f out of range. Clamping to [0,1]", fade); - fade = AZ::GetClamp(fade, 0.0f, 1.0f); - - if (fade != m_configuration.m_probeFade) - { - m_configuration.m_probeFade = fade; - m_configuration.MinorPropertyChanged(); - } - } - - float EditorLightComponent::GetProbeFade() - { - return m_configuration.m_probeFade; - } - - void EditorLightComponent::SetIndoorOnly(bool newIndoorOnly) - { - if (m_configuration.m_indoorOnly != newIndoorOnly) - { - m_configuration.m_indoorOnly = newIndoorOnly; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetIndoorOnly() - { - return m_configuration.m_indoorOnly; - } - - void EditorLightComponent::SetCastShadowSpec(AZ::u32 newCastShadowSpec) - { - EngineSpec shadowSpec = static_cast(newCastShadowSpec); - if (m_configuration.m_castShadowsSpec != shadowSpec) - { - m_configuration.m_castShadowsSpec = shadowSpec; - m_configuration.MinorPropertyChanged(); - } - } - AZ::u32 EditorLightComponent::GetCastShadowSpec() - { - return static_cast(m_configuration.m_castShadowsSpec); - } - - void EditorLightComponent::SetViewDistanceMultiplier(float newMultiplier) - { - if (m_configuration.m_viewDistMultiplier != newMultiplier) - { - m_configuration.m_viewDistMultiplier = newMultiplier; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetViewDistanceMultiplier() - { - return m_configuration.m_viewDistMultiplier; - } - - void EditorLightComponent::SetProbeArea(const AZ::Vector3& newProbeArea) - { - if (m_configuration.m_probeArea != newProbeArea) - { - m_configuration.m_probeArea = newProbeArea; - m_configuration.MinorPropertyChanged(); - } - } - AZ::Vector3 EditorLightComponent::GetProbeArea() - { - return m_configuration.m_probeArea; - } - - void EditorLightComponent::SetProbeSortPriority(AZ::u32 newProbeSortPriority) - { - if (m_configuration.m_probeSortPriority != newProbeSortPriority) - { - m_configuration.m_probeSortPriority = newProbeSortPriority; - m_configuration.MinorPropertyChanged(); - } - } - AZ::u32 EditorLightComponent::GetProbeSortPriority() - { - return m_configuration.m_probeSortPriority; - } - - void EditorLightComponent::SetVolumetricFog(bool newVolumetricFog) - { - if (m_configuration.m_volumetricFog != newVolumetricFog) - { - m_configuration.m_volumetricFog = newVolumetricFog; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetVolumetricFog() - { - return m_configuration.m_volumetricFog; - } - - void EditorLightComponent::SetVolumetricFogOnly(bool newVolumetricFogOnly) - { - if (m_configuration.m_volumetricFogOnly != newVolumetricFogOnly) - { - m_configuration.m_volumetricFogOnly = newVolumetricFogOnly; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetVolumetricFogOnly() - { - return m_configuration.m_volumetricFogOnly; - } - - void EditorLightComponent::SetAttenuationFalloffMax(float newAttenFalloffMax) - { - if (m_configuration.m_attenFalloffMax != newAttenFalloffMax) - { - m_configuration.m_attenFalloffMax = newAttenFalloffMax; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetAttenuationFalloffMax() - { - return m_configuration.m_attenFalloffMax; - } - - void EditorLightComponent::SetUseVisAreas(bool useVisAreas) - { - if (m_configuration.m_useVisAreas != useVisAreas) - { - m_configuration.m_useVisAreas = useVisAreas; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetUseVisAreas() - { - return m_configuration.m_useVisAreas; - } - - void EditorLightComponent::SetAffectsThisAreaOnly(bool affectsThisAreaOnly) - { - if (m_configuration.m_affectsThisAreaOnly != affectsThisAreaOnly) - { - m_configuration.m_affectsThisAreaOnly = affectsThisAreaOnly; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetAffectsThisAreaOnly() - { - return m_configuration.m_affectsThisAreaOnly; - } - - void EditorLightComponent::SetBoxHeight(float newBoxHeight) - { - if (m_configuration.m_boxHeight != newBoxHeight) - { - m_configuration.m_boxHeight = newBoxHeight; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetBoxHeight() - { - return m_configuration.m_boxHeight; - } - - void EditorLightComponent::SetBoxWidth(float newBoxWidth) - { - if (m_configuration.m_boxWidth != newBoxWidth) - { - m_configuration.m_boxWidth = newBoxWidth; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetBoxWidth() - { - return m_configuration.m_boxWidth; - } - - void EditorLightComponent::SetBoxLength(float newBoxLength) - { - if (m_configuration.m_boxLength != newBoxLength) - { - m_configuration.m_boxLength = newBoxLength; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetBoxLength() - { - return m_configuration.m_boxLength; - } - - void EditorLightComponent::SetBoxProjected(bool newBoxProjected) - { - if (m_configuration.m_isBoxProjected != newBoxProjected) - { - m_configuration.m_isBoxProjected = newBoxProjected; - m_configuration.MinorPropertyChanged(); - } - } - bool EditorLightComponent::GetBoxProjected() - { - return m_configuration.m_isBoxProjected; - } - /////////////////////////////////////////////////////////////////// - - void EditorLightComponent::SetShadowBias(float shadowBias) - { - if (m_configuration.m_shadowBias != shadowBias) - { - m_configuration.m_shadowBias = shadowBias; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetShadowBias() - { - return m_configuration.m_shadowBias; - } - - void EditorLightComponent::SetShadowSlopeBias(float shadowSlopeBias) - { - if (m_configuration.m_shadowSlopeBias != shadowSlopeBias) - { - m_configuration.m_shadowSlopeBias = shadowSlopeBias; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetShadowSlopeBias() - { - return m_configuration.m_shadowSlopeBias; - } - - void EditorLightComponent::SetShadowResScale(float shadowResScale) - { - if (m_configuration.m_shadowResScale != shadowResScale) - { - m_configuration.m_shadowResScale = shadowResScale; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetShadowResScale() - { - return m_configuration.m_shadowResScale; - } - - void EditorLightComponent::SetShadowUpdateMinRadius(float shadowUpdateMinRadius) - { - if (m_configuration.m_shadowUpdateMinRadius != shadowUpdateMinRadius) - { - m_configuration.m_shadowUpdateMinRadius = shadowUpdateMinRadius; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetShadowUpdateMinRadius() - { - return m_configuration.m_shadowUpdateMinRadius; - } - - void EditorLightComponent::SetShadowUpdateRatio(float shadowUpdateRatio) - { - if (m_configuration.m_shadowUpdateRatio != shadowUpdateRatio) - { - m_configuration.m_shadowUpdateRatio = shadowUpdateRatio; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetShadowUpdateRatio() - { - return m_configuration.m_shadowUpdateRatio; - } - - // Animation parameters - void EditorLightComponent::SetAnimIndex(AZ::u32 animIndex) - { - if (m_configuration.m_animIndex != animIndex) - { - m_configuration.m_animIndex = animIndex; - m_configuration.MinorPropertyChanged(); - } - } - AZ::u32 EditorLightComponent::GetAnimIndex() - { - return m_configuration.m_animIndex; - } - - void EditorLightComponent::SetAnimSpeed(float animSpeed) - { - if (m_configuration.m_animSpeed != animSpeed) - { - m_configuration.m_animSpeed = animSpeed; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetAnimSpeed() - { - return m_configuration.m_animSpeed; - } - - void EditorLightComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_cubemapPreview.SetTransform(AZTransformToLYTransform(world)); - } - - void EditorLightComponent::SetAnimPhase(float animPhase) - { - if (m_configuration.m_animPhase != animPhase) - { - m_configuration.m_animPhase = animPhase; - m_configuration.MinorPropertyChanged(); - } - } - float EditorLightComponent::GetAnimPhase() - { - return m_configuration.m_animPhase; - } - - const char* EditorLightComponent::GetLightTypeText() const - { - return "Deprecated Light"; - } - - void EditorLightComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - // Don't draw extra visualization unless selected. - if (!IsSelected()) - { - return; - } - - AZ::Transform transform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformInterface::GetWorldTM); - - transform.ExtractScale(); - debugDisplay.PushMatrix(transform); - const AZ::Color& color = m_configuration.m_color; - debugDisplay.SetColor(AZ::Vector4(color.GetR(), color.GetG(), color.GetB(), 1.f)); - - switch (m_configuration.m_lightType) - { - case EditorLightConfiguration::LightType::Point: - { - debugDisplay.DrawWireSphere(AZ::Vector3::CreateZero(), m_configuration.m_pointMaxDistance); - debugDisplay.DrawWireSphere(AZ::Vector3::CreateZero(), m_configuration.m_pointAttenuationBulbSize); - break; - } - case EditorLightConfiguration::LightType::Area: - { - debugDisplay.SetColor(AZ::Vector4(color.GetR(), color.GetG(), color.GetB(), 0.5f)); - - // Some initial calculations for drawing - AZ::Matrix3x3 rotYMatrix = AZ::Matrix3x3::CreateRotationY(AZ::DegToRad(m_configuration.m_areaFOV)); - AZ::Matrix3x3 rotXMatrix = AZ::Matrix3x3::CreateRotationX(AZ::DegToRad(45)); - AZ::Vector3 AngleRefPoint = AZ::Vector3(m_configuration.m_areaMaxDistance, 0, 0); - AngleRefPoint *= rotYMatrix; - const float roundedRectangleOffset = AngleRefPoint.GetZ(); - AngleRefPoint *= rotXMatrix; - - // draw box around light - AZ::Vector3 points[4]; - points[0] = AZ::Vector3(0, -m_configuration.m_areaWidth * 0.5f, -m_configuration.m_areaHeight * 0.5f); - points[1] = AZ::Vector3(0, m_configuration.m_areaWidth * 0.5f, -m_configuration.m_areaHeight * 0.5f); - points[2] = AZ::Vector3(0, m_configuration.m_areaWidth * 0.5f, m_configuration.m_areaHeight * 0.5f); - points[3] = AZ::Vector3(0, -m_configuration.m_areaWidth * 0.5f, m_configuration.m_areaHeight * 0.5f); - debugDisplay.DrawPolyLine(points, 4, true); - - // draw lines from corners of light - debugDisplay.DrawLine(points[0], points[0] + AZ::Vector3(AngleRefPoint.GetX(), -AngleRefPoint.GetY(), -AngleRefPoint.GetZ())); - debugDisplay.DrawLine(points[1], points[1] + AZ::Vector3(AngleRefPoint.GetX(), AngleRefPoint.GetY(), -AngleRefPoint.GetZ())); - debugDisplay.DrawLine(points[2], points[2] + AZ::Vector3(AngleRefPoint.GetX(), AngleRefPoint.GetY(), AngleRefPoint.GetZ())); - debugDisplay.DrawLine(points[3], points[3] + AZ::Vector3(AngleRefPoint.GetX(), -AngleRefPoint.GetY(), AngleRefPoint.GetZ())); - - // draw curves to the corners of the max distance box - const float sqrthalf = sqrt(0.5f); - debugDisplay.DrawArc(points[0], m_configuration.m_areaMaxDistance, 0, m_configuration.m_areaFOV, 1.0f, AZ::Vector3(0, sqrthalf, -sqrthalf)); - debugDisplay.DrawArc(points[1], m_configuration.m_areaMaxDistance, -m_configuration.m_areaFOV, m_configuration.m_areaFOV, 1.0f, AZ::Vector3(0, -sqrthalf, -sqrthalf)); - debugDisplay.DrawArc(points[2], m_configuration.m_areaMaxDistance, 0, m_configuration.m_areaFOV, 1.0f, AZ::Vector3(0, -sqrthalf, sqrthalf)); - debugDisplay.DrawArc(points[3], m_configuration.m_areaMaxDistance, -m_configuration.m_areaFOV, m_configuration.m_areaFOV, 1.0f, AZ::Vector3(0, sqrthalf, sqrthalf)); - - // Draw middle rounded rect - debugDisplay.DrawLine( - AZ::Vector3(AngleRefPoint.GetX(), points[0].GetY(), points[0].GetZ() - roundedRectangleOffset), - AZ::Vector3(AngleRefPoint.GetX(), points[1].GetY(), points[1].GetZ() - roundedRectangleOffset) - ); - debugDisplay.DrawLine( - AZ::Vector3(AngleRefPoint.GetX(), points[1].GetY() + roundedRectangleOffset, points[1].GetZ()), - AZ::Vector3(AngleRefPoint.GetX(), points[2].GetY() + roundedRectangleOffset, points[2].GetZ()) - ); - debugDisplay.DrawLine( - AZ::Vector3(AngleRefPoint.GetX(), points[2].GetY(), points[2].GetZ() + roundedRectangleOffset), - AZ::Vector3(AngleRefPoint.GetX(), points[3].GetY(), points[3].GetZ() + roundedRectangleOffset) - ); - debugDisplay.DrawLine( - AZ::Vector3(AngleRefPoint.GetX(), points[3].GetY() - roundedRectangleOffset, points[3].GetZ()), - AZ::Vector3(AngleRefPoint.GetX(), points[0].GetY() - roundedRectangleOffset, points[0].GetZ()) - ); - - debugDisplay.DrawArc(AZ::Vector3(AngleRefPoint.GetX(), points[0].GetY(), points[0].GetZ()), roundedRectangleOffset, 270.0f, 90.0f, 2.0f, AZ::Vector3(1.0f, 0.0f, 0.0f)); - debugDisplay.DrawArc(AZ::Vector3(AngleRefPoint.GetX(), points[1].GetY(), points[1].GetZ()), roundedRectangleOffset, 0.0f, 90.0f, 2.0f, AZ::Vector3(1.0f, 0.0f, 0.0f)); - debugDisplay.DrawArc(AZ::Vector3(AngleRefPoint.GetX(), points[2].GetY(), points[2].GetZ()), roundedRectangleOffset, 90.0f, 90.0f, 2.0f, AZ::Vector3(1.0f, 0.0f, 0.0f)); - debugDisplay.DrawArc(AZ::Vector3(AngleRefPoint.GetX(), points[3].GetY(), points[3].GetZ()), roundedRectangleOffset, 180.0f, 90.0f, 2.0f, AZ::Vector3(1.0f, 0.0f, 0.0f)); - - // draw box at max distance in front of light - points[0] = AZ::Vector3(m_configuration.m_areaMaxDistance, -m_configuration.m_areaWidth * 0.5f, -m_configuration.m_areaHeight * 0.5f); - points[1] = AZ::Vector3(m_configuration.m_areaMaxDistance, m_configuration.m_areaWidth * 0.5f, -m_configuration.m_areaHeight * 0.5f); - points[2] = AZ::Vector3(m_configuration.m_areaMaxDistance, m_configuration.m_areaWidth * 0.5f, m_configuration.m_areaHeight * 0.5f); - points[3] = AZ::Vector3(m_configuration.m_areaMaxDistance, -m_configuration.m_areaWidth * 0.5f, m_configuration.m_areaHeight * 0.5f); - debugDisplay.DrawPolyLine(points, 4, true); - - break; - } - case EditorLightConfiguration::LightType::Projector: - { - debugDisplay.SetColor(AZ::Vector4(color.GetR(), color.GetG(), color.GetB(), 0.5f)); - - const float range = m_configuration.m_projectorRange; - const float attenuation = m_configuration.m_projectorAttenuationBulbSize; - const float nearPlane = m_configuration.m_projectorNearPlane; - - DrawProjectionGizmo(debugDisplay, range); - DrawProjectionGizmo(debugDisplay, attenuation); - DrawPlaneGizmo(debugDisplay, nearPlane); - - break; - } - case EditorLightConfiguration::LightType::Probe: - { - AZ::Vector3 halfAreaSize = m_configuration.m_probeArea/2; - debugDisplay.SetColor(1, 1, 0, 0.8f); - debugDisplay.DrawWireBox( -halfAreaSize, halfAreaSize); - if (m_configuration.m_isBoxProjected) - { - AZ::Vector3 halfBoxSize = AZ::Vector3(m_configuration.m_boxWidth, m_configuration.m_boxLength, m_configuration.m_boxHeight) / 2; - debugDisplay.SetColor(0, 1, 0, 0.8f); - debugDisplay.DrawWireBox(-halfBoxSize, halfBoxSize); - } - - // Note that rendering the cubemap preview is handled by m_cubemapPreview - - break; - } - } - - debugDisplay.PopMatrix(); - } - - void EditorLightComponent::DrawProjectionGizmo( - AzFramework::DebugDisplayRequests& debugDisplay, const float radius) const - { - //Don't draw if the radius isn't going to result in anything visible - if (radius <= 0) - { - return; - } - - const int numPoints = 16; // per one arc - const int numArcs = 6; - - AZ::Vector3 points[numPoints * numArcs]; - { - // Generate 4 arcs on intersection of sphere with pyramid. - const float fov = DEG2RAD(m_configuration.m_projectorFOV); - - const AZ::Vector3 lightAxis(radius, 0.0f, 0.0f); - const float tanA = tan_tpl(fov * 0.5f); - const float fovProj = asin_tpl(1.0f / sqrtf(2.0f + 1.0f / (tanA * tanA))) * 2.0f; - - const float halfFov = 0.5f * fov; - const float halfFovProj = fovProj * 0.5f; - const float anglePerSegmentOfFovProj = 1.0f / (numPoints - 1) * fovProj; - - const AZ::Quaternion yRot = AZ::Quaternion::CreateRotationY(halfFov); - AZ::Vector3* arcPoints = points; - for (int i = 0; i < numPoints; ++i) - { - float angle = i * anglePerSegmentOfFovProj - halfFovProj; - arcPoints[i] = (yRot * AZ::Quaternion::CreateRotationZ(angle)).TransformVector(lightAxis); - } - - const AZ::Quaternion zRot = AZ::Quaternion::CreateRotationZ(halfFov); - arcPoints += numPoints; - for (int i = 0; i < numPoints; ++i) - { - float angle = (numPoints - i - 1) * anglePerSegmentOfFovProj - halfFovProj; - arcPoints[i] = (zRot * AZ::Quaternion::CreateRotationY(angle)).TransformVector(lightAxis); - } - - const AZ::Quaternion nyRot = AZ::Quaternion::CreateRotationY(-halfFov); - arcPoints += numPoints; - for (int i = 0; i < numPoints; ++i) - { - float angle = (numPoints - i - 1) * anglePerSegmentOfFovProj - halfFovProj; - arcPoints[i] = (nyRot * AZ::Quaternion::CreateRotationZ(angle)).TransformVector(lightAxis); - } - - const AZ::Quaternion nzRot = AZ::Quaternion::CreateRotationZ(-halfFov); - arcPoints += numPoints; - for (int i = 0; i < numPoints; ++i) - { - float angle = i * anglePerSegmentOfFovProj - halfFovProj; - arcPoints[i] = (nzRot * AZ::Quaternion::CreateRotationY(angle)).TransformVector(lightAxis); - } - - arcPoints += numPoints; - const float anglePerSegmentOfFov = 1.0f / (numPoints - 1) * fov; - for (int i = 0; i < numPoints; ++i) - { - float angle = i * anglePerSegmentOfFov - halfFov; - arcPoints[i] = AZ::Quaternion::CreateRotationY(angle).TransformVector(lightAxis); - } - - arcPoints += numPoints; - for (int i = 0; i < numPoints; ++i) - { - float angle = i * anglePerSegmentOfFov - halfFov; - arcPoints[i] = AZ::Quaternion::CreateRotationZ(angle).TransformVector(lightAxis); - } - } - - // Draw pyramid and sphere intersection. - debugDisplay.DrawPolyLine(points, numPoints * 4, false); - - // Draw cross. - debugDisplay.DrawPolyLine(points + numPoints * 4, numPoints, false); - debugDisplay.DrawPolyLine(points + numPoints * 5, numPoints, false); - debugDisplay.DrawLine(AZ::Vector3::CreateZero(), points[numPoints * 0]); - debugDisplay.DrawLine(AZ::Vector3::CreateZero(), points[numPoints * 1]); - debugDisplay.DrawLine(AZ::Vector3::CreateZero(), points[numPoints * 2]); - debugDisplay.DrawLine(AZ::Vector3::CreateZero(), points[numPoints * 3]); - } - - void EditorLightComponent::DrawPlaneGizmo(AzFramework::DebugDisplayRequests& debugDisplay, const float depth) const - { - //Don't draw if depth isn't going to result in anything visible - if (depth <= 0) - { - return; - } - - const uint32_t numPoints = 8; //8 Points - 4 corners and 4 half widths - - AZ::Vector3 points[numPoints]; - - const float fov = DEG2RAD(m_configuration.m_projectorFOV); - const float halfWidth = tanf(0.5f * fov) * depth; //Calculate the half width of the frustum at this depth - - //Add corners - points[0] = AZ::Vector3(depth, +halfWidth, +halfWidth); //Top-Left - points[1] = AZ::Vector3(depth, -halfWidth, +halfWidth); //Top-Right - points[2] = AZ::Vector3(depth, -halfWidth, -halfWidth); //Bottom-Right - points[3] = AZ::Vector3(depth, +halfWidth, -halfWidth); //Bottom-Left - - //Add points halfway between corners - points[4] = AZ::Vector3(depth, 0, +halfWidth); //Top-Middle - points[5] = AZ::Vector3(depth, -halfWidth, 0); //Right-Middle - points[6] = AZ::Vector3(depth, 0, -halfWidth); //Bottom-Middle - points[7] = AZ::Vector3(depth, +halfWidth, 0); //Left-Middle - - - //Draw Square - debugDisplay.DrawLine(points[0], points[1]); //TL to TR - debugDisplay.DrawLine(points[1], points[2]); //TR to BR - debugDisplay.DrawLine(points[2], points[3]); //BR to BL - debugDisplay.DrawLine(points[3], points[0]); //BL to TL - - const AZ::Vector3 depthVec(depth, 0, 0); - - // Draw Cross - debugDisplay.DrawLine(depthVec, points[4]); - debugDisplay.DrawLine(depthVec, points[5]); - debugDisplay.DrawLine(depthVec, points[6]); - debugDisplay.DrawLine(depthVec, points[7]); - } - - EditorLightComponent::CubemapPreview::CubemapPreview() - : m_renderTransform(Matrix34::CreateIdentity()) - , m_statObj(nullptr) - { - m_dwRndFlags |= ERF_RENDER_ALWAYS; - } - - void EditorLightComponent::CubemapPreview::Setup(const char* textureName) - { - if (!m_editor) - { - AzToolsFramework::EditorRequestBus::BroadcastResult(m_editor, &AzToolsFramework::EditorRequests::GetEditor); - } - - if (!m_editor->Get3DEngine()) - { - return; - } - - if (!m_materialManager) - { - m_materialManager = m_editor->Get3DEngine()->GetMaterialManager(); - } - - _smart_ptr material = m_materialManager->LoadMaterial("Objects/envcube", false, true); - QString matName = Path::GetFileName(textureName); - if (material) - { - SShaderItem& si = material->GetShaderItem(); - - // We need to clone the material in order for multiple Environment Probes to not stomp each other's preview materials. - material = m_materialManager->CreateMaterial(matName.toUtf8().data(), material->GetFlags() | MTL_FLAG_NON_REMOVABLE); - if (material) - { - SInputShaderResources isr = si.m_pShaderResources; - // The following operation will create a texture slot entry and copy the name to it. - isr.m_TexturesResourcesMap[EFTT_ENV].m_Name = textureName; - - SShaderItem siDst = m_editor->GetRenderer()->EF_LoadShaderItem(si.m_pShader->GetName(), true, 0, &isr, si.m_pShader->GetGenerationMask()); - material->AssignShaderItem(siDst); - } - } - - m_statObj = m_editor->Get3DEngine()->LoadStatObjAutoRef("Objects/envcube.cgf", nullptr, nullptr, false); - if (m_statObj) - { - // We need to clone the object in order for multiple Environment Probes to not stomp each other's preview materials. - m_statObj = m_statObj->Clone(false, false, false); - - m_statObj->SetMaterial(material); - } - } - - void EditorLightComponent::CubemapPreview::UpdateTexture(const char* textureName) - { - if (m_statObj) - { - _smart_ptr material = m_statObj->GetMaterial(); - - if (material) - { - SShaderItem& si = material->GetShaderItem(); - - SInputShaderResources isr = si.m_pShaderResources; - // The following operation will create a texture slot entry and copy the name to it. - isr.m_TexturesResourcesMap[EFTT_ENV].m_Name = textureName; - - SShaderItem siDst = m_editor->GetRenderer()->EF_LoadShaderItem(si.m_pShader->GetName(), true, 0, &isr, si.m_pShader->GetGenerationMask()); - material->AssignShaderItem(siDst); - } - } - } - - void EditorLightComponent::CubemapPreview::SetTransform(const Matrix34& transform) - { - m_renderTransform = transform; - } - - void EditorLightComponent::CubemapPreview::Render([[maybe_unused]] const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo) - { - if (m_statObj) - { - SRendParams rp; - rp.AmbientColor = ColorF(1.0f, 1.0f, 1.0f, 1); - rp.fAlpha = 1; - rp.pMatrix = &m_renderTransform; - rp.pMaterial = m_statObj->GetMaterial(); - - m_statObj->Render(rp, passInfo); - } - } - - EERType EditorLightComponent::CubemapPreview::GetRenderNodeType() - { - return eERType_RenderComponent; - } - - const char* EditorLightComponent::CubemapPreview::GetName() const - { - return "CubemapPreview"; - } - - const char* EditorLightComponent::CubemapPreview::GetEntityClassName() const - { - return "CubemapPreview"; - } - - Vec3 EditorLightComponent::CubemapPreview::GetPos([[maybe_unused]] bool bWorldOnly) const - { - return m_renderTransform.GetTranslation(); - } - - const AABB EditorLightComponent::CubemapPreview::GetBBox() const - { - AABB transformedAABB; - transformedAABB.Reset(); - if (m_statObj) - { - transformedAABB.SetTransformedAABB(QuatT(m_renderTransform), m_statObj->GetAABB()); - } - return transformedAABB; - } - - _smart_ptr EditorLightComponent::CubemapPreview::GetMaterial([[maybe_unused]] Vec3* pHitPos) - { - return m_statObj ? m_statObj->GetMaterial() : nullptr; - } - - _smart_ptr EditorLightComponent::CubemapPreview::GetMaterialOverride() - { - return m_statObj ? m_statObj->GetMaterial() : nullptr; - } - - IStatObj* EditorLightComponent::CubemapPreview::GetEntityStatObj(unsigned int nPartId, [[maybe_unused]] unsigned int nSubPartId, Matrix34A* pMatrix, [[maybe_unused]] bool bReturnOnlyVisible) - { - if (0 == nPartId) - { - if (pMatrix) - { - *pMatrix = m_renderTransform; - } - - return m_statObj; - } - - return nullptr; - } - - float EditorLightComponent::CubemapPreview::GetMaxViewDist() - { - return FLT_MAX; - } - - void EditorLightComponent::CubemapPreview::GetMemoryUsage(class ICrySizer* pSizer) const - { - pSizer->AddObjectSize(this); - } - - - -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorLightComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorLightComponent.h deleted file mode 100644 index 3b1de2c528..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorLightComponent.h +++ /dev/null @@ -1,408 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "LightComponent.h" - -#include - -namespace LmbrCentral -{ - class EditorLightComponent; - - /** - * Extends LightConfiguration structure to add editor functionality - * such as property handlers and visibility filters, as well as - * reflection for editing. - */ - - class EditorLightConfiguration - : public LightConfiguration - { - public: - AZ_TYPE_INFO(EditorLightConfiguration, "{1D3B114F-8FB2-47BD-9C21-E089F4F37861}"); - - ~EditorLightConfiguration() override {} - - static void Reflect(AZ::ReflectContext* context); - - AZ::Crc32 GetAmbientLightVisibility() const override; - AZ::Crc32 GetPointLightVisibility() const override; - AZ::Crc32 GetProjectorLightVisibility() const override; - AZ::Crc32 GetProbeLightVisibility() const override; - AZ::Crc32 GetShadowSpecVisibility() const override; - AZ::Crc32 GetShadowSettingsVisibility() const override; - AZ::Crc32 GetAreaSettingVisibility() const override; - - AZ::Crc32 MinorPropertyChanged() override; - AZ::Crc32 MajorPropertyChanged() override; - AZ::Crc32 OnAnimationSettingChanged() override; - AZ::Crc32 OnCubemapAssetChanged() override; - bool CanGenerateCubemap() const override; - - void SetComponent(EditorLightComponent* component); - EditorLightComponent* m_component; - }; - - /*! - * In-editor light component. - * Handles previewing and activating lights in the editor. - */ - class EditorLightComponent - : public AzToolsFramework::Components::EditorComponentBase - , private AzToolsFramework::EditorVisibilityNotificationBus::Handler - , private AzToolsFramework::EditorEvents::Bus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private EditorLightComponentRequestBus::Handler - , private RenderNodeRequestBus::Handler - , private AzFramework::AssetCatalogEventBus::Handler - , private AZ::TransformNotificationBus::Handler - , private EditorCameraCorrectionRequestBus::Handler - { - private: - using Base = AzToolsFramework::Components::EditorComponentBase; - public: - - friend EditorLightConfiguration; - //old guid "{33BB1CD4-6A33-46AA-87ED-8BBB40D94B0D}" before splitting editor light component - AZ_COMPONENT(EditorLightComponent, "{7C18B273-5BA3-4E0F-857D-1F30BD6B0733}", AzToolsFramework::Components::EditorComponentBase); - - EditorLightComponent(); - ~EditorLightComponent() override; - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Init() override; - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AzToolsFramework::EditorVisibilityNotificationBus interface implementation - void OnEntityVisibilityChanged(bool visibility) override; - ////////////////////////////////////////////////////////////////////////// - - // AzFramework::EntityDebugDisplayEventBus - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - ////////////////////////////////////////////////////////////////////////// - // EditorLightComponentRequestBus::Handler interface implementation - void SetCubemap(const AZStd::string& cubemap) override; - void SetProjectorTexture(const AZStd::string& projectorTexture) override; - - AZ::u32 GetCubemapResolution() override; - void SetCubemapResolution(AZ::u32 resolution) override; - bool UseCustomizedCubemap() const override; - void RefreshLight() override; - const LightConfiguration& GetConfiguration() const override; - AZ::Crc32 OnCubemapAssetChanged(); - AZ::Crc32 OnCustomizedCubemapChanged(); - - // EditorCameraCorrectionRequestBus interface implementation - // Light is aligned along the the x-axis so add a transform correction to align along the y-axis. - AZ::Matrix3x3 GetTransformCorrection() override { return AZ::Matrix3x3::CreateRotationZ(-AZ::Constants::HalfPi); } - - /////////////////////////////////////////// - // EditorLightComponentRequestBus Modifiers - void SetVisible(bool isVisible) override; - bool GetVisible() override; - - void SetOnInitially(bool onInitially) override; - bool GetOnInitially() override; - - void SetColor(const AZ::Color& newColor) override; - const AZ::Color GetColor() override; - - void SetDiffuseMultiplier(float newMultiplier) override; - float GetDiffuseMultiplier() override; - - void SetSpecularMultiplier(float newMultiplier) override; - float GetSpecularMultiplier() override; - - void SetAmbient(bool isAmbient) override; - bool GetAmbient() override; - - void SetPointMaxDistance(float newMaxDistance) override; - float GetPointMaxDistance() override; - - void SetPointAttenuationBulbSize(float newAttenuationBulbSize) override; - float GetPointAttenuationBulbSize() override; - - void SetAreaMaxDistance(float newMaxDistance) override; - float GetAreaMaxDistance() override; - - void SetAreaWidth(float newWidth) override; - float GetAreaWidth() override; - - void SetAreaHeight(float newHeight) override; - float GetAreaHeight() override; - - void SetAreaFOV(float newFOV) override; - float GetAreaFOV() override; - - void SetProjectorMaxDistance(float newMaxDistance) override; - float GetProjectorMaxDistance() override; - - void SetProjectorAttenuationBulbSize(float newAttenuationBulbSize) override; - float GetProjectorAttenuationBulbSize() override; - - void SetProjectorFOV(float newFOV) override; - float GetProjectorFOV() override; - - void SetProjectorNearPlane(float newNearPlane) override; - float GetProjectorNearPlane() override; - - // Environment Probe Settings - void SetProbeAreaDimensions(const AZ::Vector3& newDimensions) override; - const AZ::Vector3 GetProbeAreaDimensions() override; - - void SetProbeSortPriority(AZ::u32 newPriority) override; - AZ::u32 GetProbeSortPriority() override; - - void SetProbeBoxProjected(bool isProbeBoxProjected) override; - bool GetProbeBoxProjected() override; - - void SetProbeBoxHeight(float newHeight) override; - float GetProbeBoxHeight() override; - - void SetProbeBoxLength(float newLength) override; - float GetProbeBoxLength() override; - - void SetProbeBoxWidth(float newWidth) override; - float GetProbeBoxWidth() override; - - void SetProbeAttenuationFalloff(float newAttenuationFalloff) override; - float GetProbeAttenuationFalloff() override; - - void SetProbeFade(float fade) override; - float GetProbeFade() override; - - void SetIndoorOnly(bool indoorOnly) override; - bool GetIndoorOnly() override; - - void SetCastShadowSpec(AZ::u32 castShadowSpec) override; - AZ::u32 GetCastShadowSpec() override; - - void SetViewDistanceMultiplier(float viewDistanceMultiplier) override; - float GetViewDistanceMultiplier() override; - - void SetProbeArea(const AZ::Vector3& probeArea) override; - AZ::Vector3 GetProbeArea() override; - - void SetVolumetricFogOnly(bool volumetricFogOnly) override; - bool GetVolumetricFogOnly() override; - - void SetVolumetricFog(bool volumetricFog) override; - bool GetVolumetricFog() override; - - void SetAttenuationFalloffMax(float attenFalloffMax); - float GetAttenuationFalloffMax(); - - void SetUseVisAreas(bool useVisAreas) override; - bool GetUseVisAreas() override; - - void SetAffectsThisAreaOnly(bool affectsThisAreaOnly) override; - bool GetAffectsThisAreaOnly() override; - - void SetBoxHeight(float boxHeight) override; - float GetBoxHeight() override; - - void SetBoxWidth(float boxWidth) override; - float GetBoxWidth() override; - - void SetBoxLength(float boxLength) override; - float GetBoxLength() override; - - void SetBoxProjected(bool boxProjected) override; - bool GetBoxProjected() override; - - void SetShadowBias(float shadowBias) override; - float GetShadowBias() override; - - void SetShadowSlopeBias(float shadowSlopeBias) override; - float GetShadowSlopeBias() override; - - void SetShadowResScale(float shadowResScale) override; - float GetShadowResScale() override; - - void SetShadowUpdateMinRadius(float shadowUpdateMinRadius) override; - float GetShadowUpdateMinRadius() override; - - void SetShadowUpdateRatio(float shadowUpdateRatio) override; - float GetShadowUpdateRatio() override; - ////////////////////////////////////////////////////////////////////////// - - // Animation parameters - void SetAnimIndex(AZ::u32 animIndex) override; - AZ::u32 GetAnimIndex() override; - - void SetAnimSpeed(float animSpeed) override; - float GetAnimSpeed() override; - - void SetAnimPhase(float animPhase) override; - float GetAnimPhase() override; - - ////////////////////////////////////////////////////////////////////////// - // RenderNodeRequestBus::Handler interface implementation - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // TransformNotificationBus::Handler interface implementation - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - ////////////////////////////////////////////////////////////////////////// - - void BuildGameEntity(AZ::Entity* gameEntity) override; - - ////////////////////////////////////////////////////////////////////////// - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - LightComponent::GetProvidedServices(provided); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - LightComponent::GetRequiredServices(required); - } - - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - LightComponent::GetDependentServices(dependent); - dependent.push_back(AZ_CRC("EditorVisibilityService", 0x90888caf)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - LightComponent::GetIncompatibleServices(incompatible); - } - - static AZ::ExportedComponent ExportLightComponent(AZ::Component* thisComponent, const AZ::PlatformTagSet& /*platformTags*/); - - static void Reflect(AZ::ReflectContext* context); - ////////////////////////////////////////////////////////////////////////// - - protected: - void SetLightType(EditorLightConfiguration::LightType lightType) - { - m_configuration.m_lightType = lightType; - } - - AZ::Uuid GetCubemapId() - { - return m_configuration.m_cubemapId; - } - - virtual const char* GetLightTypeText() const; - - private: - - static bool VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement); - - //! Handles rendering of the preview cubemap by creating a simple cubemapped sphere. - class CubemapPreview : public IRenderNode - { - public: - CubemapPreview(); - void Setup(const char* textureName); - void UpdateTexture(const char* textureName); - void SetTransform(const Matrix34& transform); - - private: - ////////////////////////////////////////////////////////////////////////// - // IRenderNode interface implementation - void Render(const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo) override; - EERType GetRenderNodeType() override; - const char* GetName() const override; - const char* GetEntityClassName() const override; - Vec3 GetPos(bool bWorldOnly = true) const override; - const AABB GetBBox() const override; - void SetBBox([[maybe_unused]] const AABB& WSBBox) override {} - void OffsetPosition([[maybe_unused]] const Vec3& delta) override {} - void SetMaterial(_smart_ptr pMat) override {} - _smart_ptr GetMaterial(Vec3* pHitPos = nullptr) override; - _smart_ptr GetMaterialOverride() override; - IStatObj* GetEntityStatObj(unsigned int nPartId = 0, unsigned int nSubPartId = 0, Matrix34A* pMatrix = nullptr, bool bReturnOnlyVisible = false); - float GetMaxViewDist() override; - void GetMemoryUsage(class ICrySizer* pSizer) const override; - ////////////////////////////////////////////////////////////////////////// - private: - Matrix34 m_renderTransform; - _smart_ptr m_statObj; - }; - - //if an cubemap asset is added or changed - void OnCatalogAssetAdded(const AZ::Data::AssetId& assetId) override; - void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override; - - void OnEditorSpecChange() override; - - //! Returns whether the light is an environment probe - bool IsProbe() const; - - //! Returns whether the light has a cubemap assigned - bool HasCubemap() const; - - //! Triggers regeneration of the environment probe's cubemap (the current cubemap output will be baked into the new cubemap as well). - void GenerateCubemap(); - - //! Removes the associated cubemap, returning the environment probe to its default state - void ClearCubemap(); - - void OnViewCubemapChanged(); - - //! Returns true if it's an environment probe and not using customized cubemap - bool CanGenerateCubemap() const; - - //! Returns the name to use for the Generate Cubemap button. - const char* GetGenerateCubemapButtonName() const; - - const char* GetCubemapAssetName() const; - - void DrawProjectionGizmo(AzFramework::DebugDisplayRequests& dc, const float radius) const; - void DrawPlaneGizmo(AzFramework::DebugDisplayRequests& dc, const float depth) const; - - EditorLightConfiguration m_configuration; - bool m_viewCubemap; - bool m_useCustomizedCubemap; - bool m_cubemapRegen; - bool m_cubemapClear; - - CubemapPreview m_cubemapPreview; - - LightInstance m_light; - - //Statics that can be used by every light - static IEditor* m_editor; - static IMaterialManager* m_materialManager; - static const char* BUTTON_GENERATE; - static const char* BUTTON_ADDBOUNCE; - }; -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.cpp deleted file mode 100644 index 64254ee8f0..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.cpp +++ /dev/null @@ -1,580 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include "EditorMeshComponent.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include // For updating nav tiles on creation of editor physics. -#include // For basic physicalization at edit-time for object snapping. -#include -#include -#include - -#include -#include -#include - -namespace LmbrCentral -{ - AZ_CVAR(bool, cl_editorMeshIntersectionDebug, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Enable editor mesh intersection debugging"); - - void EditorMeshComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("Static Mesh Render Node", &EditorMeshComponent::m_mesh) - ; - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("Mesh", "The Mesh component is the primary method of adding visual geometry to entities") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/StaticMesh.svg") - ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/StaticMesh.png") - ->Attribute(AZ::Edit::Attributes::DynamicIconOverride, &EditorMeshComponent::GetMeshViewportIconPath) - ->Attribute(AZ::Edit::Attributes::PreferNoViewportIcon, true) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-static-mesh.html") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorMeshComponent::m_mesh) - ; - - editContext->Class( - "Render Options", "Rendering options for the mesh.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) - - ->ClassElement(AZ::Edit::ClassElements::Group, "Options") - ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - - ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentRenderNode::MeshRenderOptions::m_opacity, "Opacity", "Opacity value") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, 1.f) - ->Attribute(AZ::Edit::Attributes::Step, 0.1f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_maxViewDist, "Max view distance", "Maximum view distance in meters.") - ->Attribute(AZ::Edit::Attributes::Suffix, " m") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::Max, &MeshComponentRenderNode::GetDefaultMaxViewDist) - ->Attribute(AZ::Edit::Attributes::Step, 0.1f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_viewDistMultiplier, "View distance multiplier", "Adjusts max view distance. If 1.0 then default is used. 1.1 would be 10% further than default.") - ->Attribute(AZ::Edit::Attributes::Suffix, "x") - ->Attribute(AZ::Edit::Attributes::Min, 0.f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Slider, &MeshComponentRenderNode::MeshRenderOptions::m_lodRatio, "LOD distance ratio", "Controls LOD ratio over distance.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Min, 0) - ->Attribute(AZ::Edit::Attributes::Max, 255) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_castShadows, "Cast shadows", "Casts shadows.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_lodBoundingBoxBased, "LOD based on Bounding Boxes", "LOD based on Bounding Boxes.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_useVisAreas, "Use VisAreas", "Allow VisAreas to control this component's visibility.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - - ->ClassElement(AZ::Edit::ClassElements::Group, "Advanced") - ->Attribute(AZ::Edit::Attributes::AutoExpand, false) - - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_rainOccluder, "Rain occluder", "Occludes dynamic raindrops.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_affectDynamicWater, "Affect dynamic water", "Will generate ripples in dynamic water.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_receiveWind, "Receive wind", "Receives wind.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMajorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_acceptDecals, "Accept decals", "Can receive decals.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_affectNavmesh, "Affect navmesh", "Will affect navmesh generation.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_visibilityOccluder, "Visibility occluder", "Is appropriate for occluding visibility of other objects.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_dynamicMesh, "Deformable mesh", "Enables vertex deformation on mesh.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMajorChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::MeshRenderOptions::m_affectGI, "Affects GI", "Affects the global illumination results.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::MeshRenderOptions::OnMinorChanged) - ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility) - ; - - editContext->Class( - "Mesh Rendering", "Attach geometry to the entity.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20)) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_visible, "Visible", "Is currently visible.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::RefreshRenderState) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_meshAsset, "Mesh asset", "Mesh asset reference") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::OnAssetPropertyChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_material, "Material override", "Optionally specify an override material.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::OnAssetPropertyChanged) - ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentRenderNode::m_renderOptions, "Render options", "Render/draw options.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &MeshComponentRenderNode::RefreshRenderState) - ; - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class()->RequestBus("MeshComponentRequestBus"); - } - } - - void EditorMeshComponent::Activate() - { - EditorComponentBase::Activate(); - - m_mesh.AttachToEntity(m_entity->GetId()); - bool isStatic = false; - AZ::TransformBus::EventResult(isStatic, m_entity->GetId(), &AZ::TransformBus::Events::IsStaticTransform); - m_mesh.SetTransformStaticState(isStatic); - - bool visible = false; - AzToolsFramework::EditorEntityInfoRequestBus::EventResult( - visible, GetEntityId(), &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); - m_mesh.UpdateAuxiliaryRenderFlags(!visible, ERF_HIDDEN); - - // Note we are purposely connecting to buses before calling m_mesh.CreateMesh(). - // m_mesh.CreateMesh() can result in events (eg: OnMeshCreated) that we want receive. - MaterialOwnerRequestBus::Handler::BusConnect(m_entity->GetId()); - AzFramework::BoundsRequestBus::Handler::BusConnect(m_entity->GetId()); - MeshComponentRequestBus::Handler::BusConnect(m_entity->GetId()); - MeshComponentNotificationBus::Handler::BusConnect(m_entity->GetId()); - LegacyMeshComponentRequestBus::Handler::BusConnect(m_entity->GetId()); - RenderNodeRequestBus::Handler::BusConnect(m_entity->GetId()); - AZ::TransformNotificationBus::Handler::BusConnect(m_entity->GetId()); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusConnect(GetEntityId()); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId()); - AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusConnect(GetEntityId()); - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); - AzFramework::EntityIdContextQueryBus::EventResult(m_contextId, GetEntityId(), &AzFramework::EntityIdContextQueries::GetOwningContextId); - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusConnect({ GetEntityId(), m_contextId }); - - m_mesh.m_renderOptions.m_changeCallback = - [this]() - { - m_mesh.RefreshRenderState(); - AffectNavmesh(); - }; - - m_mesh.CreateMesh(); - } - - void EditorMeshComponent::Deactivate() - { - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); - AZ::Data::AssetBus::Handler::BusDisconnect(); - MaterialOwnerRequestBus::Handler::BusDisconnect(); - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - MeshComponentRequestBus::Handler::BusDisconnect(); - MeshComponentNotificationBus::Handler::BusDisconnect(); - LegacyMeshComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusDisconnect(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); - AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusDisconnect(); - - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusDisconnect(); - - m_mesh.m_renderOptions.m_changeCallback = nullptr; - - m_mesh.DestroyMesh(); - m_mesh.AttachToEntity(AZ::EntityId()); - - EditorComponentBase::Deactivate(); - } - - - void EditorMeshComponent::OnMeshCreated(const AZ::Data::Asset& asset) - { - AZ::Data::AssetBus::Handler::BusDisconnect(); - AZ::Data::AssetBus::Handler::BusConnect(asset.GetId()); - - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void EditorMeshComponent::OnMeshDestroyed() - { - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - IRenderNode* EditorMeshComponent::GetRenderNode() - { - return &m_mesh; - } - - float EditorMeshComponent::GetRenderNodeRequestBusOrder() const - { - return s_renderNodeRequestBusOrder; - } - - void EditorMeshComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - AZ_UNUSED(world); - - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void EditorMeshComponent::OnStaticChanged(bool isStatic) - { - m_mesh.SetTransformStaticState(isStatic); - if (m_mesh.m_renderOptions.m_changeCallback) - { - m_mesh.m_renderOptions.m_changeCallback(); - } - AffectNavmesh(); - } - - AZ::Aabb EditorMeshComponent::GetWorldBounds() - { - return m_mesh.CalculateWorldAABB(); - } - - AZ::Aabb EditorMeshComponent::GetLocalBounds() - { - return m_mesh.CalculateLocalAABB(); - } - - AzFramework::RenderGeometry::RayResult EditorMeshComponent::RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) - { - AzFramework::RenderGeometry::RayResult result; - if (!GetVisibility() && ray.m_onlyVisible) - { - return result; - } - - if (IStatObj* geometry = GetStatObj()) - { - const AZ::Vector3 rayDirection = (ray.m_endWorldPosition - ray.m_startWorldPosition); - const AZ::Transform& transform = GetTransform()->GetWorldTM(); - const AZ::Transform inverseTransform = transform.GetInverse(); - - const AZ::Vector3 rayStartLocal = inverseTransform.TransformPoint(ray.m_startWorldPosition); - const AZ::Vector3 rayDistNormLocal = inverseTransform.TransformVector(rayDirection).GetNormalized(); - - SRayHitInfo hi; - hi.inReferencePoint = AZVec3ToLYVec3(rayStartLocal); - hi.inRay = Ray(hi.inReferencePoint, AZVec3ToLYVec3(rayDistNormLocal)); - hi.bInFirstHit = true; - hi.bGetVertColorAndTC = true; - - if (geometry->RayIntersection(hi)) - { - AZ::Matrix3x4 invTransformMatrix = AZ::Matrix3x4::CreateFromTransform(inverseTransform); - invTransformMatrix.Transpose(); - - result.m_uv = LYVec2ToAZVec2(hi.vHitTC); - result.m_worldPosition = transform.TransformPoint(LYVec3ToAZVec3(hi.vHitPos)); - result.m_worldNormal = invTransformMatrix.Multiply3x3(LYVec3ToAZVec3(hi.vHitNormal)).GetNormalized(); - result.m_distance = (result.m_worldPosition - ray.m_startWorldPosition).GetLength(); - result.m_entityAndComponent = { GetEntityId(), GetId() }; - if (cl_editorMeshIntersectionDebug) - { - m_debugPos = result.m_worldPosition; - m_debugNormal = result.m_worldNormal; - } - } - } - - return result; - } - - void EditorMeshComponent::SetMeshAsset(const AZ::Data::AssetId& id) - { - m_mesh.SetMeshAsset(id); - AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, - GetEntityId()); - } - - void EditorMeshComponent::SetMaterial(_smart_ptr material) - { - m_mesh.SetMaterial(material); - - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); - } - - _smart_ptr EditorMeshComponent::GetMaterial() - { - return m_mesh.GetMaterial(); - } - - void EditorMeshComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId) - { - SetMeshAsset(assetId); - } - - void EditorMeshComponent::OnEntityVisibilityChanged(bool visibility) - { - m_mesh.UpdateAuxiliaryRenderFlags(!visibility, ERF_HIDDEN); - m_mesh.RefreshRenderState(); - } - - static void DecideColor( - const bool selected, const bool mouseHovered, const bool visible, - ColorB& triangleColor, ColorB& lineColor) - { - const ColorB translucentPurple = ColorB(250, 0, 250, 30); - - // default both colors to hidden - triangleColor = ColorB(AZ::u32(0)); - lineColor = ColorB(AZ::u32(0)); - - if (selected) - { - if (!visible) - { - lineColor = Col_Black; - - if (mouseHovered) - { - triangleColor = translucentPurple; - } - } - } - else - { - if (mouseHovered) - { - triangleColor = translucentPurple; - lineColor = AZColorToLYColorF(AzFramework::ViewportColors::HoverColor); - } - } - } - - void EditorMeshComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - const bool mouseHovered = m_accentType == AzToolsFramework::EntityAccentType::Hover; - - IEditor* editor = nullptr; - AzToolsFramework::EditorRequests::Bus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor); - - const bool highlightGeometryOnMouseHover = editor->GetEditorSettings()->viewports.bHighlightMouseOverGeometry; - // if the mesh component is not visible, when selected we still draw the wireframe to indicate the shapes extent and position - const bool highlightGeometryWhenSelected = editor->GetEditorSettings()->viewports.bHighlightSelectedGeometry || !GetVisibility(); - - if ((!IsSelected() && mouseHovered && highlightGeometryOnMouseHover) || (IsSelected() && highlightGeometryWhenSelected)) - { - AZ::Transform transform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - - ColorB triangleColor, lineColor; - DecideColor(IsSelected(), mouseHovered, GetVisibility(), triangleColor, lineColor); - - SGeometryDebugDrawInfo dd; - dd.tm = AZTransformToLYTransform(transform); - dd.bExtrude = true; - dd.color = triangleColor; - dd.lineColor = lineColor; - - if (IStatObj* geometry = GetStatObj()) - { - geometry->DebugDraw(dd); - } - } - - if (cl_editorMeshIntersectionDebug) - { - debugDisplay.DrawArrow(m_debugPos, m_debugPos + (0.1f * m_debugNormal), 0.1f); - debugDisplay.DrawBall(m_debugPos, 0.03f); - debugDisplay.DrawWireBox(GetWorldBounds().GetMin(), GetWorldBounds().GetMax()); - } - } - - void EditorMeshComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - if (auto meshComponent = gameEntity->CreateComponent()) - { - m_mesh.CopyPropertiesTo(meshComponent->m_meshRenderNode); - // ensure we do not copy across the edit time entity id - meshComponent->m_meshRenderNode.m_renderOptions.m_attachedToEntityId = AZ::EntityId(); - } - } - - - IStatObj* EditorMeshComponent::GetStatObj() - { - return m_mesh.GetEntityStatObj(); - } - - bool EditorMeshComponent::GetVisibility() - { - return m_mesh.GetVisible(); - } - - void EditorMeshComponent::SetVisibility(bool visible) - { - m_mesh.SetVisible(visible); - } - - void EditorMeshComponent::AffectNavmesh() - { - // Refresh the nav tile when the flag changes. - INavigationSystem* pNavigationSystem = nullptr; // INavigationSystem will be converted to an AZInterface (LY-111343) - if (pNavigationSystem) - { - pNavigationSystem->WorldChanged(AZAabbToLyAABB(GetWorldBounds())); - } - } - - AZStd::string_view staticViewportIcon = "Icons/Components/Viewport/StaticMesh.png"; - AZStd::string_view dynamicViewportIcon = "Icons/Components/Viewport/DynamicMesh.png"; - AZStd::string EditorMeshComponent::GetMeshViewportIconPath() const - { - if (m_mesh.m_renderOptions.IsStatic()) - { - return staticViewportIcon; - } - - return dynamicViewportIcon; - } - - void EditorMeshComponent::OnAssetReloaded(AZ::Data::Asset /*asset*/) - { - using namespace AzFramework::RenderGeometry; - IntersectionNotificationBus::Event(m_contextId, &IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void EditorMeshComponent::OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& /*assetInfo*/) - { - if (m_mesh.m_meshAsset.GetId() != assetId) - { - return; - } - // If this editor mesh component is loaded and active in the level, it's referencing an asset that was just removed. - // Clearing this asset reference will help visualize this change. Note that this won't clear all references to this - // asset automatically, any levels that aren't loaded won't have the reference removed. - - // Set the mesh asset to invalid on the main thread. - AZ::TickBus::QueueFunction([this, assetId]() - { - // Emit a warning so users know this has occurred, it may not be intentional because the asset was removed before - // the references were cleared. Do this on the main thread. - AZ_Warning("EditorMeshComponent", false, "asset with ID %s referenced by entity named '%s' with ID %s was removed, this reference will be cleared on the associated component.", - assetId.ToString().c_str(), - GetEntity() ? GetEntity()->GetName().c_str() : "Invalid entity", - GetEntityId().ToString().c_str()); - - m_mesh.DestroyMesh(); - AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, - GetEntityId()); - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, - AzToolsFramework::Refresh_AttributesAndValues); - }); - } - - AZ::Aabb EditorMeshComponent::GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/) - { - return GetWorldBounds(); - } - - bool EditorMeshComponent::EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/, - const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) - { - if (IStatObj* geometry = GetStatObj()) - { - AZ::Transform transform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - auto legacyTransform = AZTransformToLYTransform(transform); - const auto legacySrc = AZVec3ToLYVec3(src); - const auto legacyDir = AZVec3ToLYVec3(dir); - - const Matrix34 inverseTM = legacyTransform.GetInverted(); - const Vec3 raySrcLocal = inverseTM.TransformPoint(legacySrc); - const Vec3 rayDirLocal = inverseTM.TransformVector(legacyDir).GetNormalized(); - - SRayHitInfo hi; - hi.inReferencePoint = raySrcLocal; - hi.inRay = Ray(raySrcLocal, rayDirLocal); - if (geometry->RayIntersection(hi)) - { - const Vec3 worldHitPos = legacyTransform.TransformPoint(hi.vHitPos); - distance = legacySrc.GetDistance(worldHitPos); - return true; - } - } - - return false; - } - - void EditorMeshComponent::OnAccentTypeChanged(AzToolsFramework::EntityAccentType accent) - { - m_accentType = accent; - } - - bool AddMeshComponentWithMesh(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId) - { - // Error handling for failures should be done at the call site, this function can be invoked from Python. - if (!targetEntity.IsValid()) - { - return false; - } - AZ::ComponentTypeList componentsToAdd; - componentsToAdd.push_back(AZ::AzTypeInfo::Uuid()); - - AZStd::vector entityList; - entityList.push_back(targetEntity); - - AzToolsFramework::EntityCompositionRequests::AddComponentsOutcome outcome = - AZ::Failure(AZStd::string("Failed to call AddComponentsToEntities on EntityCompositionRequestBus")); - AzToolsFramework::EntityCompositionRequestBus::BroadcastResult(outcome, &AzToolsFramework::EntityCompositionRequests::AddComponentsToEntities, entityList, componentsToAdd); - - if (!outcome.IsSuccess()) - { - return false; - } - - AZ::Data::AssetId meshAsset(meshAssetId); - - // If necessary, the call site can verify if the mesh was actually set. - LmbrCentral::MeshComponentRequestBus::Event( - targetEntity, - &LmbrCentral::MeshComponentRequestBus::Events::SetMeshAsset, - meshAsset); - return true; - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.h deleted file mode 100644 index 7617673e3b..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorMeshComponent.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include "MeshComponent.h" - - -struct IPhysicalEntity; - -namespace LmbrCentral -{ - /** - * In-editor mesh component. - * Conducts some additional listening and operations to ensure immediate - * effects when changing fields in the editor. - */ - class EditorMeshComponent - : public AzToolsFramework::Components::EditorComponentBase - , public AZ::Data::AssetBus::Handler - , private AzFramework::AssetCatalogEventBus::Handler - , public AzFramework::BoundsRequestBus::Handler - , private AzFramework::RenderGeometry::IntersectionRequestBus::Handler - , private MeshComponentRequestBus::Handler - , private MaterialOwnerRequestBus::Handler - , private MeshComponentNotificationBus::Handler - , private RenderNodeRequestBus::Handler - , private AZ::TransformNotificationBus::Handler - , private AzToolsFramework::EntitySelectionEvents::Bus::Handler - , private AzToolsFramework::EditorVisibilityNotificationBus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private LegacyMeshComponentRequestBus::Handler - , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - , private AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler - { - public: - AZ_COMPONENT(EditorMeshComponent, "{FC315B86-3280-4D03-B4F0-5553D7D08432}", AzToolsFramework::Components::EditorComponentBase) - - ~EditorMeshComponent() = default; - - const float s_renderNodeRequestBusOrder = 100.f; - - // AZ::Component overrides ... - void Activate() override; - void Deactivate() override; - - // BoundsRequestBus and MeshComponentRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - // IntersectionRequestBus overrides ... - AzFramework::RenderGeometry::RayResult RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) override; - - // MeshComponentRequestBus overrides ... - void SetMeshAsset(const AZ::Data::AssetId& id) override; - AZ::Data::Asset GetMeshAsset() override { return m_mesh.GetMeshAsset(); } - void SetVisibility(bool visible) override; - bool GetVisibility() override; - - // MaterialOwnerRequestBus overrides ... - void SetMaterial(_smart_ptr) override; - _smart_ptr GetMaterial() override; - - // MeshComponentNotificationBus overrides ... - void OnMeshCreated(const AZ::Data::Asset& asset) override; - void OnMeshDestroyed() override; - - // RenderNodeRequestBus overrides ... - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - - // TransformNotificationBus overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - void OnStaticChanged(bool isStatic) override; - - // EditorVisibilityNotificationBus overrides ... - void OnEntityVisibilityChanged(bool visibility) override; - - // AzFramework::EntityDebugDisplayEventBus overrides .... - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - //! Called when you want to change the game asset through code (like when creating components based on assets). - void SetPrimaryAsset(const AZ::Data::AssetId& assetId) override; - - // LegacyMeshComponentRequests overrides ... - IStatObj* GetStatObj() override; - - // EditorComponentBase overrides ... - void BuildGameEntity(AZ::Entity* gameEntity) override; - - // AZ::Data::AssetBus overrides ... - void OnAssetReloaded(AZ::Data::Asset asset) override; - - // AzFramework::AssetCatalogEventBus overrides ... - void OnCatalogAssetRemoved(const AZ::Data::AssetId& assetId, const AZ::Data::AssetInfo& assetInfo) override; - - // EditorComponentSelectionRequestsBus overrides ... - AZ::Aabb GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& viewportInfo) override; - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, - const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override; - bool SupportsEditorRayIntersect() override { return true; } - - // EditorComponentSelectionNotificationsBus overrides ... - void OnAccentTypeChanged(AzToolsFramework::EntityAccentType accent) override; - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("MeshService", 0x71d8a455)); - provided.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - dependent.push_back(AZ_CRC("EditorVisibilityService", 0x90888caf)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("MeshService", 0x71d8a455)); - incompatible.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void Reflect(AZ::ReflectContext* context); - - protected: - - // Decides if this mesh affects the navmesh or not. - void AffectNavmesh(); - - AZStd::string GetMeshViewportIconPath() const; - - AzToolsFramework::EntityAccentType m_accentType = AzToolsFramework::EntityAccentType::None; ///< State of the entity selection in the viewport. - MeshComponentRenderNode m_mesh; ///< IRender node implementation. - - AzFramework::EntityContextId m_contextId; - AZ::Vector3 m_debugPos = AZ::Vector3(0); - AZ::Vector3 m_debugNormal = AZ::Vector3(0); - }; - - // Helper function useful for automation. - bool AddMeshComponentWithMesh(const AZ::EntityId& targetEntity, const AZ::Uuid& meshAssetId); -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorPointLightComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorPointLightComponent.cpp deleted file mode 100644 index ac2a4ec822..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorPointLightComponent.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include "EditorPointLightComponent.h" - -namespace LmbrCentral -{ - void EditorPointLightComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Point Light", "The Point Light component allows an entity to create a point of light") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/PointLight.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/PointLight.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-point-light.html") - ->Attribute(AZ::Edit::Attributes::ExportIfAllPlatformTags, AZStd::vector{AZ_CRC("renderer", 0xf199a19c)}) // Only export on platforms that render - ->Attribute(AZ::Edit::Attributes::RuntimeExportCallback, &EditorLightComponent::ExportLightComponent) - ; - } - } - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class()->RequestBus("EditorPointLightComponentBus"); - } - } - - void EditorPointLightComponent::Init() - { - SetLightType(EditorLightConfiguration::LightType::Point); - EditorLightComponent::Init(); - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorPointLightComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorPointLightComponent.h deleted file mode 100644 index 4438c6f2f1..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorPointLightComponent.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include "EditorLightComponent.h" - -namespace LmbrCentral -{ - /*! - * In-editor point light component. - * Handles previewing and activating lights in the editor. - */ - class EditorPointLightComponent - : public EditorLightComponent - { - public: - AZ_COMPONENT(EditorPointLightComponent, "{00818135-138D-42AD-8657-FF3FD38D9E7A}", AzToolsFramework::Components::EditorComponentBase); - - static void Reflect(AZ::ReflectContext* context); - - void Init() override; - - protected: - const char* GetLightTypeText() const override - { - return "Point Light"; - } - }; -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorProjectorLightComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/EditorProjectorLightComponent.cpp deleted file mode 100644 index 3faab93d82..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorProjectorLightComponent.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include - -#include "EditorProjectorLightComponent.h" - -namespace LmbrCentral -{ - void EditorProjectorLightComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class( - "Projector Light", "The Projector Light component allows an entity to project a light") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/ProjectorLight.svg") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/ProjectorLight.png") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://docs.aws.amazon.com/lumberyard/latest/userguide/component-projector-light.html") - ->Attribute(AZ::Edit::Attributes::ExportIfAllPlatformTags, AZStd::vector{AZ_CRC("renderer", 0xf199a19c)}) // Only export on platforms that render - ->Attribute(AZ::Edit::Attributes::RuntimeExportCallback, &EditorLightComponent::ExportLightComponent) - ; - } - } - - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class()->RequestBus("EditorProjectorLightComponentBus"); - } - } - - void EditorProjectorLightComponent::Init() - { - SetLightType(EditorLightConfiguration::LightType::Projector); - EditorLightComponent::Init(); - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/EditorProjectorLightComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/EditorProjectorLightComponent.h deleted file mode 100644 index 5526c5917e..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/EditorProjectorLightComponent.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include "EditorLightComponent.h" - -namespace LmbrCentral -{ - /*! - * In-editor point light component. - * Handles previewing and activating lights in the editor. - */ - class EditorProjectorLightComponent - : public EditorLightComponent - { - public: - AZ_COMPONENT(EditorProjectorLightComponent, "{41928E34-B558-4559-82CF-8B5795A38CB4}", EditorLightComponent); - - static void Reflect(AZ::ReflectContext* context); - - void Init() override; - - protected: - const char* GetLightTypeText() const override - { - return "Projector Light"; - } - }; -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/GeomCacheComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/GeomCacheComponent.cpp deleted file mode 100644 index 8739030a56..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/GeomCacheComponent.cpp +++ /dev/null @@ -1,817 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include "GeomCacheComponent.h" - -#include -#include - -#include "MathConversion.h" - -#include - -namespace LmbrCentral -{ - //BehaviorContext GeometryCacheComponentNotificationBus Forwarder - class BehaviorGeometryCacheComponentNotificationBusHandler - : public GeometryCacheComponentNotificationBus::Handler - , public AZ::BehaviorEBusHandler - { - public: - AZ_EBUS_BEHAVIOR_BINDER(BehaviorGeometryCacheComponentNotificationBusHandler, "{8E0B4617-DD82-47D8-AA2F-3DF3E6677B4B}", AZ::SystemAllocator, - OnPlaybackStart, - OnPlaybackPause, - OnPlaybackStop, - OnStandinChanged); - - void OnPlaybackStart() override - { - Call(FN_OnPlaybackStart); - } - - void OnPlaybackPause() override - { - Call(FN_OnPlaybackPause); - } - - void OnPlaybackStop() override - { - Call(FN_OnPlaybackStop); - } - - void OnStandinChanged(StandinType standinType) override - { - Call(FN_OnStandinChanged, standinType); - } - }; - - void GeometryCacheCommon::Reflect(AZ::ReflectContext* context) - { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("Visible", &GeometryCacheCommon::m_visible) - ->Field("MinSpec", &GeometryCacheCommon::m_minSpec) - ->Field("GeomCacheAsset", &GeometryCacheCommon::m_geomCacheAsset) - ->Field("MaterialOverrideAsset", &GeometryCacheCommon::m_materialOverrideAsset) - ->Field("Loop", &GeometryCacheCommon::m_loop) - ->Field("PlayOnStart", &GeometryCacheCommon::m_playOnStart) - ->Field("StartTime", &GeometryCacheCommon::m_startTime) - ->Field("StreamInDistance", &GeometryCacheCommon::m_streamInDistance) - ->Field("FirstFrameStandin", &GeometryCacheCommon::m_firstFrameStandin) - ->Field("LastFrameStandin", &GeometryCacheCommon::m_lastFrameStandin) - ->Field("Standin", &GeometryCacheCommon::m_standin) - ->Field("StandinDistance", &GeometryCacheCommon::m_standinDistance) - ->Field("MaxViewDistance", &GeometryCacheCommon::m_maxViewDistance) - ->Field("ViewDistanceMultiplier", &GeometryCacheCommon::m_viewDistanceMultiplier) - ->Field("LODDistanceRatio", &GeometryCacheCommon::m_lodDistanceRatio) - ->Field("CastShadows", &GeometryCacheCommon::m_castShadows) - ->Field("UseVisArea", &GeometryCacheCommon::m_useVisAreas) - ; - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("GeometryCacheComponentRequestBus") - ->Event("Play", &GeometryCacheComponentRequestBus::Events::Play) - ->Event("Pause", &GeometryCacheComponentRequestBus::Events::Pause) - ->Event("Stop", &GeometryCacheComponentRequestBus::Events::Stop) - - ->Event("GetTimeRemaining", &GeometryCacheComponentRequestBus::Events::GetTimeRemaining) - - ->Event("SetVisible", &GeometryCacheComponentRequestBus::Events::SetVisible) - ->Event("GetVisible", &GeometryCacheComponentRequestBus::Events::GetVisible) - ->VirtualProperty("Visible", "GetVisible", "SetVisible") - - ->Event("SetLoop", &GeometryCacheComponentRequestBus::Events::SetLoop) - ->Event("GetLoop", &GeometryCacheComponentRequestBus::Events::GetLoop) - ->VirtualProperty("Loop", "GetLoop", "SetLoop") - - ->Event("SetStartTime", &GeometryCacheComponentRequestBus::Events::SetStartTime) - ->Event("GetStartTime", &GeometryCacheComponentRequestBus::Events::GetStartTime) - ->VirtualProperty("StartTime", "GetStartTime", "SetStartTime") - - ->Event("SetFirstFrameStandIn", &GeometryCacheComponentRequestBus::Events::SetFirstFrameStandIn) - ->Event("GetFirstFrameStandIn", &GeometryCacheComponentRequestBus::Events::GetFirstFrameStandIn) - ->VirtualProperty("FirstFrameStandIn", "GetFirstFrameStandIn", "SetFirstFrameStandIn") - - ->Event("SetLastFrameStandIn", &GeometryCacheComponentRequestBus::Events::SetLastFrameStandIn) - ->Event("GetLastFrameStandIn", &GeometryCacheComponentRequestBus::Events::GetLastFrameStandIn) - ->VirtualProperty("LastFrameStandIn", "GetLastFrameStandIn", "SetLastFrameStandIn") - - ->Event("SetStandIn", &GeometryCacheComponentRequestBus::Events::SetStandIn) - ->Event("GetStandIn", &GeometryCacheComponentRequestBus::Events::GetStandIn) - ->VirtualProperty("StandIn", "GetStandIn", "SetStandIn") - - ->Event("SetStandInDistance", &GeometryCacheComponentRequestBus::Events::SetStandInDistance) - ->Event("GetStandInDistance", &GeometryCacheComponentRequestBus::Events::GetStandInDistance) - ->VirtualProperty("StandInDistance", "GetStandInDistance", "SetStandInDistance") - - ->Event("SetStreamInDistance", &GeometryCacheComponentRequestBus::Events::SetStreamInDistance) - ->Event("GetStreamInDistance", &GeometryCacheComponentRequestBus::Events::GetStreamInDistance) - ->VirtualProperty("StreamInDistance", "GetStreamInDistance", "SetStreamInDistance") - - ; - - behaviorContext->EBus("GeometryCacheComponentNotificationBus") - ->Handler() - ; - - behaviorContext->Class() - ->RequestBus("GeometryCacheComponentRequestBus") - ->NotificationBus("GeometryCacheComponentNotificationBus") - ; - } - } - - GeometryCacheCommon::~GeometryCacheCommon() - { - if (m_geomCacheRenderNode) - { - delete m_geomCacheRenderNode; - m_geomCacheRenderNode = nullptr; - } - } - - void GeometryCacheCommon::Init(const AZ::EntityId& entityId) - { - m_entityId = entityId; - - if (gEnv && gEnv->p3DEngine && !m_geomCacheRenderNode) - { - m_geomCacheRenderNode = static_cast(gEnv->p3DEngine->CreateRenderNode(eERType_GeomCache)); - } - } - - void GeometryCacheCommon::Activate() - { - m_isRegisteredWithRenderer = false; - - m_currentTime = m_startTime; //We default to m_startTime here instead of 0.0 so that animations actually start at m_startTime - - //If there is no set asset use the defaultgeomcache asset that is expected to exist in EngineAssets - if (!m_geomCacheAsset.GetId().IsValid()) - { - AZ::Data::AssetId defaultGeomCacheAssetId; - const char* defaultGeomCacheAssetName = "engineassets/geomcaches/defaultgeomcache.cax"; - AZ::Data::AssetCatalogRequestBus::BroadcastResult(defaultGeomCacheAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, defaultGeomCacheAssetName, AZ::Data::s_invalidAssetType, false); - - if (defaultGeomCacheAssetId.IsValid()) - { - m_geomCacheAsset.Create(defaultGeomCacheAssetId); - } - else - { - AZ_Warning("GeometryCache", false, "Default Geometry Cache was not found"); - } - } - - CreateGeomCache(); - - //Hide all referenced entities by default - //If a standin *should* be shown that will be determined on the first tick - HideAllStandins(); - m_currentStandinType = StandinType::None; - ShowCurrentStandin(); - - GeometryCacheComponentRequestBus::Handler::BusConnect(m_entityId); - AZ::TransformNotificationBus::Handler::BusConnect(m_entityId); - AZ::TickBus::Handler::BusConnect(); - MaterialOwnerRequestBus::Handler::BusConnect(m_entityId); - - //Get initial transform and update the render node with it - AZ::Transform world = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(world, m_entityId, &AZ::TransformBus::Events::GetWorldTM); - - OnTransformChanged(AZ::Transform::CreateIdentity(), world); - - m_playing = false; - if (m_playOnStart) - { - Play(); - } - } - - void GeometryCacheCommon::Deactivate() - { - HideAllStandins(); - - GeometryCacheComponentRequestBus::Handler::BusDisconnect(m_entityId); - AZ::TransformNotificationBus::Handler::BusDisconnect(m_entityId); - AZ::TickBus::Handler::BusDisconnect(); - MaterialOwnerRequestBus::Handler::BusDisconnect(m_entityId); - - DestroyGeomCache(); - } - - void GeometryCacheCommon::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_currentWorldPos = world.GetTranslation(); - - if (m_geomCacheRenderNode) - { - Matrix34 cryMat = AZTransformToLYTransform(world); - m_geomCacheRenderNode->SetMatrix(cryMat); - - //Re-register to update position - RegisterRenderNode(); - } - } - - void GeometryCacheCommon::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) - { - if (m_geomCacheRenderNode && m_playing) - { - float playbackTime = m_currentTime; - - m_currentTime += deltaTime; - playbackTime = m_currentTime; - - m_geomCacheRenderNode->SetPlaybackTime(playbackTime); - } - - //Don't care about handling stand-in visibility if the whole - //GeomCache shouldn't be visible - if (m_hidden) - { - return; - } - - bool standinInUse = false; - - //Distance based stand-in - //This has the highest priority - const Vec3 cameraPos = gEnv->p3DEngine->GetRenderingCamera().GetPosition(); - float distance = (LYVec3ToAZVec3(cameraPos) - m_currentWorldPos).GetLength(); - if (distance > m_standinDistance) - { - standinInUse = true; - - if (m_standin.IsValid() && m_currentStandinType != StandinType::Distance) - { - HideCurrentStandin(); - m_currentStandinType = StandinType::Distance; - ShowCurrentStandin(); - } - } - else - { - //Stand-in for first frame - if (m_currentTime == m_startTime) - { - standinInUse = true; - - if (m_firstFrameStandin.IsValid() && m_currentStandinType != StandinType::FirstFrame) - { - HideCurrentStandin(); - m_currentStandinType = StandinType::FirstFrame; - ShowCurrentStandin(); - } - } - //Stand-in for last frame - else if (!m_loop && m_geomCache && m_currentTime >= m_geomCache->GetDuration()) - { - standinInUse = true; - - if (m_lastFrameStandin.IsValid() && m_currentStandinType != StandinType::LastFrame) - { - HideCurrentStandin(); - m_currentStandinType = StandinType::LastFrame; - ShowCurrentStandin(); - } - } - } - - //If none of the other stand-ins are being rendered, remove any existing ones - //and go back to just rendering the geom cache - if (!standinInUse && m_currentStandinType != StandinType::None) - { - HideCurrentStandin(); - m_currentStandinType = StandinType::None; - ShowCurrentStandin(); - } - } - - void GeometryCacheCommon::OnAssetReady(AZ::Data::Asset asset) - { - if (asset == m_geomCacheAsset) - { - m_geomCacheAsset = asset; - m_geomCache = m_geomCacheAsset.Get()->m_geomCache; - - if (m_geomCache != nullptr) - { - m_geomCacheRenderNode->SetGeomCache(m_geomCache); - - //Allow this geom cache to clean up after we've properly set it on the render node - m_geomCache->SetProcessedByRenderNode(true); - - if (m_materialOverride) - { - m_geomCacheRenderNode->SetMaterial(m_materialOverride); - } - - if (gEnv && gEnv->p3DEngine) - { - gEnv->p3DEngine->RegisterEntity(m_geomCacheRenderNode); - m_isRegisteredWithRenderer = true; - } - - //Apply latest transform to the render node - AZ::Transform world = AZ::Transform::CreateIdentity(); - AZ::TransformBus::EventResult(world, m_entityId, &AZ::TransformBus::Events::GetWorldTM); - - OnTransformChanged(AZ::Transform::CreateIdentity(), world); - } - } - } - - void GeometryCacheCommon::OnAssetReloaded(AZ::Data::Asset asset) - { - if (asset == m_geomCacheAsset) - { - // We need to make sure m_geomCacheAsset is assigned with the new asset. - // Since the new asset passed in has zero refCount. The assigning will clear the refCount of the old m_geomCacheAsset - // and set the refCount of the new asset to 1, otherwise it will be unloaded. - m_geomCacheAsset = asset; - m_geomCache = m_geomCacheAsset.Get()->m_geomCache; - } - } - - void GeometryCacheCommon::SetMaterial(_smart_ptr material) - { - m_materialOverride = material; - - if (material) - { - m_materialOverrideAsset.SetAssetPath(material->GetName()); - } - else - { - m_materialOverrideAsset.SetAssetPath(""); - } - - DestroyGeomCache(); - CreateGeomCache(); - } - - _smart_ptr GeometryCacheCommon::GetMaterial() - { - if (m_materialOverride) - { - return m_materialOverride; - } - - if (m_geomCache == nullptr) - { - return nullptr; - } - - return m_geomCache->GetMaterial(); - } - - void GeometryCacheCommon::Play() - { - if (!m_playing) - { - m_playing = true; - GeometryCacheComponentNotificationBus::Broadcast(&GeometryCacheComponentNotificationBus::Events::OnPlaybackStart); - } - } - - void GeometryCacheCommon::Pause() - { - if (m_playing) - { - m_playing = false; - GeometryCacheComponentNotificationBus::Broadcast(&GeometryCacheComponentNotificationBus::Events::OnPlaybackPause); - } - } - - void GeometryCacheCommon::Stop() - { - if (m_playing) - { - m_playing = false; - m_currentTime = 0; - if (m_geomCacheRenderNode) - { - m_geomCacheRenderNode->StopStreaming(); - } - GeometryCacheComponentNotificationBus::Broadcast(&GeometryCacheComponentNotificationBus::Events::OnPlaybackStop); - } - } - - float GeometryCacheCommon::GetTimeRemaining() - { - if (m_playing) - { - return m_geomCache->GetDuration() - m_currentTime; - } - else - { - return -1.0f; - } - } - - void GeometryCacheCommon::SetGeomCacheAsset(const AZ::Data::AssetId& id) - { - DestroyGeomCache(); - m_geomCacheAsset.Create(id); - CreateGeomCache(); - } - - void GeometryCacheCommon::SetVisible(bool visible) - { - m_visible = visible; - OnRenderOptionsChanged(); - } - - void GeometryCacheCommon::SetLoop(bool loop) - { - m_loop = loop; - OnLoopChanged(); - } - - void GeometryCacheCommon::SetStartTime(float startTime) - { - m_startTime = startTime; - OnStartTimeChanged(); - } - - void GeometryCacheCommon::SetFirstFrameStandIn(AZ::EntityId entityId) - { - if (!entityId.IsValid()) - { - return; - } - - if (m_currentStandinType == StandinType::FirstFrame) - { - HideCurrentStandin(); - } - - m_firstFrameStandin = entityId; - - if (m_currentStandinType == StandinType::FirstFrame) - { - ShowCurrentStandin(); - } - } - - void GeometryCacheCommon::SetLastFrameStandIn(AZ::EntityId entityId) - { - if (!entityId.IsValid()) - { - return; - } - - if (m_currentStandinType == StandinType::LastFrame) - { - HideCurrentStandin(); - } - - m_lastFrameStandin = entityId; - - if (m_currentStandinType == StandinType::LastFrame) - { - ShowCurrentStandin(); - } - } - - void GeometryCacheCommon::SetStandIn(AZ::EntityId entityId) - { - if (!entityId.IsValid()) - { - return; - } - - if (m_currentStandinType == StandinType::Distance) - { - HideCurrentStandin(); - } - - m_standin = entityId; - - if (m_currentStandinType == StandinType::Distance) - { - ShowCurrentStandin(); - } - } - - void GeometryCacheCommon::SetStandInDistance(float standInDistance) - { - m_standinDistance = standInDistance; - } - - void GeometryCacheCommon::SetStreamInDistance(float streamInDistance) - { - m_streamInDistance = streamInDistance; - OnStreamInDistanceChanged(); - } - - void GeometryCacheCommon::OnRenderOptionsChanged() - { - AZ::u32 rendFlags = 0; - - //We want to hide the GeomCache if we're rendering a stand-in - if (m_renderingStandin) - { - rendFlags |= ERF_HIDDEN; - } - //But if the GeomCache is marked as invisible (or the min spec is too high), neither - //the GeomCache or any stand-ins should render - const int configSpec = gEnv->pSystem->GetConfigSpec(true); - - m_hidden = !m_visible || (static_cast(configSpec) < static_cast(m_minSpec)); - if (m_hidden) - { - rendFlags |= ERF_HIDDEN; - HideAllStandins(); - } - - if (!m_useVisAreas) - { - rendFlags |= ERF_OUTDOORONLY; - } - - if (m_castShadows) - { - rendFlags |= ERF_HAS_CASTSHADOWMAPS; - rendFlags |= ERF_CASTSHADOWMAPS; - } - - rendFlags |= ERF_COMPONENT_ENTITY; - m_geomCacheRenderNode->SetRndFlags(rendFlags); - - //Re-register to update flags - RegisterRenderNode(); - } - - void GeometryCacheCommon::OnGeomCacheAssetChanged() - { - DestroyGeomCache(); - CreateGeomCache(); - } - - void GeometryCacheCommon::OnMaterialOverrideChanged() - { - LoadMaterialOverride(); - if (m_materialOverride) - { - m_geomCacheRenderNode->SetMaterial(m_materialOverride); - } - - //On Activate this will be false and that's expected. - //However when the asset actually loads, the material should be applied. - //This is just for whenever the material override *changes* - //but not necessarily for material application on startup. - RegisterRenderNode(); - } - - void GeometryCacheCommon::OnStartTimeChanged() - { - if (m_geomCache) - { - if (m_startTime > m_geomCache->GetDuration()) - { - m_startTime = m_geomCache->GetDuration(); - } - } - - //If the start time has changed, restart the animation - m_currentTime = m_startTime; - } - - void GeometryCacheCommon::OnLoopChanged() - { - m_geomCacheRenderNode->SetLooping(m_loop); - } - - void GeometryCacheCommon::OnMaxViewDistanceChanged() - { - m_geomCacheRenderNode->SetBaseMaxViewDistance(m_maxViewDistance); - - RegisterRenderNode(); - } - - void GeometryCacheCommon::OnViewDistanceMultiplierChanged() - { - m_geomCacheRenderNode->SetViewDistanceMultiplier(m_viewDistanceMultiplier); - - RegisterRenderNode(); - } - - void GeometryCacheCommon::OnLODDistanceRatioChanged() - { - m_geomCacheRenderNode->SetLodRatio(m_lodDistanceRatio); - - RegisterRenderNode(); - } - - void GeometryCacheCommon::OnStreamInDistanceChanged() - { - m_geomCacheRenderNode->SetStreamInDistance(m_streamInDistance); - } - - void GeometryCacheCommon::LoadMaterialOverride() - { - const AZStd::string& materialOverridePath = m_materialOverrideAsset.GetAssetPath(); - if (!materialOverridePath.empty()) - { - m_materialOverride = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(materialOverridePath.c_str()); - - AZ_Warning("GeomCacheComponent", m_materialOverride != gEnv->p3DEngine->GetMaterialManager()->GetDefaultMaterial(), - "Failed to load override material \"%s\".", - materialOverridePath.c_str()); - } - else - { - m_materialOverride = nullptr; - } - } - - void GeometryCacheCommon::RegisterRenderNode() - { - if(m_isRegisteredWithRenderer && gEnv && gEnv->p3DEngine) - { - gEnv->p3DEngine->RegisterEntity(m_geomCacheRenderNode); - } - } - - void GeometryCacheCommon::CreateGeomCache() - { - if (gEnv && gEnv->p3DEngine && !m_geomCacheRenderNode) - { - m_geomCacheRenderNode = static_cast(gEnv->p3DEngine->CreateRenderNode(eERType_GeomCache)); - } - - if (m_geomCacheAsset.GetId().IsValid()) - { - if (!AZ::Data::AssetBus::Handler::BusIsConnected()) - { - AZ::Data::AssetBus::Handler::BusConnect(m_geomCacheAsset.GetId()); - } - - m_geomCacheAsset.QueueLoad(); - } - - //Apply starting params to the render node - ApplyAllRenderNodeParams(); - } - - void GeometryCacheCommon::DestroyGeomCache() - { - if (m_isRegisteredWithRenderer && m_geomCacheRenderNode) - { - m_geomCacheRenderNode->StopStreaming(); - m_isRegisteredWithRenderer = false; - - gEnv->p3DEngine->FreeRenderNodeState(m_geomCacheRenderNode); - } - - m_geomCache = nullptr; - m_materialOverride = nullptr; - - m_geomCacheAsset.Release(); - - AZ::Data::AssetBus::Handler::BusDisconnect(); - } - - void GeometryCacheCommon::ApplyAllRenderNodeParams() - { - OnRenderOptionsChanged(); - OnMaterialOverrideChanged(); - OnLoopChanged(); - OnMaxViewDistanceChanged(); - OnViewDistanceMultiplierChanged(); - OnLODDistanceRatioChanged(); - OnStreamInDistanceChanged(); - } - - void GeometryCacheCommon::ShowCurrentStandin() - { - switch (m_currentStandinType) - { - case StandinType::FirstFrame: - { - MeshComponentRequestBus::Event(m_firstFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, true); - break; - } - case StandinType::LastFrame: - { - MeshComponentRequestBus::Event(m_lastFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, true); - break; - } - case StandinType::Distance: - { - MeshComponentRequestBus::Event(m_standin, &MeshComponentRequestBus::Events::SetVisibility, true); - break; - } - case StandinType::None: - { - //Show the geom cache by removing the ERF_HIDDEN flag - m_renderingStandin = false; - OnRenderOptionsChanged(); - break; - } - } - - GeometryCacheComponentNotificationBus::Broadcast(&GeometryCacheComponentNotificationBus::Events::OnStandinChanged, m_currentStandinType); - } - - void GeometryCacheCommon::HideCurrentStandin() - { - switch (m_currentStandinType) - { - case StandinType::FirstFrame: - { - MeshComponentRequestBus::Event(m_firstFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, false); - break; - } - case StandinType::LastFrame: - { - MeshComponentRequestBus::Event(m_lastFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, false); - break; - } - case StandinType::Distance: - { - MeshComponentRequestBus::Event(m_standin, &MeshComponentRequestBus::Events::SetVisibility, false); - break; - } - case StandinType::None: - { - //Hide the geom cache by adding the ERF_HIDDEN flag - m_renderingStandin = true; - OnRenderOptionsChanged(); - break; - } - } - } - - void GeometryCacheCommon::HideAllStandins() - { - if (m_firstFrameStandin.IsValid()) - { - MeshComponentRequestBus::Event(m_firstFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, false); - } - if (m_lastFrameStandin.IsValid()) - { - MeshComponentRequestBus::Event(m_lastFrameStandin, &MeshComponentRequestBus::Events::SetVisibility, false); - } - if (m_standin.IsValid()) - { - MeshComponentRequestBus::Event(m_standin, &MeshComponentRequestBus::Events::SetVisibility, false); - } - } - - void GeometryCacheComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides) - { - provides.push_back(AZ_CRC("GeomCacheService", 0x3d2bc48c)); - } - - void GeometryCacheComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires) - { - requires.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - void GeometryCacheComponent::Reflect(AZ::ReflectContext* context) - { - if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("Common", &GeometryCacheComponent::m_common) - ; - } - - GeometryCacheCommon::Reflect(context); - } - - void GeometryCacheComponent::Init() - { - m_common.Init(GetEntityId()); - } - - void GeometryCacheComponent::Activate() - { - m_common.Activate(); - } - - void GeometryCacheComponent::Deactivate() - { - m_common.Deactivate(); - } -} //namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/GeomCacheComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/GeomCacheComponent.h deleted file mode 100644 index 3f011c6e62..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/GeomCacheComponent.h +++ /dev/null @@ -1,225 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include - -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include - -#include - -#include - -namespace LmbrCentral -{ - enum class StandinType : AZ::u32 - { - None, - FirstFrame, - LastFrame, - Distance - }; - - /** - * A Common structure for the GeometryCache and EditorGeometryCache. - * - * This is where most of the GeometryCache logic lives and it's made - * available to the GeometryCacheComponent and the EditorGeometryCacheComponent. - */ - class GeometryCacheCommon - : public AZ::TransformNotificationBus::Handler - , public AZ::Data::AssetBus::Handler - , public AZ::TickBus::Handler - , public MaterialOwnerRequestBus::Handler - , public GeometryCacheComponentRequestBus::Handler - { - friend class EditorGeometryCacheCommon; //So that we can reflect private members - - public: - AZ_TYPE_INFO(GeometryCacheCommon, "{4534C4C4-50CC-4256-83F0-85B0274A5E26}"); - AZ_CLASS_ALLOCATOR(GeometryCacheCommon, AZ::SystemAllocator, 0); - - static void Reflect(AZ::ReflectContext* context); - - virtual ~GeometryCacheCommon(); - - //Startup helpers - void Init(const AZ::EntityId& entityId); - virtual void Activate(); - virtual void Deactivate(); - - // AZ::TransformNotificationBus interface implementation - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // AZ::TickBus - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - - // AZ::Data::AssetBus - void OnAssetReady(AZ::Data::Asset asset) override; - void OnAssetReloaded(AZ::Data::Asset asset) override; - - // MaterialOwnerRequestBus - void SetMaterial(_smart_ptr material) override; - _smart_ptr GetMaterial() override; - - // GeometryCacheComponentRequestBus - void Play() override; - void Pause() override; - void Stop() override; - - float GetTimeRemaining() override; - - StandinType GetCurrentStandinType() override { return m_currentStandinType; } - - void SetGeomCacheAsset(const AZ::Data::AssetId& id); - AZ::Data::Asset GetGeomCacheAsset() { return m_geomCacheAsset; } - - void SetVisible(bool visible) override; - bool GetVisible() override { return m_visible; } - - void SetLoop(bool loop) override; - bool GetLoop() override { return m_loop; } - - void SetStartTime(float startTime) override; - float GetStartTime() override { return m_startTime; } - - void SetFirstFrameStandIn(AZ::EntityId entityId) override; - AZ::EntityId GetFirstFrameStandIn() override { return m_firstFrameStandin; } - - void SetLastFrameStandIn(AZ::EntityId entityId) override; - AZ::EntityId GetLastFrameStandIn() override { return m_lastFrameStandin; } - - void SetStandIn(AZ::EntityId entityId) override; - AZ::EntityId GetStandIn() override { return m_standin; } - - void SetStandInDistance(float standInDistance) override; - float GetStandInDistance() override { return m_standinDistance; } - - void SetStreamInDistance(float streamInDistance) override; - float GetStreamInDistance() override { return m_streamInDistance; } - - IGeomCacheRenderNode* GetGeomCacheRenderNode() override { return m_geomCacheRenderNode; } - - void ClearGeomCacheRenderNode() { m_geomCacheRenderNode = nullptr; } - - protected: - //Reflected Members - bool m_visible = true; - bool m_loop = false; - bool m_playOnStart = false; - bool m_castShadows = true; - bool m_useVisAreas = true; - float m_startTime = 0.0f; - EngineSpec m_minSpec = EngineSpec::Low; - float m_standinDistance = 100.0f; - float m_streamInDistance = 150.0f; - float m_maxViewDistance = 8000.0f; - float m_viewDistanceMultiplier = 1.0f; - AZ::u32 m_lodDistanceRatio = 100; - AZ::EntityId m_firstFrameStandin; - AZ::EntityId m_lastFrameStandin; - AZ::EntityId m_standin; - AZ::Data::Asset m_geomCacheAsset; - AzFramework::SimpleAssetReference m_materialOverrideAsset; - - //Unreflected members - bool m_hidden; //< This is different from visible because this can also be controlled by the min spec being too high. - bool m_isRegisteredWithRenderer = false; //< We keep track of this because if some params are change we want to re-register but only if already registered. - bool m_renderingStandin = false; - bool m_playing; - float m_currentTime; - StandinType m_currentStandinType; - _smart_ptr m_materialOverride; - IGeomCacheRenderNode* m_geomCacheRenderNode = nullptr; - _smart_ptr m_geomCache; - AZ::EntityId m_entityId; - AZ::Vector3 m_currentWorldPos; - AZStd::vector m_currentStandinEntities; - - //Helper methods - void OnRenderOptionsChanged(); - void OnGeomCacheAssetChanged(); - void OnMaterialOverrideChanged(); - void OnStartTimeChanged(); - virtual void OnPlayOnStartChanged() {} //Only matters at edit time - void OnLoopChanged(); - void OnMaxViewDistanceChanged(); - void OnViewDistanceMultiplierChanged(); - void OnLODDistanceRatioChanged(); - void OnStreamInDistanceChanged(); - virtual void OnFirstFrameStandinChanged() {} - virtual void OnLastFrameStandinChanged() {} - virtual void OnStandinChanged() {} - - void LoadMaterialOverride(); - - void RegisterRenderNode(); - - void CreateGeomCache(); - void DestroyGeomCache(); - - void ApplyAllRenderNodeParams(); - - void ShowCurrentStandin(); - void HideCurrentStandin(); - void HideAllStandins(); - - AZ::EntityId m_prevFirstFrameStandin; - AZ::EntityId m_prevLastFrameStandin; - AZ::EntityId m_prevStandin; - }; - - /** - * A Component for handling Alembic geometry cache animations. - * - * Most of the logic lives in GeometryCacheCommon. - */ - class GeometryCacheComponent - : public AZ::Component - { - public: - AZ_COMPONENT(GeometryCacheComponent, "{B2974790-5A3B-4641-868F-6148C67830EE}", AZ::Component); - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires); - static void Reflect(AZ::ReflectContext* context); - - GeometryCacheComponent() {}; - explicit GeometryCacheComponent(GeometryCacheCommon* common) - { - m_common = *common; - m_common.ClearGeomCacheRenderNode(); //We don't want to copy the render node from the given common structure - } - ~GeometryCacheComponent() = default; - - void Init() override; - void Activate() override; - void Deactivate() override; - - private: - //Reflected members - GeometryCacheCommon m_common; - }; -} //namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/HighQualityShadowComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/HighQualityShadowComponent.cpp deleted file mode 100644 index c537c2f8f6..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/HighQualityShadowComponent.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "LmbrCentral_precompiled.h" -#include "HighQualityShadowComponent.h" - -#include -#include -#include -#include -#include - - -namespace LmbrCentral -{ - ////////////////////////////////////////////////////////////////////////// - - HighQualityShadowConfig::HighQualityShadowConfig() - : m_enabled(true) - , m_constBias(0.001f) - , m_slopeBias(0.01f) - , m_jitter(0.01f) - , m_bboxScale(1,1,1) - , m_shadowMapSize(1024) - { - - } - - void HighQualityShadowConfig::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Enabled", &HighQualityShadowConfig::m_enabled) - ->Field("ConstBias", &HighQualityShadowConfig::m_constBias) - ->Field("SlopeBias", &HighQualityShadowConfig::m_slopeBias) - ->Field("Jitter", &HighQualityShadowConfig::m_jitter) - ->Field("BBoxScale", &HighQualityShadowConfig::m_bboxScale) - ->Field("ShadowMapSize", &HighQualityShadowConfig::m_shadowMapSize) - ; - } - } - - ////////////////////////////////////////////////////////////////////////// - - void HighQualityShadowComponent::Reflect(AZ::ReflectContext* context) - { - HighQualityShadowConfig::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("HighQualityShadowConfig", &HighQualityShadowComponent::m_config); - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("HighQualityShadowComponentRequestBus") - ->Event("SetEnabled", &HighQualityShadowComponentRequestBus::Events::SetEnabled, { { {"Enabled", ""} } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Enables or disables the High Quality Shadow") - ->Event("GetEnabled", &HighQualityShadowComponentRequestBus::Events::GetEnabled) - ->Attribute(AZ::Script::Attributes::ToolTip, "Returns whether the High Quality Shadow is enabled") - ->VirtualProperty("Enabled", "GetEnabled", "SetEnabled"); - } - } - - - - void HighQualityShadowComponent::Activate() - { - HighQualityShadowComponentRequestBus::Handler::BusConnect(GetEntityId()); - MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); - } - - void HighQualityShadowComponent::Deactivate() - { - HighQualityShadowComponentUtils::RemoveShadow(GetEntityId()); - HighQualityShadowComponentRequestBus::Handler::BusDisconnect(); - MeshComponentNotificationBus::Handler::BusDisconnect(GetEntityId()); - } - - bool HighQualityShadowComponent::GetEnabled() - { - return m_config.m_enabled; - } - - void HighQualityShadowComponent::SetEnabled(bool enabled) - { - m_config.m_enabled = enabled; - HighQualityShadowComponentUtils::ApplyShadowSettings(GetEntityId(), m_config); - } - - void HighQualityShadowComponentUtils::ApplyShadowSettings(AZ::EntityId entityId, const HighQualityShadowConfig& config) - { - int numRenderNodesApplied = 0; - - AZ::EBusAggregateResults renderNodes; - LmbrCentral::RenderNodeRequestBus::EventResult(renderNodes, entityId, &LmbrCentral::RenderNodeRequests::GetRenderNode); - for(IRenderNode* renderNode : renderNodes.values) - { - if (renderNode) - { - const EERType type = renderNode->GetRenderNodeType(); - - const bool typeIsSupported = - type == eERType_StaticMeshRenderComponent || // Mesh Component uses this - type == eERType_DynamicMeshRenderComponent || // Mesh Component uses this - type == eERType_SkinnedMeshRenderComponent || // Skinned Mesh Component uses this; probably isn't necessary since this is deprecated, but is included for completion's sake - type == eERType_RenderComponent; // Actor Component uses this - - if (typeIsSupported) - { - ++numRenderNodesApplied; - - if (config.m_enabled && renderNode->IsReady()) // Note that if the mesh isn't ready yet, OnMeshCreated will be called when it is ready, which will call ApplyShadowSettings again - { - const Vec3 bboxScaleVec3(config.m_bboxScale.GetX(), config.m_bboxScale.GetY(), config.m_bboxScale.GetZ()); - gEnv->p3DEngine->AddPerObjectShadow(renderNode, config.m_constBias, config.m_slopeBias, config.m_jitter, bboxScaleVec3, config.m_shadowMapSize); - } - else - { - gEnv->p3DEngine->RemovePerObjectShadow(renderNode); - } - } - - } - } - - // This should never fail because "MeshService" components are mutually exclusive. It is possible that numRenderNodesApplied be 0, - // because some mesh-based components, like ActorComponent, may return a null IRenderNode when they aren't initialized yet. - AZ_Assert(numRenderNodesApplied <= 1, "Expected exactly one mesh-based component. Found %d", numRenderNodesApplied); - } - - void HighQualityShadowComponentUtils::RemoveShadow(AZ::EntityId entityId) - { - AZ::EBusAggregateResults renderNodes; - LmbrCentral::RenderNodeRequestBus::EventResult(renderNodes, entityId, &LmbrCentral::RenderNodeRequests::GetRenderNode); - for (IRenderNode* renderNode : renderNodes.values) - { - if (renderNode) - { - gEnv->p3DEngine->RemovePerObjectShadow(renderNode); - } - } - } - - void HighQualityShadowComponent::OnMeshCreated([[maybe_unused]] const AZ::Data::Asset& asset) - { - HighQualityShadowComponentUtils::ApplyShadowSettings(GetEntityId(), m_config); - } - - void HighQualityShadowComponent::OnMeshDestroyed() - { - HighQualityShadowComponentUtils::RemoveShadow(GetEntityId()); - } - -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/HighQualityShadowComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/HighQualityShadowComponent.h deleted file mode 100644 index c51899bab2..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/HighQualityShadowComponent.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace LmbrCentral -{ - /*! - * Stores configuration settings for per-entity shadows - */ - class HighQualityShadowConfig - { - public: - AZ_TYPE_INFO(HighQualityShadowConfig, "{3B3CD21A-E61B-401A-8F54-B76FB6278B11}"); - - HighQualityShadowConfig(); - virtual ~HighQualityShadowConfig() {} - - static void Reflect(AZ::ReflectContext* context); - - bool m_enabled; - float m_constBias; - float m_slopeBias; - float m_jitter; - AZ::Vector3 m_bboxScale; - int m_shadowMapSize; - - // Property event-handlers implemented in editor component. - virtual void EditorRefresh() { } - }; - - /*! - * Provides a entity-specific shadow map to achieving higher quality shadows on a specific entity. - * Has performance and memory impact so use sparingly. - * Corresponds to legacy PerEntityShadows feature. - */ - class HighQualityShadowComponent - : public AZ::Component - , public HighQualityShadowComponentRequestBus::Handler - , public MeshComponentNotificationBus::Handler - { - public: - friend class EditorHighQualityShadowComponent; - - AZ_COMPONENT(HighQualityShadowComponent, "{B692F9D9-4850-4D6E-9A32-760901455E40}"); - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // HighQualityShadowComponentRequestBus interface implementation - void SetEnabled(bool enabled) override; - bool GetEnabled() override; - /////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // MeshComponentNotificationBus interface implementation - void OnMeshCreated(const AZ::Data::Asset& asset) override; - void OnMeshDestroyed() override; - /////////////////////////////////// - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("HighQualityShadowService", 0x43dea981)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("HighQualityShadowService", 0x43dea981)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - // HighQualityShadowComponent is only applicable to Entities that cast and/or receive shadows. - required.push_back(AZ_CRC("MeshService", 0x71d8a455)); - } - - static void Reflect(AZ::ReflectContext* context); - - protected: - - HighQualityShadowConfig m_config; - }; - - namespace HighQualityShadowComponentUtils - { - void ApplyShadowSettings(AZ::EntityId entityId, const HighQualityShadowConfig& config); - void RemoveShadow(AZ::EntityId entityId); - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareAssetHandler.cpp b/Gems/LmbrCentral/Code/Source/Rendering/LensFlareAssetHandler.cpp deleted file mode 100644 index d1f44a0cff..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareAssetHandler.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include - -#include - -#include -#include "LensFlareAssetHandler.h" - -#include - -#define LENS_FLARE_EXT "xml" - -namespace LmbrCentral -{ - LensFlareAssetHandler::~LensFlareAssetHandler() - { - Unregister(); - } - - AZ::Data::AssetPtr LensFlareAssetHandler::CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) - { - (void)type; - AZ_Assert(type == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We handle only 'LensFlareAsset'"); - - if (!CanHandleAsset(id)) - { - return nullptr; - } - - return aznew LensFlareAsset; - } - - AZ::Data::AssetHandler::LoadResult LensFlareAssetHandler::LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& assetLoadFilterCB) - { - (void)assetLoadFilterCB; - - // Load from preloaded stream. - AZ_Assert(asset.GetType() == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We handle only 'LensFlareAsset'"); - if (stream) - { - LensFlareAsset* data = asset.GetAs(); - - const size_t sizeBytes = static_cast(stream->GetLength()); - char* buffer = new char[sizeBytes]; - stream->Read(sizeBytes, buffer); - - bool loaded = LoadFromBuffer(data, buffer, sizeBytes); - - delete[] buffer; - - return loaded ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error; - } - - return AZ::Data::AssetHandler::LoadResult::Error; - } - - void LensFlareAssetHandler::DestroyAsset(AZ::Data::AssetPtr ptr) - { - delete ptr; - } - - void LensFlareAssetHandler::GetHandledAssetTypes(AZStd::vector& assetTypes) - { - assetTypes.push_back(AZ::AzTypeInfo::Uuid()); - } - - void LensFlareAssetHandler::Register() - { - AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!"); - AZ::Data::AssetManager::Instance().RegisterHandler(this, AZ::AzTypeInfo::Uuid()); - - AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid()); - } - - void LensFlareAssetHandler::Unregister() - { - AZ::AssetTypeInfoBus::Handler::BusDisconnect(); - - if (AZ::Data::AssetManager::IsReady()) - { - AZ::Data::AssetManager::Instance().UnregisterHandler(this); - } - } - - AZ::Data::AssetType LensFlareAssetHandler::GetAssetType() const - { - return AZ::AzTypeInfo::Uuid(); - } - - const char* LensFlareAssetHandler::GetAssetTypeDisplayName() const - { - return "Lens Flare"; - } - - const char* LensFlareAssetHandler::GetBrowserIcon() const - { - return "Icons/Components/LensFlare.svg"; - } - - AZ::Uuid LensFlareAssetHandler::GetComponentTypeId() const - { - return AZ::Uuid("{4B85E77D-91F9-40C5-8FCB-B494000A9E69}"); - } - - void LensFlareAssetHandler::GetAssetTypeExtensions(AZStd::vector& extensions) - { - extensions.push_back(LENS_FLARE_EXT); - } - - bool LensFlareAssetHandler::CanHandleAsset(const AZ::Data::AssetId& id) const - { - // Look up the asset path to ensure it's actually a lens flare library. - AZStd::string assetPath; - EBUS_EVENT_RESULT(assetPath, AZ::Data::AssetCatalogRequestBus, GetAssetPathById, id); - - bool isLensFlareLibrary = false; - if (!assetPath.empty() && strstr(assetPath.c_str(), "." LENS_FLARE_EXT)) - { - //check whether the file includes "LensFlareLibrary" string - AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance(); - AZ_Assert(fileIO, "FileIO is not initialized."); - AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle; - const AZ::IO::Result result = fileIO->Open(assetPath.c_str(), AZ::IO::OpenMode::ModeRead, fileHandle); - if (result) - { - AZ::u64 fileSize = 0; - if (fileIO->Size(fileHandle, fileSize) && fileSize) - { - AZStd::vector memoryBuffer; - memoryBuffer.resize_no_construct(fileSize); - if (fileIO->Read(fileHandle, memoryBuffer.begin(), fileSize, true)) - { - //compare string instead of parse the entire xml because it's faster. - isLensFlareLibrary = (nullptr != strstr(memoryBuffer.begin(), "LensFlareLibrary")); - } - } - - fileIO->Close(fileHandle); - } - } - return isLensFlareLibrary; - } - - bool LensFlareAssetHandler::LoadFromBuffer(LensFlareAsset* data, char* buffer, [[maybe_unused]] size_t bufferSize) - { - using namespace AZ::rapidxml; - - xml_document xmlDoc; - xmlDoc.parse(buffer); - - xml_node* root = xmlDoc.first_node(); - if (root) - { - //get the name of this lens flare library - xml_attribute* nameAttribute = root->first_attribute("Name"); - if (nameAttribute) - { - const char* libName = nameAttribute->value(); - if (libName && libName[0]) - { - xml_node* flareNode = root->first_node("FlareItem"); - while (flareNode) - { - //for each of FlareItem add their path, combined with lib name, to LensFlareAsset data. - xml_attribute* flareNameAttribute = flareNode->first_attribute("Name"); - if (flareNameAttribute) - { - const char* effectName = flareNameAttribute->value(); - if (effectName && effectName[0]) - { - AZStd::string flarePath = AZStd::string::format("%s.%s", libName, effectName); - data->AddPath(std::move(flarePath)); - } - } - - flareNode = flareNode->next_sibling("FlareItem"); - } - return true; - } - } - } - - return false; - } -} // namespace LmbrCentral - diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareAssetHandler.h b/Gems/LmbrCentral/Code/Source/Rendering/LensFlareAssetHandler.h deleted file mode 100644 index acbfb97e84..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareAssetHandler.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include - -namespace LmbrCentral -{ - class LensFlareAssetHandler - : public AZ::Data::AssetHandler - , public AZ::AssetTypeInfoBus::Handler - { - public: - - AZ_CLASS_ALLOCATOR(LensFlareAssetHandler, AZ::SystemAllocator, 0); - - ~LensFlareAssetHandler() override; - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetHandler - AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override; - AZ::Data::AssetHandler::LoadResult LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& assetLoadFilterCB) override; - void DestroyAsset(AZ::Data::AssetPtr ptr) override; - void GetHandledAssetTypes(AZStd::vector& assetTypes) override; - bool CanHandleAsset(const AZ::Data::AssetId& id) const override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::AssetTypeInfoBus::Handler - AZ::Data::AssetType GetAssetType() const override; - const char* GetAssetTypeDisplayName() const override; - const char* GetBrowserIcon() const override; - AZ::Uuid GetComponentTypeId() const override; - void GetAssetTypeExtensions(AZStd::vector& extensions) override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - void Register(); - void Unregister(); - - private: - static bool LoadFromBuffer(LensFlareAsset* data, char* buffer, size_t bufferSize); - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/LensFlareComponent.cpp deleted file mode 100644 index 49b433f3e8..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareComponent.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include - -#include "LensFlareComponent.h" - -namespace LmbrCentral -{ - ////////////////////////////////////////////////////////////////////////// - // BehaviorContext LensFlareComponentNotificationBus forwarder - class BehaviorLensFlareComponentNotificationBusHandler : public LensFlareComponentNotificationBus::Handler, public AZ::BehaviorEBusHandler - { - public: - AZ_EBUS_BEHAVIOR_BINDER(BehaviorLensFlareComponentNotificationBusHandler, "{285A6AB7-82CF-472F-8C3B-1659A59213FF}", AZ::SystemAllocator, - LensFlareTurnedOn, LensFlareTurnedOff); - - void LensFlareTurnedOn() - { - Call(FN_LensFlareTurnedOn); - } - - void LensFlareTurnedOff() - { - Call(FN_LensFlareTurnedOff); - } - }; - - // Class to encapsulate LensFlareComponentRequests::State values. - class BehaviorLensFlareComponentState - { - public: - AZ_TYPE_INFO(BehaviorLensFlareComponentState, "{1A63ED6B-C2D2-4D3C-AC27-5FDBF22B5B38}"); - AZ_CLASS_ALLOCATOR(BehaviorLensFlareComponentState, AZ::SystemAllocator, 0); - }; - - void LensFlareComponent::Reflect(AZ::ReflectContext* context) - { - LensFlareConfiguration::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1)-> - Field("LensFlareConfiguration", &LensFlareComponent::m_configuration); - } - - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class("LensFlareComponentState") - ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) - ->Constant("Off", BehaviorConstant(LensFlareComponentRequests::State::Off)) - ->Constant("On", BehaviorConstant(LensFlareComponentRequests::State::On)) - ; - - behaviorContext->EBus("LensFlareComponentRequestBus") - ->Event("SetLensFlareState", &LensFlareComponentRequestBus::Events::SetLensFlareState) - ->Event("TurnOnLensFlare", &LensFlareComponentRequestBus::Events::TurnOnLensFlare) - ->Event("TurnOffLensFlare", &LensFlareComponentRequestBus::Events::TurnOffLensFlare) - ->Event("ToggleLensFlare", &LensFlareComponentRequestBus::Events::ToggleLensFlare) - ; - - behaviorContext->EBus("LensFlareComponentNotificationBus") - ->Handler(); - } - } - - void LensFlareConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(4, &VersionConverter)-> - Field("Visible", &LensFlareConfiguration::m_visible)-> - Field("LensFlare", &LensFlareConfiguration::m_lensFlare)-> - Field("Asset", &LensFlareConfiguration::m_asset)-> - - Field("MinimumSpec", &LensFlareConfiguration::m_minSpec)-> - Field("LensFlareFrustumAngle", &LensFlareConfiguration::m_lensFlareFrustumAngle)-> - Field("Size", &LensFlareConfiguration::m_size)-> - Field("AttachToSun", &LensFlareConfiguration::m_attachToSun)-> - Field("AffectsThisAreaOnly", &LensFlareConfiguration::m_affectsThisAreaOnly)-> - Field("UseVisAreas", &LensFlareConfiguration::m_useVisAreas)-> - Field("IndoorOnly", &LensFlareConfiguration::m_indoorOnly)-> - Field("OnInitially", &LensFlareConfiguration::m_onInitially)-> - Field("ViewDistanceMultiplier", &LensFlareConfiguration::m_viewDistMultiplier)-> - - Field("Tint", &LensFlareConfiguration::m_tint)-> - Field("TintAlpha", &LensFlareConfiguration::m_tintAlpha)-> - Field("Brightness", &LensFlareConfiguration::m_brightness)-> - - Field("SyncAnimWithLight", &LensFlareConfiguration::m_syncAnimWithLight)-> - Field("LightEntity", &LensFlareConfiguration::m_lightEntity)-> - Field("AnimIndex", &LensFlareConfiguration::m_animIndex)-> - Field("AnimSpeed", &LensFlareConfiguration::m_animSpeed)-> - Field("AnimPhase", &LensFlareConfiguration::m_animPhase)-> - - Field("SyncedAnimIndex", &LensFlareConfiguration::m_syncAnimIndex)-> - Field("SyncedAnimSpeed", &LensFlareConfiguration::m_syncAnimSpeed)-> - Field("SyncedAnimPhase", &LensFlareConfiguration::m_syncAnimPhase) - ; - } - } - - bool LensFlareConfiguration::VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) - { - // conversion from version 2 to version 3: - // - Need to rename IgnoreVisAreas to UseVisAreas - // UseVisAreas is the Inverse of IgnoreVisAreas - if (classElement.GetVersion() <= 2) - { - int ignoreVisAreasIndex = classElement.FindElement(AZ_CRC("IgnoreVisAreas", 0x01823201)); - - if (ignoreVisAreasIndex < 0) - { - return false; - } - - AZ::SerializeContext::DataElementNode& useVisAreasNode = classElement.GetSubElement(ignoreVisAreasIndex); - useVisAreasNode.SetName("UseVisAreas"); - - bool ignoreVisAreas = true; - if (!useVisAreasNode.GetData(ignoreVisAreas)) - { - return false; - } - - if (!useVisAreasNode.SetData(context, !ignoreVisAreas)) - { - return false; - } - } - - return true; - } - - void LensFlareComponent::TurnOnLensFlare() - { - bool success = m_light.TurnOn(); - if (success) - { - LensFlareComponentNotificationBus::Event(GetEntityId(), &LensFlareComponentNotificationBus::Events::LensFlareTurnedOn); - } - } - - void LensFlareComponent::TurnOffLensFlare() - { - bool success = m_light.TurnOff(); - if (success) - { - LensFlareComponentNotificationBus::Event(GetEntityId(), &LensFlareComponentNotificationBus::Events::LensFlareTurnedOff); - } - } - - void LensFlareComponent::ToggleLensFlare() - { - if (m_light.IsOn()) - { - TurnOffLensFlare(); - } - else - { - TurnOnLensFlare(); - } - } - - LensFlareConfiguration LensFlareComponent::GetLensFlareConfiguration() - { - return m_configuration; - } - - void LensFlareComponent::SetLensFlareState(State state) - { - switch (state) - { - case LensFlareComponentRequests::State::On: - { - TurnOnLensFlare(); - } - break; - - case LensFlareComponentRequests::State::Off: - { - TurnOffLensFlare(); - } - break; - } - } - - IRenderNode* LensFlareComponent::GetRenderNode() - { - return m_light.GetRenderNode(); - } - - float LensFlareComponent::GetRenderNodeRequestBusOrder() const - { - return s_renderNodeRequestBusOrder; - } - - const float LensFlareComponent::s_renderNodeRequestBusOrder = 600.f; - - void LensFlareComponent::Init() - { - //Set this in Init because it will never change and doesn't need to be reset if the component re-activates - m_configuration.m_material.SetAssetPath("EngineAssets/Materials/lens_optics"); - } - - void LensFlareComponent::Activate() - { - const AZ::EntityId entityId = GetEntityId(); - - m_light.SetEntity(entityId); - m_light.CreateRenderLight(m_configuration); - - LensFlareComponentRequestBus::Handler::BusConnect(entityId); - RenderNodeRequestBus::Handler::BusConnect(entityId); - - if (m_configuration.m_onInitially) - { - TurnOnLensFlare(); - } - else - { - TurnOffLensFlare(); - } - } - - void LensFlareComponent::Deactivate() - { - LensFlareComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - - m_light.DestroyRenderLight(); - m_light.SetEntity(AZ::EntityId()); - } - - LensFlareConfiguration::LensFlareConfiguration() - : m_minSpec(EngineSpec::Low) - , m_visible(true) - , m_onInitially(true) - , m_tint(1.f) - , m_brightness(1.f) - , m_viewDistMultiplier(1.f) - , m_affectsThisAreaOnly(1.f) - , m_useVisAreas(true) - , m_indoorOnly(false) - , m_animSpeed(1.f) - , m_animPhase(0.f) - , m_animIndex(0) - , m_lensFlareFrustumAngle(360.f) - , m_size(1.0f) - , m_attachToSun(false) - , m_syncAnimWithLight(false) - { - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/LensFlareComponent.h deleted file mode 100644 index 885e436b2a..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LensFlareComponent.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include - -#include "LightInstance.h" -#include -#include -#include -#include - -#include - -namespace LmbrCentral -{ - /*! - * Stores configuration settings for engine lens flares. - */ - class LensFlareConfiguration - { - public: - AZ_TYPE_INFO(LensFlareConfiguration, "{1E28DADD-0BD4-4AD5-A94B-2665813BF346}"); - - LensFlareConfiguration(); - virtual ~LensFlareConfiguration() {}; - - static void Reflect(AZ::ReflectContext* context); - static bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); - - AZ::Data::Asset m_asset { AZ::Data::AssetLoadBehavior::PreLoad }; //! Used at asset compile time to track the dependency. Not used at edit or runtime. - - //! Settings common to all LY engine lights - EngineSpec m_minSpec; - - //! Turned on by default? - bool m_onInitially; - - //! Currently visible? - bool m_visible; - - //! Lens flare size - float m_size; - - AZ::Vector3 m_tint; - AZ::u32 m_tintAlpha; - float m_brightness; - - float m_viewDistMultiplier; - float m_viewDistMultiplierUser; // Value set by user from UI. - bool m_affectsThisAreaOnly; - bool m_useVisAreas; - bool m_indoorOnly; - bool m_attachToSun; - - bool m_syncAnimWithLight; - AZ::EntityId m_lightEntity; - float m_animSpeed; - float m_animPhase; - AZ::u32 m_animIndex; - - AZStd::string m_lensFlare; - float m_lensFlareFrustumAngle; - - // Animation settings from the light - float m_syncAnimSpeed; - float m_syncAnimPhase; - AZ::u32 m_syncAnimIndex; - - // Settings not reflected in the editor - AzFramework::SimpleAssetReference m_material; //Same name as the material in the LightSettings - - AZ_INLINE bool ShouldShowAnimationSettings() { - return !m_syncAnimWithLight; - } - - AZ_INLINE bool ShouldViewDistanceMultiplier() { - return !m_attachToSun; - } - - // Property event-handlers implemented in editor component. - virtual AZ::u32 PropertyChanged() { return 0; } - virtual AZ::u32 SyncAnimationChanged() { return AZ_CRC("RefreshNone", 0x98a5045b); } - virtual AZ::u32 AttachToSunChanged() {return AZ_CRC("RefreshNone", 0x98a5045b); } - }; - - - /*! - * In-game light component. - */ - class LensFlareComponent - : public AZ::Component - , public LensFlareComponentRequestBus::Handler - , public RenderNodeRequestBus::Handler - { - public: - friend class EditorLensFlareComponent; - - AZ_COMPONENT(LensFlareComponent, "{07593109-4A57-473F-B868-C2DCF9270186}"); - - LensFlareComponent() {} - ~LensFlareComponent() override {} - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Init() override; - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // LensFlareComponentRequestBus::Handler interface implementation - void TurnOnLensFlare() override; - void TurnOffLensFlare() override; - void SetLensFlareState(State state) override; - void ToggleLensFlare() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // RenderNodeRequestBus::Handler interface implementation - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - static const float s_renderNodeRequestBusOrder; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("LensFlareService", 0xda3286e8)); - } - - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - dependent.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void Reflect(AZ::ReflectContext* context); - ////////////////////////////////////////////////////////////////////////// - - LensFlareConfiguration GetLensFlareConfiguration(); - - protected: - - LensFlareConfiguration m_configuration; - LightInstance m_light; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LightComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/LightComponent.cpp deleted file mode 100644 index b52feac3fd..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LightComponent.cpp +++ /dev/null @@ -1,875 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include - -#include "LightInstance.h" -#include "LightComponent.h" - -namespace LmbrCentral -{ - ////////////////////////////////////////////////////////////////////////// - class BehaviorLightComponentNotificationBusHandler : public LightComponentNotificationBus::Handler, public AZ::BehaviorEBusHandler - { - public: - AZ_EBUS_BEHAVIOR_BINDER(BehaviorLightComponentNotificationBusHandler, "{969C5B17-10D1-41DB-8123-6664FA64B4E9}", AZ::SystemAllocator, - LightTurnedOn, LightTurnedOff); - - // Sent when the light is turned on. - void LightTurnedOn() override - { - Call(FN_LightTurnedOn); - } - - // Sent when the light is turned off. - void LightTurnedOff() override - { - Call(FN_LightTurnedOff); - } - }; - - void LightComponent::Reflect(AZ::ReflectContext* context) - { - LightConfiguration::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("LightConfiguration", &LightComponent::m_configuration); - } - - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->Class()->RequestBus("LightComponentRequestBus"); - ; - auto probeFadeDefaultValue(behaviorContext->MakeDefaultValue(1.0f)); - - behaviorContext->EBus("Light", "LightComponentRequestBus") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Event("SetState", &LightComponentRequestBus::Events::SetLightState, "SetLightState", { { { "State", "1=On, 0=Off" } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Set the light state") - ->Event("TurnOn", &LightComponentRequestBus::Events::TurnOnLight, "TurnOnLight") - ->Event("TurnOff", &LightComponentRequestBus::Events::TurnOffLight, "TurnOffLight") - ->Event("Toggle", &LightComponentRequestBus::Events::ToggleLight, "ToggleLight") - // General Settings Modifiers - ->Event("GetVisible", &LightComponentRequestBus::Events::GetVisible) - ->Event("SetVisible", &LightComponentRequestBus::Events::SetVisible, { { { "IsVisible", "" } } }) - ->VirtualProperty("Visible", "GetVisible", "SetVisible") - ->Event("GetColor", &LightComponentRequestBus::Events::GetColor) - ->Event("SetColor", &LightComponentRequestBus::Events::SetColor, { { { "Color", "The color to set" } } }) - ->VirtualProperty("Color", "GetColor", "SetColor") - ->Event("GetDiffuseMultiplier", &LightComponentRequestBus::Events::GetDiffuseMultiplier) - ->Event("SetDiffuseMultiplier", &LightComponentRequestBus::Events::SetDiffuseMultiplier, { { { "Multiplier", "The multiplier" } } }) - ->VirtualProperty("DiffuseMultiplier", "GetDiffuseMultiplier", "SetDiffuseMultiplier") - ->Event("GetSpecularMultiplier", &LightComponentRequestBus::Events::GetSpecularMultiplier) - ->Event("SetSpecularMultiplier", &LightComponentRequestBus::Events::SetSpecularMultiplier, { { { "Multiplier", "The multiplier" } } }) - ->VirtualProperty("SpecularMultiplier", "GetSpecularMultiplier", "SetSpecularMultiplier") - ->Event("GetAmbient", &LightComponentRequestBus::Events::GetAmbient) - ->Event("SetAmbient", &LightComponentRequestBus::Events::SetAmbient, { { { "IsAmbient", "" } } }) - ->VirtualProperty("Ambient", "GetAmbient", "SetAmbient") - // Point Light Modifiers - ->Event("GetPointMaxDistance", &LightComponentRequestBus::Events::GetPointMaxDistance) - ->Event("SetPointMaxDistance", &LightComponentRequestBus::Events::SetPointMaxDistance, { { { "Distance", "The max point distance" } } }) - ->VirtualProperty("PointMaxDistance", "GetPointMaxDistance", "SetPointMaxDistance") - ->Event("GetPointAttenuationBulbSize", &LightComponentRequestBus::Events::GetPointAttenuationBulbSize) - ->Event("SetPointAttenuationBulbSize", &LightComponentRequestBus::Events::SetPointAttenuationBulbSize, { { { "BulbSize", "The size of the bulb" } } }) - ->VirtualProperty("PointAttenuationBulbSize", "GetPointAttenuationBulbSize", "SetPointAttenuationBulbSize") - // Area Light Modifiers - ->Event("GetAreaMaxDistance", &LightComponentRequestBus::Events::GetAreaMaxDistance) - ->Event("SetAreaMaxDistance", &LightComponentRequestBus::Events::SetAreaMaxDistance, { { { "Distance", "The max point distance" } } }) - ->VirtualProperty("AreaMaxDistance", "GetAreaMaxDistance", "SetAreaMaxDistance") - ->Event("GetAreaWidth", &LightComponentRequestBus::Events::GetAreaWidth) - ->Event("SetAreaWidth", &LightComponentRequestBus::Events::SetAreaWidth, { { { "Width", "Area Width" } } }) - ->VirtualProperty("AreaWidth", "GetAreaWidth", "SetAreaWidth") - ->Event("GetAreaHeight", &LightComponentRequestBus::Events::GetAreaHeight) - ->Event("SetAreaHeight", &LightComponentRequestBus::Events::SetAreaHeight, { { { "Height", "Area Height" } } }) - ->VirtualProperty("AreaHeight", "GetAreaHeight", "SetAreaHeight") - ->Event("GetAreaFOV", &LightComponentRequestBus::Events::GetAreaFOV) - ->Event("SetAreaFOV", &LightComponentRequestBus::Events::SetAreaFOV, { { { "FOV", "Field of View" } } }) - ->VirtualProperty("AreaFOV", "GetAreaFOV", "SetAreaFOV") - // Projector Light Modifiers - ->Event("GetProjectorMaxDistance", &LightComponentRequestBus::Events::GetProjectorMaxDistance) - ->Event("SetProjectorMaxDistance", &LightComponentRequestBus::Events::SetProjectorMaxDistance, { { { "Distance", "Projector distance" } } }) - ->VirtualProperty("ProjectorMaxDistance", "GetProjectorMaxDistance", "SetProjectorMaxDistance") - ->Event("GetProjectorAttenuationBulbSize", &LightComponentRequestBus::Events::GetProjectorAttenuationBulbSize) - ->Event("SetProjectorAttenuationBulbSize", &LightComponentRequestBus::Events::SetProjectorAttenuationBulbSize, { { { "BulbSize", "The size of the bulb" } } }) - ->VirtualProperty("ProjectorAttenuationBulbSize", "GetProjectorAttenuationBulbSize", "SetProjectorAttenuationBulbSize") - ->Event("GetProjectorFOV", &LightComponentRequestBus::Events::GetProjectorFOV) - ->Event("SetProjectorFOV", &LightComponentRequestBus::Events::SetProjectorFOV, { { { "FOV", "Field of View" } } }) - ->VirtualProperty("ProjectorFOV", "GetProjectorFOV", "SetProjectorFOV") - ->Event("GetProjectorNearPlane", &LightComponentRequestBus::Events::GetProjectorNearPlane) - ->Event("SetProjectorNearPlane", &LightComponentRequestBus::Events::SetProjectorNearPlane, { { { "Plane", "Plane distance" } } }) - ->VirtualProperty("ProjectorNearPlane", "GetProjectorNearPlane", "SetProjectorNearPlane") - // Environment Probe Light Modifiers - ->Event("GetProbeAreaDimensions", &LightComponentRequestBus::Events::GetProbeAreaDimensions) - ->Event("SetProbeAreaDimensions", &LightComponentRequestBus::Events::SetProbeAreaDimensions, { { { "Dimension", "The X,Y and Z extents" } } }) - ->VirtualProperty("ProbeAreaDimensions", "GetProbeAreaDimensions", "SetProbeAreaDimensions") - ->Event("GetProbeSortPriority", &LightComponentRequestBus::Events::GetProbeSortPriority) - ->Event("SetProbeSortPriority", &LightComponentRequestBus::Events::SetProbeSortPriority, { { { "Priority", "" } } }) - ->VirtualProperty("ProbeSortPriority", "GetProbeSortPriority", "SetProbeSortPriority") - ->Event("GetProbeBoxProjected", &LightComponentRequestBus::Events::GetProbeBoxProjected) - ->Event("SetProbeBoxProjected", &LightComponentRequestBus::Events::SetProbeBoxProjected, { { { "IsProjected", "TRUE will project the box, False otherwise." } } }) - ->VirtualProperty("ProbeBoxProjected", "GetProbeBoxProjected", "SetProbeBoxProjected") - ->Event("GetProbeBoxHeight", &LightComponentRequestBus::Events::GetProbeBoxHeight) - ->Event("SetProbeBoxHeight", &LightComponentRequestBus::Events::SetProbeBoxHeight, { { { "Height", "Box Height" } } }) - ->VirtualProperty("ProbeBoxHeight", "GetProbeBoxHeight", "SetProbeBoxHeight") - ->Event("GetProbeBoxLength", &LightComponentRequestBus::Events::GetProbeBoxLength) - ->Event("SetProbeBoxLength", &LightComponentRequestBus::Events::SetProbeBoxLength, { { { "Length", "Box Length" } } }) - ->VirtualProperty("ProbeBoxLength", "GetProbeBoxLength", "SetProbeBoxLength") - ->Event("GetProbeBoxWidth", &LightComponentRequestBus::Events::GetProbeBoxWidth) - ->Event("SetProbeBoxWidth", &LightComponentRequestBus::Events::SetProbeBoxWidth, { { { "Width", "Box Width" } } }) - ->VirtualProperty("ProbeBoxWidth", "GetProbeBoxWidth", "SetProbeBoxWidth") - ->Event("GetProbeAttenuationFalloff", &LightComponentRequestBus::Events::GetProbeAttenuationFalloff) - ->Event("SetProbeAttenuationFalloff", &LightComponentRequestBus::Events::SetProbeAttenuationFalloff, { { { "Falloff", "Smoothness of the falloff around the probe's bounds" } } }) - ->VirtualProperty("ProbeAttenuationFalloff", "GetProbeAttenuationFalloff", "SetProbeAttenuationFalloff") - ->Event("GetProbeFade", &LightComponentRequestBus::Events::GetProbeFade) - ->Event("SetProbeFade", &LightComponentRequestBus::Events::SetProbeFade, { { { "Fade", "Multiplier for fading out a probe [0-1]", probeFadeDefaultValue } } }) - ->VirtualProperty("ProbeFade", "GetProbeFade", "SetProbeFade") - ; - - behaviorContext->EBus("LightNotification", "LightComponentNotificationBus", "Notifications for the Light Components") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Handler(); - } - } - - void LightConfiguration::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(8, &VersionConverter) - ->Field("LightType", &LightConfiguration::m_lightType) - ->Field("Visible", &LightConfiguration::m_visible) - ->Field("OnInitially", &LightConfiguration::m_onInitially) - ->Field("Color", &LightConfiguration::m_color) - ->Field("DiffuseMultiplier", &LightConfiguration::m_diffuseMultiplier) - ->Field("SpecMultiplier", &LightConfiguration::m_specMultiplier) - ->Field("Ambient", &LightConfiguration::m_ambient) - ->Field("PointMaxDistance", &LightConfiguration::m_pointMaxDistance) - ->Field("PointAttenuationBulbSize", &LightConfiguration::m_pointAttenuationBulbSize) - ->Field("AreaWidth", &LightConfiguration::m_areaWidth) - ->Field("AreaHeight", &LightConfiguration::m_areaHeight) - ->Field("AreaMaxDistance", &LightConfiguration::m_areaMaxDistance) - ->Field("AreaFOV", &LightConfiguration::m_areaFOV) - ->Field("ProjectorDistance", &LightConfiguration::m_projectorRange) - ->Field("ProjectorAttenuationBulbSize", &LightConfiguration::m_projectorAttenuationBulbSize) - ->Field("ProjectorFOV", &LightConfiguration::m_projectorFOV) - ->Field("ProjectorNearPlane", &LightConfiguration::m_projectorNearPlane) - ->Field("ProjectorTexture", &LightConfiguration::m_projectorTexture) - ->Field("ProjectorMaterial", &LightConfiguration::m_material) - ->Field("Area X,Y,Z", &LightConfiguration::m_probeArea) - ->Field("SortPriority", &LightConfiguration::m_probeSortPriority) - ->Field("CubemapResolution", &LightConfiguration::m_probeCubemapResolution) - ->Field("CubemapTexture", &LightConfiguration::m_probeCubemap) - ->Field("BoxProject", &LightConfiguration::m_isBoxProjected) - ->Field("BoxHeight", &LightConfiguration::m_boxHeight) - ->Field("BoxLength", &LightConfiguration::m_boxLength) - ->Field("BoxWidth", &LightConfiguration::m_boxWidth) - ->Field("AttenuationFalloffMax", &LightConfiguration::m_attenFalloffMax) - ->Field("ViewDistanceMultiplier", &LightConfiguration::m_viewDistMultiplier) - ->Field("MinimumSpec", &LightConfiguration::m_minSpec) - ->Field("CastShadowsSpec", &LightConfiguration::m_castShadowsSpec) - ->Field("VoxelGIMode", &LightConfiguration::m_voxelGIMode) - ->Field("UseVisAreas", &LightConfiguration::m_useVisAreas) - ->Field("IndoorOnly", &LightConfiguration::m_indoorOnly) - ->Field("AffectsThisAreaOnly", &LightConfiguration::m_affectsThisAreaOnly) - ->Field("VolumetricFogOnly", &LightConfiguration::m_volumetricFogOnly) - ->Field("VolumetricFog", &LightConfiguration::m_volumetricFog) - ->Field("Deferred", &LightConfiguration::m_deferred) - ->Field("TerrainShadows", &LightConfiguration::m_castTerrainShadows) - ->Field("ShadowBias", &LightConfiguration::m_shadowBias) - ->Field("ShadowResScale", &LightConfiguration::m_shadowResScale) - ->Field("ShadowSlopeBias", &LightConfiguration::m_shadowSlopeBias) - ->Field("ShadowUpdateMinRadius", &LightConfiguration::m_shadowUpdateMinRadius) - ->Field("ShadowUpdateRatio", &LightConfiguration::m_shadowUpdateRatio) - ->Field("AnimIndex", &LightConfiguration::m_animIndex) - ->Field("AnimSpeed", &LightConfiguration::m_animSpeed) - ->Field("AnimPhase", &LightConfiguration::m_animPhase) - ->Field("CubemapId", &LightConfiguration::m_cubemapId); - } - } - - // Private Static - bool LightConfiguration::VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement) - { - // conversion from version 1: - // - Need to rename OmniRadius to MaxDistance - // - remove ShadowBlurStrength - if (classElement.GetVersion() <= 1) - { - int radiusIndex = classElement.FindElement(AZ_CRC("OmniRadius", 0x3fbb253e)); - - if (radiusIndex < 0) - { - return false; - } - - AZ::SerializeContext::DataElementNode& radius = classElement.GetSubElement(radiusIndex); - radius.SetName("MaxDistance"); - - classElement.RemoveElementByName(AZ_CRC("ShadowBlurStrength", 0x70ac8e34)); - } - - // conversion from version 2: - // - Replace AreaSize with AreaWidth and AreaHeights - if (classElement.GetVersion() <= 2) - { - int areaIndex = classElement.FindElement(AZ_CRC("AreaSize", 0x287b852c)); - - if (areaIndex < 0) - { - return false; - } - - //Get the size - AZ::SerializeContext::DataElementNode& area = classElement.GetSubElement(areaIndex); - AZ::Vector3 size; - - area.GetData(size); - - //Create width and height - int areaWidthIndex = classElement.AddElement(context, "AreaWidth"); - int areaHeightIndex = classElement.AddElement(context, "AreaHeight"); - - AZ::SerializeContext::DataElementNode& areaWidth = classElement.GetSubElement(areaWidthIndex); - AZ::SerializeContext::DataElementNode& areaHeight = classElement.GetSubElement(areaHeightIndex); - - //Set width and height data to x and y from the old size - areaWidth.SetData(context, size.GetX()); - areaHeight.SetData(context, size.GetY()); - classElement.RemoveElement(areaIndex); - } - - // conversion from version 3: - // - MaxDistance turned into PointMaxDistance and AreaMaxDistance - // - AttenuationBulbSize turned into PointAttenuationBulbSize and ProjectorAttenuationBulbSize - // - Apply old area size to new probe area - if (classElement.GetVersion() <= 3) - { - int maxDistanceIndex = classElement.FindElement(AZ_CRC("MaxDistance", 0xfc2921b8)); - int attenBulbIndex = classElement.FindElement(AZ_CRC("AttenuationBulbSize", 0x3ca0f5c0)); - int areaWidthIndex = classElement.FindElement(AZ_CRC("AreaWidth", 0x137a1a2b)); - int areaHeightIndex = classElement.FindElement(AZ_CRC("AreaHeight", 0xf2bf4149)); - - if (maxDistanceIndex < 0 || attenBulbIndex < 0 || areaWidthIndex < 0 || areaHeightIndex < 0) - { - return false; - } - - //Get some values - AZ::SerializeContext::DataElementNode& maxDistance = classElement.GetSubElement(maxDistanceIndex); - AZ::SerializeContext::DataElementNode& attenBulbSize = classElement.GetSubElement(attenBulbIndex); - AZ::SerializeContext::DataElementNode& areaWidth = classElement.GetSubElement(areaWidthIndex); - AZ::SerializeContext::DataElementNode& areaHeight = classElement.GetSubElement(attenBulbIndex); - - float maxDistVal, attenBulbVal, areaWidthVal, areaHeightVal; - - maxDistance.GetData(maxDistVal); - attenBulbSize.GetData(attenBulbVal); - areaWidth.GetData(areaWidthVal); - areaHeight.GetData(areaHeightVal); - - //Create AreaMaxDistance, PointMaxDistance, PointAttenuationBulbSize and ProjectorAttenuationBulbSize - int areaMaxDistIndex = classElement.AddElement(context, "AreaMaxDistance"); - int pointMaxDistIndex = classElement.AddElement(context, "PointMaxDistance"); - int pointAttenBulbIndex = classElement.AddElement(context, "PointAttenuationBulbSize"); - int projectorAttenBulbIndex = classElement.AddElement(context, "ProjectorAttenuationBulbSize"); - int areaXYZIndex = classElement.AddElement(context, "Area X,Y,Z"); - - AZ::SerializeContext::DataElementNode& areaMaxDist = classElement.GetSubElement(areaMaxDistIndex); - AZ::SerializeContext::DataElementNode& pointMaxDist = classElement.GetSubElement(pointMaxDistIndex); - AZ::SerializeContext::DataElementNode& pointAttenBulb = classElement.GetSubElement(pointAttenBulbIndex); - AZ::SerializeContext::DataElementNode& projectorAttenBulb = classElement.GetSubElement(projectorAttenBulbIndex); - AZ::SerializeContext::DataElementNode& areaXYZ = classElement.GetSubElement(areaXYZIndex); - - //Set width and height data to x and y from the old size - areaMaxDist.SetData(context, maxDistVal); - pointMaxDist.SetData(context, maxDistVal); - pointAttenBulb.SetData(context, attenBulbVal); - projectorAttenBulb.SetData(context, attenBulbVal); - - //Set new area XYZ values based on existing area values - areaXYZ.SetData(context, AZ::Vector3(maxDistVal, areaWidthVal, areaHeightVal)); - - //Remove old MaxDistance and AttenuationBulbSize - classElement.RemoveElement(maxDistanceIndex); - classElement.RemoveElement(attenBulbIndex); - } - - // conversion from version 4: - // m_color: AZ::Vector4 -> AZ::Color - if (classElement.GetVersion() <= 4) - { - int colorIndex = classElement.FindElement(AZ_CRC("Color", 0x665648e9)); - if (colorIndex == -1) - { - return false; - } - - AZ::SerializeContext::DataElementNode& color = classElement.GetSubElement(colorIndex); - AZ::Vector4 colorVec; - color.GetData(colorVec); - AZ::Color colorVal(colorVec.GetX(), colorVec.GetY(), colorVec.GetZ(), colorVec.GetW()); - color.Convert(context); - color.SetData(context, colorVal); - } - - // conversion from version 6 to version 7: - // - Need to rename IgnoreVisAreas to UseVisAreas - // UseVisAreas is the Inverse of IgnoreVisAreas - if (classElement.GetVersion() <= 6) - { - int ignoreVisAreasIndex = classElement.FindElement(AZ_CRC("IgnoreVisAreas", 0x01823201)); - - if (ignoreVisAreasIndex < 0) - { - return false; - } - - AZ::SerializeContext::DataElementNode& useVisAreasNode = classElement.GetSubElement(ignoreVisAreasIndex); - useVisAreasNode.SetName("UseVisAreas"); - - bool ignoreVisAreas = true; - if (!useVisAreasNode.GetData(ignoreVisAreas)) - { - return false; - } - - if (!useVisAreasNode.SetData(context, !ignoreVisAreas)) - { - return false; - } - } - - if (classElement.GetVersion() <= 7) - { - AZ::SerializeContext::DataElementNode* cubemapTexture = classElement.FindSubElement(AZ_CRC("CubemapTexture", 0xbf6d8df4)); - - if (!cubemapTexture) - { - return false; - } - - AZStd::string cubemapPath; - - if (!cubemapTexture->GetData(cubemapPath)) - { - return false; - } - - AzFramework::SimpleAssetReference cubemapSimpleAsset; - - cubemapSimpleAsset.SetAssetPath(cubemapPath.c_str()); - - if (!classElement.RemoveElementByName(AZ_CRC("CubemapTexture", 0xbf6d8df4))) - { - return false; - } - - if (!classElement.AddElementWithData>(context, "CubemapTexture", cubemapSimpleAsset)) - { - return false; - } - } - - return true; - } - - bool LightComponent::TurnOnLight() - { - bool success = m_light.TurnOn(); - if (success) - { - EBUS_EVENT_ID(GetEntityId(), LightComponentNotificationBus, LightTurnedOn); - } - return success; - } - - bool LightComponent::TurnOffLight() - { - bool success = m_light.TurnOff(); - if (success) - { - EBUS_EVENT_ID(GetEntityId(), LightComponentNotificationBus, LightTurnedOff); - } - return success; - } - - /////////////////////////////////////////////////////////////////////// - // Modifiers - void LightComponent::SetVisible(bool isVisible) - { - if (isVisible != m_configuration.m_visible) - { - m_configuration.m_visible = isVisible; - - if (m_configuration.m_visible) - { - if (!TurnOnLight()) - { - // unable to turn on light. This happens when trying to turn on a light was was previously not visible. Use UpdateRenderLight to - // update the light's visibility (by recreating it) to turn it on. - m_light.UpdateRenderLight(m_configuration); - } - } - else - { - TurnOffLight(); - } - } - } - - bool LightComponent::GetVisible() - { - return m_light.IsOn(); - } - - void LightComponent::SetColor(const AZ::Color& newColor) - { - if (m_configuration.m_color != newColor) - { - m_configuration.m_color = newColor; - m_light.UpdateRenderLight(m_configuration); - } - } - - const AZ::Color LightComponent::GetColor() - { - return m_configuration.m_color; - } - - void LightComponent::SetDiffuseMultiplier(float newMultiplier) - { - if (m_configuration.m_diffuseMultiplier != newMultiplier) - { - m_configuration.m_diffuseMultiplier = newMultiplier; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetDiffuseMultiplier() - { - return m_configuration.m_diffuseMultiplier; - } - - void LightComponent::SetSpecularMultiplier(float newMultiplier) - { - if (m_configuration.m_specMultiplier != newMultiplier) - { - m_configuration.m_specMultiplier = newMultiplier; - m_light.UpdateRenderLight(m_configuration); - } - } - - float LightComponent::GetSpecularMultiplier() - { - return m_configuration.m_specMultiplier; - } - - void LightComponent::SetAmbient(bool isAmbient) - { - if (isAmbient != m_configuration.m_ambient) - { - m_configuration.m_ambient = isAmbient; - m_light.UpdateRenderLight(m_configuration); - } - } - bool LightComponent::GetAmbient() - { - return m_configuration.m_ambient; - } - - void LightComponent::SetPointMaxDistance(float newMaxDistance) - { - if (newMaxDistance != m_configuration.m_pointMaxDistance) - { - m_configuration.m_pointMaxDistance = newMaxDistance; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetPointMaxDistance() - { - return m_configuration.m_pointMaxDistance; - } - - void LightComponent::SetPointAttenuationBulbSize(float newAttenuationBulbSize) - { - if (newAttenuationBulbSize != m_configuration.m_pointAttenuationBulbSize) - { - m_configuration.m_pointAttenuationBulbSize = newAttenuationBulbSize; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetPointAttenuationBulbSize() - { - return m_configuration.m_pointAttenuationBulbSize; - } - - void LightComponent::SetAreaMaxDistance(float newMaxDistance) - { - if (newMaxDistance != m_configuration.m_areaMaxDistance) - { - m_configuration.m_areaMaxDistance = newMaxDistance; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetAreaMaxDistance() - { - return m_configuration.m_areaMaxDistance; - } - - void LightComponent::SetAreaWidth(float newWidth) - { - if (newWidth != m_configuration.m_areaWidth) - { - m_configuration.m_areaWidth = newWidth; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetAreaWidth() - { - return m_configuration.m_areaWidth; - } - - void LightComponent::SetAreaHeight(float newHeight) - { - if (newHeight != m_configuration.m_areaHeight) - { - m_configuration.m_areaHeight = newHeight; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetAreaHeight() - { - return m_configuration.m_areaHeight; - } - - void LightComponent::SetAreaFOV(float newFOV) - { - if (newFOV != m_configuration.m_areaFOV) - { - m_configuration.m_areaFOV = newFOV; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetAreaFOV() - { - return m_configuration.m_areaFOV; - } - - void LightComponent::SetProjectorMaxDistance(float newMaxDistance) - { - if (newMaxDistance != m_configuration.m_projectorRange) - { - m_configuration.m_projectorRange = newMaxDistance; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetProjectorMaxDistance() - { - return m_configuration.m_projectorRange; - } - - void LightComponent::SetProjectorAttenuationBulbSize(float newAttenuationBulbSize) - { - if (newAttenuationBulbSize != m_configuration.m_projectorAttenuationBulbSize) - { - m_configuration.m_projectorAttenuationBulbSize = newAttenuationBulbSize; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetProjectorAttenuationBulbSize() - { - return m_configuration.m_projectorAttenuationBulbSize; - } - - void LightComponent::SetProjectorFOV(float newFOV) - { - if (newFOV != m_configuration.m_projectorFOV) - { - m_configuration.m_projectorFOV = newFOV; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetProjectorFOV() - { - return m_configuration.m_projectorFOV; - } - - void LightComponent::SetProjectorNearPlane(float newNearPlane) - { - if (newNearPlane != m_configuration.m_projectorNearPlane) - { - m_configuration.m_projectorNearPlane = newNearPlane; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetProjectorNearPlane() - { - return m_configuration.m_projectorNearPlane; - } - - void LightComponent::SetProbeAreaDimensions(const AZ::Vector3& newDimensions) - { - if (newDimensions != m_configuration.m_probeArea) - { - m_configuration.m_probeArea = newDimensions; - m_light.UpdateRenderLight(m_configuration); - } - } - const AZ::Vector3 LightComponent::GetProbeAreaDimensions() - { - return m_configuration.m_probeArea; - } - - void LightComponent::SetProbeSortPriority(AZ::u32 newPriority) - { - if (newPriority != m_configuration.m_probeSortPriority) - { - m_configuration.m_probeSortPriority = newPriority; - m_light.UpdateRenderLight(m_configuration); - } - } - AZ::u32 LightComponent::GetProbeSortPriority() - { - return m_configuration.m_probeSortPriority; - } - - void LightComponent::SetProbeBoxProjected(bool isProbeBoxProjected) - { - if (isProbeBoxProjected != m_configuration.m_isBoxProjected) - { - m_configuration.m_isBoxProjected = isProbeBoxProjected; - m_light.UpdateRenderLight(m_configuration); - } - } - bool LightComponent::GetProbeBoxProjected() - { - return m_configuration.m_isBoxProjected; - } - - void LightComponent::SetProbeBoxHeight(float newHeight) - { - if (newHeight != m_configuration.m_boxHeight) - { - m_configuration.m_boxHeight = newHeight; - m_light.UpdateRenderLight(m_configuration); - } - } - float LightComponent::GetProbeBoxHeight() - { - return m_configuration.m_boxHeight; - } - - void LightComponent::SetProbeBoxLength(float newLength) - { - if (newLength != m_configuration.m_boxLength) - { - m_configuration.m_boxLength = newLength; - m_light.UpdateRenderLight(m_configuration); - } - } - - float LightComponent::GetProbeBoxLength() - { - return m_configuration.m_boxLength; - } - - void LightComponent::SetProbeBoxWidth(float newWidth) - { - if (newWidth != m_configuration.m_boxWidth) - { - m_configuration.m_boxWidth = newWidth; - m_light.UpdateRenderLight(m_configuration); - } - } - - float LightComponent::GetProbeBoxWidth() - { - return m_configuration.m_boxWidth; - } - - void LightComponent::SetProbeAttenuationFalloff(float newAttenuationFalloff) - { - if (newAttenuationFalloff != m_configuration.m_attenFalloffMax) - { - m_configuration.m_attenFalloffMax = newAttenuationFalloff; - m_light.UpdateRenderLight(m_configuration); - } - } - - float LightComponent::GetProbeAttenuationFalloff() - { - return m_configuration.m_attenFalloffMax; - } - - void LightComponent::SetProbeFade(float fade) - { - AZ_Warning("Lighting", 0.0f <= fade && fade <= 1.0f, "SetProbeFade value %f out of range. Clamping to [0,1]", fade); - fade = AZ::GetClamp(fade, 0.0f, 1.0f); - - if (fade != m_configuration.m_probeFade) - { - m_configuration.m_probeFade = fade; - m_light.UpdateRenderLight(m_configuration); - } - } - - float LightComponent::GetProbeFade() - { - return m_configuration.m_probeFade; - } - - /////////////////////////////////////////////////////////// - void LightComponent::ToggleLight() - { - if (m_light.IsOn()) - { - TurnOffLight(); - } - else - { - TurnOnLight(); - } - } - - void LightComponent::SetLightState(State state) - { - switch (state) - { - case LightComponentRequests::State::On: - { - TurnOnLight(); - } - break; - - case LightComponentRequests::State::Off: - { - TurnOffLight(); - } - break; - } - } - - IRenderNode* LightComponent::GetRenderNode() - { - return m_light.GetRenderNode(); - } - - float LightComponent::GetRenderNodeRequestBusOrder() const - { - return s_renderNodeRequestBusOrder; - } - - const float LightComponent::s_renderNodeRequestBusOrder = 500.f; - - LightComponent::LightComponent() - { - } - - LightComponent::~LightComponent() - { - } - - void LightComponent::Init() - { - } - - void LightComponent::Activate() - { - const AZ::EntityId entityId = GetEntityId(); - - m_light.SetEntity(entityId); - m_light.CreateRenderLight(m_configuration); - - LightComponentRequestBus::Handler::BusConnect(entityId); - RenderNodeRequestBus::Handler::BusConnect(entityId); - - if (m_configuration.m_onInitially) - { - m_light.TurnOn(); - } - else - { - m_light.TurnOff(); - } - } - - void LightComponent::Deactivate() - { - LightComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - m_light.DestroyRenderLight(); - m_light.SetEntity(AZ::EntityId()); - } - - LightConfiguration::LightConfiguration() - : m_lightType(LightType::Point) - , m_visible(true) - , m_onInitially(true) - , m_pointMaxDistance(2.f) - , m_pointAttenuationBulbSize(0.05f) - , m_areaMaxDistance(2.f) - , m_areaWidth(5.f) - , m_areaHeight(5.f) - , m_areaFOV(45.0f) - , m_projectorAttenuationBulbSize(0.05f) - , m_projectorRange(5.f) - , m_projectorFOV(90.f) - , m_projectorNearPlane(0) - , m_probeSortPriority(0) - , m_probeArea(20.0f, 20.0f, 20.0f) - , m_probeCubemapResolution(ResolutionSetting::ResDefault) - , m_isBoxProjected(false) - , m_boxWidth(20.0f) - , m_boxHeight(20.0f) - , m_boxLength(20.0f) - , m_attenFalloffMax(0.3f) - , m_probeFade(1.0f) - , m_minSpec(EngineSpec::Low) - , m_viewDistMultiplier(1.f) - , m_castShadowsSpec(EngineSpec::Never) - , m_voxelGIMode(IRenderNode::VM_None) - , m_color(1.f, 1.f, 1.f, 1.f) - , m_diffuseMultiplier(1.f) - , m_specMultiplier(1.f) - , m_affectsThisAreaOnly(true) - , m_useVisAreas(true) - , m_volumetricFog(true) - , m_volumetricFogOnly(false) - , m_indoorOnly(false) - , m_ambient(false) - , m_deferred(true) - , m_animIndex(0) - , m_animSpeed(1.f) - , m_animPhase(0.f) - , m_castTerrainShadows(false) - , m_shadowBias(1.f) - , m_shadowSlopeBias(1.f) - , m_shadowResScale(1.f) - , m_shadowUpdateMinRadius(10.f) - , m_shadowUpdateRatio(1.f) - , m_cubemapId(AZ::Uuid::Create()) - { - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LightComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/LightComponent.h deleted file mode 100644 index d562cf1701..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LightComponent.h +++ /dev/null @@ -1,303 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "LightInstance.h" - -#include - -namespace LmbrCentral -{ - /*! - * Stores configuration settings for engine lights. - * - Common color and shader settings - * - Common shadow-casting settings - * - Settings unique to different light types - */ - class LightConfiguration - { - public: - - AZ_TYPE_INFO(LightConfiguration, "{F4CC7BB4-C541-480C-88FC-C5A8F37CC67F}"); - - // LY renderer supported light types. - enum class LightType : AZ::u32 - { - Point = 0, ///> Omni-directional point light - Area, ///> Area/box light - Projector, ///> Texture projector light - Probe, ///> Environment probe - }; - - // Texture resolution settings. - enum class ResolutionSetting : AZ::u32 - { - ResDefault = 256, - Res32 = 32, - Res64 = 64, - Res128 = 128, - Res256 = 256, - Res512 = 512, - }; - - LightConfiguration(); - virtual ~LightConfiguration() {}; - - static void Reflect(AZ::ReflectContext* context); - - //! The type of render light (point/omni, projector, area, or environment probe). - LightType m_lightType; - - //! Turned on by default? - bool m_onInitially; - - //! Currently visible? - bool m_visible; - - //! Point light settings - float m_pointMaxDistance; - float m_pointAttenuationBulbSize; - - //! Settings for area lights - float m_areaWidth; - float m_areaHeight; - float m_areaMaxDistance; - float m_areaFOV; - - //! Settings for projector lights - float m_projectorRange; - float m_projectorAttenuationBulbSize; - float m_projectorFOV; - float m_projectorNearPlane; - AzFramework::SimpleAssetReference m_projectorTexture; - AzFramework::SimpleAssetReference m_material; - - //! Settings for environment lights (probes) - AZ::Vector3 m_probeArea; - AZ::u32 m_probeSortPriority; - ResolutionSetting m_probeCubemapResolution; - AzFramework::SimpleAssetReference m_probeCubemap; - //parameter to enable box projection - bool m_isBoxProjected; - float m_boxWidth; - float m_boxHeight; - float m_boxLength; - float m_attenFalloffMax; - float m_probeFade; - - //! Settings common to all LY engine lights - EngineSpec m_minSpec; - float m_viewDistMultiplier; - EngineSpec m_castShadowsSpec; - IRenderNode::EVoxelGIMode m_voxelGIMode; - - AZ::Color m_color; - float m_diffuseMultiplier; - float m_specMultiplier; - bool m_affectsThisAreaOnly; - bool m_useVisAreas; - bool m_indoorOnly; - bool m_ambient; - bool m_deferred; - AZ::u32 m_animIndex; - float m_animSpeed; - float m_animPhase; - bool m_volumetricFog; - bool m_volumetricFogOnly; - bool m_castTerrainShadows; - - //! Shadow settings - float m_shadowBias; - float m_shadowSlopeBias; - float m_shadowResScale; - float m_shadowUpdateMinRadius; - float m_shadowUpdateRatio; - - // Need to keep a unique Id to use as cubemap name - AZ::Uuid m_cubemapId; - - // \todo clip bounds - artists aren't using it. Includes fade dimensions. - - AZ::EntityId m_editorEntityId; // Editor-only, not reflected. - - // Property event-handlers implemented in editor component. - virtual AZ::Crc32 GetAmbientLightVisibility() const { return 0; } - virtual AZ::Crc32 GetPointLightVisibility() const { return 0; } - virtual AZ::Crc32 GetProjectorLightVisibility() const { return 0; } - virtual AZ::Crc32 GetProbeLightVisibility() const { return 0; } - virtual AZ::Crc32 GetShadowSpecVisibility() const { return 0; } - virtual AZ::Crc32 GetShadowSettingsVisibility() const { return 0; } - virtual AZ::Crc32 GetAreaSettingVisibility() const { return 0; } - virtual AZ::Crc32 MinorPropertyChanged() { return 0; } - virtual AZ::Crc32 MajorPropertyChanged() { return 0; } - virtual AZ::Crc32 OnAnimationSettingChanged() { return 0; } - virtual AZ::Crc32 OnCubemapAssetChanged() { return 0; } - virtual bool CanGenerateCubemap() const { return false; } - - private: - - static bool VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement); - }; - - /*! - * In-game light component. - */ - class LightComponent - : public AZ::Component - , public LightComponentRequestBus::Handler - , public RenderNodeRequestBus::Handler - { - public: - - friend class EditorLightComponent; - - AZ_COMPONENT(LightComponent, "{6B9AB512-CA8A-4D2B-B570-DF128EA7CE6A}"); - - LightComponent(); - ~LightComponent() override; - - ////////////////////////////////////////////////////////////////////////// - // AZ::Component interface implementation - void Init() override; - void Activate() override; - void Deactivate() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // LightComponentRequests::Bus::Handler interface implementation - void SetLightState(State state) override; - bool TurnOnLight() override; - bool TurnOffLight() override; - void ToggleLight() override; - - //////////////////////////////////// - // Modifiers - void SetVisible(bool isVisible) override; - bool GetVisible() override; - - void SetColor(const AZ::Color& newColor) override; - const AZ::Color GetColor() override; - - void SetDiffuseMultiplier(float newMultiplier) override; - float GetDiffuseMultiplier() override; - - void SetSpecularMultiplier(float newMultiplier) override; - float GetSpecularMultiplier() override; - - void SetAmbient(bool isAmbient) override; - bool GetAmbient() override; - - void SetPointMaxDistance(float newMaxDistance) override; - float GetPointMaxDistance() override; - - void SetPointAttenuationBulbSize(float newAttenuationBulbSize) override; - float GetPointAttenuationBulbSize() override; - - void SetAreaMaxDistance(float newMaxDistance) override; - float GetAreaMaxDistance() override; - - void SetAreaWidth(float newWidth) override; - float GetAreaWidth() override; - - void SetAreaHeight(float newHeight) override; - float GetAreaHeight() override; - - void SetAreaFOV(float newFOV) override; - float GetAreaFOV() override; - - void SetProjectorMaxDistance(float newMaxDistance) override; - float GetProjectorMaxDistance() override; - - void SetProjectorAttenuationBulbSize(float newAttenuationBulbSize) override; - float GetProjectorAttenuationBulbSize() override; - - void SetProjectorFOV(float newFOV) override; - float GetProjectorFOV() override; - - void SetProjectorNearPlane(float newNearPlane) override; - float GetProjectorNearPlane() override; - - // Environment Probe Settings - void SetProbeAreaDimensions(const AZ::Vector3& newDimensions) override; - const AZ::Vector3 GetProbeAreaDimensions() override; - - void SetProbeSortPriority(AZ::u32 newPriority) override; - AZ::u32 GetProbeSortPriority() override; - - void SetProbeBoxProjected(bool isProbeBoxProjected) override; - bool GetProbeBoxProjected() override; - - void SetProbeBoxHeight(float newHeight) override; - float GetProbeBoxHeight() override; - - void SetProbeBoxLength(float newLength) override; - float GetProbeBoxLength() override; - - void SetProbeBoxWidth(float newWidth) override; - float GetProbeBoxWidth() override; - - void SetProbeAttenuationFalloff(float newAttenuationFalloff) override; - float GetProbeAttenuationFalloff() override; - - void SetProbeFade(float fade) override; - float GetProbeFade() override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // RenderNodeRequestBus::Handler interface implementation - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - static const float s_renderNodeRequestBusOrder; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("LightService", 0xfd7fa928)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& /*dependent*/) - { - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("LightService", 0xfd7fa928)); - } - - static void Reflect(AZ::ReflectContext* context); - ////////////////////////////////////////////////////////////////////////// - - protected: - - LightConfiguration m_configuration; - LightInstance m_light; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LightInstance.cpp b/Gems/LmbrCentral/Code/Source/Rendering/LightInstance.cpp deleted file mode 100644 index 0c5da629ed..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LightInstance.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include - -#include - -#include "LightInstance.h" -#include "LightComponent.h" -#include "LensFlareComponent.h" - -namespace -{ - const float kDefaultLightFrustumAngle = 45.f; - const uint8 kDefaultLensOpticsFrustumAngle = 255; - - void UpdateLightFlag(bool enable, int mask, unsigned int& flags) - { - if (enable) - { - flags |= mask; - } - else - { - flags &= ~mask; - } - } - - AZ::u32 CreateLightId(AZ::EntityId entityId) - { - // Renderer requires a non-zero value, but doesn't care what it actually means. - // This is used only for debug coloring and tie-breaking sorts. - // Use the timestamp half of our entity Id. - const AZ::u32 lowerEntityId = static_cast(static_cast(entityId) >> 32); - return lowerEntityId; - } - - const char* GetEntityName(AZ::EntityId entityId) - { - AZ::Entity* entity = nullptr; - EBUS_EVENT_RESULT(entity, AZ::ComponentApplicationBus, FindEntity, entityId); - return (entity ? entity->GetName().c_str() : ""); - } - - void LightConfigToLightParams(const LmbrCentral::LightConfiguration& configuration, AZ::EntityId entityId, int configSpec, CDLight& lightParams) - { - // The light cannot be ambient if it is an environment probe - bool ambient = configuration.m_ambient; - if (configuration.m_lightType == LmbrCentral::LightConfiguration::LightType::Probe) - { - ambient = false; - } - - lightParams.SetPosition(Vec3_Zero); - lightParams.m_fLightFrustumAngle = kDefaultLightFrustumAngle; - lightParams.m_Flags = 0; - lightParams.m_LensOpticsFrustumAngle = kDefaultLensOpticsFrustumAngle; - Vec3 color = AZColorToLYVec3(configuration.m_color); - color *= configuration.m_diffuseMultiplier; - lightParams.SetLightColor(ColorF(color.x, color.y, color.z, 1.f)); - lightParams.SetSpecularMult(configuration.m_specMultiplier); - - lightParams.m_nLightStyle = configuration.m_animIndex; // "light style" is really a light animation curve index - lightParams.SetAnimSpeed(configuration.m_animSpeed); // maps [0, 4] to [0, 255] - lightParams.m_nLightPhase = static_cast(configuration.m_animPhase * 255.f); // maps [0, 1] to [0, 255] - - lightParams.m_nEntityId = CreateLightId(entityId); - - UpdateLightFlag(!configuration.m_useVisAreas, DLF_IGNORES_VISAREAS, lightParams.m_Flags); - UpdateLightFlag(configuration.m_indoorOnly, DLF_INDOOR_ONLY, lightParams.m_Flags); - UpdateLightFlag(configuration.m_affectsThisAreaOnly, DLF_THIS_AREA_ONLY, lightParams.m_Flags); - UpdateLightFlag(ambient, DLF_AMBIENT, lightParams.m_Flags); - UpdateLightFlag(configuration.m_deferred, DLF_DEFERRED_LIGHT, lightParams.m_Flags); - UpdateLightFlag(configuration.m_volumetricFog, DLF_VOLUMETRIC_FOG, lightParams.m_Flags); - UpdateLightFlag(configuration.m_volumetricFogOnly, DLF_VOLUMETRIC_FOG_ONLY, lightParams.m_Flags); - UpdateLightFlag(configuration.m_castTerrainShadows, DLF_CAST_TERRAIN_SHADOWS, lightParams.m_Flags); - - if (static_cast(configSpec) >= static_cast(configuration.m_castShadowsSpec)) - { - lightParams.m_Flags |= DLF_CASTSHADOW_MAPS; - } - - //Probe won't cast shadow. Enable this flag wrongly for probe could lead to wrong bbox. - if (configuration.m_lightType == LmbrCentral::LightConfiguration::LightType::Probe) - { - lightParams.m_Flags &= ~DLF_CASTSHADOW_MAPS; - } - - lightParams.m_fShadowBias = configuration.m_shadowBias; - lightParams.m_fShadowSlopeBias = configuration.m_shadowSlopeBias; - lightParams.m_fShadowResolutionScale = configuration.m_shadowResScale; - lightParams.m_fShadowUpdateMinRadius = configuration.m_shadowUpdateMinRadius; - lightParams.m_nShadowUpdateRatio = max((uint16)1, (uint16)(configuration.m_shadowUpdateRatio * (1 << DL_SHADOW_UPDATE_SHIFT))); - - switch (configuration.m_lightType) - { - case LmbrCentral::LightConfiguration::LightType::Point: - { - lightParams.m_fRadius = configuration.m_pointMaxDistance; - lightParams.m_fAttenuationBulbSize = configuration.m_pointAttenuationBulbSize; - lightParams.m_Flags |= DLF_POINT; - } - break; - - case LmbrCentral::LightConfiguration::LightType::Area: - { - lightParams.m_fRadius = configuration.m_areaMaxDistance; - lightParams.m_fAreaWidth = configuration.m_areaWidth; - lightParams.m_fAreaHeight = configuration.m_areaHeight; - lightParams.m_fLightFrustumAngle = configuration.m_areaFOV; - lightParams.m_Flags |= DLF_AREA_LIGHT; - } - break; - - case LmbrCentral::LightConfiguration::LightType::Projector: - { - lightParams.m_fRadius = configuration.m_projectorRange; - lightParams.m_fLightFrustumAngle = configuration.m_projectorFOV * 0.5f; - lightParams.m_fProjectorNearPlane = configuration.m_projectorNearPlane; - lightParams.m_fAttenuationBulbSize = configuration.m_projectorAttenuationBulbSize; - lightParams.m_Flags |= DLF_PROJECT; - - const char* texturePath = configuration.m_projectorTexture.GetAssetPath().c_str(); - const int flags = FT_DONT_STREAM; - - if (gEnv->pRenderer) - { - lightParams.m_pLightImage = gEnv->pRenderer->EF_LoadTexture(texturePath, flags); - - if (!lightParams.m_pLightImage || !lightParams.m_pLightImage->IsTextureLoaded()) - { - GetISystem()->Warning(VALIDATOR_MODULE_RENDERER, VALIDATOR_WARNING, 0, texturePath, - "Light projector texture not found: %s", texturePath); - lightParams.m_pLightImage = gEnv->pRenderer->EF_LoadTexture("Textures/defaults/red.dds", flags); - } - } - } - break; - - case LmbrCentral::LightConfiguration::LightType::Probe: - { - lightParams.m_ProbeExtents.x = configuration.m_probeArea.GetX() / 2.0f; - lightParams.m_ProbeExtents.y = configuration.m_probeArea.GetY() / 2.0f; - lightParams.m_ProbeExtents.z = configuration.m_probeArea.GetZ() / 2.0f; - lightParams.m_fRadius = lightParams.m_ProbeExtents.len(); - lightParams.m_nSortPriority = configuration.m_probeSortPriority; - lightParams.m_fProbeAttenuation = configuration.m_probeFade; - - //projection - if (configuration.m_isBoxProjected) - { - //enable box projection - lightParams.m_Flags |= DLF_BOX_PROJECTED_CM; - } - lightParams.m_fBoxHeight = configuration.m_boxHeight; - lightParams.m_fBoxLength = configuration.m_boxLength; - lightParams.m_fBoxWidth = configuration.m_boxWidth; - lightParams.SetFalloffMax(configuration.m_attenFalloffMax); - - lightParams.ReleaseCubemaps(); - - const AZStd::string& specularMap = configuration.m_probeCubemap.GetAssetPath(); - - if (!specularMap.empty()) - { - AZStd::string diffuseMap = specularMap; - AZStd::string::size_type dotPos = specularMap.find_last_of('.'); - if (dotPos != AZStd::string::npos) - { - diffuseMap.insert(dotPos, "_diff"); - } - - if (gEnv->pRenderer) - { - lightParams.SetSpecularCubemap(gEnv->pRenderer->EF_LoadCubemapTexture(specularMap.c_str(), FT_DONT_STREAM)); - lightParams.SetDiffuseCubemap(gEnv->pRenderer->EF_LoadCubemapTexture(diffuseMap.c_str(), FT_DONT_STREAM)); - } - - if (lightParams.GetDiffuseCubemap() && lightParams.GetSpecularCubemap()) - { - lightParams.m_Flags |= DLF_DEFERRED_CUBEMAPS; - } - else - { - if (!lightParams.GetSpecularCubemap()) - { - AZ_Warning("Light", false, - "Failed to load specular cubemap \"%s\" for light \"%s\".", - specularMap.c_str(), - GetEntityName(entityId)); - } - - if (!lightParams.GetDiffuseCubemap()) - { - AZ_Warning("Light", false, - "Failed to load diffuse cubemap \"%s\" for light \"%s\".", - diffuseMap.c_str(), - GetEntityName(entityId)); - } - - lightParams.m_Flags &= ~DLF_DEFERRED_CUBEMAPS; - lightParams.m_Flags |= DLF_POINT; - lightParams.ReleaseCubemaps(); - } - } - else - { - // Disable the light - lightParams.m_Flags = DLF_FAKE; - } - } - break; - } - } - - void LensFlareConfigToLightParams(const LmbrCentral::LensFlareConfiguration& configuration, [[maybe_unused]] AZ::EntityId entityId, int, CDLight& lightParams) - { - lightParams.m_Flags |= DLF_FAKE; // As long as deferred lights are separate components disable the actual deferred light - - ColorF color = AZVec3ToLYVec3(configuration.m_tint); - color.a = configuration.m_tintAlpha / 255.0f; - lightParams.SetLightColor(ColorF(1.f, 1.f, 1.f, 1.f)); //Set the light color to white. We can tint the lens flare directly - - if (configuration.m_syncAnimWithLight) - { - lightParams.m_nLightStyle = static_cast(configuration.m_syncAnimIndex); // This is really a light animation curve ID - lightParams.SetAnimSpeed(configuration.m_syncAnimSpeed); // maps [0, 4] to [0, 255] - lightParams.m_nLightPhase = static_cast(configuration.m_syncAnimPhase * 255.f); // maps [0, 1] to [0, 255] - } - else if (configuration.m_attachToSun) - { - gEnv->p3DEngine->SetSunAnimIndex(static_cast(configuration.m_animIndex)); // This is really a light animation curve ID - gEnv->p3DEngine->SetSunAnimSpeed(configuration.m_animSpeed); // maps [0, 4] to [0, 255] - gEnv->p3DEngine->SetSunAnimPhase(static_cast(configuration.m_animPhase * 255.f)); // maps [0, 1] to [0, 255] - } - else - { - lightParams.m_nLightStyle = static_cast(configuration.m_animIndex); // This is really a light animation curve ID - lightParams.SetAnimSpeed(configuration.m_animSpeed); // maps [0, 4] to [0, 255] - lightParams.m_nLightPhase = static_cast(configuration.m_animPhase * 255.f); // maps [0, 1] to [0, 255] - } - - lightParams.m_LensOpticsFrustumAngle = static_cast(configuration.m_lensFlareFrustumAngle / 360.f * 255.f); - - UpdateLightFlag(configuration.m_affectsThisAreaOnly, DLF_THIS_AREA_ONLY, lightParams.m_Flags); - UpdateLightFlag(!configuration.m_useVisAreas, DLF_IGNORES_VISAREAS, lightParams.m_Flags); - UpdateLightFlag(configuration.m_indoorOnly, DLF_INDOOR_ONLY, lightParams.m_Flags); - UpdateLightFlag(configuration.m_attachToSun, DLF_ATTACH_TO_SUN, lightParams.m_Flags); - - if (!configuration.m_lensFlare.empty()) - { - int lensOpticsID = 0; - if (gEnv->pOpticsManager->Load(configuration.m_lensFlare.c_str(), lensOpticsID)) - { - IOpticsElementBase* flare = gEnv->pOpticsManager->GetOptics(lensOpticsID); - lightParams.SetLensOpticsElement(flare); - lightParams.SetOpticsParams({ configuration.m_brightness, configuration.m_size, { color.r, color.g, color.b, color.a }, true }); - } - else - { - AZ_Warning("LensFlare", false, "Failed to load lens flare \"%s\" for entity \"%s\".", configuration.m_lensFlare.c_str(), GetEntityName(entityId)); - } - } - } -} - -namespace LmbrCentral -{ - LightInstance::LightInstance() - : m_renderLight(nullptr) - { - } - - LightInstance::~LightInstance() - { - DestroyRenderLight(); - } - - void LightInstance::SetEntity(AZ::EntityId entityId) - { - if (m_entityId.IsValid()) - { - AZ::TransformNotificationBus::Handler::BusDisconnect(); - } - - m_entityId = entityId; - - if (m_entityId.IsValid()) - { - AZ::TransformNotificationBus::Handler::BusConnect(m_entityId); - } - } - - void LightInstance::OnTransformChanged(const AZ::Transform&, const AZ::Transform& world) - { - if (m_renderLight) - { - CDLight* lightProperties = &m_renderLight->GetLightProperties(); - Matrix34 worldMatrix = AZTransformToLYTransform(world); - worldMatrix.OrthonormalizeFast(); // Lights do not support scale. - lightProperties->SetPosition(worldMatrix.GetTranslation()); - lightProperties->SetMatrix(worldMatrix); - m_renderLight->SetMatrix(worldMatrix); - } - } - - bool LightInstance::TurnOn() - { - if (!m_renderLight) - { - return false; - } - - m_renderLight->SetRndFlags(ERF_HIDDEN, false); - return true; - } - - bool LightInstance::TurnOff() - { - if (!m_renderLight) - { - return false; - } - - m_renderLight->SetRndFlags(ERF_HIDDEN, true); - return true; - } - - bool LightInstance::IsOn() const - { - if (!m_renderLight) - { - return false; - } - - return 0 == (m_renderLight->GetRndFlags() & ERF_HIDDEN); - } - - void LightInstance::CreateRenderLight(const LightConfiguration& configuration) - { - CreateRenderLightInternal(configuration, LightConfigToLightParams); - -#if defined(FEATURE_SVO_GI) - if (m_renderLight) - { - m_renderLight->SetDesiredVoxelGIMode(configuration.m_voxelGIMode); - } -#endif - } - - void LightInstance::CreateRenderLight(const LensFlareConfiguration& configuration) - { - CreateRenderLightInternal(configuration, LensFlareConfigToLightParams); - } - - void LightInstance::UpdateRenderLight(const LightConfiguration& configuration) - { - // ERF_HIDDEN is used to turn on/off the light, so cache it here and set it back later - bool isHidden = m_renderLight ? (m_renderLight->GetRndFlags() & ERF_HIDDEN) == ERF_HIDDEN : false; - DestroyRenderLight(); - CreateRenderLight(configuration); - if (m_renderLight) - { - m_renderLight->SetRndFlags(ERF_HIDDEN, isHidden); - } - } - - void LightInstance::UpdateRenderLight(const LensFlareConfiguration& configuration) - { - // ERF_HIDDEN is used to turn on/off the light, so cache it here and set it back later - bool isHidden = m_renderLight ? (m_renderLight->GetRndFlags() & ERF_HIDDEN) == ERF_HIDDEN : false; - DestroyRenderLight(); - CreateRenderLight(configuration); - if (m_renderLight) - { - m_renderLight->SetRndFlags(ERF_HIDDEN, isHidden); - } - } - - void LightInstance::DestroyRenderLight() - { - if (m_renderLight) - { - m_renderLight->ReleaseNode(); - m_renderLight = nullptr; - } - } - - IRenderNode* LightInstance::GetRenderNode() - { - return m_renderLight; - } - - template - void LightInstance::CreateRenderLightInternal(const ConfigurationType& configuration, ConfigToLightParamsFunc configToLightParams) - { - if (m_renderLight || !configuration.m_visible || !gEnv->p3DEngine) - { - return; - } - - ICVar* cvarSysSpecLight = gEnv->pConsole->GetCVar("e_LightQuality"); - const int configSpec = cvarSysSpecLight ? cvarSysSpecLight->GetIVal() : gEnv->pSystem->GetConfigSpec(true); - - if (static_cast(configSpec) < static_cast(configuration.m_minSpec)) - { - // Light is disabled in the active system spec. - return; - } - - CDLight lightParams; - configToLightParams(configuration, m_entityId, configSpec, lightParams); - - m_renderLight = gEnv->p3DEngine->CreateLightSource(); - - if (!configuration.m_material.GetAssetPath().empty()) - { - m_renderLight->SetMaterial(gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(configuration.m_material.GetAssetPath().c_str())); - } - - m_renderLight->SetLightProperties(lightParams); - m_renderLight->SetMinSpec(static_cast(configuration.m_minSpec)); - m_renderLight->SetViewDistanceMultiplier(configuration.m_viewDistMultiplier); - - AZ::Transform parentTransform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(parentTransform, m_entityId, AZ::TransformBus, GetWorldTM); - OnTransformChanged(AZ::Transform::CreateIdentity(), parentTransform); - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/LightInstance.h b/Gems/LmbrCentral/Code/Source/Rendering/LightInstance.h deleted file mode 100644 index 694aa3a227..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/LightInstance.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include - -struct ILightSource; -struct IRenderNode; -class CDLight; - -namespace LmbrCentral -{ - class LightConfiguration; - class LensFlareConfiguration; - - /*! - * Renderer specific implementation of a Renderer light - */ - class LightInstance final - : private AZ::TransformNotificationBus::Handler - { - public: - - AZ_TYPE_INFO(LightInstance, "{844D6585-6613-4E0D-BBA7-C37073B84F5F}"); - - LightInstance(); - ~LightInstance(); - - void SetEntity(AZ::EntityId id); - - void CreateRenderLight(const LightConfiguration& configuration); - void UpdateRenderLight(const LightConfiguration& configuration); - - void CreateRenderLight(const LensFlareConfiguration& configuration); - void UpdateRenderLight(const LensFlareConfiguration& configuration); - - void DestroyRenderLight(); - - IRenderNode* GetRenderNode(); - - bool IsOn() const; - - bool TurnOn(); - bool TurnOff(); - - ////////////////////////////////////////////////////////////////////////// - // AZ::TransformNotificationBus::Handler interface implementation - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - ////////////////////////////////////////////////////////////////////////// - - private: - template - void CreateRenderLightInternal(const ConfigurationType& configuration, ConfigToLightParamsFunc configToLightParams); - - AZ::EntityId m_entityId; - ILightSource* m_renderLight; - }; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MaterialHandle.cpp b/Gems/LmbrCentral/Code/Source/Rendering/MaterialHandle.cpp deleted file mode 100644 index 6171951398..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MaterialHandle.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" -#include -#include -#include -#include -#include -#include -#include - - -namespace LmbrCentral -{ - // Provides a set of reflected functions for operating on IMaterial through a MaterialHandle - // We keep these cpp-private instead of putting them in the header to align with the fact that - // MaterialHandle is not useful on the code side, and only exists to support reflection. If it - // were possible to reflect IMaterial directly, we'd still have this same set of functions here. - namespace MaterialHandleFunctions - { - void SetParamVector4(MaterialHandle* thisPtr, const AZStd::string& name, const AZ::Vector4& value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec4 vec4(value.GetX(), value.GetY(), value.GetZ(), value.GetW()); - thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, false, true); - } - else - { - AZ_Error("Material", false, "SetParamVector4 only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamVector4"); - } - } - - void SetParamVector3(MaterialHandle* thisPtr, const AZStd::string& name, const AZ::Vector3& value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec3 vec3(value.GetX(), value.GetY(), value.GetZ()); - thisPtr->m_material->SetGetMaterialParamVec3(name.c_str(), vec3, false, true); - } - else - { - AZ_Error("Material", false, "SetParamVector3 only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamVector3"); - } - } - - void SetParamColor(MaterialHandle* thisPtr, const AZStd::string& name, const AZ::Color& value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - // When value had garbage data is was not only making the material render black, it also corrupted something - // on the GPU, making black boxes flicker over the sky. - // It was garbage due to a bug in the Color object node where all fields have to be set to some value manually; the default is not 0. - if ((value.GetR() < 0 || value.GetR() > 1) || - (value.GetG() < 0 || value.GetG() > 1) || - (value.GetB() < 0 || value.GetB() > 1) || - (value.GetA() < 0 || value.GetA() > 1)) - { - return; - } - - Vec4 vec4(value.GetR(), value.GetG(), value.GetB(), value.GetA()); - thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, false, true); - } - else - { - AZ_Error("Material", false, "SetParamColor only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamColor"); - } - } - - void SetParamFloat(MaterialHandle* thisPtr, const AZStd::string& name, float value) - { - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - thisPtr->m_material->SetGetMaterialParamFloat(name.c_str(), value, false, true); - } - else - { - AZ_Error("Material", false, "SetParamFloat only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to SetParamFloat"); - } - } - - AZ::Vector4 GetParamVector4(MaterialHandle* thisPtr, const AZStd::string& name) - { - AZ::Vector4 value = AZ::Vector4::CreateZero(); - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec4 vec4; - if (thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, true, true)) - { - value.Set(vec4.x, vec4.y, vec4.z, vec4.w); - } - } - else - { - AZ_Error("Material", false, "GetParamVector4 only accepts single Materials, not Material Groups"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamVector4"); - } - - return value; - } - - AZ::Vector3 GetParamVector3(MaterialHandle* thisPtr, const AZStd::string& name) - { - AZ::Vector3 value = AZ::Vector3::CreateZero(); - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec3 vec3; - if (thisPtr->m_material->SetGetMaterialParamVec3(name.c_str(), vec3, true, true)) - { - value.Set(vec3.x, vec3.y, vec3.z); - } - } - else - { - AZ_Error("Material", false, "GetParamVector3 only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamVector3"); - } - - return value; - } - - AZ::Color GetParamColor(MaterialHandle* thisPtr, const AZStd::string& name) - { - AZ::Color value = AZ::Color::CreateZero(); - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - Vec4 vec4; - if (thisPtr->m_material->SetGetMaterialParamVec4(name.c_str(), vec4, true, true)) - { - value.Set(vec4.x, vec4.y, vec4.z, vec4.w); - } - } - else - { - AZ_Error("Material", false, "GetParamColor only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamColor"); - } - - return value; - } - - float GetParamFloat(MaterialHandle* thisPtr, const AZStd::string& name) - { - float value = 0.0f; - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsMaterialGroup()) - { - thisPtr->m_material->SetGetMaterialParamFloat(name.c_str(), value, true, true); - } - else - { - AZ_Error("Material", false, "GetParamFloat only accepts single Materials, not Material Groups"); - } - - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to GetParamFloat"); - } - - return value; - } - - MaterialHandle Clone(MaterialHandle* thisPtr) - { - MaterialHandle copy; - - if (thisPtr && thisPtr->m_material) - { - if (!thisPtr->m_material->IsSubMaterial()) - { - copy.m_material = gEnv->p3DEngine->GetMaterialManager()->CloneMultiMaterial(thisPtr->m_material); - } - else - { - AZ_Error("Material", false, "Clone does not support Sub-Materials"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to Clone"); - } - - return copy; - } - - MaterialHandle FindByName(const AZStd::string& name) - { - MaterialHandle found; - found.m_material = gEnv->p3DEngine->GetMaterialManager()->FindMaterial(name.c_str()); - return found; - } - - MaterialHandle LoadByName(const AZStd::string& name) - { - LmbrCentral::MaterialHandle handle; - handle.m_material = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(name.c_str(), false, false, IMaterialManager::ELoadingFlagsPreviewMode); - - AZ_Error(nullptr, handle.m_material, "Material.LoadByName('%s') failed", name.c_str()); - - return handle; - } - - _smart_ptr GetSubMaterialHelper(_smart_ptr materialGroup, int materialId) - { - if (materialGroup) - { - if (materialGroup->IsMaterialGroup()) - { - int subMtlCount = materialGroup->GetSubMtlCount(); - if (materialId >= 1 && materialId <= subMtlCount) - { - return materialGroup->GetSubMtl(materialId-1); - } - else - { - AZ_Error("Material", false, "Invalid Material ID %d passed to FindSubMaterial. %d Materials are available.", materialId, subMtlCount); - } - } - else - { - AZ_Error("Material", false, "FindSubMaterial does not support single Material"); - } - } - else - { - AZ_Warning("Material", false, "Invalid Material passed to FindSubMaterial."); - } - - return nullptr; - } - - - - MaterialHandle FindSubMaterial(const AZStd::string& name, int id, bool shouldLoad) - { - MaterialHandle found; - _smart_ptr materialGroup = gEnv->p3DEngine->GetMaterialManager()->FindMaterial(name.c_str()); - if (materialGroup) - { - found.m_material = GetSubMaterialHelper(materialGroup, id); - } - else - { - if (shouldLoad) - { - materialGroup = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(name.c_str(), false, false, IMaterialManager::ELoadingFlagsPreviewMode); - if (materialGroup) - { - found.m_material = GetSubMaterialHelper(materialGroup, id); - } - else - { - AZ_Error("Material", false, "Load Material '%s' failed", name.c_str()); - } - } - else - { - AZ_Warning("Material", false, "No Sub-Material is found since Material '%s' is not loaded", name.c_str()); - } - } - - return found; - } - - AZStd::string ToString(MaterialHandle* thisPtr) - { - if (!thisPtr || !thisPtr->m_material) - { - return "Invalid"; - } - else - { - return thisPtr->m_material->GetName(); - } - } - } - - void MaterialHandle::Reflect(AZ::SerializeContext* serializeContext) - { - // This is required in order to create a MaterialHandle variable in script canvas. - serializeContext->Class()->Version(0); - } - - void MaterialHandle::Reflect(AZ::BehaviorContext* behaviorContext) - { - const char* setMaterialParamTooltip = "Sets a Material param value"; - const char* getMaterialParamTooltip = "Returns a Material param value"; - AZ::BehaviorParameterOverrides setMaterialDetails = { "Material", "The Material to modify" }; - AZ::BehaviorParameterOverrides getMaterialDetails = { "Material", "The Material to inspect" }; - AZ::BehaviorParameterOverrides setParamNameDetails = { "ParamName", "The name of the Material param to set" }; - AZ::BehaviorParameterOverrides getParamNameDetails = { "ParamName", "The name of the Material param to return" }; - const AZStd::array getMaterialParamArgs = { { getMaterialDetails,getParamNameDetails } }; - const char* newValueTooltip = "The new value to apply"; - - behaviorContext->Class("Material") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Method("ToString", &MaterialHandleFunctions::ToString) - ->Attribute(AZ::Script::Attributes::Operator, AZ::Script::Attributes::OperatorType::ToString) - ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) // Hide this node because it doesn't really make sense for the user (GetName would be better), but we need "ToString" in order to provide nice output in Material Variable nodes in script canvas. - ->Method("FindByName", &MaterialHandleFunctions::FindByName, { { { "Name", "Full path name of the Material" } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Find a Material by name. Returns Invalid if the Material is not already loaded.") - ->Method("LoadByName", &MaterialHandleFunctions::LoadByName, { { { "Name", "Full path name of the Material" } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Find a Material by name, loading the asset if needed. Returns Invalid if the Material could not be found or loaded.") - ->Method("Clone", &MaterialHandleFunctions::Clone, { { { "Material", "The Material to clone" } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Creates a copy of the given Material.") - ->Method("FindSubMaterial", &MaterialHandleFunctions::FindSubMaterial, - { { { "Name", "Full path name of the Material Group to get a Sub-Material from" }, - { "MaterialID", "The ID of a Sub-Material to access. IDs start at 1.", behaviorContext->MakeDefaultValue(1) }, - { "ShouldLoad", "Whether to load the Material Group or not if it's not loaded", behaviorContext->MakeDefaultValue(true) } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, "Find a Sub-Material from a Material Group by specified Material ID. Returns Invalid if the Material Group could not be found or loaded or the Sub-Material could not be found.") - ->Method("SetParamVector4", &MaterialHandleFunctions::SetParamVector4, - { { setMaterialDetails,setParamNameDetails,{ "Vector4", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("SetParamVector3", &MaterialHandleFunctions::SetParamVector3, - { { setMaterialDetails,setParamNameDetails,{ "Vector3", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("SetParamColor", &MaterialHandleFunctions::SetParamColor, - { { setMaterialDetails,setParamNameDetails,{ "Color", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("SetParamNumber", &MaterialHandleFunctions::SetParamFloat, // Using "ParamNumber" instead of "ParamFloat" because in Script Canvas all primitives are just "numbers" - { { setMaterialDetails,setParamNameDetails,{ "Number", newValueTooltip } } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Method("GetParamVector4", &MaterialHandleFunctions::GetParamVector4, getMaterialParamArgs) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Method("GetParamVector3", &MaterialHandleFunctions::GetParamVector3, getMaterialParamArgs) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Method("GetParamColor", &MaterialHandleFunctions::GetParamColor, getMaterialParamArgs) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Method("GetParamNumber", &MaterialHandleFunctions::GetParamFloat, getMaterialParamArgs) // Using "ParamNumber" instead of "ParamFloat" because in Script Canvas all primitives are just "numbers" - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ; - } -} diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.cpp b/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.cpp deleted file mode 100644 index c478c22b43..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include -#include - -#include -#include "MeshAssetHandler.h" - -#include -#include - -namespace LmbrCentral -{ - ////////////////////////////////////////////////////////////////////////// - const AZStd::string MeshAssetHandlerHelper::s_assetAliasToken = "@assets@/"; - - // what mesh do we use as a placeholder when its currently busy compiling? - static const char* g_meshCompilingSubstituteAsset = "engineassets/objects/default.cgf"; - - MeshAssetHandlerHelper::MeshAssetHandlerHelper() - : m_asyncLoadCvar(nullptr) - { - } - - void MeshAssetHandlerHelper::StripAssetAlias(const char*& assetPath) - { - const size_t assetAliasTokenLen = s_assetAliasToken.size() - 1; - if (0 == strncmp(assetPath, s_assetAliasToken.c_str(), assetAliasTokenLen)) - { - assetPath += assetAliasTokenLen; - } - } - - ICVar* MeshAssetHandlerHelper::GetAsyncLoadCVar() - { - if (!m_asyncLoadCvar) - { - m_asyncLoadCvar = gEnv->pConsole->GetCVar(s_meshAssetHandler_AsyncCvar); - } - - return m_asyncLoadCvar; - } - - ////////////////////////////////////////////////////////////////////////// - // Static Mesh Asset Handler - ////////////////////////////////////////////////////////////////////////// - - void AsyncStatObjLoadCallback(const AZ::Data::Asset& asset, _smart_ptr statObj) - { - if (statObj) - { - asset.Get()->m_statObj = statObj; - } - else - { -#if defined(AZ_ENABLE_TRACING) - AZStd::string assetDescription = asset.ToString(); - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetDescription, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetPathById, asset.GetId()); - AZ_Error("MeshAssetHandler", false, "Failed to load mesh asset %s", assetDescription.c_str()); -#endif // AZ_ENABLE_TRACING - } - } - - MeshAssetHandler::~MeshAssetHandler() - { - Unregister(); - } - - AZ::Data::AssetPtr MeshAssetHandler::CreateAsset([[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) - { - (void)type; - - AZ_Assert(type == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We handle only 'MeshAsset'"); - - return aznew MeshAsset(); - } - - AZ::Data::AssetId MeshAssetHandler::AssetMissingInCatalog([[maybe_unused]] const AZ::Data::Asset& asset) - { - // if tracing is disabled, we are likely in a situation where we specifically don't want any diagnostic information or "errors" to appear - // so in that case, don't load anything, don't substitute anything, don't escalate anything, just let the empty blank asset return. -#if defined(AZ_ENABLE_TRACING) - if (asset.GetId().IsValid()) - { - // find out whether its still compiling or it will never be available because its source file is missing. - // this also escalates it, if found, to the top of the build queue: - AzFramework::AssetSystem::AssetStatus statusResult = AzFramework::AssetSystem::AssetStatus_Unknown; - AzFramework::AssetSystemRequestBus::BroadcastResult(statusResult, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId()); - - if ((statusResult == AzFramework::AssetSystem::AssetStatus_Compiling) || (statusResult == AzFramework::AssetSystem::AssetStatus_Queued)) - { - // note that we can also check other codes and substitute other meshes if we want, here... - // its currently compiling and will finish soon. - // substitute a placeholder mesh: - - if (!m_missingMeshAssetId.IsValid()) - { - // substitute the missing mesh assetId so that there's at least something to render that indicates a problem - // in builds where there is no diagnostics or tracing, don't substitute anything, to prefer that there's no visual indication that - // something is wrong in shipped games. - AZ::Data::AssetCatalogRequestBus::BroadcastResult(m_missingMeshAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, g_meshCompilingSubstituteAsset, azrtti_typeid(), false); - AZ_Error("Mesh Asset Handler", m_missingMeshAssetId.IsValid(), "Attempted to substitute %s for a missing asset, but it is also missing!", g_meshCompilingSubstituteAsset); - } - - if (m_missingMeshAssetId.IsValid()) - { - AZ_TracePrintf("MeshAssetHandler", " - substituting with default asset ID %s\n", m_missingMeshAssetId.ToString().c_str()); - // substitute the missing mesh asset. - return m_missingMeshAssetId; - } - } - } -#endif // defined(AZ_ENABLE_TRACING) - - // otherwise, if we get here, it means that either it was truly missing, in which case let an error occur, or the missing default substitute asset - // is also itself missing! - return AZ::Data::AssetId(); - } - - - - void MeshAssetHandler::GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo) - { - // The StatObj system only takes in a file name for loading, not a memory buffer. - // If we set our stream data length to 0, the asset system will skip any file I/O for reading the data, and will instead - // go directly into the AssetHandler for processing. - streamInfo.m_dataLen = 0; - } - - AZ::Data::AssetHandler::LoadResult MeshAssetHandler::LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& /*assetLoadFilterCB*/) - { - const char* assetPath = stream->GetFilename(); - - AZ_Assert(asset.GetType() == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We only load 'MeshAsset'"); - if (MeshAsset* meshAsset = asset.GetAs()) - { - AZ_Assert(!meshAsset->m_statObj.get(), "Attempting to create static mesh without cleaning up the old one."); - - // Strip the alias. StatObj instances are stored in a dictionary by their path, - // so to share instances with legacy cry entities, we need to use the same un-aliased format. - StripAssetAlias(assetPath); - - // Temporary cvar guard while async loading of legacy mesh formats is stabilized. - ICVar* cvar = GetAsyncLoadCVar(); - if (!cvar || cvar->GetIVal() == 0) - { - if (gEnv->mMainThreadId != CryGetCurrentThreadId()) - { - AZStd::binary_semaphore signaller; - - auto callback = [&asset, &signaller](IStatObj* obj) - { - AsyncStatObjLoadCallback(asset, obj); - signaller.release(); - }; - - gEnv->p3DEngine->LoadStatObjAsync(callback, assetPath); - signaller.acquire(); - } - else - { - AsyncStatObjLoadCallback(asset, gEnv->p3DEngine->LoadStatObjAutoRef(assetPath)); - } - } - else - { - _smart_ptr statObj = gEnv->p3DEngine->LoadStatObjAutoRef(assetPath); - - if (statObj) - { - meshAsset->m_statObj = statObj; - } - else - { -#if defined(AZ_ENABLE_TRACING) - AZStd::string assetDescription = asset.GetId().ToString(); - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetDescription, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetPathById, asset.GetId()); - AZ_Error("MeshAssetHandler", false, "Failed to load mesh asset \"%s\".", assetDescription.c_str()); -#endif // AZ_ENABLE_TRACING - } - } - - return AZ::Data::AssetHandler::LoadResult::LoadComplete; - } - return AZ::Data::AssetHandler::LoadResult::Error; - } - - void MeshAssetHandler::DestroyAsset(AZ::Data::AssetPtr ptr) - { - delete ptr; - } - - void MeshAssetHandler::GetHandledAssetTypes(AZStd::vector& assetTypes) - { - assetTypes.push_back(AZ::AzTypeInfo::Uuid()); - } - - void MeshAssetHandler::Register() - { - AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!"); - AZ::Data::AssetManager::Instance().RegisterHandler(this, AZ::AzTypeInfo::Uuid()); - - AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid()); - } - - void MeshAssetHandler::Unregister() - { - AZ::AssetTypeInfoBus::Handler::BusDisconnect(AZ::AzTypeInfo::Uuid()); - - if (AZ::Data::AssetManager::IsReady()) - { - AZ::Data::AssetManager::Instance().UnregisterHandler(this); - } - } - - AZ::Data::AssetType MeshAssetHandler::GetAssetType() const - { - return AZ::AzTypeInfo::Uuid(); - } - - const char* MeshAssetHandler::GetAssetTypeDisplayName() const - { - return "Static Mesh"; - } - - const char* MeshAssetHandler::GetGroup() const - { - return "Geometry"; - } - - const char* MeshAssetHandler::GetBrowserIcon() const - { - return "Icons/Components/StaticMesh.svg"; - } - - AZ::Uuid MeshAssetHandler::GetComponentTypeId() const - { - return AZ::Uuid("{FC315B86-3280-4D03-B4F0-5553D7D08432}"); - } - - void MeshAssetHandler::GetAssetTypeExtensions(AZStd::vector& extensions) - { - extensions.push_back(CRY_GEOMETRY_FILE_EXT); - } - - GeomCacheAssetHandler::~GeomCacheAssetHandler() - { - Unregister(); - } - - AZ::Data::AssetPtr GeomCacheAssetHandler::CreateAsset([[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) - { - (void)type; - - AZ_Assert(type == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We handle only 'GeomCacheAsset'"); - - return aznew GeomCacheAsset(); - } - - void GeomCacheAssetHandler::GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo) - { - // The GeomCache system only takes in a file name for loading, not a memory buffer. - // If we set our stream data length to 0, the asset system will skip any file I/O for reading the data, and will instead - // go directly into the AssetHandler for processing. - streamInfo.m_dataLen = 0; - } - - AZ::Data::AssetHandler::LoadResult GeomCacheAssetHandler::LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& /*assetLoadFilterCB*/) - { - const char* assetPath = stream->GetFilename(); - - AZ_Assert(asset.GetType() == AZ::AzTypeInfo::Uuid(), "Invalid asset type! We only load 'GeomCacheAsset'"); - if (GeomCacheAsset* geomCacheAsset = asset.GetAs()) - { - AZ_Assert(!geomCacheAsset->m_geomCache.get(), "Attempting to create geom cache without cleaning up the old one."); - - // Strip the alias. GeomCache instances are stored in a dictionary by their path, - // so to share instances with legacy cry entities, we need to use the same un-aliased format. - StripAssetAlias(assetPath); - - //Load GeomCaches synchronously, there is no Async support currently in the 3DEngine. - //Assets can stream asynchronously but this load step must be synchronous. - - _smart_ptr geomCache = gEnv->p3DEngine->LoadGeomCache(assetPath); - - if (geomCache) - { - geomCache->SetProcessedByRenderNode(false); - geomCacheAsset->m_geomCache = geomCache; - } - else - { -#if defined(AZ_ENABLE_TRACING) - AZStd::string assetDescription = asset.ToString(); - AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetDescription, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetPathById, asset.GetId()); - AZ_Error("GeomCacheAssetHandler", false, "Failed to load geom cache asset %s", assetDescription.c_str()); -#endif // AZ_ENABLE_TRACING - } - - return AZ::Data::AssetHandler::LoadResult::LoadComplete; - } - return AZ::Data::AssetHandler::LoadResult::Error; - } - - void GeomCacheAssetHandler::DestroyAsset(AZ::Data::AssetPtr ptr) - { - delete ptr; - } - - void GeomCacheAssetHandler::GetHandledAssetTypes(AZStd::vector& assetTypes) - { - assetTypes.push_back(AZ::AzTypeInfo::Uuid()); - } - - void GeomCacheAssetHandler::Register() - { - AZ_Assert(AZ::Data::AssetManager::IsReady(), "Asset manager isn't ready!"); - AZ::Data::AssetManager::Instance().RegisterHandler(this, AZ::AzTypeInfo::Uuid()); - - AZ::AssetTypeInfoBus::Handler::BusConnect(AZ::AzTypeInfo::Uuid()); - } - - void GeomCacheAssetHandler::Unregister() - { - AZ::AssetTypeInfoBus::Handler::BusDisconnect(AZ::AzTypeInfo::Uuid()); - - if (AZ::Data::AssetManager::IsReady()) - { - AZ::Data::AssetManager::Instance().UnregisterHandler(this); - } - } - - AZ::Data::AssetType GeomCacheAssetHandler::GetAssetType() const - { - return AZ::AzTypeInfo::Uuid(); - } - - const char* GeomCacheAssetHandler::GetAssetTypeDisplayName() const - { - return "Geom Cache"; - } - - const char* GeomCacheAssetHandler::GetGroup() const - { - return "Geometry"; - } - - AZ::Uuid GeomCacheAssetHandler::GetComponentTypeId() const - { - return AZ::Uuid("{045C0C58-C13E-49B0-A471-D4AC5D3FC6BD}"); - } - - void GeomCacheAssetHandler::GetAssetTypeExtensions(AZStd::vector& extensions) - { - extensions.push_back(CRY_GEOM_CACHE_FILE_EXT); - } - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.h b/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.h deleted file mode 100644 index f0ccdf7410..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshAssetHandler.h +++ /dev/null @@ -1,133 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include - -struct ICVar; - -namespace LmbrCentral -{ - static const char* s_meshAssetHandler_AsyncCvar = "az_Asset_EnableAsyncMeshLoading"; - - /** - * Base class for mesh asset handlers. Contains shared utilities and functionality. - */ - class MeshAssetHandlerHelper - { - public: - - MeshAssetHandlerHelper(); - - protected: - - /** - * Removes the asset alias from a string - * - * StatObjs, CharacterInstances and GeometryCaches are stored in - * dictionaries by their path which is not aliased like the new AZ systems. - * To look up mesh instances we need the un-aliased path. - * - * This method assumes that the alias will be at the beginning of the string. - * - * @param assetPath The asset path string to remove the alias from - */ - void StripAssetAlias(const char*& assetPath); - - static const AZStd::string s_assetAliasToken; //< The token used to strip the asset alias in StripAssetAlias - - ICVar* GetAsyncLoadCVar(); - ICVar* m_asyncLoadCvar; - }; - - /** - * Handler for static mesh assets (cgf). - */ - class MeshAssetHandler - : public AZ::Data::AssetHandler - , public AZ::AssetTypeInfoBus::Handler - , private MeshAssetHandlerHelper - { - public: - - AZ_CLASS_ALLOCATOR(MeshAssetHandler, AZ::SystemAllocator, 0); - - ~MeshAssetHandler() override; - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetHandler - AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override; - void GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo) override; - AZ::Data::AssetHandler::LoadResult LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& assetLoadFilterCB) override; - AZ::Data::AssetId AssetMissingInCatalog(const AZ::Data::Asset& asset) override; - void DestroyAsset(AZ::Data::AssetPtr ptr) override; - void GetHandledAssetTypes(AZStd::vector& assetTypes) override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////////////////////////// - // AZ::AssetTypeInfoBus::Handler - AZ::Data::AssetType GetAssetType() const override; - const char* GetAssetTypeDisplayName() const override; - const char* GetGroup() const override; - const char* GetBrowserIcon() const override; - AZ::Uuid GetComponentTypeId() const override; - void GetAssetTypeExtensions(AZStd::vector& extensions) override; - ////////////////////////////////////////////////////////////////////////////////////////////// - - void Register(); - void Unregister(); - - AZ::Data::AssetId m_missingMeshAssetId; - }; - - /** - * Handler for Alembic Geometry Caches (cax) - */ - class GeomCacheAssetHandler - : public AZ::Data::AssetHandler - , public AZ::AssetTypeInfoBus::Handler - , private MeshAssetHandlerHelper - { - public: - - AZ_CLASS_ALLOCATOR(GeomCacheAssetHandler, AZ::SystemAllocator, 0); - - ~GeomCacheAssetHandler() override; - - // AZ::Data::AssetHandler - AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override; - void GetCustomAssetStreamInfoForLoad(AZ::Data::AssetStreamInfo& streamInfo) override; - AZ::Data::AssetHandler::LoadResult LoadAssetData( - const AZ::Data::Asset& asset, - AZStd::shared_ptr stream, - const AZ::Data::AssetFilterCB& assetLoadFilterCB) override; - void DestroyAsset(AZ::Data::AssetPtr ptr) override; - void GetHandledAssetTypes(AZStd::vector& assetTypes) override; - - // AZ::AssetTypeInfoBus::Handler - AZ::Data::AssetType GetAssetType() const override; - const char* GetAssetTypeDisplayName() const override; - const char* GetGroup() const override; - AZ::Uuid GetComponentTypeId() const override; - void GetAssetTypeExtensions(AZStd::vector& extensions) override; - - void Register(); - void Unregister(); - }; - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.cpp deleted file mode 100644 index 0ee72b62cf..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.cpp +++ /dev/null @@ -1,1228 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "LmbrCentral_precompiled.h" -#include "MeshComponent.h" -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include - -namespace LmbrCentral -{ - ////////////////////////////////////////////////////////////////////////// - - //! Handler/binding code that is required for Behavior Context reflection of EBus Notifications. - class MaterialOwnerNotificationBusBehaviorHandler : public MaterialOwnerNotificationBus::Handler, public AZ::BehaviorEBusHandler - { - public: - AZ_EBUS_BEHAVIOR_BINDER(MaterialOwnerNotificationBusBehaviorHandler, "{77705C0E-5ADE-496C-85FF-9278565E278E}", AZ::SystemAllocator - , OnMaterialOwnerReady); - - void OnMaterialOwnerReady() override - { - Call(FN_OnMaterialOwnerReady); - } - }; - - ////////////////////////////////////////////////////////////////////////// - - AZ::BehaviorParameterOverrides CreateMaterialIdDetails(AZ::BehaviorContext* behaviorContext) - { - return{ "MaterialID", "The ID of a Material slot to access, if the Owner has multiple Materials. IDs start at 1.", behaviorContext->MakeDefaultValue(1) }; - } - - AZStd::array GetMaterialParamArgs(AZ::BehaviorContext* behaviorContext) - { - AZ::BehaviorParameterOverrides getParamNameDetails = { "ParamName", "The name of the Material param to return" }; - return{ { getParamNameDetails, CreateMaterialIdDetails(behaviorContext) } }; - } - - void MeshComponent::Reflect(AZ::ReflectContext* context) - { - MeshComponentRenderNode::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Static Mesh Render Node", &MeshComponent::m_meshRenderNode); - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("MeshComponentRequestBus") - ->Event("SetVisibility", &MeshComponentRequestBus::Events::SetVisibility) - ->Event("GetVisibility", &MeshComponentRequestBus::Events::GetVisibility) - ->VirtualProperty("Visibility", "GetVisibility", "SetVisibility"); - - const char* setMaterialParamTooltip = "Sets a Material param value for the given Entity. The Material will be cloned once before any changes are applied, so other instances are not affected."; - const char* getMaterialParamTooltip = "Returns a Material param value for the given Entity"; - AZ::BehaviorParameterOverrides setParamNameDetails = { "ParamName", "The name of the Material param to set" }; - const char* newValueTooltip = "The new value to apply"; - - behaviorContext->EBus("MaterialOwnerRequestBus", nullptr, "Includes functions for Components that have a Material such as Mesh Component, Decal Component, etc.") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Event("IsMaterialOwnerReady", &MaterialOwnerRequestBus::Events::IsMaterialOwnerReady) - ->Attribute(AZ::Script::Attributes::ToolTip, "Indicates whether the Material Owner is fully initialized, and is ready for Material requests") - ->Event("SetMaterial", &MaterialOwnerRequestBus::Events::SetMaterialHandle) - ->Attribute(AZ::Script::Attributes::ToolTip, "Sets an Entity's Material") - ->Event("GetMaterial", &MaterialOwnerRequestBus::Events::GetMaterialHandle) - ->Attribute(AZ::Script::Attributes::ToolTip, "Returns an Entity's current Material") - ->Event("SetParamVector4", &MaterialOwnerRequestBus::Events::SetMaterialParamVector4, { { setParamNameDetails, { "Vector4", newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("SetParamVector3", &MaterialOwnerRequestBus::Events::SetMaterialParamVector3, { { setParamNameDetails, { "Vector3", newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("SetParamColor", &MaterialOwnerRequestBus::Events::SetMaterialParamColor, { { setParamNameDetails, { "Color" , newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("SetParamNumber", &MaterialOwnerRequestBus::Events::SetMaterialParamFloat, { { setParamNameDetails, { "Number" , newValueTooltip }, CreateMaterialIdDetails(behaviorContext) } }) // Using ParamNumber instead of ParamFloat because in Script Canvas all primitives are just "numbers" - ->Attribute(AZ::Script::Attributes::ToolTip, setMaterialParamTooltip) - ->Event("GetParamVector4", &MaterialOwnerRequestBus::Events::GetMaterialParamVector4, GetMaterialParamArgs(behaviorContext)) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Event("GetParamVector3", &MaterialOwnerRequestBus::Events::GetMaterialParamVector3, GetMaterialParamArgs(behaviorContext)) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Event("GetParamColor", &MaterialOwnerRequestBus::Events::GetMaterialParamColor, GetMaterialParamArgs(behaviorContext)) - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip) - ->Event("GetParamNumber", &MaterialOwnerRequestBus::Events::GetMaterialParamFloat, GetMaterialParamArgs(behaviorContext)) // Using ParamNumber instead of ParamFloat because in Script Canvas all primitives are just "numbers" - ->Attribute(AZ::Script::Attributes::ToolTip, getMaterialParamTooltip); - - behaviorContext->EBus("MaterialOwnerNotificationBus", nullptr, "Provides notifications from Components that have a Material such as Mesh Component, Decal Component, etc.") - ->Attribute(AZ::Script::Attributes::Category, "Rendering") - ->Handler() - ; - - behaviorContext->Class()->RequestBus("MeshComponentRequestBus"); - } - } - - - ////////////////////////////////////////////////////////////////////////// - - void MeshComponentRenderNode::MeshRenderOptions::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(5, &VersionConverter) - ->Field("Opacity", &MeshComponentRenderNode::MeshRenderOptions::m_opacity) - ->Field("MaxViewDistance", &MeshComponentRenderNode::MeshRenderOptions::m_maxViewDist) - ->Field("ViewDistanceMultiplier", &MeshComponentRenderNode::MeshRenderOptions::m_viewDistMultiplier) - ->Field("LODRatio", &MeshComponentRenderNode::MeshRenderOptions::m_lodRatio) - ->Field("CastShadows", &MeshComponentRenderNode::MeshRenderOptions::m_castShadows) - ->Field("LODBBoxBased", &MeshComponentRenderNode::MeshRenderOptions::m_lodBoundingBoxBased) - ->Field("UseVisAreas", &MeshComponentRenderNode::MeshRenderOptions::m_useVisAreas) - ->Field("RainOccluder", &MeshComponentRenderNode::MeshRenderOptions::m_rainOccluder) - ->Field("AffectDynamicWater", &MeshComponentRenderNode::MeshRenderOptions::m_affectDynamicWater) - ->Field("ReceiveWind", &MeshComponentRenderNode::MeshRenderOptions::m_receiveWind) - ->Field("AcceptDecals", &MeshComponentRenderNode::MeshRenderOptions::m_acceptDecals) - ->Field("AffectNavmesh", &MeshComponentRenderNode::MeshRenderOptions::m_affectNavmesh) - ->Field("VisibilityOccluder", &MeshComponentRenderNode::MeshRenderOptions::m_visibilityOccluder) - ->Field("DynamicMesh", &MeshComponentRenderNode::MeshRenderOptions::m_dynamicMesh) - ->Field("AffectsGI", &MeshComponentRenderNode::MeshRenderOptions::m_affectGI) - ; - } - } - - bool MeshComponentRenderNode::MeshRenderOptions::VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement) - { - // conversion from version 1: - // - Remove Bloom (m_allowBloom) - // - Remove MotionBlur (m_allowMotionBlur) - // - Remove DepthTest (m_depthTest) - if (classElement.GetVersion() <= 1) - { - classElement.RemoveElementByName(AZ_CRC("Bloom", 0xc6cd7d1b)); - classElement.RemoveElementByName(AZ_CRC("MotionBlur", 0x917cdb53)); - classElement.RemoveElementByName(AZ_CRC("DepthTest", 0x532f68b9)); - } - - // conversion from version 2: - // - Remove IndoorOnly (m_indoorOnly) - if (classElement.GetVersion() <= 2) - { - classElement.RemoveElementByName(AZ_CRC("IndoorOnly", 0xc8ab6ddb)); - } - - if (classElement.GetVersion() <= 3) - { - classElement.RemoveElementByName(AZ_CRC("CastLightmapShadows", 0x10ce0bf8)); - int index = classElement.FindElement(AZ_CRC("CastDynamicShadows", 0x55c75b43)); - AZ::SerializeContext::DataElementNode& shadowNode = classElement.GetSubElement(index); - shadowNode.SetName("CastShadows"); - } - - // conversion from version 4: - // - Set "CastShadows" to false if "Opacity" is less than 1.0f, in order to not break old assets. - // The new system ignores opacity for shadow casting and relies only on the "CastShadows" flag. - if (classElement.GetVersion() <= 4) - { - float opacity; - int opacityElementIndex = classElement.FindElement(AZ_CRC("Opacity", 0x43fd6d66)); - AZ::SerializeContext::DataElementNode& opacityNode = classElement.GetSubElement(opacityElementIndex); - opacityNode.GetData(opacity); - - if (opacity < 1.0f) - { - int castShadowsElementIndex = classElement.FindElement(AZ_CRC("CastShadows", 0xbe687463)); - AZ::SerializeContext::DataElementNode& castShadowsNode = classElement.GetSubElement(castShadowsElementIndex); - castShadowsNode.SetData(context, false); - } - } - - return true; - } - - bool MeshComponentRenderNode::MeshRenderOptions::IsStatic() const - { - return (m_hasStaticTransform && !m_dynamicMesh && !m_receiveWind); - } - - bool MeshComponentRenderNode::MeshRenderOptions::AffectsGi() const - { - return m_affectGI && IsStatic(); - } - - AZ::Crc32 MeshComponentRenderNode::MeshRenderOptions::StaticPropertyVisibility() const - { - return IsStatic() ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide; - } - - void MeshComponentRenderNode::Reflect(AZ::ReflectContext* context) - { - MeshRenderOptions::Reflect(context); - - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("Visible", &MeshComponentRenderNode::m_visible) - ->Field("Static Mesh", &MeshComponentRenderNode::m_meshAsset) - ->Field("Material Override", &MeshComponentRenderNode::m_material) - ->Field("Render Options", &MeshComponentRenderNode::m_renderOptions) - ; - } - } - - float MeshComponentRenderNode::GetDefaultMaxViewDist() - { - if (gEnv && gEnv->p3DEngine) - { - return gEnv->p3DEngine->GetMaxViewDistance(false); - } - - // In the editor and the game, the dynamic lookup above should *always* hit. - // This case essentially means no renderer (not even the null renderer) is present. - return FLT_MAX; - } - - MeshComponentRenderNode::MeshRenderOptions::MeshRenderOptions() - : m_opacity(1.f) - , m_viewDistMultiplier(1.f) - , m_lodRatio(100) - , m_useVisAreas(true) - , m_castShadows(true) - , m_lodBoundingBoxBased(false) - , m_rainOccluder(true) - , m_affectNavmesh(true) - , m_affectDynamicWater(false) - , m_acceptDecals(true) - , m_receiveWind(false) - , m_visibilityOccluder(false) - , m_dynamicMesh(false) - , m_hasStaticTransform(false) - , m_affectGI(true) - { - m_maxViewDist = GetDefaultMaxViewDist(); - } - - MeshComponentRenderNode::MeshComponentRenderNode() - : m_statObj(nullptr) - , m_materialOverride(nullptr) - , m_auxiliaryRenderFlags(0) - , m_auxiliaryRenderFlagsHistory(0) - , m_lodDistance(0.f) - , m_lodDistanceScaled(FLT_MAX / (SMeshLodInfo::s_nMaxLodCount + 1)) // defualt overflow prevention - it is scaled by (SMeshLodInfo::s_nMaxLodCount + 1) - , m_lodDistanceScaleValue(1.0f) - , m_isRegisteredWithRenderer(false) - , m_objectMoved(false) - , m_meshAsset(AZ::Data::AssetLoadBehavior::QueueLoad) - , m_visible(true) - { - m_localBoundingBox.Reset(); - m_worldBoundingBox.Reset(); - m_worldTransform = AZ::Transform::CreateIdentity(); - m_renderTransform = Matrix34::CreateIdentity(); - } - - MeshComponentRenderNode::~MeshComponentRenderNode() - { - DestroyMesh(); - } - - void MeshComponentRenderNode::CopyPropertiesTo(MeshComponentRenderNode& rhs) const - { - rhs.m_visible = m_visible; - rhs.m_materialOverride = m_materialOverride; - rhs.m_meshAsset = m_meshAsset; - rhs.m_material = m_material; - rhs.m_renderOptions = m_renderOptions; - } - - void MeshComponentRenderNode::AttachToEntity(AZ::EntityId id) - { - if (AZ::TransformNotificationBus::Handler::BusIsConnectedId(m_renderOptions.m_attachedToEntityId)) - { - AZ::TransformNotificationBus::Handler::BusDisconnect(m_renderOptions.m_attachedToEntityId); - } - - if (m_modificationHelper.IsConnected()) - { - m_modificationHelper.Disconnect(); - } - - if (id.IsValid()) - { - if (!AZ::TransformNotificationBus::Handler::BusIsConnectedId(id)) - { - AZ::TransformNotificationBus::Handler::BusConnect(id); - } - - auto transformHandler = AZ::TransformBus::FindFirstHandler(id); - - UpdateWorldTransform(transformHandler->GetWorldTM()); - - AzFramework::EntityBoundsUnionRequestBus::Broadcast( - &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId()); - - m_modificationHelper.Connect(id); - } - - m_renderOptions.m_attachedToEntityId = id; - } - - void MeshComponentRenderNode::OnAssetPropertyChanged() - { - if (HasMesh()) - { - DestroyMesh(); - } - - AZ::Data::AssetBus::Handler::BusDisconnect(); - - CreateMesh(); - AzFramework::RenderGeometry::IntersectionNotificationBus::Event(m_contextId, - &AzFramework::RenderGeometry::IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void MeshComponentRenderNode::RefreshRenderState() - { - if (gEnv->IsEditor()) - { - UpdateLocalBoundingBox(); - - AZ::Transform parentTransform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(parentTransform, m_renderOptions.m_attachedToEntityId, AZ::TransformBus, GetWorldTM); - OnTransformChanged(AZ::Transform::CreateIdentity(), parentTransform); - - if (HasMesh()) - { - // Re-register with the renderer, as some render settings/flags require it. - // Note that this is editor-only behavior (hence the guard above). - if (m_isRegisteredWithRenderer) - { - RegisterWithRenderer(false); - RegisterWithRenderer(true); - } - } - } - } - - void MeshComponentRenderNode::SetTransformStaticState(bool isStatic) - { - m_renderOptions.m_hasStaticTransform = isStatic; - } - - const AZ::Transform& MeshComponentRenderNode::GetTransform() const - { - return m_worldTransform; - } - - void MeshComponentRenderNode::SetAuxiliaryRenderFlags(uint32 flags) - { - m_auxiliaryRenderFlags = flags; - m_auxiliaryRenderFlagsHistory |= flags; - } - - void MeshComponentRenderNode::UpdateAuxiliaryRenderFlags(bool on, uint32 mask) - { - if (on) - { - m_auxiliaryRenderFlags |= mask; - } - else - { - m_auxiliaryRenderFlags &= ~mask; - } - - m_auxiliaryRenderFlagsHistory |= mask; - } - - bool MeshComponentRenderNode::IsReady() const - { - return HasMesh(); - } - - void MeshComponentRenderNode::CreateMesh() - { - if (m_meshAsset.GetId().IsValid()) - { - if (!AZ::Data::AssetBus::Handler::BusIsConnected()) - { - AZ::Data::AssetBus::Handler::BusConnect(m_meshAsset.GetId()); - } - - m_meshAsset.QueueLoad(); - } - } - - void MeshComponentRenderNode::DestroyMesh() - { - AZ::Data::AssetBus::Handler::BusDisconnect(); - - RegisterWithRenderer(false); - m_statObj = nullptr; - - EBUS_EVENT_ID(m_renderOptions.m_attachedToEntityId, MeshComponentNotificationBus, OnMeshDestroyed); - - m_meshAsset.Release(); - } - - bool MeshComponentRenderNode::HasMesh() const - { - return m_statObj != nullptr; - } - - void MeshComponentRenderNode::SetMeshAsset(const AZ::Data::AssetId& id) - { - AZ::Data::Asset asset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(id, m_meshAsset.GetAutoLoadBehavior()); - - if (asset) - { - m_meshAsset = asset; - OnAssetPropertyChanged(); - } - } - - void MeshComponentRenderNode::GetMemoryUsage(class ICrySizer* pSizer) const - { - pSizer->AddObjectSize(this); - } - - float MeshComponentRenderNode::GetUniformScale() - { - AZ::Vector3 scales = m_worldTransform.GetScale(); - AZ_Assert((scales.GetX() == scales.GetY()) && (scales.GetY() == scales.GetZ()), "Scales are not uniform"); - return scales.GetX(); - } - - float MeshComponentRenderNode::GetColumnScale(int column) - { - return m_worldTransform.GetScale().GetElement(column); - } - - void MeshComponentRenderNode::OnTransformChanged(const AZ::Transform&, const AZ::Transform& parentWorld) - { - // The entity to which we're attached has moved. - UpdateWorldTransform(parentWorld); - AzFramework::RenderGeometry::IntersectionNotificationBus::Event(m_contextId, - &AzFramework::RenderGeometry::IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - - void MeshComponentRenderNode::OnAssetReady(AZ::Data::Asset asset) - { - if (asset == m_meshAsset) - { - m_meshAsset = asset; - BuildRenderMesh(); - - if (HasMesh()) - { - const AZStd::string& materialOverridePath = m_material.GetAssetPath(); - if (!materialOverridePath.empty()) - { - m_materialOverride = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(materialOverridePath.c_str()); - - AZ_Warning("MeshComponent", m_materialOverride != gEnv->p3DEngine->GetMaterialManager()->GetDefaultMaterial(), - "Failed to load override Material \"%s\".", - materialOverridePath.c_str()); - } - else - { - m_materialOverride = nullptr; - } - - UpdateLocalBoundingBox(); - UpdateLodDistance(gEnv->p3DEngine->GetFrameLodInfo()); - RegisterWithRenderer(true); - - // Inform listeners that the mesh has been changed - LmbrCentral::MeshComponentNotificationBus::Event(m_renderOptions.m_attachedToEntityId, &LmbrCentral::MeshComponentNotifications::OnMeshCreated, asset); - AzFramework::RenderGeometry::IntersectionNotificationBus::Event(m_contextId, &AzFramework::RenderGeometry::IntersectionNotifications::OnGeometryChanged, GetEntityId()); - } - } - } - - void MeshComponentRenderNode::OnAssetReloaded(AZ::Data::Asset asset) - { - // note that this also corrects the assetId if it is incorrect - do not remove the following line - // even if you call OnAssetReady - OnAssetReady(asset); - } - - void MeshComponentRenderNode::UpdateWorldTransform(const AZ::Transform& entityTransform) - { - m_worldTransform = entityTransform; - - m_renderTransform = AZTransformToLYTransform(m_worldTransform); - - UpdateWorldBoundingBox(); - if (m_isRegisteredWithRenderer && m_renderOptions.AffectsGi()) - { - GiRegistrationBus::Broadcast(&GiRegistration::UpsertToGi, - m_renderOptions.m_attachedToEntityId, - m_worldTransform, - CalculateWorldAABB(), - m_meshAsset, - GetMaterial()); - } - - m_objectMoved = true; - } - - void MeshComponentRenderNode::UpdateLocalBoundingBox() - { - m_localBoundingBox.Reset(); - - if (HasMesh()) - { - m_localBoundingBox.Add(m_statObj->GetAABB()); - } - - AzFramework::EntityBoundsUnionRequestBus::Broadcast( - &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId()); - - UpdateWorldBoundingBox(); - } - - void MeshComponentRenderNode::UpdateWorldBoundingBox() - { - m_worldBoundingBox.SetTransformedAABB(m_renderTransform, m_localBoundingBox); - - if (m_isRegisteredWithRenderer) - { - // Re-register with the renderer to update culling info - gEnv->p3DEngine->RegisterEntity(this); - } - } - - void MeshComponentRenderNode::SetVisible(bool isVisible) - { - if (m_visible != isVisible) - { - m_visible = isVisible; - RegisterWithRenderer(false); - RegisterWithRenderer(true); - } - } - - bool MeshComponentRenderNode::GetVisible() - { - return m_visible; - } - - void MeshComponentRenderNode::RegisterWithRenderer(bool registerWithRenderer) - { - if (gEnv && gEnv->p3DEngine) - { - if (registerWithRenderer) - { - if (!m_isRegisteredWithRenderer) - { - ApplyRenderOptions(); - - gEnv->p3DEngine->RegisterEntity(this); - - if (m_renderOptions.AffectsGi()) - { - GiRegistrationBus::Broadcast(&GiRegistration::UpsertToGi, - m_renderOptions.m_attachedToEntityId, - m_worldTransform, - CalculateWorldAABB(), - m_meshAsset, - GetMaterial()); - } - - m_isRegisteredWithRenderer = true; - } - } - else - { - if (m_isRegisteredWithRenderer) - { - gEnv->p3DEngine->FreeRenderNodeState(this); - - GiRegistrationBus::Broadcast(&GiRegistration::RemoveFromGi, - m_renderOptions.m_attachedToEntityId); - - m_isRegisteredWithRenderer = false; - } - } - } - } - - namespace MeshInternal - { - void UpdateRenderFlag(bool enable, int mask, unsigned int& flags) - { - if (enable) - { - flags |= mask; - } - else - { - flags &= ~mask; - } - } - } - - void MeshComponentRenderNode::ApplyRenderOptions() - { - using MeshInternal::UpdateRenderFlag; - unsigned int flags = GetRndFlags(); - flags |= ERF_COMPONENT_ENTITY; - - // Turn off any flag which has ever been set via auxiliary render flags - UpdateRenderFlag(false, m_auxiliaryRenderFlagsHistory, flags); - - // Update flags according to current render settings - UpdateRenderFlag(m_renderOptions.m_useVisAreas == false, ERF_OUTDOORONLY, flags); - UpdateRenderFlag(m_renderOptions.m_castShadows, ERF_CASTSHADOWMAPS | ERF_HAS_CASTSHADOWMAPS, flags); - UpdateRenderFlag(m_renderOptions.m_rainOccluder && m_renderOptions.IsStatic(), ERF_RAIN_OCCLUDER, flags); - UpdateRenderFlag(m_visible == false, ERF_HIDDEN, flags); - UpdateRenderFlag(m_renderOptions.m_receiveWind, ERF_RECVWIND, flags); - UpdateRenderFlag(m_renderOptions.m_visibilityOccluder && m_renderOptions.IsStatic(), ERF_GOOD_OCCLUDER, flags); - //Dynamic meshes shouldn't affect the navmeshes. If that decision is changed we should change this line to no longer require - //static and note that the flag is tied to the negation of the navemesh boolean. - //Also see the editormeshcomponent.cpp AffectNavemesh function. - UpdateRenderFlag(!(m_renderOptions.m_affectNavmesh && m_renderOptions.IsStatic()), ERF_EXCLUDE_FROM_TRIANGULATION, flags); - UpdateRenderFlag(false == m_renderOptions.m_affectDynamicWater && m_renderOptions.IsStatic(), ERF_NODYNWATER, flags); - UpdateRenderFlag(false == m_renderOptions.m_acceptDecals, ERF_NO_DECALNODE_DECALS, flags); - - UpdateRenderFlag(m_renderOptions.m_lodBoundingBoxBased, ERF_LOD_BBOX_BASED, flags); - - // Apply current auxiliary render flags - UpdateRenderFlag(true, m_auxiliaryRenderFlags, flags); - - m_fWSMaxViewDist = m_renderOptions.m_maxViewDist; - - SetViewDistanceMultiplier(m_renderOptions.m_viewDistMultiplier); - - SetLodRatio(static_cast(m_renderOptions.m_lodRatio)); - - SetRndFlags(flags); - } - - CLodValue MeshComponentRenderNode::ComputeLOD( int wantedLod, const SRenderingPassInfo& passInfo) - { - // Default values as per the CVar - default fade going between 2 and 8 meters with dissolve enabled - float dissolveDistMin = 2.0f; - float dissolveDistMax = 8.0f; - int dissolveEnabled = 1; - - if (gEnv && gEnv->pConsole) - { - static ICVar* dissolveDistMinCvar = gEnv->pConsole->GetCVar("e_DissolveDistMin"); - static ICVar* dissolveDistMaxCvar = gEnv->pConsole->GetCVar("e_DissolveDistMax"); - static ICVar* dissolveEnabledCvar = gEnv->pConsole->GetCVar("e_Dissolve"); - - dissolveDistMin = dissolveDistMinCvar->GetFVal(); - dissolveDistMax = dissolveDistMaxCvar->GetFVal(); - dissolveEnabled = dissolveEnabledCvar->GetIVal() ; - } - - const Vec3 cameraPos = passInfo.GetCamera().GetPosition(); - const float entityDistance = sqrt_tpl(Distance::Point_AABBSq(cameraPos, GetBBox())) * passInfo.GetZoomFactor(); - - wantedLod = CLAMP(wantedLod, m_statObj->GetMinUsableLod(), SMeshLodInfo::s_nMaxLodCount); - int currentLod = m_statObj->FindNearesLoadedLOD(wantedLod, true); - - if (dissolveEnabled && passInfo.IsGeneralPass()) - { - float invDissolveDist = 1.0f / CLAMP(0.1f * m_fWSMaxViewDist, dissolveDistMin, dissolveDistMax ); - int nextLod = m_statObj->FindNearesLoadedLOD(currentLod + 1, true); - - // If the user chose to base LOD switch on bounding boxes, then we do not use the geometric mean computed at init. - if (GetRndFlags() & ERF_LOD_BBOX_BASED) - { - const float lodRatio = GetLodRatioNormalized(); - if (lodRatio > 0.0f) - { - // We do not use a geometric mean per object but a global value for all objects. - static ICVar* lodBoundingBoxDistanceMultiplier = gEnv->pConsole->GetCVar("e_LodBoundingBoxDistanceMultiplier"); - - m_lodDistanceScaled = lodBoundingBoxDistanceMultiplier->GetFVal() * m_lodDistanceScaleValue; - } - } - else - { - m_lodDistanceScaled = m_lodDistance * m_lodDistanceScaleValue; - } - - float lodDistance = m_lodDistanceScaled * (currentLod + 1); - uint8 dissolveRatio255 = (uint8)SATURATEB((1.0f + (entityDistance - lodDistance) * invDissolveDist) * 255.f); - - if (dissolveRatio255 == 255) - { - return CLodValue(nextLod, 0, -1); - } - return CLodValue(currentLod, dissolveRatio255, nextLod); - } - - return CLodValue(currentLod); - } - - AZ::Aabb MeshComponentRenderNode::CalculateWorldAABB() const - { - AZ::Aabb aabb = AZ::Aabb::CreateNull(); - if (!m_worldBoundingBox.IsReset()) - { - aabb.AddPoint(LYVec3ToAZVec3(m_worldBoundingBox.min)); - aabb.AddPoint(LYVec3ToAZVec3(m_worldBoundingBox.max)); - } - return aabb; - } - - AZ::Aabb MeshComponentRenderNode::CalculateLocalAABB() const - { - AZ::Aabb aabb = AZ::Aabb::CreateNull(); - if (!m_localBoundingBox.IsReset()) - { - aabb.AddPoint(LYVec3ToAZVec3(m_localBoundingBox.min)); - aabb.AddPoint(LYVec3ToAZVec3(m_localBoundingBox.max)); - } - return aabb; - } - - /*IRenderNode*/ void MeshComponentRenderNode::Render(const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo) - { - if (!HasMesh()) - { - return; - } - - if (!m_modificationHelper.GetMeshModified()) - { - IStatObj* obj = GetEntityStatObj(); - int subObjectCount = obj->GetSubObjectCount(); - - AZStd::function getSubObject; - if (subObjectCount == 0) - { - getSubObject = [obj](size_t index) - { - if (index > 0) - { - AZ_Warning("MeshComponentRenderNode", false, "Mesh indices out of range"); - return static_cast(nullptr); - } - return obj; - }; - } - else - { - getSubObject = [obj, subObjectCount](size_t index) - { - if (index >= subObjectCount) - { - AZ_Warning("MeshComponentRenderNode", false, "Mesh indices out of range"); - return static_cast(nullptr); - } - return obj->GetSubObject(index)->pStatObj; - }; - } - - for (const LmbrCentral::MeshModificationRequestHelper::MeshLODPrimIndex& meshIndices : m_modificationHelper.MeshesToEdit()) - { - if (meshIndices.lodIndex != 0) - { - continue; - } - - IStatObj* subObject = getSubObject(meshIndices.primitiveIndex); - if (!subObject) - { - continue; - } - - MeshModificationNotificationBus::Event( - GetEntityId(), - &MeshModificationNotificationBus::Events::ModifyMesh, - meshIndices.lodIndex, - meshIndices.primitiveIndex, - subObject->GetRenderMesh()); - } - - m_modificationHelper.SetMeshModified(true); - } - - SRendParams rParams(inRenderParams); - - // Assign a unique pInstance pointer, otherwise effects involving SRenderObjData will not work for this object. CEntityObject::Render does this for legacy entities. - rParams.pInstance = this; - - rParams.fAlpha = m_renderOptions.m_opacity; - - _smart_ptr previousMaterial = rParams.pMaterial; - const int previousObjectFlags = rParams.dwFObjFlags; - - if (m_materialOverride) - { - rParams.pMaterial = m_materialOverride; - } - - if (m_objectMoved) - { - rParams.dwFObjFlags |= FOB_DYNAMIC_OBJECT; - m_objectMoved = false; - } - - rParams.pMatrix = &m_renderTransform; - rParams.bForceDrawStatic = !m_renderOptions.m_dynamicMesh; - if (rParams.pMatrix->IsValid()) - { - rParams.lodValue = ComputeLOD(inRenderParams.lodValue.LodA(), passInfo); - m_statObj->Render(rParams, passInfo); - } - - rParams.pMaterial = previousMaterial; - rParams.dwFObjFlags = previousObjectFlags; - } - - /*IRenderNode*/ bool MeshComponentRenderNode::GetLodDistances(const SFrameLodInfo& frameLodInfo, float* distances) const - { - const float lodRatio = GetLodRatioNormalized(); - if (lodRatio > 0.0f) - { - const float distMultiplier = 1.f / (lodRatio * frameLodInfo.fTargetSize); - - for (int lodIndex = 0; lodIndex < SMeshLodInfo::s_nMaxLodCount; ++lodIndex) - { - distances[lodIndex] = m_lodDistance * (lodIndex + 1) * distMultiplier; - } - } - else - { - for (int lodIndex = 0; lodIndex < SMeshLodInfo::s_nMaxLodCount; ++lodIndex) - { - distances[lodIndex] = FLT_MAX; - } - } - return true; - } - - void MeshComponentRenderNode::UpdateLodDistance(const SFrameLodInfo& frameLodInfo) - { - SMeshLodInfo lodInfo; - - if (HasMesh()) - { - m_statObj->ComputeGeometricMean(lodInfo); - } - - m_lodDistance = sqrt(lodInfo.fGeometricMean); - - // The following computation need to stay in accordance with the 'GetLodDistances' formula. - const float lodRatio = GetLodRatioNormalized(); - if (lodRatio > 0.0f) - { - m_lodDistanceScaled = m_lodDistance / (lodRatio * frameLodInfo.fTargetSize); - m_lodDistanceScaleValue = 1.0f / (lodRatio * frameLodInfo.fTargetSize); - } - } - - /*IRenderNode*/ EERType MeshComponentRenderNode::GetRenderNodeType() - { - return m_renderOptions.IsStatic() ? eERType_StaticMeshRenderComponent : eERType_DynamicMeshRenderComponent; - } - - /*IRenderNode*/ bool MeshComponentRenderNode::CanExecuteRenderAsJob() - { - return !m_renderOptions.m_dynamicMesh - && !m_renderOptions.m_receiveWind - && m_modificationHelper.MeshesToEdit().empty(); - } - - /*IRenderNode*/ const char* MeshComponentRenderNode::GetName() const - { - return "MeshComponentRenderNode"; - } - - /*IRenderNode*/ const char* MeshComponentRenderNode::GetEntityClassName() const - { - return "MeshComponentRenderNode"; - } - - /*IRenderNode*/ Vec3 MeshComponentRenderNode::GetPos([[maybe_unused]] bool bWorldOnly /*= true*/) const - { - return m_renderTransform.GetTranslation(); - } - - /*IRenderNode*/ const AABB MeshComponentRenderNode::GetBBox() const - { - return m_worldBoundingBox; - } - - /*IRenderNode*/ void MeshComponentRenderNode::SetBBox(const AABB& WSBBox) - { - m_worldBoundingBox = WSBBox; - } - - /*IRenderNode*/ void MeshComponentRenderNode::OffsetPosition(const Vec3& delta) - { - // Recalculate local transform - AZ::Transform localTransform = AZ::Transform::CreateIdentity(); - EBUS_EVENT_ID_RESULT(localTransform, m_renderOptions.m_attachedToEntityId, AZ::TransformBus, GetLocalTM); - - localTransform.SetTranslation(localTransform.GetTranslation() + LYVec3ToAZVec3(delta)); - EBUS_EVENT_ID(m_renderOptions.m_attachedToEntityId, AZ::TransformBus, SetLocalTM, localTransform); - - m_objectMoved = true; - } - - /*IRenderNode*/ void MeshComponentRenderNode::SetMaterial(_smart_ptr pMat) - { - m_materialOverride = pMat; - - if (pMat) - { - m_material.SetAssetPath(pMat->GetName()); - } - else - { - // If no material is provided, we intend to reset to the original material so we treat - // it as an asset reset to recreate the mesh. - m_material.SetAssetPath(""); - OnAssetPropertyChanged(); - } - } - - /*IRenderNode*/ _smart_ptr MeshComponentRenderNode::GetMaterial([[maybe_unused]] Vec3* pHitPos /*= nullptr*/) - { - if (m_materialOverride) - { - return m_materialOverride; - } - - if (HasMesh()) - { - return m_statObj->GetMaterial(); - } - - return nullptr; - } - - /*IRenderNode*/ _smart_ptr MeshComponentRenderNode::GetMaterialOverride() - { - return m_materialOverride; - } - - /*IRenderNode*/ float MeshComponentRenderNode::GetMaxViewDist() - { - return(m_renderOptions.m_maxViewDist * 0.75f * GetViewDistanceMultiplier()); - } - - /*IRenderNode*/ IStatObj* MeshComponentRenderNode::GetEntityStatObj(unsigned int nPartId, [[maybe_unused]] unsigned int nSubPartId, Matrix34A* pMatrix, [[maybe_unused]] bool bReturnOnlyVisible) - { - if (0 == nPartId) - { - if (pMatrix) - { - *pMatrix = m_renderTransform; - } - - return m_statObj; - } - - return nullptr; - } - - /*IRenderNode*/ _smart_ptr MeshComponentRenderNode::GetEntitySlotMaterial(unsigned int nPartId, [[maybe_unused]] bool bReturnOnlyVisible, [[maybe_unused]] bool* pbDrawNear) - { - if (0 == nPartId) - { - return m_materialOverride; - } - - return nullptr; - } - - ////////////////////////////////////////////////////////////////////////// - // MeshComponent - const float MeshComponent::s_renderNodeRequestBusOrder = 100.f; - - MeshComponent::MeshComponent() - { - m_materialBusHandler = aznew MaterialOwnerRequestBusHandlerImpl(); - } - - MeshComponent::~MeshComponent() - { - delete m_materialBusHandler; - } - - void MeshComponent::Activate() - { - m_meshRenderNode.AttachToEntity(m_entity->GetId()); - m_materialBusHandler->Activate(&m_meshRenderNode, m_entity->GetId()); - bool isStatic = false; - AZ::TransformBus::EventResult(isStatic, m_entity->GetId(), &AZ::TransformBus::Events::IsStaticTransform); - m_meshRenderNode.SetTransformStaticState(isStatic); - // Note we are purposely connecting to buses before calling m_mesh.CreateMesh(). - // m_mesh.CreateMesh() can result in events (eg: OnMeshCreated) that we want receive. - MaterialOwnerRequestBus::Handler::BusConnect(m_entity->GetId()); - MeshComponentRequestBus::Handler::BusConnect(m_entity->GetId()); - AzFramework::BoundsRequestBus::Handler::BusConnect(m_entity->GetId()); - RenderNodeRequestBus::Handler::BusConnect(m_entity->GetId()); - AzFramework::EntityContextId contextId; - AzFramework::EntityIdContextQueryBus::EventResult(contextId, GetEntityId(), &AzFramework::EntityIdContextQueries::GetOwningContextId); - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusConnect({ GetEntityId(), contextId }); - m_meshRenderNode.SetContextId(contextId); - m_meshRenderNode.CreateMesh(); - LegacyMeshComponentRequestBus::Handler::BusConnect(GetEntityId()); - } - - void MeshComponent::Deactivate() - { - AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusDisconnect(); - - MeshComponentRequestBus::Handler::BusDisconnect(); - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - MaterialOwnerRequestBus::Handler::BusDisconnect(); - LegacyMeshComponentRequestBus::Handler::BusDisconnect(); - RenderNodeRequestBus::Handler::BusDisconnect(); - - m_meshRenderNode.DestroyMesh(); - m_meshRenderNode.AttachToEntity(AZ::EntityId()); - m_materialBusHandler->Deactivate(); - } - - AZ::Aabb MeshComponent::GetWorldBounds() - { - return m_meshRenderNode.CalculateWorldAABB(); - } - - AZ::Aabb MeshComponent::GetLocalBounds() - { - return m_meshRenderNode.CalculateLocalAABB(); - } - - void MeshComponent::SetMeshAsset(const AZ::Data::AssetId& id) - { - m_meshRenderNode.SetMeshAsset(id); - } - - bool MeshComponent::IsMaterialOwnerReady() - { - return m_materialBusHandler->IsMaterialOwnerReady(); - } - - void MeshComponent::SetMaterial(_smart_ptr material) - { - m_materialBusHandler->SetMaterial(material); - } - - _smart_ptr MeshComponent::GetMaterial() - { - return m_materialBusHandler->GetMaterial(); - } - - void MeshComponent::SetMaterialHandle(const MaterialHandle& materialHandle) - { - m_materialBusHandler->SetMaterialHandle(materialHandle); - } - - MaterialHandle MeshComponent::GetMaterialHandle() - { - return m_materialBusHandler->GetMaterialHandle(); - } - - void MeshComponent::SetMaterialParamVector4(const AZStd::string& name, const AZ::Vector4& value, int materialId) - { - m_materialBusHandler->SetMaterialParamVector4(name, value, materialId); - } - - void MeshComponent::SetMaterialParamVector3(const AZStd::string& name, const AZ::Vector3& value, int materialId) - { - m_materialBusHandler->SetMaterialParamVector3(name, value, materialId); - } - - void MeshComponent::SetMaterialParamColor(const AZStd::string& name, const AZ::Color& value, int materialId) - { - m_materialBusHandler->SetMaterialParamColor(name, value, materialId); - } - - void MeshComponent::SetMaterialParamFloat(const AZStd::string& name, float value, int materialId) - { - m_materialBusHandler->SetMaterialParamFloat(name, value, materialId); - } - - AZ::Vector4 MeshComponent::GetMaterialParamVector4(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamVector4(name, materialId); - } - - AZ::Vector3 MeshComponent::GetMaterialParamVector3(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamVector3(name, materialId); - } - - AZ::Color MeshComponent::GetMaterialParamColor(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamColor(name, materialId); - } - - float MeshComponent::GetMaterialParamFloat(const AZStd::string& name, int materialId) - { - return m_materialBusHandler->GetMaterialParamFloat(name, materialId); - } - - IRenderNode* MeshComponent::GetRenderNode() - { - return &m_meshRenderNode; - } - - float MeshComponent::GetRenderNodeRequestBusOrder() const - { - return s_renderNodeRequestBusOrder; - } - - IStatObj* MeshComponent::GetStatObj() - { - return m_meshRenderNode.GetEntityStatObj(); - } - - AzFramework::RenderGeometry::RayResult MeshComponent::RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) - { - AzFramework::RenderGeometry::RayResult result; - if (!GetVisibility() && ray.m_onlyVisible) - { - return result; - } - - if (IStatObj* geometry = GetStatObj()) - { - const AZ::Vector3 rayDirection = (ray.m_endWorldPosition - ray.m_startWorldPosition); - const AZ::Transform& transform = m_meshRenderNode.GetTransform(); - const AZ::Transform inverseTransform = transform.GetInverse(); - - const AZ::Vector3 rayStartLocal = inverseTransform.TransformPoint(ray.m_startWorldPosition); - const AZ::Vector3 rayDistNormLocal = inverseTransform.TransformVector(rayDirection).GetNormalized(); - - SRayHitInfo hi; - hi.inReferencePoint = AZVec3ToLYVec3(rayStartLocal); - hi.inRay = Ray(hi.inReferencePoint, AZVec3ToLYVec3(rayDistNormLocal)); - hi.bInFirstHit = true; - hi.bGetVertColorAndTC = true; - if (geometry->RayIntersection(hi)) - { - AZ::Matrix3x4 invTransformMatrix = AZ::Matrix3x4::CreateFromTransform(inverseTransform); - invTransformMatrix.Transpose(); - - result.m_uv = LYVec2ToAZVec2(hi.vHitTC); - result.m_worldPosition = transform.TransformPoint(LYVec3ToAZVec3(hi.vHitPos)); - result.m_worldNormal = invTransformMatrix.Multiply3x3(LYVec3ToAZVec3(hi.vHitNormal)).GetNormalized(); - result.m_distance = (result.m_worldPosition - ray.m_startWorldPosition).GetLength(); - result.m_entityAndComponent = { GetEntityId(), GetId() }; - } - } - return result; - } - - bool MeshComponent::GetVisibility() - { - return m_meshRenderNode.GetVisible(); - } - - void MeshComponent::SetVisibility(bool isVisible) - { - m_meshRenderNode.SetVisible(isVisible); - } - - void MeshComponentRenderNode::BuildRenderMesh() - { - m_statObj = nullptr; // Release smart pointer - - MeshAsset* data = m_meshAsset.Get(); - if (!data || !data->m_statObj) - { - return; - } - - // Populate m_statObj. If the mesh doesn't require to be unique, we reuse the render mesh from the asset. If the - // mesh requires to be unique, we create a copy of the asset's render mesh since it will be modified. - - bool hasClothData = !data->m_statObj->GetClothData().empty(); - const int subObjectCount = data->m_statObj->GetSubObjectCount(); - for (int i = 0; i < subObjectCount && !hasClothData; ++i) - { - IStatObj::SSubObject* subObject = data->m_statObj->GetSubObject(i); - if (subObject && - subObject->pStatObj && - !subObject->pStatObj->GetClothData().empty()) - { - hasClothData = true; - } - } - - bool useUniqueMesh = hasClothData; - - if (useUniqueMesh) - { - // Create a copy since each mesh can be deforming differently and we need to send different meshes to render - m_statObj = data->m_statObj->Clone( /*bCloneGeometry*/ true, /*bCloneChildren*/ true, /*bMeshesOnly*/ false); - } - else - { - // Reuse the same render mesh - m_statObj = data->m_statObj; - } - } -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.h b/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.h deleted file mode 100644 index f7a7f5d861..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/MeshComponent.h +++ /dev/null @@ -1,393 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace LmbrCentral -{ - class MaterialOwnerRequestBusHandlerImpl; - - /*! - * RenderNode implementation responsible for integrating with the renderer. - * The node owns render flags, the mesh instance, and the render transform. - */ - class MeshComponentRenderNode - : public IRenderNode - , public AZ::TransformNotificationBus::Handler - , public AZ::Data::AssetBus::Handler - { - friend class EditorMeshComponent; - public: - using MaterialPtr = _smart_ptr < IMaterial > ; - using MeshPtr = _smart_ptr < IStatObj > ; - - AZ_TYPE_INFO(MeshComponentRenderNode, "{46FF2BC4-BEF9-4CC4-9456-36C127C310D7}"); - - MeshComponentRenderNode(); - ~MeshComponentRenderNode() override; - - void CopyPropertiesTo(MeshComponentRenderNode& rhs) const; - - //! Notifies render node which entity owns it, for subscribing to transform - //! bus, etc. - void AttachToEntity(AZ::EntityId id); - - //! Returns true after all required assets are loaded - bool IsReady() const override; - - //! Instantiate mesh instance. - void CreateMesh(); - - //! Destroy mesh instance. - void DestroyMesh(); - - //! Returns true if the node has geometry assigned. - bool HasMesh() const; - - //! Assign a new mesh asset - void SetMeshAsset(const AZ::Data::AssetId& id); - - //! Get the mesh asset - AZ::Data::Asset GetMeshAsset() { return m_meshAsset; } - - //! Invoked in the editor when the user assigns a new asset. - void OnAssetPropertyChanged(); - - //! Render the mesh - void RenderMesh(const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo); - - //! Updates the render node's world transform based on the entity's. - void UpdateWorldTransform(const AZ::Transform& entityTransform); - - //! Computes world-space AABB. - AZ::Aabb CalculateWorldAABB() const; - - //! Computes local-space AABB. - AZ::Aabb CalculateLocalAABB() const; - - ////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetBus::Handler - void OnAssetReady(AZ::Data::Asset asset) override; - void OnAssetReloaded(AZ::Data::Asset asset) override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // AZ::TransformNotificationBus::Handler interface implementation - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - // IRenderNode interface implementation - void Render(const struct SRendParams& inRenderParams, const struct SRenderingPassInfo& passInfo) override; - bool GetLodDistances(const SFrameLodInfo& frameLodInfo, float* distances) const override; - float GetFirstLodDistance() const override { return m_lodDistance; } - EERType GetRenderNodeType() override; - bool CanExecuteRenderAsJob() override; - const char* GetName() const override; - const char* GetEntityClassName() const override; - Vec3 GetPos(bool bWorldOnly = true) const override; - const AABB GetBBox() const override; - void SetBBox(const AABB& WSBBox) override; - void OffsetPosition(const Vec3& delta) override; - void SetMaterial(_smart_ptr pMat) override; - _smart_ptr GetMaterial(Vec3* pHitPos = nullptr) override; - _smart_ptr GetMaterialOverride() override; - IStatObj* GetEntityStatObj(unsigned int nPartId = 0, unsigned int nSubPartId = 0, Matrix34A* pMatrix = nullptr, bool bReturnOnlyVisible = false) override; - _smart_ptr GetEntitySlotMaterial(unsigned int nPartId, bool bReturnOnlyVisible = false, bool* pbDrawNear = nullptr) override; - float GetMaxViewDist() override; - void GetMemoryUsage(class ICrySizer* pSizer) const override; - AZ::EntityId GetEntityId() override { return m_renderOptions.m_attachedToEntityId; } - float GetUniformScale() override; - float GetColumnScale(int column) override; - ////////////////////////////////////////////////////////////////////////// - - //! Invoked in the editor when a property requiring render state refresh - //! has changed. - void RefreshRenderState(); - - //! Set/get auxiliary render flags. - void SetAuxiliaryRenderFlags(uint32 flags); - uint32 GetAuxiliaryRenderFlags() const { return m_auxiliaryRenderFlags; } - void UpdateAuxiliaryRenderFlags(bool on, uint32 mask); - - void SetVisible(bool isVisible); - bool GetVisible(); - - static void Reflect(AZ::ReflectContext* context); - - static float GetDefaultMaxViewDist(); - static AZ::Uuid GetRenderOptionsUuid() { return AZ::AzTypeInfo::Uuid(); } - - //! Registers or unregisters our render node with the render. - void RegisterWithRenderer(bool registerWithRenderer); - bool IsRegisteredWithRenderer() const { return m_isRegisteredWithRenderer; } - - //! This function caches off the static flag stat of the transform; - void SetTransformStaticState(bool isStatic); - const AZ::Transform& GetTransform() const; - - void SetContextId(AzFramework::EntityContextId contextId) { m_contextId = contextId; } - - protected: - - //! Calculates base LOD distance based on mesh characteristics. - //! We do this each time the mesh resource changes. - void UpdateLodDistance(const SFrameLodInfo& frameLodInfo); - - //! Computes desired LOD level for the assigned mesh instance. - CLodValue ComputeLOD(int wantedLod, const SRenderingPassInfo& passInfo); - - //! Computes the entity-relative (local space) bounding box for - //! the assigned mesh. - virtual void UpdateLocalBoundingBox(); - - //! Updates the world-space bounding box and world space transform - //! for the assigned mesh. - void UpdateWorldBoundingBox(); - - //! Applies configured render options to the render node. - void ApplyRenderOptions(); - - //! Populates the render mesh from the mesh asset - void BuildRenderMesh(); - - class MeshRenderOptions - { - public: - - AZ_TYPE_INFO(MeshRenderOptions, "{EFF77BEB-CB99-44A3-8F15-111B0200F50D}") - - MeshRenderOptions(); - - float m_opacity; //!< Alpha/opacity value for rendering. - float m_maxViewDist; //!< Maximum draw distance. - float m_viewDistMultiplier; //!< Adjusts max view distance. If 1.0 then default max view distance is used. - AZ::u32 m_lodRatio; //!< Controls LOD distance ratio. - bool m_useVisAreas; //!< Allow VisAreas to control this component's visibility. - bool m_castShadows; //!< Casts shadows. - bool m_lodBoundingBoxBased; //!< LOD based on Bounding Boxes. - bool m_rainOccluder; //!< Occludes raindrops. - bool m_affectNavmesh; //!< Cuts out of the navmesh. - bool m_affectDynamicWater; //!< Affects dynamic water (ripples). - bool m_acceptDecals; //!< Accepts decals. - bool m_receiveWind; //!< Receives wind. - bool m_visibilityOccluder; //!< Appropriate for visibility occluding. - bool m_dynamicMesh; // Mesh can change or deform independent of transform - bool m_hasStaticTransform; - bool m_affectGI; //!< Mesh affects Global Illumination. - - //! The Id of the entity we're associated with, for bus subscription. - //Moved from render mesh to this struct for serialization/reflection utility - AZ::EntityId m_attachedToEntityId; - - AZStd::function m_changeCallback; - - // Minor property changes don't require refreshing/rebuilding the property tree since no other properties - // are shown/hidden as a result of a change. - AZ::u32 OnMinorChanged() - { - if (m_changeCallback) - { - m_changeCallback(); - } - return AZ::Edit::PropertyRefreshLevels::None; - } - - AZ::u32 OnMajorChanged() - { - if (m_changeCallback) - { - m_changeCallback(); - } - return AZ::Edit::PropertyRefreshLevels::EntireTree; - } - - //Returns true if the transform is static and the mesh is not deformable. - bool IsStatic() const; - bool AffectsGi() const; - AZ::Crc32 StaticPropertyVisibility() const; - static void Reflect(AZ::ReflectContext* context); - - private: - static bool VersionConverter(AZ::SerializeContext& context, - AZ::SerializeContext::DataElementNode& classElement); - }; - - //! Should be visible. - bool m_visible; - - //! User-specified material override. - AzFramework::SimpleAssetReference m_material; - - //! Render flags/options. - MeshRenderOptions m_renderOptions; - - //! Currently-assigned material. Null if no material is manually assigned. - MaterialPtr m_materialOverride; - - //! World and render transforms. - //! These are equivalent, but for different math libraries. - AZ::Transform m_worldTransform; - Matrix34 m_renderTransform; - - //! Local and world bounding boxes. - AABB m_localBoundingBox; - AABB m_worldBoundingBox; - - //! Additional render flags -- for special editor behavior, etc. - uint32 m_auxiliaryRenderFlags; - - //! Remember which flags have ever been toggled externally so that we can shut them off - uint32 m_auxiliaryRenderFlagsHistory; - - //! Reference to current asset - AZ::Data::Asset m_meshAsset; - MeshPtr m_statObj; - - //! Computed LOD distance. - float m_lodDistance; - - //! Computed first LOD distance (the following are multiplies of the index) - float m_lodDistanceScaled; - - //! Scale we need to multiply the distance by. - float m_lodDistanceScaleValue; - - //! Identifies whether we've already registered our node with the renderer. - bool m_isRegisteredWithRenderer; - - //! Tracks if the object was moved so we can notify the renderer. - bool m_objectMoved; - - // Helper to store indices for meshes to be modified by other components. - MeshModificationRequestHelper m_modificationHelper; - - // EntityContext of the component - AzFramework::EntityContextId m_contextId; - }; - - - - class MeshComponent - : public AZ::Component - , public MeshComponentRequestBus::Handler - , public MaterialOwnerRequestBus::Handler - , public RenderNodeRequestBus::Handler - , public LegacyMeshComponentRequestBus::Handler - , public AzFramework::BoundsRequestBus::Handler - , public AzFramework::RenderGeometry::IntersectionRequestBus::Handler - { - public: - friend class EditorMeshComponent; - - AZ_COMPONENT(MeshComponent, "{2F4BAD46-C857-4DCB-A454-C412DE67852A}"); - - MeshComponent(); - ~MeshComponent() override; - - AZ_DISABLE_COPY_MOVE(MeshComponent); - - // AZ::Component overrides ... - void Activate() override; - void Deactivate() override; - - // BoundsRequestBus and MeshComponentRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - // MeshComponentRequestBus overrides ... - void SetMeshAsset(const AZ::Data::AssetId& id) override; - AZ::Data::Asset GetMeshAsset() override { return m_meshRenderNode.GetMeshAsset(); } - void SetVisibility(bool newVisibility) override; - bool GetVisibility() override; - - // MaterialOwnerRequestBus overrides ... - bool IsMaterialOwnerReady() override; - void SetMaterial(_smart_ptr) override; - _smart_ptr GetMaterial() override; - void SetMaterialHandle(const MaterialHandle& materialHandle) override; - MaterialHandle GetMaterialHandle() override; - void SetMaterialParamVector4(const AZStd::string& /*name*/, const AZ::Vector4& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamVector3(const AZStd::string& /*name*/, const AZ::Vector3& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamColor(const AZStd::string& /*name*/, const AZ::Color& /*value*/, int /*materialId = 1*/) override; - void SetMaterialParamFloat(const AZStd::string& /*name*/, float /*value*/, int /*materialId = 1*/) override; - AZ::Vector4 GetMaterialParamVector4(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - AZ::Vector3 GetMaterialParamVector3(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - AZ::Color GetMaterialParamColor(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - float GetMaterialParamFloat(const AZStd::string& /*name*/, int /*materialId = 1*/) override; - - // RenderNodeRequestBus overrides ... - IRenderNode* GetRenderNode() override; - float GetRenderNodeRequestBusOrder() const override; - static const float s_renderNodeRequestBusOrder; - - // MeshComponentRequestBus overrides ... - IStatObj* GetStatObj() override; - - // IntersectionRequestBus overrides ... - AzFramework::RenderGeometry::RayResult RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) override; - - protected: - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("MeshService", 0x71d8a455)); - provided.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("MeshService", 0x71d8a455)); - incompatible.push_back(AZ_CRC("LegacyMeshService", 0xb462a299)); - } - - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - static void Reflect(AZ::ReflectContext* context); - - void RequireSendingRenderMeshForEditing(size_t lodIndex, size_t primitiveIndex); - void NoRenderMeshesForEditing(); - - ////////////////////////////////////////////////////////////////////////// - // Reflected Data - MeshComponentRenderNode m_meshRenderNode; - MaterialOwnerRequestBusHandlerImpl* m_materialBusHandler; - }; - -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Source/Rendering/StereoRendererComponent.cpp b/Gems/LmbrCentral/Code/Source/Rendering/StereoRendererComponent.cpp deleted file mode 100644 index 44b78e5578..0000000000 --- a/Gems/LmbrCentral/Code/Source/Rendering/StereoRendererComponent.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" -#include -#include -#include - -#include "StereoRendererComponent.h" - - -namespace LmbrCentral -{ - void StereoRendererComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1); - } - - AZ::BehaviorContext* behaviorContext = azrtti_cast(context); - if (behaviorContext) - { - behaviorContext->EBus("StereoRendererRequestBus") - ->Event("IsRenderingToHMD", &AZ::StereoRendererRequestBus::Events::IsRenderingToHMD); - } - } -} diff --git a/Gems/LmbrCentral/Code/Tests/EditorLensFlareComponentTests.cpp b/Gems/LmbrCentral/Code/Tests/EditorLensFlareComponentTests.cpp deleted file mode 100644 index 5c1fc214fa..0000000000 --- a/Gems/LmbrCentral/Code/Tests/EditorLensFlareComponentTests.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" -#include "Source/Rendering/EditorLensFlareComponent.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -using ::testing::NiceMock; - -namespace UnitTest -{ - // Provides public access to protected/private members to allow for testing. - class Test_EditorLensFlareComponent : - public LmbrCentral::EditorLensFlareComponent - { - public: - AZ_COMPONENT(Test_EditorLensFlareComponent, "{2FB6C076-BB92-47A3-93C1-6ED7E622D7E0}", LmbrCentral::EditorLensFlareComponent); - - Test_EditorLensFlareComponent() : EditorLensFlareComponent() - { - - } - - ~Test_EditorLensFlareComponent() override - { - - } - - static void Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - - if (serializeContext) - { - serializeContext->Class()-> - Version(1); - } - } - - LmbrCentral::EditorLensFlareConfiguration Public_GetEditorLensFlareConfiguration() const - { - return GetEditorLensFlareConfiguration(); - } - }; - - class MockLensFlareHandlerAndCatalog - : public AZ::Data::AssetHandler - , public AZ::Data::AssetCatalog - { - public: - AZ_CLASS_ALLOCATOR(MockLensFlareHandlerAndCatalog, AZ::SystemAllocator, 0); - - AZ::Data::AssetPtr CreateAsset([[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& /*type*/) override - { - return aznew LmbrCentral::LensFlareAsset(); - } - - AZ::Data::AssetHandler::LoadResult LoadAssetData( - const AZ::Data::Asset& /*asset*/, - AZStd::shared_ptr /*stream*/, - const AZ::Data::AssetFilterCB& /*assetLoadFilterCB*/) override - { - return AZ::Data::AssetHandler::LoadResult::LoadComplete; - } - - void DestroyAsset(AZ::Data::AssetPtr ptr) override - { - delete ptr; - } - - void GetHandledAssetTypes(AZStd::vector& assetTypes) override - { - assetTypes.push_back(AZ::AzTypeInfo::Uuid()); - } - - AZ::Data::AssetStreamInfo GetStreamInfoForLoad(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& /*type*/) override - { - AZ::Data::AssetStreamInfo info; - // Set valid stream info. This ensures the asset load doesn't result in an - // error on another thread that can occur during shutdown. - info.m_streamName = AZStd::string::format("MockLensFlareHandlerAndCatalog%s", assetId.ToString().c_str()); - info.m_dataOffset = 0; - info.m_streamFlags = AZ::IO::OpenMode::ModeRead; - return info; - } - }; - - class EditorLensFlareComponentTests - : public ::testing::Test - , public UnitTest::TraceBusRedirector - , public AZ::Data::AssetBus::MultiHandler - { - protected: - ////////////////////////////////////////////////////////////////////////// - // AZ::Data::AssetBus::MultiHandler - - void OnAssetReady(AZ::Data::Asset asset) override - { - EXPECT_EQ(asset.GetId(), m_waitForAssetIdLoad); - m_waitForAssetIdLoad.SetInvalid(); - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); - } - - void OnAssetCanceled(AZ::Data::AssetId assetId) override - { - // With the right timing, it's possible for the asset to get canceled if the test ends - // before the load actually starts. Make sure that if this case happens, we still clear out - // the pending asset Id and disconnect from the bus. - EXPECT_EQ(assetId, m_waitForAssetIdLoad); - m_waitForAssetIdLoad.SetInvalid(); - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); - } - - void OnAssetError([[maybe_unused]] AZ::Data::Asset asset) override - { - // No asset errors should happen during this test. - EXPECT_TRUE(false); - } - - ////////////////////////////////////////////////////////////////////////// - void SetUp() override - { - m_app.Start(m_descriptor); - - // Mock up the File I/O system - m_priorFileIO = AZ::IO::FileIOBase::GetInstance(); - // for FileIO, you must set the instance to null before changing it. - // this is a way to tell the singleton system that you mean to replace a singleton and its - // not a mistake. - AZ::IO::FileIOBase::SetInstance(nullptr); - AZ::IO::FileIOBase::SetInstance(&m_fileIOMock); - AZ::IO::MockFileIOBase::InstallDefaultReturns(m_fileIOMock); - - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); - - m_EditorLensFlareComponentDescriptor = LmbrCentral::EditorLensFlareComponent::CreateDescriptor(); - m_testEditorLensFlareComponentDescriptor = Test_EditorLensFlareComponent::CreateDescriptor(); - m_lensFlareComponentDescriptor = LmbrCentral::LensFlareComponent::CreateDescriptor(); - - m_testEditorLensFlareComponentDescriptor->Reflect(m_app.GetSerializeContext()); - m_lensFlareComponentDescriptor->Reflect(m_app.GetSerializeContext()); - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - - AZ::Data::AssetManager::Instance().RegisterHandler(&m_lensFlareHandlerAndCatalog, AZ::AzTypeInfo::Uuid()); - AZ::Data::AssetManager::Instance().RegisterCatalog(&m_lensFlareHandlerAndCatalog, AZ::AzTypeInfo::Uuid()); - - EXPECT_CALL(m_system, GetConfigSpec(::testing::_)) - .WillRepeatedly(::testing::Return(CONFIG_AUTO_SPEC)); - - // Setup Mocks on a stub environment - m_stubEnv.pConsole = &m_console; - m_stubEnv.pSystem = &m_system; - m_priorEnv = gEnv; - gEnv = &m_stubEnv; - } - void TearDown() override - { - gEnv = m_priorEnv; - - if (m_waitForAssetIdLoad.IsValid()) - { - const int assetLoadSleepMS = 20; - int totalWaitTimeMS = 5000; - while (m_waitForAssetIdLoad.IsValid() && totalWaitTimeMS > 0) - { - AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(assetLoadSleepMS)); - AZ::SystemTickBus::Broadcast(&AZ::SystemTickBus::Events::OnSystemTick); - if (m_waitForAssetIdLoad.IsValid()) - { - totalWaitTimeMS -= assetLoadSleepMS; - } - } - EXPECT_GT(totalWaitTimeMS, 0); - EXPECT_FALSE(m_waitForAssetIdLoad.IsValid()); - AZ::Data::AssetBus::MultiHandler::BusDisconnect(); - } - - AZ::Data::AssetManager::Instance().UnregisterHandler(&m_lensFlareHandlerAndCatalog); - AZ::Data::AssetManager::Instance().UnregisterCatalog(&m_lensFlareHandlerAndCatalog); - - m_EditorLensFlareComponentDescriptor->ReleaseDescriptor(); - m_testEditorLensFlareComponentDescriptor->ReleaseDescriptor(); - m_lensFlareComponentDescriptor->ReleaseDescriptor(); - - AZ::IO::FileIOBase::SetInstance(nullptr); - AZ::IO::FileIOBase::SetInstance(m_priorFileIO); - - m_app.Stop(); - - // Disconnect last, ToolsApplication::Stop() can result in messages that we are using - // TraceMessageBus to handle. - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); - } - - void SetupLensFlareEntity(AZ::Entity& entity) - { - entity.CreateComponent(); - entity.CreateComponent(); - - entity.Init(); - entity.Activate(); - } - - AzToolsFramework::ToolsApplication m_app; - AZ::ComponentApplication::Descriptor m_descriptor; - - MockLensFlareHandlerAndCatalog m_lensFlareHandlerAndCatalog; - - AZ::ComponentDescriptor* m_EditorLensFlareComponentDescriptor = nullptr; - AZ::ComponentDescriptor* m_testEditorLensFlareComponentDescriptor = nullptr; - AZ::ComponentDescriptor* m_lensFlareComponentDescriptor = nullptr; - - // If this is set to a valid asset ID, teardown won't finish until - // this asset has been loaded. If this takes too long, teardown will error out. - AZ::Data::AssetId m_waitForAssetIdLoad; - - SSystemGlobalEnvironment m_stubEnv; - NiceMock m_system; - NiceMock m_console; - SSystemGlobalEnvironment* m_priorEnv = nullptr; - AZ::IO::FileIOBase* m_priorFileIO = nullptr; - ::testing::NiceMock m_fileIOMock; - }; - - TEST_F(EditorLensFlareComponentTests, EditorLensFlareComponent_AddEditorLensFlareComponent_ComponentExists) - { - AZ::Entity entity; - SetupLensFlareEntity(entity); - - Test_EditorLensFlareComponent* lensFlareComponent = - entity.FindComponent(); - EXPECT_TRUE(lensFlareComponent != nullptr); - } - - TEST_F(EditorLensFlareComponentTests, EditorLensFlareComponent_SetAssetId_GetAssetIdMatchesSet) - { - AZ::Entity entity; - SetupLensFlareEntity(entity); - - // Use an arbitrary, non-default asset ID to verify the set & get work. - AZ::Data::AssetId assetIdToSet(AZ::Uuid("{377939BD-57BB-4476-B7B5-35A162B1335E}"), 5); - AZ::Data::AssetInfo assetInfo; - assetInfo.m_assetType = azrtti_typeid(); - assetInfo.m_assetId = assetIdToSet; - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::RegisterAsset, assetIdToSet, assetInfo); - - // m_waitForAssetIdLoad is cleared when the asset load finishes, so keep a local copy of the asset ID. - m_waitForAssetIdLoad = assetIdToSet; - AZ::Data::AssetBus::MultiHandler::BusConnect(m_waitForAssetIdLoad); - - Test_EditorLensFlareComponent* lensFlareComponent = - entity.FindComponent(); - lensFlareComponent->SetPrimaryAsset(assetIdToSet); - - LmbrCentral::EditorLensFlareConfiguration lensFlareConfiguration = - lensFlareComponent->Public_GetEditorLensFlareConfiguration(); - EXPECT_EQ(lensFlareConfiguration.m_asset.GetId(), assetIdToSet); - } - - TEST_F(EditorLensFlareComponentTests, EditorLensFlareComponent_SetAssetIdBuildGameEntity_GameEntityHasAssetId) - { - AZ::Entity entity; - SetupLensFlareEntity(entity); - - // Use an arbitrary, non-default asset ID to verify the set & get work. - AZ::Data::AssetId assetIdToSet(AZ::Uuid("{BC7C7A76-C5F2-44E2-8E32-3CE03C3C5ADE}"), 6); - AZ::Data::AssetInfo assetInfo; - assetInfo.m_assetType = azrtti_typeid(); - assetInfo.m_assetId = assetIdToSet; - AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::RegisterAsset, assetIdToSet, assetInfo); - // m_waitForAssetIdLoad is cleared when the asset load finishes, so keep a local copy of the asset ID. - m_waitForAssetIdLoad = assetIdToSet; - AZ::Data::AssetBus::MultiHandler::BusConnect(m_waitForAssetIdLoad); - - Test_EditorLensFlareComponent* lensFlareComponent = - entity.FindComponent(); - lensFlareComponent->SetPrimaryAsset(assetIdToSet); - - AZ::Entity gameEntity; - lensFlareComponent->BuildGameEntity(&gameEntity); - LmbrCentral::LensFlareComponent* gameComponent = - gameEntity.FindComponent(); - EXPECT_TRUE(gameComponent != nullptr); - EXPECT_EQ(gameComponent->GetLensFlareConfiguration().m_asset.GetId(), assetIdToSet); - - } -} // namespace UnitTest diff --git a/Gems/LmbrCentral/Code/Tests/EditorMeshComponentTests.cpp b/Gems/LmbrCentral/Code/Tests/EditorMeshComponentTests.cpp deleted file mode 100644 index 8586955254..0000000000 --- a/Gems/LmbrCentral/Code/Tests/EditorMeshComponentTests.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "LmbrCentral_precompiled.h" - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "Source/Rendering/EditorMeshComponent.h" - -namespace UnitTest -{ - // base physical entity which can be derived from to detect other specific use-cases - struct PhysicalEntityPlaceHolder - : public IPhysicalEntity - { - pe_type GetType() const override { return PE_NONE; } - int AddRef() override { return 0; } - int Release() override { return 0; } - int SetParams([[maybe_unused]] const pe_params* params, [[maybe_unused]] int bThreadSafe = 0) override { return 0; } - int GetParams([[maybe_unused]] pe_params* params) const override { return 0; } - int GetStatus([[maybe_unused]] pe_status* status) const override { return 0; } - int Action(const pe_action*, [[maybe_unused]] int bThreadSafe = 0) override { return 0; } - int AddGeometry([[maybe_unused]] phys_geometry* pgeom, [[maybe_unused]] pe_geomparams* params, [[maybe_unused]] int id = -1, [[maybe_unused]] int bThreadSafe = 0) override { return 0; } - void RemoveGeometry([[maybe_unused]] int id, [[maybe_unused]] int bThreadSafe = 0) override {} - PhysicsForeignData GetForeignData([[maybe_unused]] int itype = 0) const override { return PhysicsForeignData{}; } - int GetiForeignData() const override { return 0; } - int GetStateSnapshot([[maybe_unused]] class CStream& stm, [[maybe_unused]] float time_back = 0, [[maybe_unused]] int flags = 0) override { return 0; } - int GetStateSnapshot([[maybe_unused]] TSerialize ser, [[maybe_unused]] float time_back = 0, [[maybe_unused]] int flags = 0) override { return 0; } - int SetStateFromSnapshot([[maybe_unused]] class CStream& stm, [[maybe_unused]] int flags = 0) override { return 0; } - int PostSetStateFromSnapshot() override { return 0; } - unsigned int GetStateChecksum() override { return 0; } - void SetNetworkAuthority([[maybe_unused]] int authoritive = -1, [[maybe_unused]] int paused = -1) override {} - int SetStateFromSnapshot([[maybe_unused]] TSerialize ser, [[maybe_unused]] int flags = 0) override { return 0; } - int SetStateFromTypedSnapshot([[maybe_unused]] TSerialize ser, [[maybe_unused]] int type, [[maybe_unused]] int flags = 0) override { return 0; } - int GetStateSnapshotTxt([[maybe_unused]] char* txtbuf, [[maybe_unused]] int szbuf, [[maybe_unused]] float time_back = 0) override { return 0; } - void SetStateFromSnapshotTxt([[maybe_unused]] const char* txtbuf, [[maybe_unused]] int szbuf) override {} - int DoStep([[maybe_unused]] float time_interval) override { return 0; } - int DoStep([[maybe_unused]] float time_interval, [[maybe_unused]] int iCaller) override { return 0; } - void StartStep([[maybe_unused]] float time_interval) override {} - void StepBack([[maybe_unused]] float time_interval) override {} - void GetMemoryStatistics([[maybe_unused]] ICrySizer* pSizer) const override {} - }; - - // special test fake to validate incoming pe_params - struct PhysicalEntitySetParamsCheck - : public PhysicalEntityPlaceHolder - { - int SetParams(const pe_params* params, [[maybe_unused]] int bThreadSafe = 0) override - { - if (params->type == pe_params_pos::type_id) - { - pe_params_pos* params_pos = (pe_params_pos*)params; - - Vec3 s; - if (Matrix34* m34 = params_pos->pMtx3x4) - { - s.Set(m34->GetColumn(0).len(), m34->GetColumn(1).len(), m34->GetColumn(2).len()); - Matrix33 m33(m34->GetColumn(0) / s.x, m34->GetColumn(1) / s.y, m34->GetColumn(2) / s.z); - // ensure passed in params_pos->pMtx3x4 is orthonormal - // ref - see Cry_Quat.h - explicit ILINE Quat_tpl(const Matrix33_tpl&m) - m_isOrthonormal = m33.IsOrthonormalRH(0.1f); - } - } - - return 0; - } - - bool m_isOrthonormal = false; - }; - - class TestEditorMeshComponent - : public LmbrCentral::EditorMeshComponent - { - public: - AZ_EDITOR_COMPONENT(TestEditorMeshComponent, "{6C6B593A-1946-4239-AE16-E8B96D9835E5}", LmbrCentral::EditorMeshComponent) - - static void Reflect(AZ::ReflectContext* context); - - TestEditorMeshComponent() = default; - - }; - - void TestEditorMeshComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(0); - } - } - - class EditorMeshComponentTestFixture - : public ToolsApplicationFixture - { - AZStd::unique_ptr m_testMeshComponentDescriptor; - - public: - void SetUpEditorFixtureImpl() override - { - AZ::SerializeContext* serializeContext = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); - - m_testMeshComponentDescriptor = - AZStd::unique_ptr(TestEditorMeshComponent::CreateDescriptor()); - m_testMeshComponentDescriptor->Reflect(serializeContext); - } - - void TearDownEditorFixtureImpl() override - { - m_testMeshComponentDescriptor.reset(); - } - }; - - struct MeshAssetHandlerFixture - : ScopedAllocatorSetupFixture - { - protected: - void SetUp() override - { - AZ::AllocatorInstance::Create(); - AZ::AllocatorInstance::Create(); - - AZ::Data::AssetManager::Create(AZ::Data::AssetManager::Descriptor()); - AZ::Data::AssetManager::Instance().SetAssetInfoUpgradingEnabled(false); - - m_handler.Register(); - } - - void TearDown() override - { - m_handler.Unregister(); - AZ::Data::AssetManager::Destroy(); - - AZ::AllocatorInstance::Destroy(); - AZ::AllocatorInstance::Destroy(); - } - - LmbrCentral::MeshAssetHandler m_handler; - }; - - struct MockAssetSystemRequestHandler - : AzFramework::AssetSystemRequestBus::Handler - { - MockAssetSystemRequestHandler() - { - BusConnect(); - } - - ~MockAssetSystemRequestHandler() - { - BusDisconnect(); - } - - AzFramework::AssetSystem::AssetStatus GetAssetStatusById([[maybe_unused]] const AZ::Data::AssetId& assetId) override - { - m_statusRequest = true; - - return AzFramework::AssetSystem::AssetStatus_Queued; - } - - MOCK_METHOD1(CompileAssetSync, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD1(CompileAssetSync_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD1(CompileAssetSyncById, AzFramework::AssetSystem::AssetStatus (const AZ::Data::AssetId&)); - MOCK_METHOD1(CompileAssetSyncById_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZ::Data::AssetId&)); - MOCK_METHOD4(ConfigureSocketConnection, bool (const AZStd::string&, const AZStd::string&, const AZStd::string&, const AZStd::string&)); - MOCK_METHOD1(Connect, bool (const char*)); - MOCK_METHOD2(ConnectWithTimeout, bool (const char*, AZStd::chrono::duration)); - MOCK_METHOD0(Disconnect, bool ()); - MOCK_METHOD1(EscalateAssetBySearchTerm, bool (AZStd::string_view)); - MOCK_METHOD1(EscalateAssetByUuid, bool (const AZ::Uuid&)); - MOCK_METHOD0(GetAssetProcessorPingTimeMilliseconds, float ()); - MOCK_METHOD1(GetAssetStatus, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD1(GetAssetStatus_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZStd::string&)); - MOCK_METHOD2(GetAssetStatusSearchType, AzFramework::AssetSystem::AssetStatus(const AZStd::string&, int)); - MOCK_METHOD2(GetAssetStatusSearchType_FlushIO, AzFramework::AssetSystem::AssetStatus(const AZStd::string&, int)); - MOCK_METHOD1(GetAssetStatusById_FlushIO, AzFramework::AssetSystem::AssetStatus (const AZ::Data::AssetId&)); - MOCK_METHOD3(GetUnresolvedProductReferences, void (AZ::Data::AssetId, AZ::u32&, AZ::u32&)); - MOCK_METHOD0(SaveCatalog, bool ()); - MOCK_METHOD1(SetAssetProcessorIP, void (const AZStd::string&)); - MOCK_METHOD1(SetAssetProcessorPort, void (AZ::u16)); - MOCK_METHOD1(SetBranchToken, void (const AZStd::string&)); - MOCK_METHOD1(SetProjectName, void (const AZStd::string&)); - MOCK_METHOD0(ShowAssetProcessor, void ()); - MOCK_METHOD1(ShowInAssetProcessor, void (const AZStd::string&)); - MOCK_METHOD1(WaitUntilAssetProcessorReady, bool(AZStd::chrono::duration)); - MOCK_METHOD1(WaitUntilAssetProcessorConnected, bool(AZStd::chrono::duration)); - MOCK_METHOD1(WaitUntilAssetProcessorDisconnected, bool(AZStd::chrono::duration)); - MOCK_METHOD0(AssetProcessorIsReady, bool()); - MOCK_METHOD0(ConnectedWithAssetProcessor, bool()); - MOCK_METHOD0(DisconnectedWithAssetProcessor, bool()); - MOCK_METHOD0(NegotiationWithAssetProcessorFailed, bool()); - MOCK_METHOD0(StartDisconnectingAssetProcessor, void()); - MOCK_METHOD1(EstablishAssetProcessorConnection, bool(const AzFramework::AssetSystem::ConnectionSettings&)); - MOCK_METHOD3(AppendAssetToPrioritySet, bool (const AZStd::string&, const AZ::Uuid&, uint32_t)); - MOCK_METHOD3(AppendAssetsToPrioritySet, bool (const AZStd::string&, const AZStd::vector&, uint32_t)); - MOCK_METHOD2(RemoveAssetFromPrioritySet, bool (const AZStd::string&, const AZ::Uuid&)); - MOCK_METHOD2(RemoveAssetsFromPrioritySet, bool (const AZStd::string&, const AZStd::vector&)); - bool m_statusRequest = false; - }; - - struct MockCatalog - : AZ::Data::AssetCatalogRequestBus::Handler - { - MockCatalog() - { - BusConnect(); - } - - ~MockCatalog() - { - BusDisconnect(); - } - - AZ::Data::AssetId GetAssetIdByPath(const char*, const AZ::Data::AssetType&, bool) override - { - m_generatedId = AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 1234); - - return m_generatedId; - } - - MOCK_METHOD1(GetAssetInfoById, AZ::Data::AssetInfo (const AZ::Data::AssetId&)); - MOCK_METHOD1(AddAssetType, void (const AZ::Data::AssetType&)); - MOCK_METHOD1(AddDeltaCatalog, bool (AZStd::shared_ptr)); - MOCK_METHOD1(AddExtension, void (const char*)); - MOCK_METHOD0(ClearCatalog, void ()); - MOCK_METHOD5(CreateBundleManifest, bool (const AZStd::string&, const AZStd::vector&, const AZStd::string&, int, const AZStd::vector&)); - MOCK_METHOD2(CreateDeltaCatalog, bool (const AZStd::vector&, const AZStd::string&)); - MOCK_METHOD0(DisableCatalog, void ()); - MOCK_METHOD1(EnableCatalogForAsset, void (const AZ::Data::AssetType&)); - MOCK_METHOD3(EnumerateAssets, void (BeginAssetEnumerationCB, AssetEnumerationCB, EndAssetEnumerationCB)); - MOCK_METHOD1(GenerateAssetIdTEMP, AZ::Data::AssetId (const char*)); - MOCK_METHOD1(GetAllProductDependencies, AZ::Outcome, AZStd::string> (const AZ::Data::AssetId&)); - MOCK_METHOD3(GetAllProductDependenciesFilter, AZ::Outcome, AZStd::string> (const AZ::Data::AssetId&, const AZStd::unordered_set&, const AZStd::vector&)); - MOCK_METHOD1(GetAssetPathById, AZStd::string (const AZ::Data::AssetId&)); - MOCK_METHOD1(GetDirectProductDependencies, AZ::Outcome, AZStd::string> (const AZ::Data::AssetId&)); - MOCK_METHOD1(GetHandledAssetTypes, void (AZStd::vector&)); - MOCK_METHOD0(GetRegisteredAssetPaths, AZStd::vector ()); - MOCK_METHOD2(InsertDeltaCatalog, bool (AZStd::shared_ptr, size_t)); - MOCK_METHOD2(InsertDeltaCatalogBefore, bool (AZStd::shared_ptr, AZStd::shared_ptr)); - MOCK_METHOD1(LoadCatalog, bool (const char*)); - MOCK_METHOD2(RegisterAsset, void (const AZ::Data::AssetId&, AZ::Data::AssetInfo&)); - MOCK_METHOD1(RemoveDeltaCatalog, bool (AZStd::shared_ptr)); - MOCK_METHOD1(SaveCatalog, bool (const char*)); - MOCK_METHOD0(StartMonitoringAssets, void ()); - MOCK_METHOD0(StopMonitoringAssets, void ()); - MOCK_METHOD1(UnregisterAsset, void (const AZ::Data::AssetId&)); - - AZ::Data::AssetId m_generatedId{}; - }; - - struct MockAssetData - : LmbrCentral::MeshAsset - { - MockAssetData(AZ::Data::AssetId assetId) - { - m_assetId = assetId; - } - }; - - TEST_F(MeshAssetHandlerFixture, LoadAsset_StillInQueue_LoadsSubstituteAsset) - { - MockAssetSystemRequestHandler assetSystem; - MockCatalog catalog; - AZ::Data::AssetId assetId(AZ::Uuid::CreateRandom(), 0); - - AZ::Data::Asset asset(aznew MockAssetData(assetId), AZ::Data::AssetLoadBehavior::Default); - auto substituteAssetId = m_handler.AssetMissingInCatalog(asset); - - ASSERT_TRUE(assetSystem.m_statusRequest); - ASSERT_TRUE(catalog.m_generatedId.IsValid()); - ASSERT_EQ(substituteAssetId, catalog.m_generatedId); - } - - - -} // namespace UnitTest diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h new file mode 100644 index 0000000000..b24ac2709b --- /dev/null +++ b/Gems/LmbrCentral/Code/include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h @@ -0,0 +1,54 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include +#include + +namespace LmbrCentral +{ + /*! + * SkeletonHierarchyRequestBus + * Messages serviced by components to provide information about skeletal hierarchies. + */ + class SkeletalHierarchyRequests + : public AZ::ComponentBus + { + public: + + /** + * \return Number of joints in the skeleton joint hierarchy. + */ + virtual AZ::u32 GetJointCount() { return 0; } + + /** + * \param jointIndex Index of joint whose name should be returned. + * \return Name of the joint at the specified index. Null if joint index is not valid. + */ + virtual const char* GetJointNameByIndex(AZ::u32 /*jointIndex*/) { return nullptr; } + + /** + * \param jointName Name of joint whose index should be returned. + * \return Index of the joint with the specified name. -1 if the joint was not found. + */ + virtual AZ::s32 GetJointIndexByName(const char* /*jointName*/) { return 0; } + + /** + * \param jointIndex Index of joint whose local-space transform should be returned. + * \return Joint's character-space transform. Identify if joint index was not valid. + */ + virtual AZ::Transform GetJointTransformCharacterRelative(AZ::u32 /*jointIndex*/) { return AZ::Transform::CreateIdentity(); } + }; + + using SkeletalHierarchyRequestBus = AZ::EBus; + +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/GeomCacheComponentBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/GeomCacheComponentBus.h deleted file mode 100644 index 4418856e7e..0000000000 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/GeomCacheComponentBus.h +++ /dev/null @@ -1,366 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include - -#include - -namespace LmbrCentral -{ - //Forward decl - enum class StandinType : AZ::u32; - - class EditorGeometryCacheComponentRequests - : public AZ::ComponentBus - { - public: - // EBus Traits overrides (Configuring this EBus) - // Using Defaults - - virtual ~EditorGeometryCacheComponentRequests() {} - - /** - * Sets the minimum spec for the Geometry Cache - * - * The geom cache will not render when the current graphics spec is - * below this minimum spec. - */ - virtual void SetMinSpec(EngineSpec minSpec) = 0; - //! Gets the minimum spec for the Geom Cache - virtual EngineSpec GetMinSpec() = 0; - - /** - * Sets whether or not the Geom Cache's animation will play on start - * - * When set to true the Geometry Cache will play in the editor. In game - * mode the Geom Cache will begin playing immediately. - */ - virtual void SetPlayOnStart(bool playOnStart) = 0; - //! Gets whether or not the Geom Cache's animation will play on start - virtual bool GetPlayOnStart() = 0; - - /** - * Sets the max view distance that this Geom Cache will be visible from - * - * The actual max view distance is calculated from - * maxViewDistance * viewDistanceMultiplier. - */ - virtual void SetMaxViewDistance(float maxViewDistance) = 0; - /** - * Gets the max view distance that the Geom Cache will be visible from - * - * This is the max view distance without the view distance multiplier - */ - virtual float GetMaxViewDistance() = 0; - - /** - * Sets the view distance multiplier - * - * The view distance multiplier is multiplied into the max view distance - * to determine how far you can be from the Geom Cache before it stops - * being rendered. - * - * A value of 1.0 will leave the max view distance as the actual max view distance. - */ - virtual void SetViewDistanceMultiplier(float viewDistanceMultiplier) = 0; - //! Gets the view distance multiplier - virtual float GetViewDistanceMultiplier() = 0; - - /** - * Sets the LOD Distance Ratio - * - * The LOD Distance ratio affects how LODs are chosen. A lower value means - * less detailed LODs are used at shorter view distances. - */ - virtual void SetLODDistanceRatio(AZ::u32 lodDistanceRatio) = 0; - //! Gets the LOD Distance Ratio - virtual AZ::u32 GetLODDistanceRatio() = 0; - - //! Sets whether or not the Geometry Cache will cast shadows - virtual void SetCastShadows(bool castShadows) = 0; - //! Gets whether or not the Geometry Cache casts shadows - virtual bool GetCastShadows() = 0; - - //! Sets whether or not the Geometry Cache will be affected by VisAreas and Portals - virtual void SetUseVisAreas(bool useVisAreas) = 0; - //! Gets whether or not the Geometry Cache is affected by VisAreas and Portals - virtual bool GetUseVisAreas() = 0; - }; - - using EditorGeometryCacheComponentRequestBus = AZ::EBus; - - class GeometryCacheComponentRequests - : public AZ::ComponentBus - { - public: - // EBus Traits overrides (Configuring this EBus) - // Using Defaults - - virtual ~GeometryCacheComponentRequests() {} - - /** - * Begins Geometry Cache animation playback - * - * If the animation is already playing, this does nothing. - * This may be the case if PlayOnStart was set during edit mode. - */ - virtual void Play() = 0; - //! Pauses Geometry Cache animation playback - virtual void Pause() = 0; - /** - * Stops Geometry Cache animation playback - * - * This will reset the playback time to 0. This means - * that when Play is called again that the animation - * will start from StartTime. - */ - virtual void Stop() = 0; - - /** - * Gets how much time remains in the animation - * - * Returns -1.0 if the animation is paused or stopped. - * - * @return How much time in seconds is left in the animation - */ - virtual float GetTimeRemaining() = 0; - - /** - * Gets the type of the stand-in that's currently in use - * - * If no stand-in is in use this will return - * StandinType::None. - * - * @return The type of stand-in currently in use - */ - virtual StandinType GetCurrentStandinType() = 0; - - /** - * Sets the geom cache asset to be rendered - */ - virtual void SetGeomCacheAsset(const AZ::Data::AssetId& id) = 0; - - /** - * Gets the geom cache asset in use by this component - */ - virtual AZ::Data::Asset GetGeomCacheAsset() = 0; - - /** - * Sets whether or not the Geometry Cache will be processed for rendering - * - * If Visibility is turned off, all Stand-ins for this - * Geometry Cache will also be turned off. - * - * This does not mean that the Geometry Cache is visible in the current - * frame or the next frame. This just means that it will be - * submitted to the visibility system for rendering. It can still - * be culled. - * - * @param visible Pass True for the Geometry Cache to render - */ - virtual void SetVisible(bool visible) = 0; - /** - * Gets whether or not the Geometry Cache will be processed for rendering - * - * If this returns false then all related Stand-ins should also - * not be visible. - * - * @return True if the Geometry Cache should be rendered. - */ - virtual bool GetVisible() = 0; - - /** - * Sets whether or not the Geometry Cache animation should loop - * - * The Last Frame Stand-in will never be visible as long as this remains - * true. - * - * @param loop Pass true if you want the Geometry Cache animation to loop - */ - virtual void SetLoop(bool loop) = 0; - /** - * Gets whether or not the Geometry Cache animation is set to loop - * - * @return True if the Geometry Cache animation will loop - */ - virtual bool GetLoop() = 0; - - /** - * Sets the time point that the Geometry Cache animation should start at - * - * Changing the start time of the animation will restart the animation. - * - * @param startTime The starting time point in seconds. - */ - virtual void SetStartTime(float startTime) = 0; - /** - * Gets the current start time point for the Geometry Cache animation - * - * @return The Geometry Cache's animation start time in seconds. - */ - virtual float GetStartTime() = 0; - - /** - * Sets the distance threshold that controls Geometry Cache streaming - * - * When the distance between the center of the Geometry Cache and the - * current camera is greater than this value the Geometry Cache's animation - * will begin to stream into memory. - * - * @param streamInDistance The distance threshold for Geometry Cache streaming - */ - virtual void SetStreamInDistance(float streamInDistance) = 0; - /** - * Gets the distance threshold that controls when the Geometry Cache will stream to memory - * - * @return The distance threshold for Geometry Cache streaming - */ - virtual float GetStreamInDistance() = 0; - - /** - * Sets the entity to be used for the First Frame Stand-in - * - * It's assumed that the entityId points to an entity that has - * a MeshComponent attached. The stand-in is controlled by the - * visibility parameter of the MeshComponent. - * - * The given entity will not be transformed or moved at all. The - * only change that will be made to it will be when it's made - * visible/invisible as a stand-in. - * - * Invalid entity ids will be ignored. - * - * This stand-in will be used until the Geometry Cache animation - * starts playing. - * - * @param entityId The ID of the Entity to use as the First Frame Stand-in - */ - virtual void SetFirstFrameStandIn(AZ::EntityId entityId) = 0; - /** - * Gets the entity that is used as the First Frame Stand-in - * - * @return The entity with a mesh component that's used as the First Frame Stand-in - */ - virtual AZ::EntityId GetFirstFrameStandIn() = 0; - - /** - * Sets the entity to be used for the Last Frame Stand-in - * - * It's assumed that the entityId points to an entity that has - * a MeshComponent attached. The stand-in is controlled by the - * visibility parameter of the MeshComponent. - * - * The given entity will not be transformed or moved at all. The - * only change that will be made to it will be when it's made - * visible/invisible as a stand-in. - * - * Invalid entity ids will be ignored. - * - * This stand-in will never be used if the Loop parameter is set to true. - * - * @param entityId The ID of the Entity to use as the Last Frame Stand-in - */ - virtual void SetLastFrameStandIn(AZ::EntityId entityId) = 0; - /** - * Gets the entity that is used as the Last Frame Stand-in - * - * @return The entity with a mesh component that's used as the Last Frame Stand-in - */ - virtual AZ::EntityId GetLastFrameStandIn() = 0; - - /** - * Sets the entity to be used for the distance-based Stand-in - * - * It's assumed that the entityId points to an entity that has - * a MeshComponent attached. The stand-in is controlled by the - * visibility parameter of the MeshComponent. - * - * The given entity will not be transformed or moved at all. The - * only change that will be made to it will be when it's made - * visible/invisible as a stand-in. - * - * Invalid entity ids will be ignored. - * - * This Stand-in will be used as long as the distance between the - * Geometry Cache's center and the current camera's position is larger - * than the Stand-in Distance parameter. - * - * @param entityId The ID of the Entity to use as the distance-based Stand-in - */ - virtual void SetStandIn(AZ::EntityId entityId) = 0; - /** - * Gets the entity that is used as the distance-based Stand-in - * - * @return The entity with a mesh component that's used as the distance-based Stand-in - */ - virtual AZ::EntityId GetStandIn() = 0; - - /** - * Sets the distance threshold that controls the visibility of the stand-in - * - * The stand-in will be used when the distance between the center of the - * Geometry Cache and the current camera is greater than this value. - * - * @param standInDistance The distance threshold for the stand-in - */ - virtual void SetStandInDistance(float standInDistance) = 0; - /** - * Gets the distance threshold that controls the visibility of the stand-in - * - * @return The distance threshold for the stand-in - */ - virtual float GetStandInDistance() = 0; - - /** - * Gets the Geometry Cache's render node - * - * This method is only exposed to C++. - * - * @return A pointer to the geometry cache's internal render node - */ - virtual IGeomCacheRenderNode* GetGeomCacheRenderNode() = 0; - }; - - using GeometryCacheComponentRequestBus = AZ::EBus; - - class GeometryCacheComponentNotifications - : public AZ::EBusTraits - { - public: - // EBus Traits overrides (Configuring this EBus) - // Using Defaults - - virtual ~GeometryCacheComponentNotifications() {} - - //! Event that triggers when Geometry Cache playback starts - virtual void OnPlaybackStart() = 0; - //! Event that triggers when Geometry Cache playback pauses - virtual void OnPlaybackPause() = 0; - //! Event that triggers when Geometry Cache playback stops - virtual void OnPlaybackStop() = 0; - - /** - * Event that triggers when the Geometry Cache changes which stand-in is in use - * - * This does fire if a stand-in is turned off and the Geometry Cache becomes - * active instead. - * - * @param standinType The new stand-in type that will be used - */ - virtual void OnStandinChanged(StandinType standinType) = 0; - }; - - using GeometryCacheComponentNotificationBus = AZ::EBus; - -} //namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/HighQualityShadowComponentBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/HighQualityShadowComponentBus.h deleted file mode 100644 index e738f9b0b2..0000000000 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/HighQualityShadowComponentBus.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include - -namespace LmbrCentral -{ - /*! - * Messages serviced by the unique shadow component. - */ - class HighQualityShadowComponentRequests - : public AZ::ComponentBus - { - public: - - virtual void SetEnabled(bool enabled) = 0; - virtual bool GetEnabled() = 0; - }; - - using HighQualityShadowComponentRequestBus = AZ::EBus; - - /*! - * Messages serviced by the unique shadow editor component. - */ - class EditorHighQualityShadowComponentRequests - : public AZ::ComponentBus - { - public: - - virtual void RefreshProperties() = 0; - }; - - using EditorHighQualityShadowComponentRequestBus = AZ::EBus; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/LensFlareComponentBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/LensFlareComponentBus.h deleted file mode 100644 index 988e26831a..0000000000 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/LensFlareComponentBus.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include - -namespace LmbrCentral -{ - /*! - * LensFlareComponentRequestsBus - * Messages serviced by the Lens Flare component. - */ - class LensFlareComponentRequests - : public AZ::ComponentBus - { - public: - enum class State - { - Off, - On, - }; - - virtual ~LensFlareComponentRequests() {} - - //! Control lens flare state. - virtual void SetLensFlareState(State state) { (void)state; } - - //! Turns lens flare on - virtual void TurnOnLensFlare() {} - - //! Turns lens flare off - virtual void TurnOffLensFlare() {} - - //! Toggles lens flare state. - virtual void ToggleLensFlare() {} - }; - - using LensFlareComponentRequestBus = AZ::EBus; - - - /*! - * LensFlareEditorRequestBus - * Editor/UI messages serviced by the Lens Flare component. - */ - class EditorLensFlareComponentRequests - : public AZ::ComponentBus - { - public: - virtual ~EditorLensFlareComponentRequests() {} - - //! Recreates the lens flare. - virtual void RefreshLensFlare() = 0; - }; - - using EditorLensFlareComponentRequestBus = AZ::EBus; - - /*! - * LensFlareComponentEventBus - * Events dispatched by the Lens Flare component. - */ - class LensFlareComponentNotifications - : public AZ::ComponentBus - { - public: - virtual ~LensFlareComponentNotifications() {} - - //! Lens flare has been turned on - virtual void LensFlareTurnedOn() {} - - //! Lens flare has been turned off - virtual void LensFlareTurnedOff() {} - }; - - using LensFlareComponentNotificationBus = AZ::EBus; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/MeshComponentBus.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/MeshComponentBus.h deleted file mode 100644 index 2f64bb084a..0000000000 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/MeshComponentBus.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include - -struct IStatObj; -struct SRenderingPassInfo; -struct SRendParams; - -namespace LmbrCentral -{ - /*! - * MeshComponentRequestBus - * Messages serviced by the mesh component. - */ - class MeshComponentRequests - : public AZ::ComponentBus - { - public: - - /** - * Returns the axis aligned bounding box in world coordinates - */ - virtual AZ::Aabb GetWorldBounds() = 0; - - /** - * Returns the axis aligned bounding box in model coordinates - */ - virtual AZ::Aabb GetLocalBounds() = 0; - - /** - * Sets the mesh asset for this component - */ - virtual void SetMeshAsset(const AZ::Data::AssetId& id) = 0; - - /** - * Returns the asset used by the mesh - */ - virtual AZ::Data::Asset GetMeshAsset() = 0; - - /** - * Returns true if the mesh is currently visible - */ - virtual bool GetVisibility() { return true; } - - /** - * Sets the current visibility of the mesh - */ - virtual void SetVisibility([[maybe_unused]] bool isVisible) {} - }; - - using MeshComponentRequestBus = AZ::EBus; - - /*! - * SkeletonHierarchyRequestBus - * Messages serviced by components to provide information about skeletal hierarchies. - */ - class SkeletalHierarchyRequests - : public AZ::ComponentBus - { - public: - - /** - * \return Number of joints in the skeleton joint hierarchy. - */ - virtual AZ::u32 GetJointCount() { return 0; } - - /** - * \param jointIndex Index of joint whose name should be returned. - * \return Name of the joint at the specified index. Null if joint index is not valid. - */ - virtual const char* GetJointNameByIndex(AZ::u32 /*jointIndex*/) { return nullptr; } - - /** - * \param jointName Name of joint whose index should be returned. - * \return Index of the joint with the specified name. -1 if the joint was not found. - */ - virtual AZ::s32 GetJointIndexByName(const char* /*jointName*/) { return 0; } - - /** - * \param jointIndex Index of joint whose local-space transform should be returned. - * \return Joint's character-space transform. Identify if joint index was not valid. - */ - virtual AZ::Transform GetJointTransformCharacterRelative(AZ::u32 /*jointIndex*/) { return AZ::Transform::CreateIdentity(); } - }; - - using SkeletalHierarchyRequestBus = AZ::EBus; - - /*! - * LegacyMeshComponentRequestBus - * Messages serviced by the mesh component. - */ - class LegacyMeshComponentRequests - : public AZ::ComponentBus - { - public: - virtual IStatObj* GetStatObj() = 0; - }; - - using LegacyMeshComponentRequestBus = AZ::EBus; - - /*! - * MeshComponentNotificationBus - * Events dispatched by the mesh component. - */ - class MeshComponentNotifications - : public AZ::ComponentBus - { - public: - - /** - * Notifies listeners the mesh instance has been created. - * \param asset - The asset the mesh instance is based on. - */ - virtual void OnMeshCreated(const AZ::Data::Asset& asset) { (void)asset; } - - /** - * Notifies listeners that the mesh instance has been destroyed. - */ - virtual void OnMeshDestroyed() {} - - virtual void OnBoundsReset() {}; - - /* - * Notifies listeners prior to making the render call - */ - virtual void OnMeshPreRender([[maybe_unused]] const struct SRendParams& inOutRenderParams, [[maybe_unused]] const SRenderingPassInfo& passInfo) {}; - - /** - * When connecting to this bus if the asset is ready you will immediately get an OnMeshCreated event - **/ - template - struct ConnectionPolicy - : public AZ::EBusConnectionPolicy - { - static void Connect(typename Bus::BusPtr& busPtr, typename Bus::Context& context, typename Bus::HandlerNode& handler, typename Bus::Context::ConnectLockGuard& connectLock, const typename Bus::BusIdType& id = 0) - { - AZ::EBusConnectionPolicy::Connect(busPtr, context, handler, connectLock, id); - - AZ::Data::Asset asset; - EBUS_EVENT_ID_RESULT(asset, id, MeshComponentRequestBus, GetMeshAsset); - if (asset.GetStatus() == AZ::Data::AssetData::AssetStatus::Ready) - { - handler->OnMeshCreated(asset); - } - } - }; - }; - - using MeshComponentNotificationBus = AZ::EBus; -} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h index 2779f68eb4..6fc0e85553 100644 --- a/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h +++ b/Gems/LmbrCentral/Code/include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h @@ -12,7 +12,6 @@ #pragma once #include -#include #include #include @@ -28,8 +27,7 @@ namespace LmbrCentral //! This does not actually inherit the MaterialOwnerRequestBus::Handler interface because it is //! not intended to subscribe to that bus, but it does provide implementations for all the same functions. class MaterialOwnerRequestBusHandlerImpl - : public MeshComponentNotificationBus::Handler - , public AZ::TickBus::Handler + : public AZ::TickBus::Handler , public MaterialOwnerRequestBus::Handler { using MaterialPtr = _smart_ptr < IMaterial >; @@ -57,14 +55,7 @@ namespace LmbrCentral if (m_renderNode) { - if (!m_renderNode->IsReady()) - { - // Some material owners, in particular MeshComponents, may not be ready upon activation because the - // actual mesh data and default material haven't been loaded yet. Until the RenderNode is ready, - // it's material probably isn't valid. - MeshComponentNotificationBus::Handler::BusConnect(entityId); - } - else + if (m_renderNode->IsReady()) { // For some material owner types (like DecalComponent), the material is ready immediately. But we can't // send the event yet because components are still being Activated, so we delay until the first tick. @@ -81,7 +72,6 @@ namespace LmbrCentral void Deactivate() { m_notificationBus = nullptr; - MeshComponentNotificationBus::Handler::BusDisconnect(); MaterialOwnerRequestBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); } @@ -300,16 +290,6 @@ namespace LmbrCentral } ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // MeshComponentNotificationBus interface implementation - void OnMeshCreated([[maybe_unused]] const AZ::Data::Asset& asset) override - { - AZ_Assert(IsMaterialOwnerReady(), "Got OnMeshCreated but the RenderNode still isn't ready"); - SendReadyEvent(); - MeshComponentNotificationBus::Handler::BusDisconnect(); - } - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // TickBus interface implementation void OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) override diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake index ab245a07f4..be62919093 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_files.cmake @@ -12,14 +12,11 @@ set(FILES include/LmbrCentral/Rendering/EditorCameraCorrectionBus.h include/LmbrCentral/Rendering/EditorLightComponentBus.h - include/LmbrCentral/Rendering/EditorMeshBus.h include/LmbrCentral/Shape/EditorPolygonPrismShapeComponentBus.h include/LmbrCentral/Shape/EditorSplineComponentBus.h include/LmbrCentral/Shape/EditorTubeShapeComponentBus.h include/LmbrCentral/Component/EditorWrappedComponentBase.h include/LmbrCentral/Component/EditorWrappedComponentBase.inl - Source/Animation/EditorAttachmentComponent.h - Source/Animation/EditorAttachmentComponent.cpp Source/Audio/EditorAudioAreaEnvironmentComponent.h Source/Audio/EditorAudioAreaEnvironmentComponent.cpp Source/Audio/EditorAudioEnvironmentComponent.h @@ -40,26 +37,6 @@ set(FILES Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderComponent.cpp Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.h Source/Builders/BenchmarkAssetBuilder/BenchmarkAssetBuilderWorker.cpp - Source/Rendering/EditorDecalComponent.h - Source/Rendering/EditorDecalComponent.cpp - Source/Rendering/EditorLensFlareComponent.h - Source/Rendering/EditorLensFlareComponent.cpp - Source/Rendering/EditorLightComponent.h - Source/Rendering/EditorLightComponent.cpp - Source/Rendering/EditorPointLightComponent.h - Source/Rendering/EditorPointLightComponent.cpp - Source/Rendering/EditorAreaLightComponent.h - Source/Rendering/EditorAreaLightComponent.cpp - Source/Rendering/EditorProjectorLightComponent.h - Source/Rendering/EditorProjectorLightComponent.cpp - Source/Rendering/EditorEnvProbeComponent.h - Source/Rendering/EditorEnvProbeComponent.cpp - Source/Rendering/EditorMeshComponent.h - Source/Rendering/EditorMeshComponent.cpp - Source/Rendering/EditorHighQualityShadowComponent.h - Source/Rendering/EditorHighQualityShadowComponent.cpp - Source/Rendering/EditorGeomCacheComponent.h - Source/Rendering/EditorGeomCacheComponent.cpp Source/Scripting/EditorLookAtComponent.h Source/Scripting/EditorLookAtComponent.cpp Source/Scripting/EditorRandomTimedSpawnerComponent.cpp diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake index 648840c7c8..b78ff769c2 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake @@ -14,13 +14,11 @@ set(FILES Tests/LmbrCentralReflectionTest.h Tests/LmbrCentralReflectionTest.cpp Tests/EditorBoxShapeComponentTests.cpp - Tests/EditorLensFlareComponentTests.cpp Tests/EditorSphereShapeComponentTests.cpp Tests/EditorCapsuleShapeComponentTests.cpp Tests/EditorCompoundShapeComponentTests.cpp Tests/EditorCylinderShapeComponentTests.cpp Tests/EditorPolygonPrismShapeComponentTests.cpp - Tests/EditorMeshComponentTests.cpp Tests/SpawnerComponentTest.cpp Tests/Builders/CopyDependencyBuilderTest.cpp Tests/Builders/SliceBuilderTests.cpp diff --git a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake index d0df6c7dd0..df6bafd499 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_files.cmake @@ -17,6 +17,7 @@ set(FILES include/LmbrCentral/Ai/NavigationSystemBus.h include/LmbrCentral/Ai/NavigationSeedBus.h include/LmbrCentral/Animation/AttachmentComponentBus.h + include/LmbrCentral/Animation/SkeletalHierarchyRequestBus.h include/LmbrCentral/Audio/AudioEnvironmentComponentBus.h include/LmbrCentral/Audio/AudioListenerComponentBus.h include/LmbrCentral/Audio/AudioMultiPositionComponentBus.h @@ -35,18 +36,13 @@ set(FILES include/LmbrCentral/Physics/ForceVolumeRequestBus.h include/LmbrCentral/Physics/WaterNotificationBus.h include/LmbrCentral/Rendering/DecalComponentBus.h - include/LmbrCentral/Rendering/LensFlareAsset.h - include/LmbrCentral/Rendering/LensFlareComponentBus.h include/LmbrCentral/Rendering/LightComponentBus.h include/LmbrCentral/Rendering/MaterialAsset.h include/LmbrCentral/Rendering/MaterialHandle.h include/LmbrCentral/Rendering/MaterialOwnerBus.h include/LmbrCentral/Rendering/MeshAsset.h - include/LmbrCentral/Rendering/MeshComponentBus.h include/LmbrCentral/Rendering/MeshModificationBus.h include/LmbrCentral/Rendering/RenderNodeBus.h - include/LmbrCentral/Rendering/HighQualityShadowComponentBus.h - include/LmbrCentral/Rendering/GeomCacheComponentBus.h include/LmbrCentral/Rendering/GiRegistrationBus.h include/LmbrCentral/Rendering/RenderBoundsBus.h include/LmbrCentral/Rendering/Utils/MaterialOwnerRequestBusHandlerImpl.h @@ -73,8 +69,6 @@ set(FILES include/LmbrCentral/Terrain/TerrainSystemRequestBus.h Source/Ai/NavigationSystemComponent.h Source/Ai/NavigationSystemComponent.cpp - Source/Animation/AttachmentComponent.h - Source/Animation/AttachmentComponent.cpp Source/Audio/AudioAreaEnvironmentComponent.h Source/Audio/AudioAreaEnvironmentComponent.cpp Source/Audio/AudioEnvironmentComponent.h @@ -103,27 +97,6 @@ set(FILES Source/Events/ReflectScriptableEvents.cpp Source/Geometry/GeometrySystemComponent.h Source/Geometry/GeometrySystemComponent.cpp - Source/Rendering/DecalComponent.h - Source/Rendering/DecalComponent.cpp - Source/Rendering/LensFlareAssetHandler.h - Source/Rendering/LensFlareAssetHandler.cpp - Source/Rendering/LensFlareComponent.h - Source/Rendering/LensFlareComponent.cpp - Source/Rendering/LightComponent.h - Source/Rendering/LightComponent.cpp - Source/Rendering/LightInstance.h - Source/Rendering/LightInstance.cpp - Source/Rendering/MaterialHandle.cpp - Source/Rendering/MeshAssetHandler.h - Source/Rendering/MeshAssetHandler.cpp - Source/Rendering/MeshComponent.h - Source/Rendering/MeshComponent.cpp - Source/Rendering/StereoRendererComponent.h - Source/Rendering/StereoRendererComponent.cpp - Source/Rendering/HighQualityShadowComponent.h - Source/Rendering/HighQualityShadowComponent.cpp - Source/Rendering/GeomCacheComponent.h - Source/Rendering/GeomCacheComponent.cpp Source/Rendering/EntityDebugDisplayComponent.h Source/Rendering/EntityDebugDisplayComponent.cpp Source/Scripting/LookAtComponent.h diff --git a/Gems/LyShine/Assets/Textures/Basic/Button_Sliced_Normal.tif b/Gems/LyShine/Assets/Textures/Basic/Button_Sliced_Normal.tif deleted file mode 100644 index c51e06aa9a..0000000000 --- a/Gems/LyShine/Assets/Textures/Basic/Button_Sliced_Normal.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1e6a98954dd2b2da87309cf522959efc601444080cf99b850ad64f2b7c5e8668 -size 38228 diff --git a/Gems/LyShine/Assets/Textures/Basic/button_sliced_normal.sprite b/Gems/LyShine/Assets/Textures/Basic/button_sliced_normal.sprite deleted file mode 100644 index 3f6cfe0345..0000000000 --- a/Gems/LyShine/Assets/Textures/Basic/button_sliced_normal.sprite +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f91c1587e5d611d253528c82c93b83e460f7ea71412d2489ff368eca4d8798db -size 122 diff --git a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.cpp b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.cpp index a65e220cbd..225f4e0b1a 100644 --- a/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.cpp +++ b/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.cpp @@ -16,7 +16,6 @@ #include "UiEditorDLLBus.h" #include "UiAnimViewSequenceManager.h" #include "UiAnimViewUndo.h" -#include "Material/MaterialManager.h" #include "AnimationContext.h" #include "GameEngine.h" #include diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index 286e756ffa..3ea451b7c5 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -72,6 +72,8 @@ #include #include +#include + #include "Animation/UiAnimationSystem.h" #include "World/UiCanvasAssetRefComponent.h" #include "World/UiCanvasProxyRefComponent.h" @@ -425,11 +427,8 @@ void CLyShine::Render() { FRAME_PROFILER(__FUNCTION__, gEnv->pSystem, PROFILE_UI); - // LYSHINE_ATOM_TODO - convert to use Atom interface to check for null renderer - if (!gEnv || !gEnv->pRenderer || gEnv->pRenderer->GetRenderType() == ERenderType::eRT_Null) + if (AZ::RHI::IsNullRenderer()) { - // if the renderer is not initialized or it is the null renderer (e.g. running as a server) - // then do nothing return; } diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index 5ea01c5c1e..76b4030106 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -115,11 +115,13 @@ static int Create2DTexture(int width, int height, byte* data, ETEX_Format format #endif #endif +#if !defined(_RELEASE) static AZ::Vector2 GetTextureSize(AZ::Data::Instance image) { AZ::RHI::Size size = image->GetDescriptor().m_size; return AZ::Vector2(size.m_width, size.m_height); } +#endif //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp index 2af773734c..8578e6b8eb 100644 --- a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp @@ -257,13 +257,13 @@ namespace UiRenderer* GetUiRendererForGame() { CLyShine* lyShine = static_cast(gEnv->pLyShine); - return lyShine->GetUiRenderer(); + return lyShine ? lyShine->GetUiRenderer() : nullptr; } UiRenderer* GetUiRendererForEditor() { CLyShine* lyShine = static_cast(gEnv->pLyShine); - return lyShine->GetUiRendererForEditor(); + return lyShine ? lyShine->GetUiRendererForEditor() : nullptr; } bool IsValidInteractable(const AZ::EntityId& entityId) @@ -4255,8 +4255,8 @@ UiCanvasComponent* UiCanvasComponent::FixupPostLoad(AZ::Entity* canvasEntity, AZ // Initialize the target canvas size and uniform scale // This should be done before calling InGamePostActivate so that the // canvas space rects of the elements are accurate - AZ_Assert(gEnv->pRenderer, "Attempting to access IRenderer before it has been initialized"); - if (gEnv->pRenderer) + UiRenderer* uiRenderer = forEditor ? GetUiRendererForEditor() : GetUiRendererForGame(); + if (uiRenderer) // can be null in automated testing { AZ::Vector2 targetCanvasSize; if (canvasSize) @@ -4265,8 +4265,7 @@ UiCanvasComponent* UiCanvasComponent::FixupPostLoad(AZ::Entity* canvasEntity, AZ } else { - targetCanvasSize.SetX(static_cast(gEnv->pRenderer->GetOverlayWidth())); - targetCanvasSize.SetY(static_cast(gEnv->pRenderer->GetOverlayHeight())); + targetCanvasSize = uiRenderer->GetViewportSize(); } canvasComponent->SetTargetCanvasSizeAndUniformScale(!forEditor, targetCanvasSize); } diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.cpp b/Gems/LyShine/Code/Source/UiCanvasManager.cpp index 6575a1d2f0..958dba0ab8 100644 --- a/Gems/LyShine/Code/Source/UiCanvasManager.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasManager.cpp @@ -612,10 +612,12 @@ void UiCanvasManager::RenderLoadedCanvases() m_fontTextureHasChanged = false; } +#ifdef LYSHINE_ATOM_TODO // render target conversion to Atom // clear the stencil buffer before rendering the loaded canvases - required for masking // NOTE: We want to use ClearTargetsImmediately instead of ClearTargetsLater since we will not be setting the render target ColorF viewportBackgroundColor(0, 0, 0, 0); // if clearing color we want to set alpha to zero also gEnv->pRenderer->ClearTargetsImmediately(FRT_CLEAR_STENCIL, viewportBackgroundColor); +#endif for (auto canvas : m_loadedCanvases) { diff --git a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp index a2fdfa201f..e54f61fbfa 100644 --- a/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp +++ b/Gems/LyShine/Code/Source/UiParticleEmitterComponent.cpp @@ -764,9 +764,6 @@ void UiParticleEmitterComponent::InGamePostActivate() //////////////////////////////////////////////////////////////////////////////////////////////////// void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph) { - const char* profileMarker = "UI_PARTICLESYS"; - gEnv->pRenderer->PushProfileMarker(profileMarker); - AZ::Matrix4x4 transform = AZ::Matrix4x4::CreateIdentity(); AZ::Vector2 emitterOffset = AZ::Vector2::CreateZero(); @@ -840,8 +837,6 @@ void UiParticleEmitterComponent::Render(LyShine::IRenderGraph* renderGraph) m_cachedPrimitive.m_numVertices = totalVerticesInserted; m_cachedPrimitive.m_numIndices = totalParticlesInserted * indicesPerParticle; renderGraph->AddPrimitive(&m_cachedPrimitive, texture, isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, m_blendMode); - - gEnv->pRenderer->PopProfileMarker(profileMarker); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index b1092ab92f..937f323b01 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -1911,9 +1911,6 @@ void UiTextComponent::Render(LyShine::IRenderGraph* renderGraph) for (RenderCacheBatch* batch : m_renderCache.m_batches) { - const char* profileMarker = "UI_TEXT"; - gEnv->pRenderer->PushProfileMarker(profileMarker); - AZ::FFont* font = static_cast(batch->m_font); // LYSHINE_ATOM_TODO - find a different solution from downcasting FFont to IFont AZ::Data::Instance fontImage = font->GetFontImage(); if (fontImage) @@ -1944,8 +1941,6 @@ void UiTextComponent::Render(LyShine::IRenderGraph* renderGraph) isClampTextureMode, isTextureSRGB, isTexturePremultipliedAlpha, blendMode); } } - - gEnv->pRenderer->PopProfileMarker(profileMarker); } } diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleFrame.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleFrame.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleFrame.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleGradient.png.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleGradient.png.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/CircleGradient.png.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/Circle_Shadow.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/Circle_Shadow.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/Circle_Shadow.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTest.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTest.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTest.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTestPow2.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTestPow2.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ColorTestPow2.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ParticleGlow.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ParticleGlow.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/ParticleGlow.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/button.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/button.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/button.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonPressed.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonPressed.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonPressed.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonSlider.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonSlider.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/buttonSlider.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkbox_spritesheet.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkbox_spritesheet.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkbox_spritesheet.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkered3.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkered3.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/checkered3.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/empty_icon.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/empty_icon.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/empty_icon.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/fixed_image.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/fixed_image.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/fixed_image.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/flipbook_walking.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/flipbook_walking.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/flipbook_walking.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/mask.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/mask.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/mask.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outline.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outline.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outline.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outlineRounded.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outlineRounded.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/outlineRounded.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/panelBkgd.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/panelBkgd.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/panelBkgd.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02_big.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02_big.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02_big.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical_big.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical_big.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern02vertical_big.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03_big.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03_big.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/pattern03_big.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_1.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_1.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_1.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_10.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_10.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_10.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_2.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_2.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_2.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_3.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_3.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_3.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_4.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_4.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_4.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_5.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_5.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_5.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_6.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_6.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_6.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_7.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_7.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_7.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_8.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_8.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_8.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_9.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_9.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_icon_9.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_map.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_map.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/scroll_box_map.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/selected.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/selected.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/selected.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInside2.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInside2.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInside2.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInsideSquare.tif.assetinfo b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInsideSquare.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/LyShineExamples/Assets/UI/Textures/LyShineExamples/shadowInsideSquare.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp index 80750efe7f..cb33ccac98 100644 --- a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp +++ b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp @@ -97,7 +97,8 @@ namespace LyShineExamples if (!texture) { // if there is no texture we will just use a white texture - texture = gEnv->pRenderer->EF_GetTextureByID(gEnv->pRenderer->GetWhiteTextureId()); + // TODO: Get a default atom texture here when possible + //texture = gEnv->pRenderer->EF_GetTextureByID(gEnv->pRenderer->GetWhiteTextureId()); } if (m_isRenderCacheDirty) diff --git a/Gems/Metastream/Code/CMakeLists.txt b/Gems/Metastream/Code/CMakeLists.txt index 47b6f6f9c5..326c21c5a9 100644 --- a/Gems/Metastream/Code/CMakeLists.txt +++ b/Gems/Metastream/Code/CMakeLists.txt @@ -36,6 +36,7 @@ ly_add_target( metastream_shared_files.cmake ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake PLATFORM_INCLUDE_FILES + ${pal_source_dir}/metastream_${PAL_PLATFORM_NAME_LOWERCASE}.cmake ${common_source_dir}/${PAL_TRAIT_COMPILER_ID}/metastream_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake INCLUDE_DIRECTORIES PRIVATE @@ -62,6 +63,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) metastream_shared_files.cmake ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake PLATFORM_INCLUDE_FILES + ${pal_source_dir}/metastream_${PAL_PLATFORM_NAME_LOWERCASE}.cmake ${common_source_dir}/${PAL_TRAIT_COMPILER_ID}/metastream_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake INCLUDE_DIRECTORIES PRIVATE diff --git a/Gems/Metastream/Code/Source/Platform/Android/metastream_android.cmake b/Gems/Metastream/Code/Source/Platform/Android/metastream_android.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Gems/Metastream/Code/Source/Platform/Android/metastream_android.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Gems/Metastream/Code/Source/Platform/Common/MSVC/metastream_msvc.cmake b/Gems/Metastream/Code/Source/Platform/Common/MSVC/metastream_msvc.cmake index 2a42a01b08..5cebdbd198 100644 --- a/Gems/Metastream/Code/Source/Platform/Common/MSVC/metastream_msvc.cmake +++ b/Gems/Metastream/Code/Source/Platform/Common/MSVC/metastream_msvc.cmake @@ -11,7 +11,3 @@ # CivetHttpServer.cpp uses a try catch block set(LY_COMPILE_OPTIONS PRIVATE /EHsc) -set(LY_BUILD_DEPENDENCIES - PRIVATE - 3rdParty::civetweb -) \ No newline at end of file diff --git a/Gems/Metastream/Code/Source/Platform/Linux/metastream_linux.cmake b/Gems/Metastream/Code/Source/Platform/Linux/metastream_linux.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Gems/Metastream/Code/Source/Platform/Linux/metastream_linux.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Gems/Metastream/Code/Source/Platform/Mac/metastream_mac.cmake b/Gems/Metastream/Code/Source/Platform/Mac/metastream_mac.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Gems/Metastream/Code/Source/Platform/Mac/metastream_mac.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Gems/Metastream/Code/Source/Platform/Windows/metastream_windows.cmake b/Gems/Metastream/Code/Source/Platform/Windows/metastream_windows.cmake new file mode 100644 index 0000000000..3705f7d6fc --- /dev/null +++ b/Gems/Metastream/Code/Source/Platform/Windows/metastream_windows.cmake @@ -0,0 +1,15 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(LY_BUILD_DEPENDENCIES + PRIVATE + 3rdParty::civetweb +) diff --git a/Gems/Metastream/Code/Source/Platform/iOS/metastream_ios.cmake b/Gems/Metastream/Code/Source/Platform/iOS/metastream_ios.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Gems/Metastream/Code/Source/Platform/iOS/metastream_ios.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp index c295eca188..8f97b212a3 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.cpp @@ -27,11 +27,11 @@ namespace NvCloth { namespace Internal { - bool ObtainSkinningData( + bool ObtainSkinningInfluences( AZ::EntityId entityId, const MeshNodeInfo& meshNodeInfo, - const size_t numSimParticles, - AZStd::vector& skinningData) + const size_t numVertices, + AZStd::vector& skinningInfluences) { AZ::Data::Asset modelAsset; AZ::Render::MeshComponentRequestBus::EventResult( @@ -67,7 +67,7 @@ namespace NvCloth const auto& skinToSkeletonIndexMap = actor->GetSkinToSkeletonIndexMap(); - skinningData.resize(numSimParticles); + size_t numberOfInfluencesPerVertex = 0; // For each submesh... for (const auto& subMeshInfo : meshNodeInfo.m_subMeshes) @@ -98,28 +98,48 @@ namespace NvCloth if (sourceSkinJointIndices.empty() || sourceSkinWeights.empty()) { - continue; + // Ignoring skinning when there is no skin data. + // All submeshes will either have or not have skin data, since they come from the same mesh. + return false; } AZ_Assert(sourceSkinJointIndices.size() == sourceSkinWeights.size(), "Size of skin joint indices buffer (%zu) different from skin weights buffer (%zu)", sourceSkinJointIndices.size(), sourceSkinWeights.size()); - const size_t influenceCount = sourceSkinWeights.size() / sourcePositions.size(); - if (influenceCount == 0) + const size_t subMeshInfluenceCount = sourceSkinWeights.size() / sourcePositions.size(); + AZ_Assert(subMeshInfluenceCount > 0, + "Submesh %d skinning data has zero joint influences per vertex.", + subMeshInfo.m_primitiveIndex); + + if (numberOfInfluencesPerVertex == 0) { - continue; + // Resize only in the first loop once we know the number of influences per vertex. + // The other submeshes should match the number of influences. + numberOfInfluencesPerVertex = subMeshInfluenceCount; + skinningInfluences.resize(numVertices * numberOfInfluencesPerVertex); + } + else if (subMeshInfluenceCount != numberOfInfluencesPerVertex) + { + AZ_Error("ActorClothSkinning", false, + "Submesh %d number of influences (%d) is different from a previous submesh (%d).", + subMeshInfo.m_primitiveIndex, + subMeshInfluenceCount, + numberOfInfluencesPerVertex); + return false; } for (int vertexIndex = 0; vertexIndex < subMeshInfo.m_numVertices; ++vertexIndex) { - SkinningInfo& skinningInfo = skinningData[subMeshInfo.m_verticesFirstIndex + vertexIndex]; - skinningInfo.m_jointIndices.resize(influenceCount); - skinningInfo.m_jointWeights.resize(influenceCount); + const size_t subMeshVertexIndex = vertexIndex * numberOfInfluencesPerVertex; + const size_t meshVertexIndex = (subMeshInfo.m_verticesFirstIndex + vertexIndex) * numberOfInfluencesPerVertex; - for (size_t influenceIndex = 0; influenceIndex < influenceCount; ++influenceIndex) + for (size_t influenceIndex = 0; influenceIndex < numberOfInfluencesPerVertex; ++influenceIndex) { - const AZ::u16 jointIndex = sourceSkinJointIndices[vertexIndex * influenceCount + influenceIndex]; - const float weight = sourceSkinWeights[vertexIndex * influenceCount + influenceIndex]; + const size_t subMeshVertexInfluenceIndex = subMeshVertexIndex + influenceIndex; + const size_t meshVertexInfluenceIndex = meshVertexIndex + influenceIndex; + + const AZ::u16 jointIndex = sourceSkinJointIndices[subMeshVertexInfluenceIndex]; + const float weight = sourceSkinWeights[subMeshVertexInfluenceIndex]; auto skeletonIndexIt = skinToSkeletonIndexMap.find(jointIndex); if (skeletonIndexIt == skinToSkeletonIndexMap.end()) @@ -130,8 +150,8 @@ namespace NvCloth return false; } - skinningInfo.m_jointIndices[influenceIndex] = skeletonIndexIt->second; - skinningInfo.m_jointWeights[influenceIndex] = weight; + skinningInfluences[meshVertexInfluenceIndex].m_jointIndex = skeletonIndexIt->second; + skinningInfluences[meshVertexInfluenceIndex].m_jointWeight = weight; } } } @@ -198,17 +218,21 @@ namespace NvCloth { } - protected: // ActorClothSkinning overrides ... void UpdateSkinning() override; - bool HasSkinningTransformData() override; - void ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) override; - AZ::Vector3 ComputeSkinningPosition(const AZ::Vector3& originalPosition) override; - AZ::Vector3 ComputeSkinningVector(const AZ::Vector3& originalVector) override; + void ApplySkinning( + const AZStd::vector& originalPositions, + AZStd::vector& positions) override; + void ApplySkinningOnNonSimulatedVertices( + const MeshClothInfo& originalData, + ClothComponentMesh::RenderData& renderData) override; private: + AZ::Matrix3x4 ComputeVertexSkinnningTransform(AZ::u32 vertexIndex); + const AZ::Matrix3x4* m_skinningMatrices = nullptr; - AZ::Matrix3x4 m_vertexSkinningTransform = AZ::Matrix3x4::CreateIdentity(); + + inline static const AZ::Matrix3x4 s_zeroMatrix3x4 = AZ::Matrix3x4::CreateZero(); }; void ActorClothSkinningLinear::UpdateSkinning() @@ -218,41 +242,75 @@ namespace NvCloth m_skinningMatrices = Internal::ObtainSkinningMatrices(m_entityId); } - bool ActorClothSkinningLinear::HasSkinningTransformData() + void ActorClothSkinningLinear::ApplySkinning( + const AZStd::vector& originalPositions, + AZStd::vector& positions) { - return m_skinningMatrices != nullptr; - } - - void ActorClothSkinningLinear::ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) - { - m_vertexSkinningTransform = AZ::Matrix3x4::CreateZero(); - for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex) + if (!m_skinningMatrices || + originalPositions.empty() || + originalPositions.size() != positions.size() || + originalPositions.size() != m_simulatedVertices.size()) { - const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex]; - const float jointWeight = skinningInfo.m_jointWeights[weightIndex]; + return; + } - if (AZ::IsClose(jointWeight, 0.0f)) - { - continue; - } + AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth); - // Blending matrices the same way done in GPU shaders, by adding each weighted matrix element by element. - // This way the skinning results are much similar to the skinning performed in GPU. - for (int i = 0; i < 3; ++i) - { - m_vertexSkinningTransform.SetRow(i, m_vertexSkinningTransform.GetRow(i) + m_skinningMatrices[jointIndex].GetRow(i) * jointWeight); - } + const size_t vertexCount = m_simulatedVertices.size(); + for (size_t index = 0; index < vertexCount; ++index) + { + const AZ::Matrix3x4 vertexSkinningTransform = ComputeVertexSkinnningTransform(m_simulatedVertices[index]); + + const AZ::Vector3 skinnedPosition = vertexSkinningTransform * originalPositions[index].GetAsVector3(); + positions[index].Set(skinnedPosition, positions[index].GetW()); // Avoid overwriting the w component } } - AZ::Vector3 ActorClothSkinningLinear::ComputeSkinningPosition(const AZ::Vector3& originalPosition) + void ActorClothSkinningLinear::ApplySkinningOnNonSimulatedVertices( + const MeshClothInfo& originalData, + ClothComponentMesh::RenderData& renderData) { - return m_vertexSkinningTransform * originalPosition; + if (!m_skinningMatrices || + originalData.m_particles.empty() || + originalData.m_particles.size() != renderData.m_particles.size() || + originalData.m_particles.size() != m_skinningInfluences.size() / m_numberOfInfluencesPerVertex) + { + return; + } + + AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth); + + for (const AZ::u32 index : m_nonSimulatedVertices) + { + const AZ::Matrix3x4 vertexSkinningTransform = ComputeVertexSkinnningTransform(index); + + const AZ::Vector3 skinnedPosition = vertexSkinningTransform * originalData.m_particles[index].GetAsVector3(); + renderData.m_particles[index].Set(skinnedPosition, renderData.m_particles[index].GetW()); // Avoid overwriting the w component + + // Calculate the reciprocal scale version of the matrix to transform the vectors. + const AZ::Matrix3x4 vertexSkinningTransformReciprocalScale = vertexSkinningTransform.GetReciprocalScaled(); + + renderData.m_tangents[index] = vertexSkinningTransformReciprocalScale.TransformVector(originalData.m_tangents[index]).GetNormalized(); + renderData.m_bitangents[index] = vertexSkinningTransformReciprocalScale.TransformVector(originalData.m_bitangents[index]).GetNormalized(); + renderData.m_normals[index] = vertexSkinningTransformReciprocalScale.TransformVector(originalData.m_normals[index]).GetNormalized(); + } } - AZ::Vector3 ActorClothSkinningLinear::ComputeSkinningVector(const AZ::Vector3& originalVector) + AZ::Matrix3x4 ActorClothSkinningLinear::ComputeVertexSkinnningTransform(AZ::u32 vertexIndex) { - return (m_vertexSkinningTransform * AZ::Vector4::CreateFromVector3AndFloat(originalVector, 0.0f)).GetAsVector3().GetNormalized(); + AZ::Matrix3x4 vertexSkinningTransform = s_zeroMatrix3x4; + for (size_t influenceIndex = 0; influenceIndex < m_numberOfInfluencesPerVertex; ++influenceIndex) + { + const size_t vertexInfluenceIndex = vertexIndex * m_numberOfInfluencesPerVertex + influenceIndex; + + const AZ::u16 jointIndex = m_skinningInfluences[vertexInfluenceIndex].m_jointIndex; + const float jointWeight = m_skinningInfluences[vertexInfluenceIndex].m_jointWeight; + + // Blending matrices the same way done in GPU shaders, by adding each weighted matrix element by element. + // This way the skinning results are much similar to the skinning performed in GPU. + vertexSkinningTransform += m_skinningMatrices[jointIndex] * jointWeight; + } + return vertexSkinningTransform; } // Specialized class that applies dual quaternion blending skinning @@ -265,17 +323,21 @@ namespace NvCloth { } - protected: // ActorClothSkinning overrides ... void UpdateSkinning() override; - bool HasSkinningTransformData() override; - void ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) override; - AZ::Vector3 ComputeSkinningPosition(const AZ::Vector3& originalPosition) override; - AZ::Vector3 ComputeSkinningVector(const AZ::Vector3& originalVector) override; + void ApplySkinning( + const AZStd::vector& originalPositions, + AZStd::vector& positions) override; + void ApplySkinningOnNonSimulatedVertices( + const MeshClothInfo& originalData, + ClothComponentMesh::RenderData& renderData) override; private: + MCore::DualQuaternion ComputeVertexSkinnningTransform(AZ::u32 vertexIndex); + AZStd::unordered_map m_skinningDualQuaternions; - MCore::DualQuaternion m_vertexSkinningTransform; + + inline static const MCore::DualQuaternion s_zeroDualQuaternion = MCore::DualQuaternion(AZ::Quaternion::CreateZero(), AZ::Quaternion::CreateZero()); }; void ActorClothSkinningDualQuaternion::UpdateSkinning() @@ -285,58 +347,93 @@ namespace NvCloth m_skinningDualQuaternions = Internal::ObtainSkinningDualQuaternions(m_entityId, m_jointIndices); } - bool ActorClothSkinningDualQuaternion::HasSkinningTransformData() + void ActorClothSkinningDualQuaternion::ApplySkinning( + const AZStd::vector& originalPositions, + AZStd::vector& positions) { - return !m_skinningDualQuaternions.empty(); - } - - void ActorClothSkinningDualQuaternion::ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) - { - m_vertexSkinningTransform = MCore::DualQuaternion(AZ::Quaternion::CreateZero(), AZ::Quaternion::CreateZero()); - for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex) + if (m_skinningDualQuaternions.empty() || + originalPositions.empty() || + originalPositions.size() != positions.size() || + originalPositions.size() != m_simulatedVertices.size()) { - const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex]; - const float jointWeight = skinningInfo.m_jointWeights[weightIndex]; - - if (AZ::IsClose(jointWeight, 0.0f)) - { - continue; - } - - m_vertexSkinningTransform += m_skinningDualQuaternions.at(jointIndex) * jointWeight; + return; + } + + AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth); + + const size_t vertexCount = m_simulatedVertices.size(); + for (size_t index = 0; index < vertexCount; ++index) + { + const MCore::DualQuaternion vertexSkinningTransform = ComputeVertexSkinnningTransform(m_simulatedVertices[index]); + + const AZ::Vector3 skinnedPosition = vertexSkinningTransform.TransformPoint(originalPositions[index].GetAsVector3()); + positions[index].Set(skinnedPosition, positions[index].GetW()); // Avoid overwriting the w component } - m_vertexSkinningTransform.Normalize(); } - AZ::Vector3 ActorClothSkinningDualQuaternion::ComputeSkinningPosition(const AZ::Vector3& originalPosition) + void ActorClothSkinningDualQuaternion::ApplySkinningOnNonSimulatedVertices( + const MeshClothInfo& originalData, + ClothComponentMesh::RenderData& renderData) { - return m_vertexSkinningTransform.TransformPoint(originalPosition); + if (m_skinningDualQuaternions.empty() || + originalData.m_particles.empty() || + originalData.m_particles.size() != renderData.m_particles.size() || + originalData.m_particles.size() != m_skinningInfluences.size() / m_numberOfInfluencesPerVertex) + { + return; + } + + AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth); + + for (const AZ::u32 index : m_nonSimulatedVertices) + { + const MCore::DualQuaternion vertexSkinningTransform = ComputeVertexSkinnningTransform(index); + + const AZ::Vector3 skinnedPosition = vertexSkinningTransform.TransformPoint(originalData.m_particles[index].GetAsVector3()); + renderData.m_particles[index].Set(skinnedPosition, renderData.m_particles[index].GetW()); // Avoid overwriting the w component + + // ComputeVertexSkinnningTransform is normalizing the dual quaternion, so it won't have scale + // and there is no need to compute the reciprocal scale version for transforming vectors. + + renderData.m_tangents[index] = vertexSkinningTransform.TransformVector(originalData.m_tangents[index]).GetNormalized(); + renderData.m_bitangents[index] = vertexSkinningTransform.TransformVector(originalData.m_bitangents[index]).GetNormalized(); + renderData.m_normals[index] = vertexSkinningTransform.TransformVector(originalData.m_normals[index]).GetNormalized(); + } } - AZ::Vector3 ActorClothSkinningDualQuaternion::ComputeSkinningVector(const AZ::Vector3& originalVector) + MCore::DualQuaternion ActorClothSkinningDualQuaternion::ComputeVertexSkinnningTransform(AZ::u32 vertexIndex) { - return m_vertexSkinningTransform.TransformVector(originalVector).GetNormalized(); + MCore::DualQuaternion vertexSkinningTransform = s_zeroDualQuaternion; + for (size_t influenceIndex = 0; influenceIndex < m_numberOfInfluencesPerVertex; ++influenceIndex) + { + const size_t vertexInfluenceIndex = vertexIndex * m_numberOfInfluencesPerVertex + influenceIndex; + + const AZ::u16 jointIndex = m_skinningInfluences[vertexInfluenceIndex].m_jointIndex; + const float jointWeight = m_skinningInfluences[vertexInfluenceIndex].m_jointWeight; + + const MCore::DualQuaternion& skinningDualQuaternion = m_skinningDualQuaternions.at(jointIndex); + + float flip = AZ::GetSign(vertexSkinningTransform.mReal.Dot(skinningDualQuaternion.mReal)); + vertexSkinningTransform += skinningDualQuaternion * jointWeight * flip; + } + // Normalizing the dual quaternion as the GPU shaders do. This will remove the scale from the transform. + vertexSkinningTransform.Normalize(); + return vertexSkinningTransform; } AZStd::unique_ptr ActorClothSkinning::Create( AZ::EntityId entityId, const MeshNodeInfo& meshNodeInfo, - const size_t numSimParticles) + const size_t numVertices, + const size_t numSimulatedVertices, + const AZStd::vector& meshRemappedVertices) { - AZStd::vector skinningData; - if (!Internal::ObtainSkinningData(entityId, meshNodeInfo, numSimParticles, skinningData)) + AZStd::vector skinningInfluences; + if (!Internal::ObtainSkinningInfluences(entityId, meshNodeInfo, numVertices, skinningInfluences)) { return nullptr; } - if (numSimParticles != skinningData.size()) - { - AZ_Error("ActorClothSkinning", false, - "Number of simulation particles (%zu) doesn't match with skinning data obtained (%zu)", - numSimParticles, skinningData.size()); - return nullptr; - } - AZStd::unique_ptr actorClothSkinning; const auto skinningMethod = Internal::ObtainSkinningMethod(entityId); switch (skinningMethod) @@ -355,27 +452,40 @@ namespace NvCloth return nullptr; } - // Insert the indices of the joints that influence the particle (weight is not 0) - AZStd::set jointIndices; - for (size_t particleIndex = 0; particleIndex < numSimParticles; ++particleIndex) + actorClothSkinning->m_numberOfInfluencesPerVertex = skinningInfluences.size() / numVertices; + if (actorClothSkinning->m_numberOfInfluencesPerVertex == 0) { - const SkinningInfo& skinningInfo = skinningData[particleIndex]; - for (size_t weightIndex = 0; weightIndex < skinningInfo.m_jointWeights.size(); ++weightIndex) - { - const AZ::u16 jointIndex = skinningInfo.m_jointIndices[weightIndex]; - const float jointWeight = skinningInfo.m_jointWeights[weightIndex]; + AZ_Error("ActorClothSkinning", false, + "Number of skinning joint influences per vertex is zero."); + return nullptr; + } - if (AZ::IsClose(jointWeight, 0.0f)) - { - continue; - } - - jointIndices.insert(jointIndex); - } + // Collect all indices of the joints that influence the vertices + AZStd::set jointIndices; + for (const auto& skinningInfluence : skinningInfluences) + { + jointIndices.insert(skinningInfluence.m_jointIndex); } actorClothSkinning->m_jointIndices.assign(jointIndices.begin(), jointIndices.end()); - actorClothSkinning->m_skinningData = AZStd::move(skinningData); + // Collect the indices for simulated and non-simulated vertices + actorClothSkinning->m_simulatedVertices.resize(numSimulatedVertices); + actorClothSkinning->m_nonSimulatedVertices.reserve(numVertices); + for (size_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex) + { + const int remappedIndex = meshRemappedVertices[vertexIndex]; + if (remappedIndex >= 0) + { + actorClothSkinning->m_simulatedVertices[remappedIndex] = vertexIndex; + } + else + { + actorClothSkinning->m_nonSimulatedVertices.emplace_back(vertexIndex); + } + } + actorClothSkinning->m_nonSimulatedVertices.shrink_to_fit(); + + actorClothSkinning->m_skinningInfluences = AZStd::move(skinningInfluences); return actorClothSkinning; } @@ -385,69 +495,6 @@ namespace NvCloth { } - void ActorClothSkinning::ApplySkinning( - const AZStd::vector& originalPositions, - AZStd::vector& positions, - const AZStd::vector& meshRemappedVertices) - { - if (!HasSkinningTransformData() || - originalPositions.empty() || - originalPositions.size() != positions.size() || - m_skinningData.size() != meshRemappedVertices.size()) - { - return; - } - - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth); - - AZStd::unordered_set skinnedIndices; - for (size_t index = 0; index < meshRemappedVertices.size(); ++index) - { - const int remappedIndex = meshRemappedVertices[index]; - if (remappedIndex >= 0 && !skinnedIndices.contains(remappedIndex)) - { - ComputeVertexSkinnningTransform(m_skinningData[index]); - - const AZ::Vector3 skinnedPosition = ComputeSkinningPosition(originalPositions[remappedIndex].GetAsVector3()); - positions[remappedIndex].Set(skinnedPosition, positions[remappedIndex].GetW()); // Avoid overwriting the w component - - skinnedIndices.emplace(remappedIndex); // Avoid computing this index again - } - } - } - - void ActorClothSkinning::ApplySkinninOnRemovedVertices( - const MeshClothInfo& originalData, - ClothComponentMesh::RenderData& renderData, - const AZStd::vector& meshRemappedVertices) - { - if (!HasSkinningTransformData() || - originalData.m_particles.empty() || - originalData.m_particles.size() != renderData.m_particles.size() || - originalData.m_particles.size() != m_skinningData.size() || - m_skinningData.size() != meshRemappedVertices.size()) - { - return; - } - - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Cloth); - - for (size_t index = 0; index < originalData.m_particles.size(); ++index) - { - if (meshRemappedVertices[index] < 0) - { - ComputeVertexSkinnningTransform(m_skinningData[index]); - - const AZ::Vector3 skinnedPosition = ComputeSkinningPosition(originalData.m_particles[index].GetAsVector3()); - renderData.m_particles[index].Set(skinnedPosition, renderData.m_particles[index].GetW()); // Avoid overwriting the w component - - renderData.m_tangents[index] = ComputeSkinningVector(originalData.m_tangents[index]); - renderData.m_bitangents[index] = ComputeSkinningVector(originalData.m_bitangents[index]); - renderData.m_normals[index] = ComputeSkinningVector(originalData.m_normals[index]); - } - } - } - void ActorClothSkinning::UpdateActorVisibility() { bool isVisible = true; diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.h b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.h index 8cf139c75a..01df1f87ef 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.h +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ActorClothSkinning.h @@ -12,6 +12,7 @@ #pragma once +#include #include #include @@ -22,14 +23,14 @@ namespace NvCloth { struct MeshNodeInfo; - //! Skinning information of a particle. - struct SkinningInfo + //! One skinning influence of a vertex. + struct SkinningInfluence { - //! Weights of each joint that influence the particle. - AZStd::vector m_jointWeights; + //! Weight of the joint that influences the vertex. + float m_jointWeight = 0.0f; - //! List of joints that influence the particle. - AZStd::vector m_jointIndices; + //! Index of the joint that influences the vertex. + AZ::u16 m_jointIndex = AZStd::numeric_limits::max(); }; //! Class to retrieve skinning information from an actor on the same entity @@ -44,7 +45,9 @@ namespace NvCloth static AZStd::unique_ptr Create( AZ::EntityId entityId, const MeshNodeInfo& meshNodeInfo, - const size_t numSimParticles); + const size_t numVertices, + const size_t numSimulatedVertices, + const AZStd::vector& meshRemappedVertices); explicit ActorClothSkinning(AZ::EntityId entityId); @@ -53,17 +56,15 @@ namespace NvCloth //! Applies skinning to a list of positions. //! @note w components are not affected. - void ApplySkinning( + virtual void ApplySkinning( const AZStd::vector& originalPositions, - AZStd::vector& positions, - const AZStd::vector& meshRemappedVertices); + AZStd::vector& positions) = 0; //! Applies skinning to a list of positions and vectors whose vertices - //! have not been used for simulation (remapped index is negative). - void ApplySkinninOnRemovedVertices( + //! have not been used for simulation. + virtual void ApplySkinningOnNonSimulatedVertices( const MeshClothInfo& originalData, - ClothComponentMesh::RenderData& renderData, - const AZStd::vector& meshRemappedVertices); + ClothComponentMesh::RenderData& renderData) = 0; //! Updates visibility variables. void UpdateActorVisibility(); @@ -75,24 +76,20 @@ namespace NvCloth bool WasActorVisible() const; protected: - //! Returns true if it has valid skinning trasform data. - virtual bool HasSkinningTransformData() = 0; - - //! Computes the skinnning transformation to apply to a vertex data. - virtual void ComputeVertexSkinnningTransform(const SkinningInfo& skinningInfo) = 0; - - //! Computes skinning on a position. - virtual AZ::Vector3 ComputeSkinningPosition(const AZ::Vector3& originalPosition) = 0; - - //! Computes skinning on a vector. - virtual AZ::Vector3 ComputeSkinningVector(const AZ::Vector3& originalVector) = 0; - AZ::EntityId m_entityId; - // Skinning information of all particles - AZStd::vector m_skinningData; + size_t m_numberOfInfluencesPerVertex = 0; - // Collection of skeleton joint indices that influence the particles + // Skinning influences of all vertices + AZStd::vector m_skinningInfluences; + + // Indices to skinning influences that are part of the simulation + AZStd::vector m_simulatedVertices; + + // Indices to skinning influences that are not part of the simulation + AZStd::vector m_nonSimulatedVertices; + + // Collection of skeleton joint indices that influence the vertices AZStd::vector m_jointIndices; // Visibility variables diff --git a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp index 740518b61a..52c93ea672 100644 --- a/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp +++ b/Gems/NvCloth/Code/Source/Components/ClothComponentMesh/ClothComponentMesh.cpp @@ -184,7 +184,12 @@ namespace NvCloth m_actorClothColliders = ActorClothColliders::Create(m_entityId); // It will return a valid instance if it's an actor with skinning data. - m_actorClothSkinning = ActorClothSkinning::Create(m_entityId, m_meshNodeInfo, m_meshClothInfo.m_particles.size()); + m_actorClothSkinning = ActorClothSkinning::Create( + m_entityId, + m_meshNodeInfo, + m_meshClothInfo.m_particles.size(), + m_cloth->GetParticles().size(), + m_meshRemappedVertices); m_numberOfClothSkinningUpdates = 0; m_clothConstraints = ClothConstraints::Create( @@ -363,7 +368,7 @@ namespace NvCloth { // Update skinning for all particles and apply it to cloth AZStd::vector particles = m_cloth->GetParticles(); - m_actorClothSkinning->ApplySkinning(m_cloth->GetInitialParticles(), particles, m_meshRemappedVertices); + m_actorClothSkinning->ApplySkinning(m_cloth->GetInitialParticles(), particles); m_cloth->SetParticles(AZStd::move(particles)); m_cloth->DiscardParticleDelta(); } @@ -379,8 +384,8 @@ namespace NvCloth if (m_actorClothSkinning) { - m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetMotionConstraints(), m_motionConstraints, m_meshRemappedVertices); - m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetSeparationConstraints(), m_separationConstraints, m_meshRemappedVertices); + m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetMotionConstraints(), m_motionConstraints); + m_actorClothSkinning->ApplySkinning(m_clothConstraints->GetSeparationConstraints(), m_separationConstraints); } m_cloth->GetClothConfigurator()->SetMotionConstraints(m_motionConstraints); @@ -404,7 +409,7 @@ namespace NvCloth if (m_config.m_removeStaticTriangles && m_actorClothSkinning) { // Apply skinning to the non-simulated part of the mesh. - m_actorClothSkinning->ApplySkinninOnRemovedVertices(m_meshClothInfo, renderData, m_meshRemappedVertices); + m_actorClothSkinning->ApplySkinningOnNonSimulatedVertices(m_meshClothInfo, renderData); } // Calculate normals of the cloth particles (simplified mesh). diff --git a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothSkinningTest.cpp b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothSkinningTest.cpp index 75cff2da04..3fba04f695 100644 --- a/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothSkinningTest.cpp +++ b/Gems/NvCloth/Code/Tests/Components/ClothComponentMesh/ActorClothSkinningTest.cpp @@ -98,7 +98,7 @@ namespace UnitTest { AZ::EntityId entityId; AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(entityId, {}, 0); + NvCloth::ActorClothSkinning::Create(entityId, {}, 0, 0, {}); EXPECT_TRUE(actorClothSkinning.get() == nullptr); } @@ -107,7 +107,7 @@ namespace UnitTest { AZ::EntityId entityId; AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(entityId, MeshNodeInfo, MeshRemappedVertices.size()); + NvCloth::ActorClothSkinning::Create(entityId, MeshNodeInfo, MeshVertices.size(), MeshVertices.size(), MeshRemappedVertices); EXPECT_TRUE(actorClothSkinning.get() == nullptr); } @@ -122,7 +122,7 @@ namespace UnitTest } AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), {}, 0); + NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), {}, 0, 0, {}); EXPECT_TRUE(actorClothSkinning.get() == nullptr); } @@ -139,7 +139,7 @@ namespace UnitTest } AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size()); + NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshVertices.size(), MeshRemappedVertices); EXPECT_TRUE(actorClothSkinning.get() == nullptr); } @@ -156,7 +156,7 @@ namespace UnitTest } AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size()); + NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshVertices.size(), MeshRemappedVertices); EXPECT_TRUE(actorClothSkinning.get() != nullptr); } @@ -184,7 +184,7 @@ namespace UnitTest } AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size()); + NvCloth::ActorClothSkinning::Create(actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshVertices.size(), MeshRemappedVertices); ASSERT_TRUE(actorClothSkinning.get() != nullptr); const AZStd::vector clothParticles = {{ @@ -195,7 +195,7 @@ namespace UnitTest AZStd::vector skinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f)); actorClothSkinning->UpdateSkinning(); - actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles, MeshRemappedVertices); + actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles); EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticles)); @@ -208,7 +208,7 @@ namespace UnitTest AZStd::vector newSkinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f)); actorClothSkinning->UpdateSkinning(); - actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles, MeshRemappedVertices); + actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles); const AZ::Transform diffTransform = AZ::Transform::CreateRotationY(AZ::DegToRad(90.0f)); const AZStd::vector clothParticlesResult = {{ @@ -245,7 +245,7 @@ namespace UnitTest } AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size()); + NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshVertices.size(), MeshRemappedVertices); ASSERT_TRUE(actorClothSkinning.get() != nullptr); const AZStd::vector clothParticles = {{ @@ -256,7 +256,7 @@ namespace UnitTest AZStd::vector skinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f)); actorClothSkinning->UpdateSkinning(); - actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles, MeshRemappedVertices); + actorClothSkinning->ApplySkinning(clothParticles, skinnedClothParticles); EXPECT_THAT(skinnedClothParticles, ::testing::Pointwise(ContainerIsCloseTolerance(Tolerance), clothParticles)); @@ -271,7 +271,7 @@ namespace UnitTest AZStd::vector newSkinnedClothParticles(clothParticles.size(), NvCloth::SimParticleFormat(0.0f, 0.0f, 0.0f, 1.0f)); actorClothSkinning->UpdateSkinning(); - actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles, MeshRemappedVertices); + actorClothSkinning->ApplySkinning(clothParticles, newSkinnedClothParticles); const AZStd::vector clothParticlesResult = {{ NvCloth::SimParticleFormat(-48.4177f, -31.9446f, 45.2279f, 1.0f), @@ -294,7 +294,7 @@ namespace UnitTest } AZStd::unique_ptr actorClothSkinning = - NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size()); + NvCloth::ActorClothSkinning::Create(m_actorComponent->GetEntityId(), MeshNodeInfo, MeshVertices.size(), MeshVertices.size(), MeshRemappedVertices); ASSERT_TRUE(actorClothSkinning.get() != nullptr); EXPECT_FALSE(actorClothSkinning->IsActorVisible()); diff --git a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp index 516b958adb..05ac4b1363 100644 --- a/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp +++ b/Gems/PhysX/Code/Editor/Source/Components/EditorSystemComponent.cpp @@ -48,11 +48,6 @@ namespace PhysX AzToolsFramework::EditorRequests::Bus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor); ISurfaceTypeEnumerator* surfaceTypeEnumerator = nullptr; - if (editor) - { - surfaceTypeEnumerator = editor->Get3DEngine()->GetMaterialManager()->GetSurfaceTypeManager()->GetEnumerator(); - } - if (surfaceTypeEnumerator) { // Enumerate through CryEngine surface types and create a Physics API material for each of them diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index e1ea3addec..2dc8fc97ec 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -345,7 +345,6 @@ namespace PhysX AzToolsFramework::BoxManipulatorRequestBus::Handler::BusConnect( AZ::EntityComponentIdPair(GetEntityId(), GetId())); ColliderShapeRequestBus::Handler::BusConnect(GetEntityId()); - LmbrCentral::MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); AZ::Render::MeshComponentNotificationBus::Handler::BusConnect(GetEntityId()); EditorColliderComponentRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(GetEntityId(), GetId())); m_nonUniformScaleChangedHandler = AZ::NonUniformScaleChangedEvent::Handler( @@ -394,7 +393,6 @@ namespace PhysX m_nonUniformScaleChangedHandler.Disconnect(); EditorColliderComponentRequestBus::Handler::BusDisconnect(); AZ::Render::MeshComponentNotificationBus::Handler::BusDisconnect(); - LmbrCentral::MeshComponentNotificationBus::Handler::BusDisconnect(); ColliderShapeRequestBus::Handler::BusDisconnect(); AzToolsFramework::BoxManipulatorRequestBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); @@ -1179,17 +1177,7 @@ namespace PhysX AZ::Render::MeshComponentRequestBus::EventResult(atomMeshAsset, GetEntityId(), &AZ::Render::MeshComponentRequestBus::Events::GetModelAsset); - if (atomMeshAsset.GetId().IsValid()) - { - return atomMeshAsset; - } - - // Try legacy render MeshComponent - AZ::Data::Asset legacyMeshAsset; - LmbrCentral::MeshComponentRequestBus::EventResult(legacyMeshAsset, - GetEntityId(), &LmbrCentral::MeshComponentRequests::GetMeshAsset); - - return legacyMeshAsset; + return atomMeshAsset; } void EditorColliderComponent::SetCollisionMeshFromRender() @@ -1264,14 +1252,6 @@ namespace PhysX renderMeshAsset.GetHint().c_str()); } } - - void EditorColliderComponent::OnMeshCreated([[maybe_unused]] const AZ::Data::Asset& asset) - { - if (ShouldUpdateCollisionMeshFromRender()) - { - SetCollisionMeshFromRender(); - } - } void EditorColliderComponent::OnModelReady([[maybe_unused]] const AZ::Data::Asset& modelAsset, [[maybe_unused]] const AZ::Data::Instance& model) diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.h b/Gems/PhysX/Code/Source/EditorColliderComponent.h index f179525802..e78be1b959 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.h +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.h @@ -32,8 +32,6 @@ #include #include -#include - #include #include #include @@ -105,7 +103,6 @@ namespace PhysX , private PhysX::MeshColliderComponentRequestsBus::Handler , private AZ::TransformNotificationBus::Handler , private PhysX::ColliderShapeRequestBus::Handler - , private LmbrCentral::MeshComponentNotificationBus::Handler , private AZ::Render::MeshComponentNotificationBus::Handler , private PhysX::EditorColliderComponentRequestBus::Handler , private Physics::WorldBodyRequestBus::Handler @@ -175,9 +172,6 @@ namespace PhysX AZ::Transform GetCurrentTransform() override; AZ::Vector3 GetBoxScale() override; - // LmbrCentral::MeshComponentNotificationBus - void OnMeshCreated(const AZ::Data::Asset& asset) override; - // AZ::Render::MeshComponentNotificationBus void OnModelReady(const AZ::Data::Asset& modelAsset, const AZ::Data::Instance& model) override; diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp index 8be67fe89b..592a8e2a75 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp @@ -290,7 +290,7 @@ namespace AZ::SceneGenerationComponents const bool hasBlendShapes = HasAnyBlendShapeChild(graph, nodeIndex); - auto [optimizedMesh, optimizedUVs, optimizedTangents, optimizedBitangents, optimizedVertexColors, optimizedSkinWeights] = OptimizeMesh(mesh, uvDatas, tangentDatas, bitangentDatas, colorDatas, skinWeightDatas, meshGroup, hasBlendShapes); + auto [optimizedMesh, optimizedUVs, optimizedTangents, optimizedBitangents, optimizedVertexColors, optimizedSkinWeights] = OptimizeMesh(mesh, mesh, uvDatas, tangentDatas, bitangentDatas, colorDatas, skinWeightDatas, meshGroup, hasBlendShapes); const NodeIndex optimizedMeshNodeIndex = graph.AddChild(graph.GetNodeParent(nodeIndex), name.c_str(), AZStd::move(optimizedMesh)); @@ -322,7 +322,7 @@ namespace AZ::SceneGenerationComponents for (const NodeIndex& blendShapeNodeIndex : nodeIndexes(Containers::MakeDerivedFilterView(childNodes(nodeIndex)))) { const IBlendShapeData* blendShapeNode = static_cast(graph.GetNodeContent(blendShapeNodeIndex).get()); - auto [optimizedBlendShape, _1, _2, _3 , _4, _5] = OptimizeMesh(blendShapeNode, {}, {}, {}, {}, {}, meshGroup, hasBlendShapes); + auto [optimizedBlendShape, _1, _2, _3 , _4, _5] = OptimizeMesh(blendShapeNode, mesh, {}, {}, {}, {}, {}, meshGroup, hasBlendShapes); const AZStd::string optimizedName {graph.GetNodeName(blendShapeNodeIndex).GetName(), graph.GetNodeName(blendShapeNodeIndex).GetNameLength()}; const NodeIndex optimizedNodeIndex = graph.AddChild(optimizedMeshNodeIndex, optimizedName.c_str(), AZStd::move(optimizedBlendShape)); @@ -383,6 +383,7 @@ namespace AZ::SceneGenerationComponents AZStd::unique_ptr > MeshOptimizerComponent::OptimizeMesh( const MeshDataType* meshData, + const IMeshData* baseMesh, const AZStd::vector>& uvs, const AZStd::vector>& tangents, const AZStd::vector>& bitangents, @@ -441,7 +442,7 @@ namespace AZ::SceneGenerationComponents const AZ::u32 faceCount = meshData->GetFaceCount(); for (AZ::u32 faceIndex = 0; faceIndex < faceCount; ++faceIndex) { - meshBuilder.BeginPolygon(GetFaceMaterialId(meshData, faceIndex)); + meshBuilder.BeginPolygon(baseMesh->GetFaceMaterialId(faceIndex)); for (const AZ::u32 vertexIndex : meshData->GetFaceInfo(faceIndex).vertexIndex) { const int orgVertexNumber = meshData->GetUsedPointIndexForControlPoint(meshData->GetControlPointIndex(vertexIndex)); @@ -584,15 +585,6 @@ namespace AZ::SceneGenerationComponents ); } - unsigned int MeshOptimizerComponent::GetFaceMaterialId([[maybe_unused]] const AZ::SceneAPI::DataTypes::IBlendShapeData* meshData, [[maybe_unused]] unsigned int index) - { - return 0; - } - unsigned int MeshOptimizerComponent::GetFaceMaterialId(const AZ::SceneAPI::DataTypes::IMeshData* meshData, unsigned int index) - { - return meshData->GetFaceMaterialId(index); - } - void MeshOptimizerComponent::AddFace(AZ::SceneData::GraphData::BlendShapeData* blendShape, unsigned int index1, unsigned int index2, unsigned int index3, [[maybe_unused]] unsigned int faceMaterialId) { blendShape->AddFace({index1, index2, index3}); diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.h b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.h index ee8fa5afe5..e499f30e2e 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.h +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.h @@ -66,6 +66,7 @@ namespace AZ::SceneGenerationComponents AZStd::unique_ptr > OptimizeMesh( const MeshDataType* meshData, + const SceneAPI::DataTypes::IMeshData* baseMesh, const AZStd::vector>& uvs, const AZStd::vector>& tangents, const AZStd::vector>& bitangents, @@ -74,9 +75,6 @@ namespace AZ::SceneGenerationComponents const AZ::SceneAPI::DataTypes::IMeshGroup& meshGroup, bool hasBlendShapes); - static unsigned int GetFaceMaterialId(const AZ::SceneAPI::DataTypes::IBlendShapeData* meshData, unsigned int index); - static unsigned int GetFaceMaterialId(const AZ::SceneAPI::DataTypes::IMeshData* meshData, unsigned int index); - static void AddFace(AZ::SceneData::GraphData::BlendShapeData* blendShape, unsigned int index1, unsigned int index2, unsigned int index3, unsigned int faceMaterialId); static void AddFace(AZ::SceneData::GraphData::MeshData* mesh, unsigned int index1, unsigned int index2, unsigned int index3, unsigned int faceMaterialId); }; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja index 27498a2aec..71681ed73b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja @@ -186,21 +186,16 @@ void {{attribute_QualifiedName}}::Reflect(AZ::ReflectContext* context) ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) {% if attribute_Category is defined %} - ->Attribute(AZ::Edit::Attributes::Category, "{{ attribute_Category }}") + ->Attribute(AZ::Edit::Attributes::Category, "{{ attribute_Category }}") {%- endif %} - {% if attribute_Icon is defined %} - ->Attribute(AZ::Edit::Attributes::Icon, "{{ attribute_Icon }}") + ->Attribute(AZ::Edit::Attributes::Icon, "{{ attribute_Icon }}") {%- endif %} - {% if attribute_Deprecated is defined %} - ->Attribute(AZ::Edit::Attributes::Deprecated, "{{ attribute_Deprecated }}") + ->Attribute(AZ::Edit::Attributes::Deprecated, "{{ attribute_Deprecated }}") {%- endif %} - {% set uihandler = 'AZ::Edit::UIHandlers::Default' %} - -{% for Property in Class.iter('Property') %} -{% for item in Property.iter('PropertyData') %} +{% for item in Class.iter('Property') %} {% if item.attrib['UIHandler'] is defined %} {% set uihandler = item.attrib['UIHandler'] %} {% endif %} @@ -208,12 +203,11 @@ void {{attribute_QualifiedName}}::Reflect(AZ::ReflectContext* context) {% if item.attrib['Description'] is defined %} {% set description = item.attrib['Description'] %} {% endif %} - // {{ item.attrib['Name'] }} - ->DataElement({{ uihandler }}, &{{ attribute_Name }}::{{ Property.attrib['Name'] }}, "{{ item.attrib['Name'] }}", "{{ description }}") -{% for EditAttribute in Property.iter('EditAttribute') %} - ->Attribute({{ EditAttribute.attrib['Key'] }}, {{ EditAttribute.attrib['Value'] }}) -{% endfor %} -{% endfor %} + // {{ item.attrib['Name'] }} + ->DataElement({{ uihandler }}, &{{ attribute_Name }}::{{ item.attrib['Name'] }}, "{{ item.attrib['Name'] }}", "{{ description }}") +{% for EditAttribute in item.iter('EditAttribute') %} + ->Attribute({{ EditAttribute.attrib['Key'] }}, {{ EditAttribute.attrib['Value'] }}) +{% endfor %} {% endfor %} ; } diff --git a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h index cb3c9cdccb..7f026edf58 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h +++ b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h @@ -122,6 +122,8 @@ namespace ScriptCanvasTests ::Nodes::InputTypeExampleNode::Reflect(m_behaviorContext); ::Nodes::BranchInputTypeExampleNode::Reflect(m_serializeContext); ::Nodes::BranchInputTypeExampleNode::Reflect(m_behaviorContext); + ::Nodes::PropertyExampleNode::Reflect(m_serializeContext); + ::Nodes::PropertyExampleNode::Reflect(m_behaviorContext); TestNodeableObject::Reflect(m_serializeContext); TestNodeableObject::Reflect(m_behaviorContext); diff --git a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/NodeableTestingLibrary.cpp b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/NodeableTestingLibrary.cpp index 6a9f7fd6c3..5d8574fb10 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/NodeableTestingLibrary.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/NodeableTestingLibrary.cpp @@ -44,6 +44,7 @@ namespace ScriptCanvasTesting ScriptCanvas::Library::AddNodeToRegistry(nodeRegistry); ScriptCanvas::Library::AddNodeToRegistry(nodeRegistry); ScriptCanvas::Library::AddNodeToRegistry(nodeRegistry); + ScriptCanvas::Library::AddNodeToRegistry(nodeRegistry); } AZStd::vector NodeableTestingLibrary::GetComponentDescriptors() @@ -53,7 +54,8 @@ namespace ScriptCanvasTesting ::Nodes::BranchMethodSharedDataSlotExampleNode::CreateDescriptor(), ::Nodes::ReturnTypeExampleNode::CreateDescriptor(), ::Nodes::InputTypeExampleNode::CreateDescriptor(), - ::Nodes::BranchInputTypeExampleNode::CreateDescriptor() + ::Nodes::BranchInputTypeExampleNode::CreateDescriptor(), + ::Nodes::PropertyExampleNode::CreateDescriptor() }); } } diff --git a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.ScriptCanvasNodeable.xml b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.ScriptCanvasNodeable.xml index efebbefce7..0be3c8c81a 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.ScriptCanvasNodeable.xml +++ b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.ScriptCanvasNodeable.xml @@ -32,7 +32,7 @@ - + @@ -51,13 +51,27 @@ Namespace="None" Description="Example of passing as input by value, pointer and reference."> - + - + - + + + + + + + diff --git a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.cpp b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.cpp index 154508d5f1..e2e425fb57 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.cpp @@ -66,5 +66,15 @@ namespace ScriptCanvasTesting { input.clear(); } + + void PropertyExample::In() + { + for ([[maybe_unused]] auto& num : Numbers) + { + AZ_TracePrintf("ScriptCanvas", "%f", num); + } + + AZ_TracePrintf("ScriptCanvas", "Slang: %s", Slang.c_str()); + } } } diff --git a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.h b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.h index 7bcfed8bb4..8c19e1916c 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.h +++ b/Gems/ScriptCanvasTesting/Code/Source/Nodes/Nodeables/ValuePointerReferenceExample.h @@ -48,5 +48,11 @@ namespace ScriptCanvasTesting { SCRIPTCANVAS_NODE(InputTypeExample); }; + + class PropertyExample + : public ScriptCanvas::Nodeable + { + SCRIPTCANVAS_NODE(PropertyExample); + }; } } diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Normal.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Pressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Sliced_Selected.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Normal.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Pressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Button_Stretched_Selected.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check_Background.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check_Background.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Check_Background.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Cross.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Cross.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Cross.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Off.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Off.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_Off.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/CheckBox_On.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_On.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/CheckBox_On.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Disabled.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Disabled.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Hover.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Hover.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Hover.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkbox_Background_Normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Checkered.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Disabled.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Disabled.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Hover.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Hover.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Hover.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Background_Normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Sliced.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Sliced.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Sliced.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Stretch.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Stretch.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Fill_Stretch.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Manipulator.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Manipulator.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Manipulator.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Sliced.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Sliced.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Sliced.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Stretch.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Stretch.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Slider_Track_Stretch.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Normal.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Pressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.assetinfo b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.exportsettings b/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/UiBasics/Assets/Textures/Basic/Text_Input_Sliced_Selected.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Arrow.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Arrow.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Arrow.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowL.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowL.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowL.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowR.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowR.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowR.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowU.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowU.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_ArrowU.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Button.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Button.tif.assetinfo new file mode 100644 index 0000000000..95b548a2eb --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Button.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Menu.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Menu.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/Dropdown_Menu.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Disabled.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Hover.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Hover.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Hover.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Background_Normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Dot.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Dot.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/RadioButton_Dot.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/button_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_disabled.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/button_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_normal.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/button_normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_disabled.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_hover.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_hover.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_hover.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_normal.tif.assetinfo new file mode 100644 index 0000000000..2eb5be8e93 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_box_normal.tif.assetinfo @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_check.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_check.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/checkbox_check.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_handle.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_handle.tif.assetinfo new file mode 100644 index 0000000000..95b548a2eb --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_handle.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_horiz_track.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_horiz_track.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_horiz_track.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_vert_track.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_vert_track.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/scrollbar_vert_track.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_disabled.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_fill_normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_disabled.tif.assetinfo new file mode 100644 index 0000000000..95b548a2eb --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_handle_normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_disabled.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_normal.tif.assetinfo new file mode 100644 index 0000000000..61b2832ff3 --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/slider_track_normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_disabled.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_disabled.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_disabled.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_hover.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_hover.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_hover.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_normal.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_normal.tif.assetinfo new file mode 100644 index 0000000000..c6f6ca1e9c --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/textinput_normal.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/UiBasics/Assets/UI/Textures/Prefab/tooltip_sliced.tif.assetinfo b/Gems/UiBasics/Assets/UI/Textures/Prefab/tooltip_sliced.tif.assetinfo new file mode 100644 index 0000000000..dd1d22706e --- /dev/null +++ b/Gems/UiBasics/Assets/UI/Textures/Prefab/tooltip_sliced.tif.assetinfo @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp b/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp index ef2b52f05d..c3aa910b47 100644 --- a/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp +++ b/Gems/Vegetation/Code/Tests/DynamicSliceInstanceSpawnerTests.cpp @@ -274,8 +274,7 @@ namespace UnitTest EXPECT_TRUE(instanceSpawner1 == instanceSpawner2); } - // [SPEC-6600] This test intermittently fails on automated builds, so disabling temporarily until root cause identified - TEST_F(DynamicSliceInstanceSpawnerTests, DISABLED_DifferentSpawnersAreNotEqual) + TEST_F(DynamicSliceInstanceSpawnerTests, DifferentSpawnersAreNotEqual) { // Two spawners with different data should *not* be data-equivalent. @@ -289,9 +288,7 @@ namespace UnitTest EXPECT_TRUE(!(instanceSpawner1 == instanceSpawner2)); } - // [LY-118267] This test intermittently fails on automated builds, so disabling temporarily until the root cause - // can be identified - TEST_F(DynamicSliceInstanceSpawnerTests, DISABLED_LoadAndUnloadAssets) + TEST_F(DynamicSliceInstanceSpawnerTests, LoadAndUnloadAssets) { // The spawner should successfully load/unload assets without errors. @@ -311,8 +308,7 @@ namespace UnitTest Vegetation::DescriptorNotificationBus::Handler::BusDisconnect(); } - // [SPEC-6600] This test intermittently fails on automated builds, so disabling temporarily until root cause identified - TEST_F(DynamicSliceInstanceSpawnerTests, DISABLED_CreateAndDestroyInstance) + TEST_F(DynamicSliceInstanceSpawnerTests, CreateAndDestroyInstance) { // The spawner should successfully create and destroy an instance without errors. diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/OccluderArea_white.png b/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/OccluderArea_white.png deleted file mode 100644 index 5554bfc38e..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/OccluderArea_white.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:46757cf327aa9ed60ded1f3025140bc065569634f69e5aaba0b83086fa7642e0 -size 786 diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/Portal_white.png b/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/Portal_white.png deleted file mode 100644 index fc72adc85e..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/Portal_white.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:44150d202f318598e939bf29a543b6edaa0d2cf7455989a2d0da916ba7c83384 -size 833 diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/VisArea_white.png b/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/VisArea_white.png deleted file mode 100644 index 48a7af896a..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/Disabled/VisArea_white.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:44570118c315725d13affcc87b0eb4fb01f01cf67f9da0a4e066a347e096a36f -size 757 diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/OccluderArea.svg b/Gems/Visibility/Assets/Editor/Icons/Components/OccluderArea.svg deleted file mode 100644 index aa8840a798..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/OccluderArea.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - icon / Rendering / OccluderArea - Created with Sketch. - - - - - - - - - - diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/Portal.svg b/Gems/Visibility/Assets/Editor/Icons/Components/Portal.svg deleted file mode 100644 index 967a891222..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/Portal.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - icon / Rendering / Portal - Created with Sketch. - - - - - - - - - - diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/OccluderArea.png b/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/OccluderArea.png deleted file mode 100644 index 3e98e852dd..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/OccluderArea.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7288c80d906ec59271ccd4db168d318f4c5b4fd65fca6077acbf4aaeb76b9e24 -size 4081 diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/Portal.png b/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/Portal.png deleted file mode 100644 index b7198e5803..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/Portal.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:486816ea8e6cb090f8d78e26d9ed6a73aca8e5d6c5fb6bcb3cb2fff8277053db -size 4687 diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/VisArea.png b/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/VisArea.png deleted file mode 100644 index e2d0c7f803..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/Viewport/VisArea.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aca391fc79c7b5400465bcdaa3a1c21a0fbb3dd042420b6511ecf568048ee6ec -size 4558 diff --git a/Gems/Visibility/Assets/Editor/Icons/Components/VisArea.svg b/Gems/Visibility/Assets/Editor/Icons/Components/VisArea.svg deleted file mode 100644 index 389f4cf35d..0000000000 --- a/Gems/Visibility/Assets/Editor/Icons/Components/VisArea.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - icon / Rendering / VisArea - Created with Sketch. - - - - - - - - - - diff --git a/Gems/Visibility/Code/CMakeLists.txt b/Gems/Visibility/Code/CMakeLists.txt deleted file mode 100644 index c8650eea79..0000000000 --- a/Gems/Visibility/Code/CMakeLists.txt +++ /dev/null @@ -1,105 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -ly_add_target( - NAME Visibility.Static STATIC - NAMESPACE Gem - FILES_CMAKE - visibility_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - Source - PUBLIC - Include - BUILD_DEPENDENCIES - PUBLIC - Legacy::CryCommon -) - -ly_add_target( - NAME Visibility ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} - NAMESPACE Gem - FILES_CMAKE - visibility_shared_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - Source - PUBLIC - Include - BUILD_DEPENDENCIES - PRIVATE - Gem::Visibility.Static -) - -if(PAL_TRAIT_BUILD_HOST_TOOLS) - - ly_add_target( - NAME Visibility.Editor.Static STATIC - NAMESPACE Gem - FILES_CMAKE - visibility_editor_files.cmake - COMPILE_DEFINITIONS - PUBLIC - VISIBILITY_EDITOR - INCLUDE_DIRECTORIES - PRIVATE - Source - PUBLIC - Include - BUILD_DEPENDENCIES - PUBLIC - Legacy::Editor.Headers - Legacy::EditorCore - AZ::AzToolsFramework - Gem::Visibility.Static - ) - - ly_add_target( - NAME Visibility.Editor GEM_MODULE - - NAMESPACE Gem - FILES_CMAKE - visibility_editor_shared_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - Source - PUBLIC - Include - BUILD_DEPENDENCIES - PRIVATE - Gem::Visibility.Editor.Static - ) -endif() - -################################################################################ -# Tests -################################################################################ -if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) - if(PAL_TRAIT_BUILD_HOST_TOOLS) - ly_add_target( - NAME Visibility.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} - NAMESPACE Gem - FILES_CMAKE - visibility_editor_tests_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - Tests - Source - BUILD_DEPENDENCIES - PRIVATE - AZ::AzTest - Gem::Visibility.Editor.Static - ) - ly_add_googletest( - NAME Gem::Visibility.Editor.Tests - ) - endif() -endif() diff --git a/Gems/Visibility/Code/Include/EditorOccluderAreaComponentBus.h b/Gems/Visibility/Code/Include/EditorOccluderAreaComponentBus.h deleted file mode 100644 index f2714691cb..0000000000 --- a/Gems/Visibility/Code/Include/EditorOccluderAreaComponentBus.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include - -#include "OccluderAreaComponentBus.h" - -namespace Visibility -{ - /// Request bus for the EditorOccluderComponent. - class EditorOccluderAreaRequests - : public OccluderAreaRequests - , public AZ::FixedVertices - { - public: - virtual void SetDisplayFilled(bool displayFilled) = 0; - virtual void SetCullDistRatio(float cullDistRatio) = 0; - virtual void SetUseInIndoors(bool inDoors) = 0; - virtual void SetDoubleSide(bool doubleSided) = 0; - virtual void UpdateOccluderAreaObject() = 0; - - protected: - ~EditorOccluderAreaRequests() = default; - }; - - /// Type to inherit to implement EditorOccluderAreaComponentRequests - using EditorOccluderAreaRequestBus = AZ::EBus; - - /// Editor notification bus for EditorOccluderAreaComponent. - class EditorOccluderAreaNotifications - : public AZ::ComponentBus - { - public: - virtual void OnVerticesChangedInspector() {} - - protected: - ~EditorOccluderAreaNotifications() = default; - }; - - /// Type to inherit to implement EditorOccluderAreaNotifications. - using EditorOccluderAreaNotificationBus = AZ::EBus; - -} // namespace Visibility diff --git a/Gems/Visibility/Code/Include/EditorPortalComponentBus.h b/Gems/Visibility/Code/Include/EditorPortalComponentBus.h deleted file mode 100644 index c4ab43d8a0..0000000000 --- a/Gems/Visibility/Code/Include/EditorPortalComponentBus.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include - -#include "PortalComponentBus.h" - -namespace Visibility -{ - /// Request bus for the EditorPortalComponent. - class EditorPortalRequests - : public PortalRequests - , public AZ::FixedVertices - { - public: - virtual void SetHeight(float height) = 0; - virtual void SetDisplayFilled(bool filled) = 0; - virtual void SetAffectedBySun(bool affectedBySun) = 0; - virtual void SetViewDistRatio(float viewDistRatio) = 0; - virtual void SetSkyOnly(bool skyOnly) = 0; - virtual void SetOceanIsVisible(bool oceanVisible) = 0; - virtual void SetUseDeepness(bool useDeepness) = 0; - virtual void SetDoubleSide(bool doubleSided) = 0; - virtual void SetLightBlending(bool lightBending) = 0; - virtual void SetLightBlendValue(float lightBendAmount) = 0; - virtual void UpdatePortalObject() = 0; - - protected: - ~EditorPortalRequests() = default; - }; - - /// Type to inherit to implement EditorPortalComponentRequests - using EditorPortalRequestBus = AZ::EBus; - - /// Editor notification bus for EditorPortalComponent. - class EditorPortalNotifications - : public AZ::ComponentBus - { - public: - virtual void OnVerticesChangedInspector() {} - - protected: - ~EditorPortalNotifications() = default; - }; - - /// Type to inherit to implement EditorPortalNotifications. - using EditorPortalNotificationBus = AZ::EBus; - -} // namespace Visibility diff --git a/Gems/Visibility/Code/Include/EditorVisAreaComponentBus.h b/Gems/Visibility/Code/Include/EditorVisAreaComponentBus.h deleted file mode 100644 index 6803ea77a6..0000000000 --- a/Gems/Visibility/Code/Include/EditorVisAreaComponentBus.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include - -#include "VisAreaComponentBus.h" - -namespace Visibility -{ - /// Request bus for the EditorVisAreaComponent. - class EditorVisAreaComponentRequests - : public VisAreaComponentRequests - , public AZ::VariableVertices - { - public: - virtual void SetHeight(float height) = 0; - virtual void SetDisplayFilled(bool filled) = 0; - virtual void SetAffectedBySun(bool affectedBySun) = 0; - virtual void SetViewDistRatio(float viewDistRatio) = 0; - virtual void SetOceanIsVisible(bool oceanVisible) = 0; - virtual void UpdateVisAreaObject() = 0; - }; - - /// Type to inherit to implement EditorVisAreaComponentRequests. - using EditorVisAreaComponentRequestBus = AZ::EBus; - - /// Notification bus for the EditorVisAreaComponent. - class EditorVisAreaComponentNotifications - : public AZ::ComponentBus - , public AZ::VertexContainerNotificationInterface - { - public: - /// Called when a new vertex is added to the vis area. - void OnVertexAdded(size_t /*index*/) override {} - - /// Called when a vertex is removed from the vis area. - void OnVertexRemoved(size_t /*index*/) override {} - - /// Called when a vertex is updated. - void OnVertexUpdated(size_t /*index*/) override {} - - /// Called when all vertices on the vis area are set. - void OnVerticesSet(const AZStd::vector& /*vertices*/) override {} - - /// Called when all vertices are removed from the vis area. - void OnVerticesCleared() override {} - - protected: - ~EditorVisAreaComponentNotifications() = default; - }; - - /// Type to inherit to implement EditorVisAreaComponentNotifications. - using EditorVisAreaComponentNotificationBus = AZ::EBus; - -} // namespace Visibility diff --git a/Gems/Visibility/Code/Include/OccluderAreaComponentBus.h b/Gems/Visibility/Code/Include/OccluderAreaComponentBus.h deleted file mode 100644 index 21b66c14c1..0000000000 --- a/Gems/Visibility/Code/Include/OccluderAreaComponentBus.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -namespace Visibility -{ - /// Request bus for the OccluderAreaComponent. - class OccluderAreaRequests - { - public: - virtual bool GetDisplayFilled() = 0; - virtual float GetCullDistRatio() = 0; - virtual bool GetUseInIndoors() = 0; - virtual bool GetDoubleSide() = 0; - - protected: - ~OccluderAreaRequests() = default; - }; - - /// Type to inherit to implement OccluderAreaRequests. - using OccluderAreaRequestBus = AZ::EBus; - -} // namespace Visibility diff --git a/Gems/Visibility/Code/Include/PortalComponentBus.h b/Gems/Visibility/Code/Include/PortalComponentBus.h deleted file mode 100644 index 7de4cb4e80..0000000000 --- a/Gems/Visibility/Code/Include/PortalComponentBus.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -namespace Visibility -{ - // Request bus for the PortalComponent. - class PortalRequests - { - public: - virtual float GetHeight() = 0; - virtual bool GetDisplayFilled() = 0; - virtual bool GetAffectedBySun() = 0; - virtual float GetViewDistRatio() = 0; - virtual bool GetSkyOnly() = 0; - virtual bool GetOceanIsVisible() = 0; - virtual bool GetUseDeepness() = 0; - virtual bool GetDoubleSide() = 0; - virtual bool GetLightBlending() = 0; - virtual float GetLightBlendValue() = 0; - - protected: - ~PortalRequests() = default; - }; - - /// Type to inherit to implement PortalRequests. - using PortalRequestBus = AZ::EBus; - -} // namespace Visibility diff --git a/Gems/Visibility/Code/Include/VisAreaComponentBus.h b/Gems/Visibility/Code/Include/VisAreaComponentBus.h deleted file mode 100644 index 632e68ffc5..0000000000 --- a/Gems/Visibility/Code/Include/VisAreaComponentBus.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -namespace Visibility -{ - /// Request bus for the VisAreaComponent. - class VisAreaComponentRequests - { - public: - virtual float GetHeight() = 0; - virtual bool GetDisplayFilled() = 0; - virtual bool GetAffectedBySun() = 0; - virtual float GetViewDistRatio() = 0; - virtual bool GetOceanIsVisible() = 0; - - protected: - ~VisAreaComponentRequests() = default; - }; - - /// Type to inherit to implement VisAreaComponentRequests. - using VisAreaComponentRequestBus = AZ::EBus; - -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorOccluderAreaComponent.cpp b/Gems/Visibility/Code/Source/EditorOccluderAreaComponent.cpp deleted file mode 100644 index 9a88799a31..0000000000 --- a/Gems/Visibility/Code/Source/EditorOccluderAreaComponent.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "Visibility_precompiled.h" -#include "EditorOccluderAreaComponent.h" -#include "EditorOccluderAreaComponentMode.h" - -#include -#include -#include -#include -#include -#include - -// Include files needed for writing DisplayEntity functions that access the DisplayContext directly. -#include - -#include "MathConversion.h" - -namespace Visibility -{ - void EditorOccluderAreaComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides) - { - provides.push_back(AZ_CRC("EditorOccluderAreaService", 0xf943e16a)); - provides.push_back(AZ_CRC("OccluderAreaService", 0x2fefad66)); - provides.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - } - - void EditorOccluderAreaComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires) - { - requires.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - void EditorOccluderAreaComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - dependent.push_back(AZ_CRC("QuadShapeService", 0xe449b0fc)); - } - - void EditorOccluderAreaComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("EditorOccluderAreaService", 0xf943e16a)); - incompatible.push_back(AZ_CRC("OccluderAreaService", 0x2fefad66)); - incompatible.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - } - - void EditorOccluderAreaConfiguration::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1); - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("OccluderArea Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true); - - editContext->Class("OccluderArea Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &OccluderAreaConfiguration::m_displayFilled, "DisplayFilled", "Display the Occlude Area as a filled quad.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &OccluderAreaConfiguration::OnChange) - ->DataElement(AZ::Edit::UIHandlers::Default, &OccluderAreaConfiguration::m_cullDistRatio, "CullDistRatio", "The range of the culling effect.") - ->Attribute(AZ::Edit::Attributes::Max, 100.0f) - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &OccluderAreaConfiguration::OnChange) - ->DataElement(AZ::Edit::UIHandlers::Default, &OccluderAreaConfiguration::m_useInIndoors, "UseInIndoors", "Should this occluder work inside VisAreas.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &OccluderAreaConfiguration::OnChange) - ->DataElement(AZ::Edit::UIHandlers::Default, &OccluderAreaConfiguration::m_doubleSide, "DoubleSide", "Should this occlude from both sides.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &OccluderAreaConfiguration::OnChange) - ->DataElement(AZ::Edit::UIHandlers::Default, &OccluderAreaConfiguration::m_vertices, "Vertices", "Points that make up the OccluderArea.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &OccluderAreaConfiguration::OnVerticesChange) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; - } - } - } - - void EditorOccluderAreaComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(2) - ->Field("m_config", &EditorOccluderAreaComponent::m_config) - ->Field("ComponentMode", &EditorOccluderAreaComponent::m_componentModeDelegate) - ; - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("OccluderArea", "An area that blocks objects behind it from rendering.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/OccluderArea.png") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/OccluderArea.svg") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "http://docs.aws.amazon.com/console/lumberyard/userguide/occluder-area-component") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorOccluderAreaComponent::m_config, "m_config", "No Description") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorOccluderAreaComponent::m_componentModeDelegate, "Component Mode", "OccluderArea Component Mode") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ; - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("EditorOccluderAreaRequestBus") - ->Event("SetDisplayFilled", &EditorOccluderAreaRequestBus::Events::SetDisplayFilled) - ->Event("GetDisplayFilled", &EditorOccluderAreaRequestBus::Events::GetDisplayFilled) - ->VirtualProperty("DisplayFilled", "GetDisplayFilled", "SetDisplayFilled") - - ->Event("SetCullDistRatio", &EditorOccluderAreaRequestBus::Events::SetCullDistRatio) - ->Event("GetCullDistRatio", &EditorOccluderAreaRequestBus::Events::GetCullDistRatio) - ->VirtualProperty("CullDistRatio", "GetCullDistRatio", "SetCullDistRatio") - - ->Event("SetUseInIndoors", &EditorOccluderAreaRequestBus::Events::SetUseInIndoors) - ->Event("GetUseInIndoors", &EditorOccluderAreaRequestBus::Events::GetUseInIndoors) - ->VirtualProperty("UseInIndoors", "GetUseInIndoors", "SetUseInIndoors") - - ->Event("SetDoubleSide", &EditorOccluderAreaRequestBus::Events::SetDoubleSide) - ->Event("GetDoubleSide", &EditorOccluderAreaRequestBus::Events::GetDoubleSide) - ->VirtualProperty("DoubleSide", "GetDoubleSide", "SetDoubleSide") - ; - - behaviorContext->Class()->RequestBus("EditorOccluderAreaRequestBus"); - } - - EditorOccluderAreaConfiguration::Reflect(context); - } - - void EditorOccluderAreaConfiguration::OnChange() - { - EditorOccluderAreaRequestBus::Event(m_entityId, &EditorOccluderAreaRequests::UpdateOccluderAreaObject); - } - - void EditorOccluderAreaConfiguration::OnVerticesChange() - { - EditorOccluderAreaRequestBus::Event( - m_entityId, &EditorOccluderAreaRequests::UpdateOccluderAreaObject); - EditorOccluderAreaNotificationBus::Event( - m_entityId, &EditorOccluderAreaNotifications::OnVerticesChangedInspector); - } - - void EditorOccluderAreaConfiguration::SetEntityId(const AZ::EntityId entityId) - { - m_entityId = entityId; - } - - EditorOccluderAreaComponent::~EditorOccluderAreaComponent() - { - if (m_area) - { - GetIEditor()->Get3DEngine()->DeleteVisArea(m_area); - m_area = nullptr; - } - } - - void EditorOccluderAreaComponent::Activate() - { - Base::Activate(); - - const AZ::EntityId entityId = GetEntityId(); - m_config.SetEntityId(entityId); - - // NOTE: We create the vis-area here at activate, but destroy it in the destructor. - // We have to do this, otherwise the vis-area is not saved into the level. - // Unfortunately, at this time we cannot create the vis-areas at game runtime. - // This means that dynamic slices cannot effectively contain vis areas until we fix - // the core rendering system to allow that. - const auto visGUID = static_cast(entityId); - if(!m_area && GetIEditor()) - { - m_area = GetIEditor()->Get3DEngine()->CreateVisArea(visGUID); - } - - m_componentModeDelegate.ConnectWithSingleComponentMode< - EditorOccluderAreaComponent, EditorOccluderAreaComponentMode>( - AZ::EntityComponentIdPair(entityId, GetId()), this); - - EditorOccluderAreaRequestBus::Handler::BusConnect(entityId); - AZ::FixedVerticesRequestBus::Handler::BusConnect(entityId); - AZ::TransformNotificationBus::Handler::BusConnect(entityId); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(entityId); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(entityId); - AzFramework::BoundsRequestBus::Handler::BusConnect(entityId); - - UpdateOccluderAreaObject(); - } - - void EditorOccluderAreaComponent::Deactivate() - { - m_componentModeDelegate.Disconnect(); - - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - AZ::FixedVerticesRequestBus::Handler::BusDisconnect(); - EditorOccluderAreaRequestBus::Handler::BusDisconnect(); - - Base::Deactivate(); - } - - /// Update the object runtime after changes to the Configuration. - /// Called by the default RequestBus SetXXX implementations, - /// and used to initially set up the object the first time the - /// Configuration are set. - void EditorOccluderAreaComponent::UpdateOccluderAreaObject() - { - if (m_area) - { - AZStd::array verts; - - const Matrix34& wtm = AZTransformToLYTransform(GetWorldTM()); - for (size_t i = 0; i < m_config.m_vertices.size(); ++i) - { - verts[i] = wtm.TransformPoint(AZVec3ToLYVec3(m_config.m_vertices[i])); - } - - SVisAreaInfo info; - info.fHeight = 0; - info.vAmbientColor = Vec3(0, 0, 0); - info.bAffectedByOutLights = false; - info.bSkyOnly = false; - info.fViewDistRatio = m_config.m_cullDistRatio; - info.bDoubleSide = m_config.m_doubleSide; - info.bUseDeepness = false; - info.bUseInIndoors = m_config.m_useInIndoors; - info.bOceanIsVisible = false; - info.fPortalBlending = -1.0f; - - const AZStd::string name = AZStd::string("OcclArea_") + GetEntity()->GetName(); - GetIEditor()->Get3DEngine()->UpdateVisArea(m_area, &verts[0], verts.size(), name.c_str(), info, false); - - AzFramework::EntityBoundsUnionRequestBus::Broadcast( - &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId()); - } - } - - void EditorOccluderAreaComponent::SetDisplayFilled(const bool value) - { - m_config.m_displayFilled = value; - UpdateOccluderAreaObject(); - } - - bool EditorOccluderAreaComponent::GetDisplayFilled() - { - return m_config.m_displayFilled; - } - - void EditorOccluderAreaComponent::SetCullDistRatio(const float value) - { - m_config.m_cullDistRatio = value; - UpdateOccluderAreaObject(); - } - - float EditorOccluderAreaComponent::GetCullDistRatio() - { - return m_config.m_cullDistRatio; - } - - void EditorOccluderAreaComponent::SetUseInIndoors(const bool value) - { - m_config.m_useInIndoors = value; - UpdateOccluderAreaObject(); - } - - bool EditorOccluderAreaComponent::GetUseInIndoors() - { - return m_config.m_useInIndoors; - } - - void EditorOccluderAreaComponent::SetDoubleSide(const bool value) - { - m_config.m_doubleSide = value; - UpdateOccluderAreaObject(); - } - - bool EditorOccluderAreaComponent::GetDoubleSide() - { - return m_config.m_doubleSide; - } - - bool EditorOccluderAreaComponent::GetVertex(const size_t index, AZ::Vector3& vertex) const - { - if (index < m_config.m_vertices.size()) - { - vertex = m_config.m_vertices[index]; - return true; - } - - return false; - } - - bool EditorOccluderAreaComponent::UpdateVertex(const size_t index, const AZ::Vector3& vertex) - { - if (index < m_config.m_vertices.size()) - { - m_config.m_vertices[index] = vertex; - return true; - } - - return false; - } - - void EditorOccluderAreaComponent::OnTransformChanged(const AZ::Transform& /*local*/, [[maybe_unused]] const AZ::Transform& world) - { - UpdateOccluderAreaObject(); - } - - void EditorOccluderAreaComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - const AZ::Transform worldFromLocal = GetWorldTM(); - const AZ::Vector4 color(0.5f, 0.25f, 0.0f, 1.0f); - const AZ::Vector4 selectedColor(1.0f, 0.5f, 0.0f, 1.0f); - const float previousLineWidth = debugDisplay.GetLineWidth(); - - debugDisplay.DepthWriteOff(); - debugDisplay.PushMatrix(worldFromLocal); - debugDisplay.SetColor(IsSelected() ? selectedColor : color); - debugDisplay.SetLineWidth(5.0f); - debugDisplay.SetAlpha(0.8f); - - for (size_t i = 2; i < 4; i++) - { - // draw the plane - if (m_config.m_displayFilled) - { - debugDisplay.SetAlpha(0.3f); - debugDisplay.CullOff(); - debugDisplay.DrawTri(m_config.m_vertices[0], m_config.m_vertices[i - 1], m_config.m_vertices[i]); - debugDisplay.CullOn(); - debugDisplay.SetAlpha(0.8f); - } - - debugDisplay.DrawLine(m_config.m_vertices[i - 2], m_config.m_vertices[i - 1]); - debugDisplay.DrawLine(m_config.m_vertices[i - 1], m_config.m_vertices[i]); - } - - // draw the closing line - debugDisplay.DrawLine(m_config.m_vertices[3], m_config.m_vertices[0]); - - if (m_componentModeDelegate.AddedToComponentMode()) - { - AzToolsFramework::VertexContainerDisplay::DisplayVertexContainerIndices( - debugDisplay, AzToolsFramework::FixedVerticesArray(m_config.m_vertices), - GetWorldTM(), AZ::Vector3::CreateOne(), IsSelected()); - } - - debugDisplay.DepthWriteOn(); - debugDisplay.SetLineWidth(previousLineWidth); - debugDisplay.PopMatrix(); - } - - void EditorOccluderAreaComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - gameEntity->CreateComponent(m_config); - } - - AZ::Aabb EditorOccluderAreaComponent::GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/) - { - return GetWorldBounds(); - } - - bool EditorOccluderAreaComponent::EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/, const AZ::Vector3& src, - const AZ::Vector3& dir, float& distance) - { - const float rayLength = 1000.0f; - AZ::Vector3 scaledDir = dir * rayLength; - AZ::Vector3 end = src + scaledDir; - float t; - float intermediateT = std::numeric_limits::max(); - bool didHit = false; - - // Transform verts to world space for tris test - AZStd::array verts; - const AZ::Transform& wtm = GetWorldTM(); - for (size_t i = 0; i < m_config.m_vertices.size(); ++i) - { - verts[i] = wtm.TransformPoint(m_config.m_vertices[i]); - } - - AZ::Vector3 normal; - for (AZ::u8 i = 2; i < 4; ++i) - { - if (AZ::Intersect::IntersectSegmentTriangleCCW(src, end, verts[0], verts[i - 1], verts[i], normal, t) > 0) - { - intermediateT = AZStd::GetMin(t, intermediateT); - didHit = true; - } - //Else if here as we shouldn't successfully ccw and cw intersect at the same time - else if (AZ::Intersect::IntersectSegmentTriangle(src, end, verts[0], verts[i - 1], verts[i], normal, t) > 0) - { - intermediateT = AZStd::GetMin(t, intermediateT); - didHit = true; - } - } - - if (didHit) - { - distance = intermediateT * rayLength; - } - return didHit; - } - - AZ::Aabb EditorOccluderAreaComponent::GetWorldBounds() - { - return GetLocalBounds().GetTransformedAabb(GetWorldTM()); - } - - AZ::Aabb EditorOccluderAreaComponent::GetLocalBounds() - { - AZ::Aabb bbox = AZ::Aabb::CreateNull(); - for (const auto& vertex : m_config.m_vertices) - { - bbox.AddPoint(vertex); - } - return bbox; - } -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorOccluderAreaComponent.h b/Gems/Visibility/Code/Source/EditorOccluderAreaComponent.h deleted file mode 100644 index 0ac6528bc7..0000000000 --- a/Gems/Visibility/Code/Source/EditorOccluderAreaComponent.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#pragma once - -#include "OccluderAreaComponent.h" -#include "EditorOccluderAreaComponentBus.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Visibility -{ - class EditorOccluderAreaComponent; - - class EditorOccluderAreaConfiguration - : public OccluderAreaConfiguration - { - public: - AZ_TYPE_INFO_LEGACY(EditorOccluderAreaConfiguration, "{032F466F-25CB-5460-AC2F-B04236C87878}", OccluderAreaConfiguration); - AZ_CLASS_ALLOCATOR(EditorOccluderAreaConfiguration, AZ::SystemAllocator, 0); - - static void Reflect(AZ::ReflectContext* context); - - void OnChange() override; - void OnVerticesChange() override; - - void SetEntityId(AZ::EntityId entityId); - - private: - AZ::EntityId m_entityId; - }; - - class EditorOccluderAreaComponent - : public AzToolsFramework::Components::EditorComponentBase - , private EditorOccluderAreaRequestBus::Handler - , private AZ::FixedVerticesRequestBus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - , private AZ::TransformNotificationBus::Handler - , public AzFramework::BoundsRequestBus::Handler - { - friend class EditorOccluderAreaConfiguration; - - using Base = AzToolsFramework::Components::EditorComponentBase; - - public: - AZ_COMPONENT(EditorOccluderAreaComponent, "{1A209C7C-6C06-5AE6-AD60-22CD8D0DAEE3}", AzToolsFramework::Components::EditorComponentBase); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires); - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - - static void Reflect(AZ::ReflectContext* context); - - EditorOccluderAreaComponent() = default; - EditorOccluderAreaComponent(const EditorOccluderAreaComponent&) = delete; - EditorOccluderAreaComponent& operator=(const EditorOccluderAreaComponent&) = delete; - ~EditorOccluderAreaComponent(); - - // AZ::Component overrides ... - void Activate() override; - void Deactivate() override; - void BuildGameEntity(AZ::Entity* gameEntity) override; - - // TransformNotificationBus overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // EditorComponentSelectionRequestsBus overrides ... - AZ::Aabb GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& viewportInfo) override; - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, - const AZ::Vector3& dir, float& distance) override; - bool SupportsEditorRayIntersect() override { return true; } - - // BoundsRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - /// EditorOccluderAreaRequestBus overrides ... - void SetDisplayFilled(bool value) override; - bool GetDisplayFilled() override; - void SetCullDistRatio(float value) override; - float GetCullDistRatio() override; - void SetUseInIndoors(bool value) override; - bool GetUseInIndoors() override; - void SetDoubleSide(bool value) override; - bool GetDoubleSide() override; - bool GetVertex(size_t index, AZ::Vector3& vertex) const override; - bool UpdateVertex(size_t index, const AZ::Vector3& vertex) override; - size_t Size() const override { return m_config.m_vertices.size(); } - void UpdateOccluderAreaObject() override; - - private: - friend EditorOccluderAreaConfiguration; - - // AzFramework::EntityDebugDisplayEventBus overrides ... - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // Reflected members - EditorOccluderAreaConfiguration m_config; - - using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate; - ComponentModeDelegate m_componentModeDelegate; ///< Responsible for detecting ComponentMode activation - ///< and creating a concrete ComponentMode. - - // Unreflected members - IVisArea* m_area = nullptr; - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorOccluderAreaComponentMode.cpp b/Gems/Visibility/Code/Source/EditorOccluderAreaComponentMode.cpp deleted file mode 100644 index 0ab51d362a..0000000000 --- a/Gems/Visibility/Code/Source/EditorOccluderAreaComponentMode.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#include "Visibility_precompiled.h" -#include "EditorOccluderAreaComponentMode.h" - -#include - -namespace Visibility -{ - AZ_CLASS_ALLOCATOR_IMPL(EditorOccluderAreaComponentMode, AZ::SystemAllocator, 0) - - EditorOccluderAreaComponentMode::EditorOccluderAreaComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType) - : EditorBaseComponentMode(entityComponentIdPair, componentType) - { - CreateManipulators(); - - AZ::TransformNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId()); - EditorOccluderAreaNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId()); - } - - EditorOccluderAreaComponentMode::~EditorOccluderAreaComponentMode() - { - EditorOccluderAreaNotificationBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - - m_vertexSelection.Destroy(); - } - - void EditorOccluderAreaComponentMode::CreateManipulators() - { - using namespace AzToolsFramework; - - m_vertexSelection.Create( - AZ::EntityComponentIdPair(GetEntityId(), GetComponentId()), g_mainManipulatorManagerId, - AZStd::make_unique(), - TranslationManipulators::Dimensions::Three, - ConfigureTranslationManipulatorAppearance3d); - - m_vertexSelection.SetVertexPositionsUpdatedCallback([this]() - { - EditorOccluderAreaRequestBus::Event( - GetEntityId(), &EditorOccluderAreaRequests::UpdateOccluderAreaObject); - }); - } - - void EditorOccluderAreaComponentMode::OnTransformChanged( - const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_vertexSelection.RefreshSpace(world); - } - - void EditorOccluderAreaComponentMode::OnVerticesChangedInspector() - { - m_vertexSelection.RefreshLocal(); - } - - void EditorOccluderAreaComponentMode::Refresh() - { - // destroy and recreate manipulators when container is modified (vertices are added or removed) - m_vertexSelection.Destroy(); - CreateManipulators(); - } - - AZStd::vector EditorOccluderAreaComponentMode::PopulateActionsImpl() - { - return m_vertexSelection.ActionOverrides(); - } - - bool EditorOccluderAreaComponentMode::HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) - { - return m_vertexSelection.HandleMouse(mouseInteraction); - } -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorOccluderAreaComponentMode.h b/Gems/Visibility/Code/Source/EditorOccluderAreaComponentMode.h deleted file mode 100644 index babef3bccc..0000000000 --- a/Gems/Visibility/Code/Source/EditorOccluderAreaComponentMode.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -#include "EditorOccluderAreaComponentBus.h" - -namespace Visibility -{ - class EditorOccluderAreaComponentMode - : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode - , private AZ::TransformNotificationBus::Handler - , private EditorOccluderAreaNotificationBus::Handler - { - public: - AZ_CLASS_ALLOCATOR_DECL - - EditorOccluderAreaComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType); - ~EditorOccluderAreaComponentMode(); - - private: - // EditorBaseComponentMode - void Refresh() override; - AZStd::vector PopulateActionsImpl() override; - bool HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; - - // Manipulator handling - void CreateManipulators(); - - // TransformNotificationBus - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // OccluderAreaNotificationBus - void OnVerticesChangedInspector() override; - - AzToolsFramework::EditorVertexSelectionFixed m_vertexSelection; ///< Handles all manipulator interactions with vertices. - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorPortalComponent.cpp b/Gems/Visibility/Code/Source/EditorPortalComponent.cpp deleted file mode 100644 index 4e1b07991a..0000000000 --- a/Gems/Visibility/Code/Source/EditorPortalComponent.cpp +++ /dev/null @@ -1,785 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#include "Visibility_precompiled.h" -#include "EditorPortalComponent.h" -#include "EditorPortalComponentMode.h" - -#include - -// Include files needed for writing DisplayEntity functions that access the DisplayContext directly. -#include - -#include -#include -#include -#include -#include - -namespace Visibility -{ - void EditorPortalComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("EditorPortalService", 0x6ead38f6)); - provided.push_back(AZ_CRC("PortalService", 0x06076210)); - provided.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - } - - void EditorPortalComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { - required.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - void EditorPortalComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent) - { - dependent.push_back(AZ_CRC("QuadShapeService", 0xe449b0fc)); - } - - void EditorPortalComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("SphereShapeService", 0x90c8dc80)); - incompatible.push_back(AZ_CRC("SplineShapeService", 0x4d4b94a2)); - incompatible.push_back(AZ_CRC("PolygonPrismShapeService", 0x1cbc4ed4)); - incompatible.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - } - - void EditorPortalConfiguration::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1); - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("Portal Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true); - - editContext->Class("Portal Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_height, "Height", "How tall the Portal is.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_displayFilled, "DisplayFilled", "Display the Portal as a filled volume.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_affectedBySun, "AffectedBySun", "Allows sunlight to affect objects inside the Portal.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_viewDistRatio, "ViewDistRatio", "Specifies how far the Portal is rendered.") - ->Attribute(AZ::Edit::Attributes::Max, 100.000000) - ->Attribute(AZ::Edit::Attributes::Min, 0.000000) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_skyOnly, "SkyOnly", "Only the Sky Box will render when looking outside the Portal.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_oceanIsVisible, "OceanIsVisible", "Ocean will be visible when looking outside the Portal.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_useDeepness, "UseDeepness", "Portal will be treated as an object with volume rather than a plane.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_doubleSide, "DoubleSide", "Cameras will be able to look through the portal from both sides.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_lightBlending, "LightBlending", "Light from neighboring VisAreas will blend into the Portal.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_lightBlendValue, "LightBlendValue", "How much to blend lights from neighboring VisAreas.") - ->Attribute(AZ::Edit::Attributes::Max, 1.000000) - ->Attribute(AZ::Edit::Attributes::Min, 0.000000) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnChange) - ->DataElement( - AZ::Edit::UIHandlers::Default, &PortalConfiguration::m_vertices, "Vertices", "Points that make up the floor of the Portal.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &PortalConfiguration::OnVerticesChange) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ; - } - } - } - - void EditorPortalComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(2) - ->Field("m_config", &EditorPortalComponent::m_config) - ->Field("ComponentMode", &EditorPortalComponent::m_componentModeDelegate) - ; - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("Portal", "An area that describes a visibility portal between VisAreas.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/Portal.png") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/Portal.svg") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "http://docs.aws.amazon.com/console/lumberyard/userguide/portal-component") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorPortalComponent::m_config, "m_config", "No Description") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorPortalComponent::m_componentModeDelegate, "Component Mode", "Portal Component Mode") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ; - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("EditorPortalRequestBus") - ->Event("SetHeight", &EditorPortalRequestBus::Events::SetHeight) - ->Event("GetHeight", &EditorPortalRequestBus::Events::GetHeight) - ->VirtualProperty("Height", "GetHeight", "SetHeight") - - ->Event("SetDisplayFilled", &EditorPortalRequestBus::Events::SetDisplayFilled) - ->Event("GetDisplayFilled", &EditorPortalRequestBus::Events::GetDisplayFilled) - ->VirtualProperty("DisplayFilled", "GetDisplayFilled", "SetDisplayFilled") - - ->Event("SetAffectedBySun", &EditorPortalRequestBus::Events::SetAffectedBySun) - ->Event("GetAffectedBySun", &EditorPortalRequestBus::Events::GetAffectedBySun) - ->VirtualProperty("AffectedBySun", "GetAffectedBySun", "SetAffectedBySun") - - ->Event("SetViewDistRatio", &EditorPortalRequestBus::Events::SetViewDistRatio) - ->Event("GetViewDistRatio", &EditorPortalRequestBus::Events::GetViewDistRatio) - ->VirtualProperty("ViewDistRatio", "GetViewDistRatio", "SetViewDistRatio") - - ->Event("SetSkyOnly", &EditorPortalRequestBus::Events::SetSkyOnly) - ->Event("GetSkyOnly", &EditorPortalRequestBus::Events::GetSkyOnly) - ->VirtualProperty("SkyOnly", "GetSkyOnly", "SetSkyOnly") - - ->Event("SetOceanIsVisible", &EditorPortalRequestBus::Events::SetOceanIsVisible) - ->Event("GetOceanIsVisible", &EditorPortalRequestBus::Events::GetOceanIsVisible) - ->VirtualProperty("OceanIsVisible", "GetOceanIsVisible", "SetOceanIsVisible") - - ->Event("SetUseDeepness", &EditorPortalRequestBus::Events::SetUseDeepness) - ->Event("GetUseDeepness", &EditorPortalRequestBus::Events::GetUseDeepness) - ->VirtualProperty("UseDeepness", "GetUseDeepness", "SetUseDeepness") - - ->Event("SetDoubleSide", &EditorPortalRequestBus::Events::SetDoubleSide) - ->Event("GetDoubleSide", &EditorPortalRequestBus::Events::GetDoubleSide) - ->VirtualProperty("DoubleSide", "GetDoubleSide", "SetDoubleSide") - - ->Event("SetLightBlending", &EditorPortalRequestBus::Events::SetLightBlending) - ->Event("GetLightBlending", &EditorPortalRequestBus::Events::GetLightBlending) - ->VirtualProperty("LightBlending", "GetLightBlending", "SetLightBlending") - - ->Event("SetLightBlendValue", &EditorPortalRequestBus::Events::SetLightBlendValue) - ->Event("GetLightBlendValue", &EditorPortalRequestBus::Events::GetLightBlendValue) - ->VirtualProperty("LightBlendValue", "GetLightBlendValue", "SetLightBlendValue") - ; - - behaviorContext->Class()->RequestBus("EditorPortalRequestBus"); - } - - EditorPortalConfiguration::Reflect(context); - } - - void EditorPortalConfiguration::OnChange() - { - EditorPortalRequestBus::Event(m_entityId, &EditorPortalRequests::UpdatePortalObject); - } - - void EditorPortalConfiguration::OnVerticesChange() - { - EditorPortalRequestBus::Event(m_entityId, &EditorPortalRequests::UpdatePortalObject); - EditorPortalNotificationBus::Event(m_entityId, &EditorPortalNotifications::OnVerticesChangedInspector); - } - - void EditorPortalConfiguration::SetEntityId(const AZ::EntityId entityId) - { - m_entityId = entityId; - } - - EditorPortalComponent::~EditorPortalComponent() - { - if (m_area) - { - // reset the listener vis area in the unlucky case that we are deleting the - // vis area where the listener is currently in - // Audio: do we still need this? - GetIEditor()->Get3DEngine()->DeleteVisArea(m_area); - m_area = nullptr; - } - } - - void EditorPortalComponent::Activate() - { - Base::Activate(); - - const AZ::EntityId entityId = GetEntityId(); - m_config.SetEntityId(entityId); - - // NOTE: We create the vis-area here at activated, but destroy it in the destructor. - // We have to do this, otherwise the vis-area is not saved into the level. - // Unfortunately, at this time we cannot create the vis-areas at game runtime. - // This means that dynamic slices cannot effectively contain vis-areas until we fix the core rendering system to allow that. - - const auto visGUID = static_cast(entityId); - if(!m_area && GetIEditor()) - { - m_area = GetIEditor()->Get3DEngine()->CreateVisArea(visGUID); - } - - m_AZCachedWorldTransform = AZ::Transform::CreateIdentity(); - m_cryCachedWorldTransform = Matrix34::CreateIdentity(); - - m_componentModeDelegate.ConnectWithSingleComponentMode< - EditorPortalComponent, EditorPortalComponentMode>( - AZ::EntityComponentIdPair(entityId, GetId()), this); - - EditorPortalRequestBus::Handler::BusConnect(entityId); - AZ::FixedVerticesRequestBus::Handler::BusConnect(entityId); - AZ::TransformNotificationBus::Handler::BusConnect(entityId); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(entityId); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(entityId); - AzFramework::BoundsRequestBus::Handler::BusConnect(entityId); - - //Call OnTransformChanged manually to cache current transform since it won't be called - //automatically for us when the level starts up. - AZ::Transform worldTM; - AZ::TransformBus::EventResult(worldTM, entityId, &AZ::TransformBus::Events::GetWorldTM); - - //Use an identity transform for localTM because the - //OnTransformChanged impl for this class doesn't need it - OnTransformChanged(AZ::Transform::CreateIdentity(), worldTM); - } - - void EditorPortalComponent::Deactivate() - { - m_componentModeDelegate.Disconnect(); - - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(GetEntityId()); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(GetEntityId()); - AZ::TransformNotificationBus::Handler::BusDisconnect(GetEntityId()); - AZ::FixedVerticesRequestBus::Handler::BusDisconnect(); - EditorPortalRequestBus::Handler::BusDisconnect(); - - Base::Deactivate(); - } - - void EditorPortalComponent::SetHeight(const float height) - { - m_config.m_height = height; - UpdatePortalObject(); - } - - float EditorPortalComponent::GetHeight() - { - return m_config.m_height; - } - - void EditorPortalComponent::SetDisplayFilled(const bool filled) - { - m_config.m_displayFilled = filled; - UpdatePortalObject(); - } - - bool EditorPortalComponent::GetDisplayFilled() - { - return m_config.m_displayFilled; - } - - void EditorPortalComponent::SetAffectedBySun(const bool affectedBySun) - { - m_config.m_affectedBySun = affectedBySun; - UpdatePortalObject(); - } - - bool EditorPortalComponent::GetAffectedBySun() - { - return m_config.m_affectedBySun; - } - - void EditorPortalComponent::SetViewDistRatio(const float viewDistRatio) - { - m_config.m_viewDistRatio = viewDistRatio; - UpdatePortalObject(); - } - - float EditorPortalComponent::GetViewDistRatio() - { - return m_config.m_viewDistRatio; - } - - void EditorPortalComponent::SetSkyOnly(const bool skyOnly) - { - m_config.m_skyOnly = skyOnly; - UpdatePortalObject(); - } - - bool EditorPortalComponent::GetSkyOnly() - { - return m_config.m_skyOnly; - } - - void EditorPortalComponent::SetOceanIsVisible(const bool oceanVisible) - { - m_config.m_oceanIsVisible = oceanVisible; - UpdatePortalObject(); - } - - bool EditorPortalComponent::GetOceanIsVisible() - { - return m_config.m_oceanIsVisible; - } - - void EditorPortalComponent::SetUseDeepness(const bool useDeepness) - { - m_config.m_useDeepness = useDeepness; - UpdatePortalObject(); - } - - bool EditorPortalComponent::GetUseDeepness() - { - return m_config.m_useDeepness; - } - - void EditorPortalComponent::SetDoubleSide(const bool doubleSided) - { - m_config.m_doubleSide = doubleSided; - UpdatePortalObject(); - } - - bool EditorPortalComponent::GetDoubleSide() - { - return m_config.m_doubleSide; - } - - void EditorPortalComponent::SetLightBlending(const bool lightBending) - { - m_config.m_lightBlending = lightBending; - UpdatePortalObject(); - } - - bool EditorPortalComponent::GetLightBlending() - { - return m_config.m_lightBlending; - } - - void EditorPortalComponent::SetLightBlendValue(const float lightBendAmount) - { - m_config.m_lightBlendValue = lightBendAmount; - UpdatePortalObject(); - } - - float EditorPortalComponent::GetLightBlendValue() - { - return m_config.m_lightBlendValue; - } - - bool EditorPortalComponent::GetVertex(const size_t index, AZ::Vector3& vertex) const - { - if (index < m_config.m_vertices.size()) - { - vertex = m_config.m_vertices[index]; - return true; - } - - return false; - } - - bool EditorPortalComponent::UpdateVertex(const size_t index, const AZ::Vector3& vertex) - { - if (index < m_config.m_vertices.size()) - { - m_config.m_vertices[index] = vertex; - return true; - } - - return false; - } - - /// Update the object runtime after changes to the Configuration. - /// Called by the default RequestBus SetXXX implementations, - /// and used to initially set up the object the first time the - /// Configuration are set. - void EditorPortalComponent::UpdatePortalObject() - { - if (m_area) - { - SVisAreaInfo info; - info.vAmbientColor = Vec3(ZERO); - info.bAffectedByOutLights = m_config.m_affectedBySun; - info.bSkyOnly = m_config.m_skyOnly; - info.fViewDistRatio = m_config.m_viewDistRatio; - info.bDoubleSide = m_config.m_doubleSide; - info.bUseDeepness = m_config.m_useDeepness; - info.bUseInIndoors = true; //Does not apply to Portals (Portals are only in VisAreas) - info.bOceanIsVisible = m_config.m_oceanIsVisible; - info.fPortalBlending = -1.0f; - - if (m_config.m_lightBlending) - { - info.fPortalBlending = m_config.m_lightBlendValue; - } - - AZStd::string name = AZStd::string("Portal_") + GetEntity()->GetName(); - - // Calculate scaled height - // Height exists separate from plane points but we still want to scale it with the transform - info.fHeight = m_config.m_height; - - /* - We have to derive at least 3 points and pass them to the vis area system - For now that means getting the 4 points of the bottom face of the box. - - If we want to send *all* points of a shape the vis system we need to make sure - that Height is 0; otherwise it'll extend the AABB of the area upwards. - */ - - //Convert to Cry vectors and apply the transform to the given points - AZStd::fixed_vector verts(4); - for (AZ::u32 i = 0; i < verts.size(); ++i) - { - verts[i] = AZVec3ToLYVec3(m_config.m_vertices[i]); - verts[i] = m_cryCachedWorldTransform.TransformPoint(verts[i]); - } - - GetIEditor()->Get3DEngine()->UpdateVisArea(m_area, &verts[0], verts.size(), name.c_str(), info, true); - - AzFramework::EntityBoundsUnionRequestBus::Broadcast( - &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId()); - } - } - - void EditorPortalComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - //Cache the transform so that we don't have to retrieve it every time UpdatePortalObject is called - m_AZCachedWorldTransform = world; - m_cryCachedWorldTransform = AZTransformToLYTransform(m_AZCachedWorldTransform); - - UpdatePortalObject(); - } - - struct PortalQuadVertices - { - AZ::Vector3 floorLeftFront; - AZ::Vector3 floorRightFront; - AZ::Vector3 floorLeftBack; - AZ::Vector3 floorRightBack; - - AZ::Vector3 quadUpperLeftFront; - AZ::Vector3 quadUpperRightFront; - AZ::Vector3 quadUpperLeftBack; - AZ::Vector3 quadUpperRightBack; - - AZ::Vector3 portalUpperLeftFront; - AZ::Vector3 portalUpperRightFront; - AZ::Vector3 portalUpperLeftBack; - AZ::Vector3 portalUpperRightBack; - }; - - PortalQuadVertices EditorPortalComponent::CalculatePortalQuadVertices(VertTranslation vertTranslation) - { - PortalQuadVertices pqv; - - //Untransformed quad corners - const AZ::Vector3 lowerLeftFront = m_config.m_vertices[0]; - const AZ::Vector3 lowerRightFront = m_config.m_vertices[1]; - const AZ::Vector3 lowerLeftBack = m_config.m_vertices[3]; - const AZ::Vector3 lowerRightBack = m_config.m_vertices[2]; - - //Need to calculate the height of the quad after transformation - const AZ::u32 quadPointCount = 4; - AZ::Vector3 transformedQuadPoints[quadPointCount]; - - transformedQuadPoints[0] = m_AZCachedWorldTransform.TransformPoint(lowerLeftFront); - transformedQuadPoints[1] = m_AZCachedWorldTransform.TransformPoint(lowerRightFront); - transformedQuadPoints[2] = m_AZCachedWorldTransform.TransformPoint(lowerLeftBack); - transformedQuadPoints[3] = m_AZCachedWorldTransform.TransformPoint(lowerRightBack); - - const AZ::Vector3 translation = m_AZCachedWorldTransform.GetTranslation(); - - float minHeight = FLT_MAX; - float maxHeight = FLT_MIN; - - for (auto& transformedQuadPoint : transformedQuadPoints) - { - // remove translation from quad points so we can use them with the DisplayContext's usage of the transform - if (vertTranslation == VertTranslation::Remove) - { - transformedQuadPoint -= translation; - } - - const float height = transformedQuadPoint.GetZ(); - if (height < minHeight) - { - minHeight = height; - } - if (height > maxHeight) - { - maxHeight = height; - } - } - - pqv.floorLeftFront = AZ::Vector3(transformedQuadPoints[0].GetX(), transformedQuadPoints[0].GetY(), minHeight); - pqv.floorRightFront = AZ::Vector3(transformedQuadPoints[1].GetX(), transformedQuadPoints[1].GetY(), minHeight); - pqv.floorLeftBack = AZ::Vector3(transformedQuadPoints[2].GetX(), transformedQuadPoints[2].GetY(), minHeight); - pqv.floorRightBack = AZ::Vector3(transformedQuadPoints[3].GetX(), transformedQuadPoints[3].GetY(), minHeight); - - pqv.quadUpperLeftFront = AZ::Vector3(transformedQuadPoints[0].GetX(), transformedQuadPoints[0].GetY(), maxHeight); - pqv.quadUpperRightFront = AZ::Vector3(transformedQuadPoints[1].GetX(), transformedQuadPoints[1].GetY(), maxHeight); - pqv.quadUpperLeftBack = AZ::Vector3(transformedQuadPoints[2].GetX(), transformedQuadPoints[2].GetY(), maxHeight); - pqv.quadUpperRightBack = AZ::Vector3(transformedQuadPoints[3].GetX(), transformedQuadPoints[3].GetY(), maxHeight); - - pqv.portalUpperLeftFront = AZ::Vector3(transformedQuadPoints[0].GetX(), transformedQuadPoints[0].GetY(), maxHeight + m_config.m_height); - pqv.portalUpperRightFront = AZ::Vector3(transformedQuadPoints[1].GetX(), transformedQuadPoints[1].GetY(), maxHeight + m_config.m_height); - pqv.portalUpperLeftBack = AZ::Vector3(transformedQuadPoints[2].GetX(), transformedQuadPoints[2].GetY(), maxHeight + m_config.m_height); - pqv.portalUpperRightBack = AZ::Vector3(transformedQuadPoints[3].GetX(), transformedQuadPoints[3].GetY(), maxHeight + m_config.m_height); - - return pqv; - } - - void EditorPortalComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - /* - IMPORTANT NOTE: This method may seem very complicated but it is an accurate visualization of - how portals actually work. The legacy visualization used with the legacy portal entity is - very misleading! - - Portals always exist as a quad but if the quad becomes non-planar, from rotation or in the legacy - system from a point being pulled up or down, the volume changes in a non-obvious way. Instead of portal - existing as the shape defined by 4 points and extruded upwards, the portal actually remains planar. - Any height difference that you add by making the shape non-planar is just applied to the height of the volume. - - If this is confusing, please actually look at the visualization created by this method. Make sure - that you rotate the portal in many weird contorted ways and examine how the visualization reacts. - The portal volume is always going to be a box rotated on only X and Y axes that stretches up along the Z axis. - - Important note on the complexity of this method: - We cannot directly visualize the OBB of the portal with an AABB that we then transform. The OBB that's mentioned - here is best imagined as the top plane being all points of the quad pulled up to the height of the highest quad's vert - and the bottom plane being all points of the quad pulled down to the height of the lowest quad's vert. Trying to - create an AABB from these points won't produce the correct visualization under complex rotations as the Min and Max - of the AABB will either only encompass part of the bounding volume or be too large. - */ - - const PortalQuadVertices pqv = CalculatePortalQuadVertices(VertTranslation::Remove); - - //Draw the outline of the OBB of the Portal's quad - AZ::Color color(0.000f, 1.0f, 0.000f, 1.0f); - debugDisplay.SetColor(AZ::Vector4(color.GetR(), color.GetG(), color.GetB(), 1.f)); - - //Remove all rotation from the transform - const AZ::Quaternion rotation = AZ::Quaternion::CreateIdentity(); - - AZ::Transform worldTMOnlyZRot = m_AZCachedWorldTransform; - worldTMOnlyZRot.SetRotation(rotation); - - debugDisplay.PushMatrix(worldTMOnlyZRot); - - //Draw the outline of the OBB of the portal quad - - //Bottom - debugDisplay.DrawLine(pqv.floorLeftFront, pqv.floorRightFront); - debugDisplay.DrawLine(pqv.floorRightFront, pqv.floorRightBack); - debugDisplay.DrawLine(pqv.floorRightBack, pqv.floorLeftBack); - debugDisplay.DrawLine(pqv.floorLeftBack, pqv.floorLeftFront); - //Top - debugDisplay.DrawLine(pqv.quadUpperLeftFront, pqv.quadUpperRightFront); - debugDisplay.DrawLine(pqv.quadUpperRightFront, pqv.quadUpperRightBack); - debugDisplay.DrawLine(pqv.quadUpperRightBack, pqv.quadUpperLeftBack); - debugDisplay.DrawLine(pqv.quadUpperLeftBack, pqv.quadUpperLeftFront); - //Left - debugDisplay.DrawLine(pqv.floorLeftFront, pqv.quadUpperLeftFront); - debugDisplay.DrawLine(pqv.quadUpperLeftFront, pqv.quadUpperLeftBack); - debugDisplay.DrawLine(pqv.quadUpperLeftBack, pqv.floorLeftBack); - debugDisplay.DrawLine(pqv.floorLeftBack, pqv.floorLeftFront); - //Right - debugDisplay.DrawLine(pqv.floorRightFront, pqv.quadUpperRightFront); - debugDisplay.DrawLine(pqv.quadUpperRightFront, pqv.quadUpperRightBack); - debugDisplay.DrawLine(pqv.quadUpperRightBack, pqv.floorRightBack); - debugDisplay.DrawLine(pqv.floorRightBack, pqv.floorRightFront); - //Front - debugDisplay.DrawLine(pqv.floorLeftFront, pqv.floorRightFront); - debugDisplay.DrawLine(pqv.floorRightFront, pqv.quadUpperRightFront); - debugDisplay.DrawLine(pqv.quadUpperRightFront, pqv.quadUpperLeftFront); - debugDisplay.DrawLine(pqv.quadUpperLeftFront, pqv.floorLeftFront); - //Back - debugDisplay.DrawLine(pqv.floorLeftBack, pqv.floorRightBack); - debugDisplay.DrawLine(pqv.floorRightBack, pqv.quadUpperRightBack); - debugDisplay.DrawLine(pqv.quadUpperRightBack, pqv.quadUpperLeftBack); - debugDisplay.DrawLine(pqv.quadUpperLeftBack, pqv.floorLeftBack); - - //Now draw the entire portal volume (Previous OBB + extra height) - if (m_config.m_displayFilled) - { - //Draw whole portal with less alpha - debugDisplay.SetColor(AZ::Vector4(color.GetR(), color.GetG(), color.GetB(), 0.1f)); - - //Draw both winding orders for quads so they appear solid from all angles - //Not drawing boxes because the corners of the quad may not be hit if the bounds are rotated oddly - - //Bottom - debugDisplay.DrawQuad(pqv.floorLeftFront, pqv.floorRightFront, pqv.floorRightBack, pqv.floorLeftBack); - debugDisplay.DrawQuad(pqv.floorLeftFront, pqv.floorLeftBack, pqv.floorRightBack, pqv.floorRightFront); - //Top - debugDisplay.DrawQuad(pqv.portalUpperLeftFront, pqv.portalUpperRightFront, pqv.portalUpperRightBack, pqv.portalUpperLeftBack); - debugDisplay.DrawQuad(pqv.portalUpperLeftFront, pqv.portalUpperLeftBack, pqv.portalUpperRightBack, pqv.portalUpperRightFront); - //Left - debugDisplay.DrawQuad(pqv.floorLeftFront, pqv.portalUpperLeftFront, pqv.portalUpperLeftBack, pqv.floorLeftBack); - debugDisplay.DrawQuad(pqv.floorLeftFront, pqv.floorLeftBack, pqv.portalUpperLeftBack, pqv.portalUpperLeftFront); - //Right - debugDisplay.DrawQuad(pqv.floorRightFront, pqv.portalUpperRightFront, pqv.portalUpperRightBack, pqv.floorRightBack); - debugDisplay.DrawQuad(pqv.floorRightFront, pqv.floorRightBack, pqv.portalUpperRightBack, pqv.portalUpperRightFront); - //Front - debugDisplay.DrawQuad(pqv.floorLeftFront, pqv.floorRightFront, pqv.portalUpperRightFront, pqv.portalUpperLeftFront); - debugDisplay.DrawQuad(pqv.floorLeftFront, pqv.portalUpperLeftFront, pqv.portalUpperRightFront, pqv.floorRightFront); - //Back - debugDisplay.DrawQuad(pqv.floorLeftBack, pqv.floorRightBack, pqv.portalUpperRightBack, pqv.portalUpperLeftBack); - debugDisplay.DrawQuad(pqv.floorLeftBack, pqv.portalUpperLeftBack, pqv.portalUpperRightBack, pqv.floorRightBack); - } - else - { - //Bottom - debugDisplay.DrawLine(pqv.floorLeftFront, pqv.floorRightFront); - debugDisplay.DrawLine(pqv.floorRightFront, pqv.floorRightBack); - debugDisplay.DrawLine(pqv.floorRightBack, pqv.floorLeftBack); - debugDisplay.DrawLine(pqv.floorLeftBack, pqv.floorLeftFront); - //Top - debugDisplay.DrawLine(pqv.portalUpperLeftFront, pqv.portalUpperRightFront); - debugDisplay.DrawLine(pqv.portalUpperRightFront, pqv.portalUpperRightBack); - debugDisplay.DrawLine(pqv.portalUpperRightBack, pqv.portalUpperLeftBack); - debugDisplay.DrawLine(pqv.portalUpperLeftBack, pqv.portalUpperLeftFront); - //Left - debugDisplay.DrawLine(pqv.floorLeftFront, pqv.portalUpperLeftFront); - debugDisplay.DrawLine(pqv.portalUpperLeftFront, pqv.portalUpperLeftBack); - debugDisplay.DrawLine(pqv.portalUpperLeftBack, pqv.floorLeftBack); - debugDisplay.DrawLine(pqv.floorLeftBack, pqv.floorLeftFront); - //Right - debugDisplay.DrawLine(pqv.floorRightFront, pqv.portalUpperRightFront); - debugDisplay.DrawLine(pqv.portalUpperRightFront, pqv.portalUpperRightBack); - debugDisplay.DrawLine(pqv.portalUpperRightBack, pqv.floorRightBack); - debugDisplay.DrawLine(pqv.floorRightBack, pqv.floorRightFront); - //Front - debugDisplay.DrawLine(pqv.floorLeftFront, pqv.floorRightFront); - debugDisplay.DrawLine(pqv.floorRightFront, pqv.portalUpperRightFront); - debugDisplay.DrawLine(pqv.portalUpperRightFront, pqv.portalUpperLeftFront); - debugDisplay.DrawLine(pqv.portalUpperLeftFront, pqv.floorLeftFront); - //Back - debugDisplay.DrawLine(pqv.floorLeftBack, pqv.floorRightBack); - debugDisplay.DrawLine(pqv.floorRightBack, pqv.portalUpperRightBack); - debugDisplay.DrawLine(pqv.portalUpperRightBack, pqv.portalUpperLeftBack); - debugDisplay.DrawLine(pqv.portalUpperLeftBack, pqv.floorLeftBack); - } - - if (m_componentModeDelegate.AddedToComponentMode()) - { - AzToolsFramework::VertexContainerDisplay::DisplayVertexContainerIndices( - debugDisplay, AzToolsFramework::FixedVerticesArray(m_config.m_vertices), - GetWorldTM(), AZ::Vector3::CreateOne(), IsSelected()); - } - - debugDisplay.PopMatrix(); - } - - void EditorPortalComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - gameEntity->CreateComponent(m_config); - } - - AZ::Aabb EditorPortalComponent::GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& /*viewportInfo*/) - { - const PortalQuadVertices pqv = CalculatePortalQuadVertices(VertTranslation::Keep); - - AZ::Aabb bbox = AZ::Aabb::CreateNull(); - bbox.AddPoint(pqv.floorLeftFront); - bbox.AddPoint(pqv.floorRightFront); - bbox.AddPoint(pqv.floorLeftBack); - bbox.AddPoint(pqv.floorRightBack); - bbox.AddPoint(pqv.portalUpperLeftFront); - return bbox; - } - - bool EditorPortalComponent::EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/, const AZ::Vector3& src, - const AZ::Vector3& dir, float& distance) - { - float t; - float intermediateT = FLT_MAX; - - const PortalQuadVertices pqv = CalculatePortalQuadVertices(VertTranslation::Keep); - - //Count each quad for intersection hits, two hits implies we are intersecting the prism from outside of it (or from too far) - AZ::u8 hits = 0; - - //Bottom - if (AZ::Intersect::IntersectRayQuad(src, dir, pqv.floorLeftFront, pqv.floorRightFront, pqv.floorRightBack, pqv.floorLeftBack, t)) - { - ++hits; - intermediateT = AZStd::GetMin(t, intermediateT); - } - //Top - if (AZ::Intersect::IntersectRayQuad(src, dir, pqv.portalUpperLeftFront, pqv.portalUpperRightFront, pqv.portalUpperRightBack, pqv.portalUpperLeftBack, t)) - { - ++hits; - intermediateT = AZStd::GetMin(t, intermediateT); - } - - //Left - if (AZ::Intersect::IntersectRayQuad(src, dir, pqv.floorLeftFront, pqv.portalUpperLeftFront, pqv.portalUpperLeftBack, pqv.floorLeftBack, t)) - { - ++hits; - intermediateT = AZStd::GetMin(t, intermediateT); - } - //Right - if (AZ::Intersect::IntersectRayQuad(src, dir, pqv.floorRightFront, pqv.portalUpperRightFront, pqv.portalUpperRightBack, pqv.floorRightBack, t)) - { - ++hits; - intermediateT = AZStd::GetMin(t, intermediateT); - } - //Front - if (AZ::Intersect::IntersectRayQuad(src, dir, pqv.floorLeftFront, pqv.floorRightFront, pqv.portalUpperRightFront, pqv.portalUpperLeftFront, t)) - { - ++hits; - intermediateT = AZStd::GetMin(t, intermediateT); - } - //Back - if (AZ::Intersect::IntersectRayQuad(src, dir, pqv.floorLeftBack, pqv.floorRightBack, pqv.portalUpperRightBack, pqv.portalUpperLeftBack, t)) - { - ++hits; - intermediateT = AZStd::GetMin(t, intermediateT); - } - - if (hits > 0) - { - distance = intermediateT; - } - return hits >= 2; - } - - AZ::Aabb EditorPortalComponent::GetWorldBounds() - { - return GetLocalBounds().GetTransformedAabb(m_AZCachedWorldTransform); - } - - AZ::Aabb EditorPortalComponent::GetLocalBounds() - { - AZ::Aabb bbox = AZ::Aabb::CreateNull(); - for (const auto& vertex : m_config.m_vertices) - { - bbox.AddPoint(vertex); - } - return bbox; - } -} //namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorPortalComponent.h b/Gems/Visibility/Code/Source/EditorPortalComponent.h deleted file mode 100644 index a8e00b9698..0000000000 --- a/Gems/Visibility/Code/Source/EditorPortalComponent.h +++ /dev/null @@ -1,148 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "PortalComponent.h" -#include "EditorPortalComponentBus.h" - -namespace Visibility -{ - class EditorPortalComponent; - struct PortalQuadVertices; - - class EditorPortalConfiguration - : public PortalConfiguration - { - public: - AZ_TYPE_INFO_LEGACY(EditorPortalConfiguration, "{C9F99449-7A77-50C4-9ED3-D69B923BFDBD}", PortalConfiguration); - AZ_CLASS_ALLOCATOR(EditorPortalConfiguration, AZ::SystemAllocator,0); - - static void Reflect(AZ::ReflectContext* context); - - void OnChange() override; - void OnVerticesChange() override; - - void SetEntityId(AZ::EntityId entityId); - - private: - AZ::EntityId m_entityId; - }; - - class EditorPortalComponent - : public AzToolsFramework::Components::EditorComponentBase - , private EditorPortalRequestBus::Handler - , private AZ::FixedVerticesRequestBus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - , public AZ::TransformNotificationBus::Handler - , public AzFramework::BoundsRequestBus::Handler - { - friend class EditorPortalConfiguration; - - using Base = AzToolsFramework::Components::EditorComponentBase; - - public: - AZ_COMPONENT(EditorPortalComponent, "{64525CDD-7DD4-5CEF-B545-559127DC834E}", AzToolsFramework::Components::EditorComponentBase); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); - static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - - static void Reflect(AZ::ReflectContext* context); - - EditorPortalComponent() = default; - EditorPortalComponent(const EditorPortalComponent&) = delete; - EditorPortalComponent& operator=(const EditorPortalComponent&) = delete; - ~EditorPortalComponent() override; - - // EditorComponentBase overrides ... - void Activate() override; - void Deactivate() override; - void BuildGameEntity(AZ::Entity* gameEntity) override; - - // TransformNotificationBus overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // EditorComponentSelectionRequestsBus overrides ... - AZ::Aabb GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& viewportInfo) override; - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, - const AZ::Vector3& dir, float& distance) override; - bool SupportsEditorRayIntersect() override { return true; } - - // PortalRequestBus overrides ... - void SetHeight(float height) override; - float GetHeight() override; - void SetDisplayFilled(bool filled) override; - bool GetDisplayFilled() override; - void SetAffectedBySun(bool affectedBySun) override; - bool GetAffectedBySun() override; - void SetViewDistRatio(float viewDistRatio) override; - float GetViewDistRatio() override; - void SetSkyOnly(bool skyOnly) override; - bool GetSkyOnly() override; - void SetOceanIsVisible(bool oceanVisible) override; - bool GetOceanIsVisible() override; - void SetUseDeepness(bool useDeepness) override; - bool GetUseDeepness() override; - void SetDoubleSide(bool doubleSided) override; - bool GetDoubleSide() override; - void SetLightBlending(bool lightBending) override; - bool GetLightBlending() override; - void SetLightBlendValue(float lightBendAmount) override; - float GetLightBlendValue() override; - bool GetVertex(size_t index, AZ::Vector3& vertex) const override; - bool UpdateVertex(size_t index, const AZ::Vector3& vertex) override; - size_t Size() const override { return m_config.m_vertices.size(); } - void UpdatePortalObject() override; - - // EntityDebugDisplayBus overrides ... - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // BoundsRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - private: - enum class VertTranslation - { - Keep, - Remove - }; - - PortalQuadVertices CalculatePortalQuadVertices(VertTranslation vertTranslation); - - // Reflected members - EditorPortalConfiguration m_config; - - using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate; - ComponentModeDelegate m_componentModeDelegate; ///< Responsible for detecting ComponentMode activation - ///< and creating a concrete ComponentMode. - - AZ::Transform m_AZCachedWorldTransform; - Matrix44 m_cryCachedWorldTransform; - IVisArea* m_area = nullptr; - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorPortalComponentMode.cpp b/Gems/Visibility/Code/Source/EditorPortalComponentMode.cpp deleted file mode 100644 index 5d9b089c65..0000000000 --- a/Gems/Visibility/Code/Source/EditorPortalComponentMode.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#include "Visibility_precompiled.h" -#include "EditorPortalComponentMode.h" - -#include - -namespace Visibility -{ - AZ_CLASS_ALLOCATOR_IMPL(EditorPortalComponentMode, AZ::SystemAllocator, 0) - - EditorPortalComponentMode::EditorPortalComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType) - : EditorBaseComponentMode(entityComponentIdPair, componentType) - { - CreateManipulators(); - - AZ::TransformNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId()); - EditorPortalNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId()); - } - - EditorPortalComponentMode::~EditorPortalComponentMode() - { - EditorPortalNotificationBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - - m_vertexSelection.Destroy(); - } - - void EditorPortalComponentMode::CreateManipulators() - { - using namespace AzToolsFramework; - - m_vertexSelection.Create( - AZ::EntityComponentIdPair(GetEntityId(), GetComponentId()), g_mainManipulatorManagerId, - AZStd::make_unique(), - TranslationManipulators::Dimensions::Three, - ConfigureTranslationManipulatorAppearance3d); - - m_vertexSelection.SetVertexPositionsUpdatedCallback([this]() - { - EditorPortalRequestBus::Event( - GetEntityId(), &EditorPortalRequests::UpdatePortalObject); - }); - } - - void EditorPortalComponentMode::OnTransformChanged( - const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_vertexSelection.RefreshSpace(world); - } - - void EditorPortalComponentMode::OnVerticesChangedInspector() - { - m_vertexSelection.RefreshLocal(); - } - - void EditorPortalComponentMode::Refresh() - { - // destroy and recreate manipulators when container is modified (vertices are added or removed) - m_vertexSelection.Destroy(); - CreateManipulators(); - } - - AZStd::vector EditorPortalComponentMode::PopulateActionsImpl() - { - return m_vertexSelection.ActionOverrides(); - } - - bool EditorPortalComponentMode::HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) - { - return m_vertexSelection.HandleMouse(mouseInteraction); - } -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorPortalComponentMode.h b/Gems/Visibility/Code/Source/EditorPortalComponentMode.h deleted file mode 100644 index 633c3a1ba8..0000000000 --- a/Gems/Visibility/Code/Source/EditorPortalComponentMode.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -#include "EditorPortalComponentBus.h" - -namespace Visibility -{ - class EditorPortalComponentMode - : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode - , private AZ::TransformNotificationBus::Handler - , private EditorPortalNotificationBus::Handler - { - public: - AZ_CLASS_ALLOCATOR_DECL - - EditorPortalComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType); - ~EditorPortalComponentMode(); - - private: - // EditorBaseComponentMode - void Refresh() override; - AZStd::vector PopulateActionsImpl() override; - bool HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; - - // Manipulator handling - void CreateManipulators(); - - // TransformNotificationBus - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // EditorPortalNotificationBus - void OnVerticesChangedInspector() override; - - AzToolsFramework::EditorVertexSelectionFixed m_vertexSelection; ///< Handles all manipulator interactions with vertices. - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorVisAreaComponent.cpp b/Gems/Visibility/Code/Source/EditorVisAreaComponent.cpp deleted file mode 100644 index 48045d9023..0000000000 --- a/Gems/Visibility/Code/Source/EditorVisAreaComponent.cpp +++ /dev/null @@ -1,629 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "Visibility_precompiled.h" -#include "EditorVisAreaComponent.h" -#include "EditorVisAreaComponentMode.h" - -#include -#include -#include -#include -#include - -// Include files needed for writing DisplayEntity functions that access the DisplayContext directly. -#include - -#include "MathConversion.h" - -namespace Visibility -{ - /*static*/ AZ::Color EditorVisAreaComponent::s_visAreaColor = AZ::Color(1.0f, 0.5f, 0.0f, 1.0f); - - void EditorVisAreaComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) - { - provided.push_back(AZ_CRC("EditorVisAreaService", 0x4507d2ae)); - provided.push_back(AZ_CRC("VisAreaService", 0x0c063fb9)); - provided.push_back(AZ_CRC("VariableVertexContainerService", 0x70c58740)); - provided.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - } - - void EditorVisAreaComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires) - { - requires.push_back(AZ_CRC("TransformService", 0x8ee22c50)); - } - - void EditorVisAreaComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) - { - incompatible.push_back(AZ_CRC("VariableVertexContainerService", 0x70c58740)); - incompatible.push_back(AZ_CRC("FixedVertexContainerService", 0x83f1bbf2)); - } - - void EditorVisAreaConfiguration::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1); - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("VisArea Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true); - - editContext->Class("VisArea Configuration", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &VisAreaConfiguration::m_height, "Height", "How tall the VisArea is.") - ->Attribute(AZ::Edit::Attributes::Max, 100.0f) - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &VisAreaConfiguration::ChangeHeight) - ->DataElement(AZ::Edit::UIHandlers::Default, &VisAreaConfiguration::m_displayFilled, "DisplayFilled", "Display the VisArea as a filled volume.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &VisAreaConfiguration::ChangeDisplayFilled) - ->DataElement(AZ::Edit::UIHandlers::Default, &VisAreaConfiguration::m_affectedBySun, "AffectedBySun", "Allows sunlight to affect objects inside the VisArea.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &VisAreaConfiguration::ChangeAffectedBySun) - ->DataElement(AZ::Edit::UIHandlers::Default, &VisAreaConfiguration::m_viewDistRatio, "ViewDistRatio", "Specifies how far the VisArea is rendered.") - ->Attribute(AZ::Edit::Attributes::Max, 100.0f) - ->Attribute(AZ::Edit::Attributes::Min, 0.0f) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &VisAreaConfiguration::ChangeViewDistRatio) - ->DataElement(AZ::Edit::UIHandlers::Default, &VisAreaConfiguration::m_oceanIsVisible, "OceanIsVisible", "Ocean will be visible when looking outside the VisArea.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &VisAreaConfiguration::ChangeOceanIsVisible) - // note: This will not work as expected. See Activate where we set the callbacks on the vertex container directly - ->DataElement(AZ::Edit::UIHandlers::Default, &VisAreaConfiguration::m_vertexContainer, "Vertices", "Points that make up the floor of the VisArea.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &VisAreaConfiguration::ChangeVertexContainer) - ; - } - } - } - - void EditorVisAreaComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(2) - ->Field("m_config", &EditorVisAreaComponent::m_config) - ->Field("ComponentMode", &EditorVisAreaComponent::m_componentModeDelegate) - ; - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("VisArea", "An area where only objects inside the area will be visible.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Category, "Rendering") - ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/VisArea.png") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/VisArea.svg") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "http://docs.aws.amazon.com/console/lumberyard/userguide/vis-area-component") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorVisAreaComponent::m_config, "m_config", "No Description") - ->DataElement(AZ::Edit::UIHandlers::Default, &EditorVisAreaComponent::m_componentModeDelegate, "Component Mode", "VisArea Component Mode") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ; - } - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("EditorVisAreaComponentRequestBus") - ->Event("SetHeight", &EditorVisAreaComponentRequestBus::Events::SetHeight) - ->Event("GetHeight", &EditorVisAreaComponentRequestBus::Events::GetHeight) - ->VirtualProperty("Height", "GetHeight", "SetHeight") - - ->Event("SetDisplayFilled", &EditorVisAreaComponentRequestBus::Events::SetDisplayFilled) - ->Event("GetDisplayFilled", &EditorVisAreaComponentRequestBus::Events::GetDisplayFilled) - ->VirtualProperty("DisplayFilled", "GetDisplayFilled", "SetDisplayFilled") - - ->Event("SetAffectedBySun", &EditorVisAreaComponentRequestBus::Events::SetAffectedBySun) - ->Event("GetAffectedBySun", &EditorVisAreaComponentRequestBus::Events::GetAffectedBySun) - ->VirtualProperty("AffectedBySun", "GetAffectedBySun", "SetAffectedBySun") - - ->Event("SetViewDistRatio", &EditorVisAreaComponentRequestBus::Events::SetViewDistRatio) - ->Event("GetViewDistRatio", &EditorVisAreaComponentRequestBus::Events::GetViewDistRatio) - ->VirtualProperty("ViewDistRatio", "GetViewDistRatio", "SetViewDistRatio") - - ->Event("SetOceanIsVisible", &EditorVisAreaComponentRequestBus::Events::SetOceanIsVisible) - ->Event("GetOceanIsVisible", &EditorVisAreaComponentRequestBus::Events::GetOceanIsVisible) - ->VirtualProperty("OceanIsVisible", "GetOceanIsVisible", "SetOceanIsVisible") - ; - - behaviorContext->Class()->RequestBus("EditorVisAreaComponentRequestBus"); - } - - EditorVisAreaConfiguration::Reflect(context); - } - - void EditorVisAreaConfiguration::ChangeHeight() - { - EditorVisAreaComponentRequestBus::Event( - m_entityId, &EditorVisAreaComponentRequests::UpdateVisAreaObject); - } - - void EditorVisAreaConfiguration::ChangeDisplayFilled() - { - EditorVisAreaComponentRequestBus::Event( - m_entityId, &EditorVisAreaComponentRequests::UpdateVisAreaObject); - } - - void EditorVisAreaConfiguration::ChangeAffectedBySun() - { - EditorVisAreaComponentRequestBus::Event( - m_entityId, &EditorVisAreaComponentRequests::UpdateVisAreaObject); - } - - void EditorVisAreaConfiguration::ChangeViewDistRatio() - { - EditorVisAreaComponentRequestBus::Event( - m_entityId, &EditorVisAreaComponentRequests::UpdateVisAreaObject); - } - - void EditorVisAreaConfiguration::ChangeOceanIsVisible() - { - EditorVisAreaComponentRequestBus::Event( - m_entityId, &EditorVisAreaComponentRequests::UpdateVisAreaObject); - } - - void EditorVisAreaConfiguration::ChangeVertexContainer() - { - EditorVisAreaComponentRequestBus::Event( - m_entityId, &EditorVisAreaComponentRequests::UpdateVisAreaObject); - } - - void EditorVisAreaConfiguration::SetEntityId(const AZ::EntityId entityId) - { - m_entityId = entityId; - } - - EditorVisAreaComponent::~EditorVisAreaComponent() - { - if (m_area) - { - // Reset the listener vis area in the unlucky case that we are deleting the - // vis area where the listener is currently in - GetIEditor()->Get3DEngine()->DeleteVisArea(m_area); - m_area = nullptr; - } - } - - void EditorVisAreaComponent::Activate() - { - Base::Activate(); - - const AZ::EntityId entityId = GetEntityId(); - - // NOTE: We create the vis-area here at activated, but destroy it in the destructor. - // We have to do this, otherwise the vis-area is not saved into the level. - // Unfortunately, at this time we cannot create the vis-areas at game runtime. - // This means that dynamic slices cannot effectively contain vis areas until we fix the core rendering system to allow that. - - const auto visGUID = AZ::u64(entityId); - if(!m_area && GetIEditor()) - { - m_area = GetIEditor()->Get3DEngine()->CreateVisArea(visGUID); - } - - m_componentModeDelegate.ConnectWithSingleComponentMode< - EditorVisAreaComponent, EditorVisAreaComponentMode>( - AZ::EntityComponentIdPair(entityId, GetId()), this); - - // give default values to the vertices if needed - if (m_config.m_vertexContainer.Size() == 0) - { - m_config.m_vertexContainer.AddVertex(AZ::Vector3(-1.0f, -1.0f, 0.0f)); - m_config.m_vertexContainer.AddVertex(AZ::Vector3(+1.0f, -1.0f, 0.0f)); - m_config.m_vertexContainer.AddVertex(AZ::Vector3(+1.0f, +1.0f, 0.0f)); - m_config.m_vertexContainer.AddVertex(AZ::Vector3(-1.0f, +1.0f, 0.0f)); - } - - const auto vertexAdded = [this](size_t vertIndex) - { - EditorVisAreaComponentNotificationBus::Event( - GetEntityId(), &EditorVisAreaComponentNotifications::OnVertexAdded, vertIndex); - - UpdateVisAreaObject(); - }; - - const auto vertexRemoved = [this](size_t vertIndex) - { - EditorVisAreaComponentNotificationBus::Event( - GetEntityId(), &EditorVisAreaComponentNotifications::OnVertexRemoved, vertIndex); - - UpdateVisAreaObject(); - }; - - const auto vertexChanged = [this](size_t vertIndex) - { - EditorVisAreaComponentNotificationBus::Event( - GetEntityId(), &EditorVisAreaComponentNotifications::OnVertexUpdated, vertIndex); - - UpdateVisAreaObject(); - }; - - const auto verticesSet = [this]() - { - EditorVisAreaComponentNotificationBus::Event( - GetEntityId(), &EditorVisAreaComponentNotifications::OnVerticesSet, - m_config.m_vertexContainer.GetVertices()); - - UpdateVisAreaObject(); - }; - - const auto verticesCleared = [this]() - { - EditorVisAreaComponentNotificationBus::Event( - GetEntityId(), &EditorVisAreaComponentNotifications::OnVerticesCleared); - - UpdateVisAreaObject(); - }; - - m_config.m_vertexContainer.SetCallbacks( - vertexAdded, vertexRemoved, vertexChanged, - verticesSet, verticesCleared); - - m_config.SetEntityId(entityId); - - AZ::TransformBus::EventResult( - m_currentWorldTransform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - - // make the initial vis area with the data we just parsed - UpdateVisAreaObject(); - - EditorVisAreaComponentRequestBus::Handler::BusConnect(entityId); - AZ::VariableVerticesRequestBus::Handler::BusConnect(entityId); - AZ::FixedVerticesRequestBus::Handler::BusConnect(entityId); - AZ::TransformNotificationBus::Handler::BusConnect(entityId); - AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(entityId); - AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect(); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(entityId); - AzFramework::BoundsRequestBus::Handler::BusConnect(entityId); - } - - void EditorVisAreaComponent::Deactivate() - { - m_componentModeDelegate.Disconnect(); - - AzFramework::BoundsRequestBus::Handler::BusDisconnect(); - AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect(); - AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); - AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - AZ::FixedVerticesRequestBus::Handler::BusDisconnect(); - AZ::VariableVerticesRequestBus::Handler::BusDisconnect(); - EditorVisAreaComponentRequestBus::Handler::BusDisconnect(); - - Base::Deactivate(); - } - - void EditorVisAreaComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_currentWorldTransform = world; - UpdateVisAreaObject(); - } - - /// Apply the component's settings to the underlying vis area - void EditorVisAreaComponent::UpdateVisAreaObject() - { - if (m_area) - { - std::vector points; - - const AZStd::vector& vertices = m_config.m_vertexContainer.GetVertices(); - const size_t vertexCount = vertices.size(); - - if (vertexCount > 3) - { - const Matrix34& wtm = AZTransformToLYTransform(GetWorldTM()); - points.resize(vertexCount); - for (size_t i = 0; i < vertexCount; i++) - { - points[i] = wtm.TransformPoint(AZVec3ToLYVec3(vertices[i])); - } - - SVisAreaInfo info; - info.fHeight = GetHeight(); - info.bAffectedByOutLights = m_config.m_affectedBySun; - info.fViewDistRatio = m_config.m_viewDistRatio; - info.bOceanIsVisible = m_config.m_oceanIsVisible; - - //Unconfigurable; these values are used by other area types - //We set them just so that debugging later it's clear that these - //aren't being used because this is a VisArea. - info.fPortalBlending = -1; - info.bDoubleSide = true; - info.bUseDeepness = false; - info.bUseInIndoors = false; - - const AZStd::string name = AZStd::string("vis-area_") + GetEntity()->GetName(); - - GetIEditor()->Get3DEngine()->UpdateVisArea(m_area, &points[0], points.size(), name.c_str(), info, true); - - AzFramework::EntityBoundsUnionRequestBus::Broadcast( - &AzFramework::EntityBoundsUnionRequestBus::Events::RefreshEntityLocalBoundsUnion, GetEntityId()); - } - } - } - - void EditorVisAreaComponent::SetHeight(const float value) - { - m_config.m_height = value; - UpdateVisAreaObject(); - } - - float EditorVisAreaComponent::GetHeight() - { - return m_config.m_height; - } - - void EditorVisAreaComponent::SetDisplayFilled(const bool value) - { - m_config.m_displayFilled = value; - UpdateVisAreaObject(); - } - - bool EditorVisAreaComponent::GetDisplayFilled() - { - return m_config.m_displayFilled; - } - - void EditorVisAreaComponent::SetAffectedBySun(const bool value) - { - m_config.m_affectedBySun = value; - UpdateVisAreaObject(); - } - - bool EditorVisAreaComponent::GetAffectedBySun() - { - return m_config.m_affectedBySun; - } - - void EditorVisAreaComponent::SetViewDistRatio(const float value) - { - m_config.m_viewDistRatio = value; - UpdateVisAreaObject(); - } - - float EditorVisAreaComponent::GetViewDistRatio() - { - return m_config.m_viewDistRatio; - } - - void EditorVisAreaComponent::SetOceanIsVisible(const bool value) - { - m_config.m_oceanIsVisible = value; - UpdateVisAreaObject(); - } - - bool EditorVisAreaComponent::GetOceanIsVisible() - { - return m_config.m_oceanIsVisible; - } - - bool EditorVisAreaComponent::GetVertex(size_t index, AZ::Vector3& vertex) const - { - return m_config.m_vertexContainer.GetVertex(index, vertex); - } - - void EditorVisAreaComponent::AddVertex(const AZ::Vector3& vertex) - { - m_config.m_vertexContainer.AddVertex(vertex); - UpdateVisAreaObject(); - } - - bool EditorVisAreaComponent::UpdateVertex(size_t index, const AZ::Vector3& vertex) - { - if (m_config.m_vertexContainer.UpdateVertex(index, vertex)) - { - UpdateVisAreaObject(); - return true; - } - - return false; - } - - bool EditorVisAreaComponent::InsertVertex(size_t index, const AZ::Vector3& vertex) - { - if (m_config.m_vertexContainer.InsertVertex(index, vertex)) - { - UpdateVisAreaObject(); - return true; - } - - return false; - } - - bool EditorVisAreaComponent::RemoveVertex(size_t index) - { - if (m_config.m_vertexContainer.RemoveVertex(index)) - { - UpdateVisAreaObject(); - return true; - } - - return false; - } - - void EditorVisAreaComponent::SetVertices(const AZStd::vector& vertices) - { - m_config.m_vertexContainer.SetVertices(vertices); - UpdateVisAreaObject(); - } - - void EditorVisAreaComponent::ClearVertices() - { - m_config.m_vertexContainer.Clear(); - UpdateVisAreaObject(); - } - - size_t EditorVisAreaComponent::Size() const - { - return m_config.m_vertexContainer.Size(); - } - - bool EditorVisAreaComponent::Empty() const - { - return m_config.m_vertexContainer.Empty(); - } - - void EditorVisAreaComponent::DisplayEntityViewport( - [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) - { - /* - The VisArea and Portal share a common strangeness with how they are displayed. - The Legacy visualization is actually incorrect! It's important to know that - the vis volumes essentially act as a points on an XY plane with a known Z - position and a height. The volumes that actually affect rendition are planar - quads with a height. The height is calculated by the largest height value on - a local point + the given height value on the component. - - Also note that this visualization does not display the floors or ceilings of the vis area - volumes. There is currently no way with the display context to easily draw a filled polygon. - We could try to draw some triangles but it would take up a great deal of rendering - time and could potentially slow down the editor more than we want if there are a lot - of volumes. - */ - - const AZStd::vector& vertices = m_config.m_vertexContainer.GetVertices(); - const size_t vertexCount = vertices.size(); - - //We do not want to push a transform with scale or rotation as the - //vis area is always snapped to the XY plane with a height. - //Scale will be applied during flattening - AZ::Transform translation = AZ::Transform::CreateIdentity(); - translation.SetTranslation(m_currentWorldTransform.GetTranslation()); - - debugDisplay.PushMatrix(translation); - debugDisplay.SetColor(s_visAreaColor.GetAsVector4()); - - AZStd::vector transformedPoints; - transformedPoints.resize(vertexCount); - - //Min and max Z value (in local space) - float minZ = FLT_MAX; - float maxZ = FLT_MIN; - - //Apply rotation and scale before removing translation. - //We want translation to apply with the matrix to make things easier - //but we need to calculate a difference in Z after rotation and scaling. - //During the next loop we'll flatten all these points down to a common XY plane - for (size_t i = 0; i < vertexCount; ++i) - { - AZ::Vector3 transformedPoint = m_currentWorldTransform.TransformPoint(vertices[i]); - - //Back into local space - transformedPoints[i] = transformedPoint - m_currentWorldTransform.GetTranslation(); - - const float transformedZ = transformedPoints[i].GetZ(); - - minZ = AZ::GetMin(transformedZ, minZ); - maxZ = AZ::GetMax(transformedZ, maxZ); - } - - //The height of the vis area + the max local height - const float actualHeight = m_config.m_height + maxZ; - - //Draw walls for every line segment - size_t transformedPointCount = transformedPoints.size(); - for (size_t i = 0; i < transformedPointCount; ++i) - { - AZ::Vector3 lowerLeft = AZ::Vector3(); - AZ::Vector3 lowerRight = AZ::Vector3(); - AZ::Vector3 upperRight = AZ::Vector3(); - AZ::Vector3 upperLeft = AZ::Vector3(); - - lowerLeft = transformedPoints[i]; - lowerRight = transformedPoints[(i + 1) % transformedPointCount]; - //The mod with transformedPointCount ensures that for the last vert it will connect back with vert 0 - //If vert count is 10, the last vert will be i = 9 and we want that to create a surface with vert 0 - - //Make all lower points planar - lowerLeft.SetZ(minZ); - lowerRight.SetZ(minZ); - - upperRight = AZ::Vector3(lowerRight.GetX(), lowerRight.GetY(), actualHeight); - upperLeft = AZ::Vector3(lowerLeft.GetX(), lowerLeft.GetY(), actualHeight); - - if (m_config.m_displayFilled) - { - debugDisplay.SetAlpha(0.3f); - //Draw filled quad with two winding orders to make it double sided - debugDisplay.DrawQuad(lowerLeft, lowerRight, upperRight, upperLeft); - debugDisplay.DrawQuad(lowerLeft, upperLeft, upperRight, lowerRight); - } - - debugDisplay.SetAlpha(1.0f); - debugDisplay.DrawLine(lowerLeft, lowerRight); - debugDisplay.DrawLine(lowerRight, upperRight); - debugDisplay.DrawLine(upperRight, upperLeft); - debugDisplay.DrawLine(upperLeft, lowerLeft); - } - - if (m_componentModeDelegate.AddedToComponentMode()) - { - AzToolsFramework::VertexContainerDisplay::DisplayVertexContainerIndices( - debugDisplay, AzToolsFramework::VariableVerticesVertexContainer(m_config.m_vertexContainer), - GetWorldTM(), AZ::Vector3::CreateOne(), IsSelected()); - } - - debugDisplay.PopMatrix(); - } - - void EditorVisAreaComponent::BuildGameEntity(AZ::Entity* gameEntity) - { - gameEntity->CreateComponent(m_config); - } - - AZ::Aabb EditorVisAreaComponent::GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& /*viewportInfo*/) - { - return GetWorldBounds(); - } - - bool EditorVisAreaComponent::EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, - const AZ::Vector3& dir, float& distance) - { - AZ::Aabb bbox = GetEditorSelectionBoundsViewport(viewportInfo); - float end; - float t; - - const bool intersection = AZ::Intersect::IntersectRayAABB2( - src, dir.GetReciprocal(), - bbox, t, end) > 0; - - if (intersection) - { - distance = t; - } - - return intersection; - } - - AZ::Aabb EditorVisAreaComponent::GetWorldBounds() - { - return GetLocalBounds().GetTransformedAabb(GetWorldTM()); - } - - AZ::Aabb EditorVisAreaComponent::GetLocalBounds() - { - AZ::Aabb bbox = AZ::Aabb::CreateNull(); - for (const auto& vertex : m_config.m_vertexContainer.GetVertices()) - { - bbox.AddPoint(vertex); - } - bbox.AddPoint(bbox.GetMax() + AZ::Vector3::CreateAxisZ(m_config.m_height)); - return bbox; - } -} //namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorVisAreaComponent.h b/Gems/Visibility/Code/Source/EditorVisAreaComponent.h deleted file mode 100644 index 45c87e13cc..0000000000 --- a/Gems/Visibility/Code/Source/EditorVisAreaComponent.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "EditorVisAreaComponentBus.h" -#include "VisAreaComponent.h" - -namespace Visibility -{ - class EditorVisAreaComponent; - - class EditorVisAreaConfiguration - : public VisAreaConfiguration - { - public: - AZ_TYPE_INFO_LEGACY(EditorVisAreaConfiguration, "{C329E65C-1F34-5C80-9A7A-4B568105256B}", VisAreaConfiguration); - AZ_CLASS_ALLOCATOR(EditorVisAreaConfiguration, AZ::SystemAllocator,0); - - static void Reflect(AZ::ReflectContext* context); - - void ChangeHeight() override; - void ChangeDisplayFilled() override; - void ChangeAffectedBySun() override; - void ChangeViewDistRatio() override; - void ChangeOceanIsVisible() override; - void ChangeVertexContainer() override; - - void SetEntityId(AZ::EntityId entityId); - - private: - AZ::EntityId m_entityId; - }; - - class EditorVisAreaComponent - : public AzToolsFramework::Components::EditorComponentBase - , private EditorVisAreaComponentRequestBus::Handler - , private AZ::FixedVerticesRequestBus::Handler - , private AZ::VariableVerticesRequestBus::Handler - , private AzFramework::EntityDebugDisplayEventBus::Handler - , private AzToolsFramework::EditorEntityInfoNotificationBus::Handler - , private AzToolsFramework::EditorComponentSelectionRequestsBus::Handler - , private AZ::TransformNotificationBus::Handler - , public AzFramework::BoundsRequestBus::Handler - { - friend class EditorVisAreaConfiguration; //So that the config can set m_vertices when the vertex container changes - - using Base = AzToolsFramework::Components::EditorComponentBase; - - public: - AZ_COMPONENT(EditorVisAreaComponent, "{F4EC32D8-D4DD-54F7-97A8-D195497D5F2C}", AzToolsFramework::Components::EditorComponentBase); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires); - static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - - static void Reflect(AZ::ReflectContext* context); - - EditorVisAreaComponent() = default; - EditorVisAreaComponent(const EditorVisAreaComponent&) = delete; - EditorVisAreaComponent& operator=(const EditorVisAreaComponent&) = delete; - virtual ~EditorVisAreaComponent(); - - // AZ::Component overrides ... - void Activate() override; - void Deactivate() override; - void BuildGameEntity(AZ::Entity* gameEntity) override; - - // TransformNotificationBus overrides ... - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // EditorComponentSelectionRequestsBus overrides ... - AZ::Aabb GetEditorSelectionBoundsViewport( - const AzFramework::ViewportInfo& viewportInfo) override; - bool EditorSelectionIntersectRayViewport( - const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, - const AZ::Vector3& dir, float& distance) override; - bool SupportsEditorRayIntersect() override { return true; } - - // VisAreaComponentRequestBus overrides ... - void SetHeight(float height) override; - float GetHeight() override; - void SetDisplayFilled(bool filled) override; - bool GetDisplayFilled() override; - void SetAffectedBySun(bool affectedBySun) override; - bool GetAffectedBySun() override; - void SetViewDistRatio(float viewDistRatio) override; - float GetViewDistRatio() override; - void SetOceanIsVisible(bool oceanVisible) override; - bool GetOceanIsVisible() override; - bool GetVertex(size_t index, AZ::Vector3& vertex) const override; - void AddVertex(const AZ::Vector3& vertex) override; - bool UpdateVertex(size_t index, const AZ::Vector3& vertex) override; - bool InsertVertex(size_t index, const AZ::Vector3& vertex) override; - bool RemoveVertex(size_t index) override; - void SetVertices(const AZStd::vector& vertices) override; - void ClearVertices() override; - size_t Size() const override; - bool Empty() const override; - void UpdateVisAreaObject() override; - - // AzFramework::EntityDebugDisplayEventBus overrides ... - void DisplayEntityViewport( - const AzFramework::ViewportInfo& viewportInfo, - AzFramework::DebugDisplayRequests& debugDisplay) override; - - // BoundsRequestBus overrides ... - AZ::Aabb GetWorldBounds() override; - AZ::Aabb GetLocalBounds() override; - - private: - // Reflected members - EditorVisAreaConfiguration m_config; - - using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate; - ComponentModeDelegate m_componentModeDelegate; ///< Responsible for detecting ComponentMode activation - ///< and creating a concrete ComponentMode. - - // Unreflected members - AZ::Transform m_currentWorldTransform; - IVisArea* m_area = nullptr; - - static AZ::Color s_visAreaColor; ///< The orange color that all vis-areas draw with. - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorVisAreaComponentMode.cpp b/Gems/Visibility/Code/Source/EditorVisAreaComponentMode.cpp deleted file mode 100644 index d479e51345..0000000000 --- a/Gems/Visibility/Code/Source/EditorVisAreaComponentMode.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#include "Visibility_precompiled.h" -#include "EditorVisAreaComponentMode.h" - -#include -#include - -namespace Visibility -{ - AZ_CLASS_ALLOCATOR_IMPL(EditorVisAreaComponentMode, AZ::SystemAllocator, 0) - - EditorVisAreaComponentMode::EditorVisAreaComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType) - : EditorBaseComponentMode(entityComponentIdPair, componentType) - { - CreateManipulators(); - - AZ::TransformNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId()); - EditorVisAreaComponentNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId()); - } - - EditorVisAreaComponentMode::~EditorVisAreaComponentMode() - { - EditorVisAreaComponentNotificationBus::Handler::BusDisconnect(); - AZ::TransformNotificationBus::Handler::BusDisconnect(); - - m_vertexSelection.Destroy(); - } - - void EditorVisAreaComponentMode::CreateManipulators() - { - using namespace AzToolsFramework; - - m_vertexSelection.Create( - GetEntityComponentIdPair(), g_mainManipulatorManagerId, - AZStd::make_unique>(GetEntityComponentIdPair(), g_mainManipulatorManagerId), - TranslationManipulators::Dimensions::Three, - ConfigureTranslationManipulatorAppearance3d); - - m_vertexSelection.SetVertexPositionsUpdatedCallback([this]() - { - EditorVisAreaComponentRequestBus::Event( - GetEntityId(), &EditorVisAreaComponentRequests::UpdateVisAreaObject); - }); - } - - void EditorVisAreaComponentMode::OnTransformChanged( - const AZ::Transform& /*local*/, const AZ::Transform& world) - { - m_vertexSelection.RefreshSpace(world); - } - - void EditorVisAreaComponentMode::OnVertexAdded(size_t index) - { - Refresh(); - - AZ::Vector3 vertex; - bool found = false; - AZ::FixedVerticesRequestBus::EventResult( - found, GetEntityId(), &AZ::FixedVerticesRequestBus::Handler::GetVertex, - index, vertex); - - if (found) - { - m_vertexSelection.CreateTranslationManipulator( - GetEntityComponentIdPair(), AzToolsFramework::g_mainManipulatorManagerId, - vertex, index); - } - } - - void EditorVisAreaComponentMode::OnVertexRemoved(size_t /*index*/) - { - Refresh(); - } - - void EditorVisAreaComponentMode::OnVerticesSet(const AZStd::vector& /*vertices*/) - { - Refresh(); - } - - void EditorVisAreaComponentMode::OnVerticesCleared() - { - Refresh(); - } - - void EditorVisAreaComponentMode::Refresh() - { - // destroy and recreate manipulators when container is modified (vertices are added or removed) - m_vertexSelection.Destroy(); - CreateManipulators(); - } - - AZStd::vector EditorVisAreaComponentMode::PopulateActionsImpl() - { - return m_vertexSelection.ActionOverrides(); - } - - bool EditorVisAreaComponentMode::HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) - { - return m_vertexSelection.HandleMouse(mouseInteraction); - } - - AZStd::string EditorVisAreaComponentMode::GetComponentModeName() const - { - return "Vis Area Edit Mode"; - } - -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/EditorVisAreaComponentMode.h b/Gems/Visibility/Code/Source/EditorVisAreaComponentMode.h deleted file mode 100644 index e33aed32f0..0000000000 --- a/Gems/Visibility/Code/Source/EditorVisAreaComponentMode.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -#include "EditorVisAreaComponentBus.h" - -namespace Visibility -{ - /// The ComponentMode for editing the Vis Area Component. - class EditorVisAreaComponentMode - : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode - , private AZ::TransformNotificationBus::Handler - , private EditorVisAreaComponentNotificationBus::Handler - { - public: - AZ_CLASS_ALLOCATOR_DECL - - EditorVisAreaComponentMode( - const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType); - ~EditorVisAreaComponentMode(); - - private: - // EditorBaseComponentMode - void Refresh() override; - AZStd::vector PopulateActionsImpl() override; - bool HandleMouseInteraction( - const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override; - AZStd::string GetComponentModeName() const override; - - // Manipulator handling - void CreateManipulators(); - - // TransformNotificationBus - void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - - // EditorVisAreaComponentNotificationBus - void OnVertexAdded(size_t index) override; - void OnVertexRemoved(size_t index) override; - void OnVerticesSet(const AZStd::vector& vertices) override; - void OnVerticesCleared() override; - - AzToolsFramework::EditorVertexSelectionVariable m_vertexSelection; ///< Handles all manipulator interactions with vertices (inserting and translating). - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/OccluderAreaComponent.cpp b/Gems/Visibility/Code/Source/OccluderAreaComponent.cpp deleted file mode 100644 index 947bc3a38b..0000000000 --- a/Gems/Visibility/Code/Source/OccluderAreaComponent.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#include "Visibility_precompiled.h" -#include "OccluderAreaComponent.h" - -#include -#include -#include - -namespace Visibility -{ - void OccluderAreaComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides) - { - provides.push_back(AZ_CRC("OccluderAreaService")); - } - void OccluderAreaComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires) - { - requires.push_back(AZ_CRC("TransformService")); - } - - void OccluderAreaConfiguration::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("DisplayFilled", &OccluderAreaConfiguration::m_displayFilled) - ->Field("CullDistRatio", &OccluderAreaConfiguration::m_cullDistRatio) - ->Field("UseInIndoors", &OccluderAreaConfiguration::m_useInIndoors) - ->Field("DoubleSide", &OccluderAreaConfiguration::m_doubleSide) - ->Field("vertices", &OccluderAreaConfiguration::m_vertices) - ; - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("OccluderAreaRequestBus") - ->Event("GetDisplayFilled", &OccluderAreaRequestBus::Events::GetDisplayFilled) - ->VirtualProperty("DisplayFilled", "GetDisplayFilled", nullptr) - - ->Event("GetCullDistRatio", &OccluderAreaRequestBus::Events::GetCullDistRatio) - ->VirtualProperty("CullDistRatio", "GetCullDistRatio", nullptr) - - ->Event("GetUseInIndoors", &OccluderAreaRequestBus::Events::GetUseInIndoors) - ->VirtualProperty("UseInIndoors", "GetUseInIndoors", nullptr) - - ->Event("GetDoubleSide", &OccluderAreaRequestBus::Events::GetDoubleSide) - ->VirtualProperty("DoubleSide", "GetDoubleSide", nullptr) - ; - - behaviorContext->Class()->RequestBus("OccluderAreaRequestBus"); - } - } - - void OccluderAreaComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("m_config", &OccluderAreaComponent::m_config) - ; - } - - OccluderAreaConfiguration::Reflect(context); - } - - OccluderAreaComponent::OccluderAreaComponent(const OccluderAreaConfiguration& params) - : m_config(params) - { - } - - void OccluderAreaComponent::Activate() - { - OccluderAreaRequestBus::Handler::BusConnect(GetEntityId()); - AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId()); - } - - void OccluderAreaComponent::Deactivate() - { - AZ::TransformNotificationBus::Handler::BusDisconnect(GetEntityId()); - OccluderAreaRequestBus::Handler::BusDisconnect(GetEntityId()); - } - - bool OccluderAreaComponent::GetDisplayFilled() - { - return m_config.m_displayFilled; - } - - float OccluderAreaComponent::GetCullDistRatio() - { - return m_config.m_cullDistRatio; - } - - bool OccluderAreaComponent::GetUseInIndoors() - { - return m_config.m_useInIndoors; - } - - bool OccluderAreaComponent::GetDoubleSide() - { - return m_config.m_doubleSide; - } - -} //namespace Visibility diff --git a/Gems/Visibility/Code/Source/OccluderAreaComponent.h b/Gems/Visibility/Code/Source/OccluderAreaComponent.h deleted file mode 100644 index 80d98af4df..0000000000 --- a/Gems/Visibility/Code/Source/OccluderAreaComponent.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#pragma once - -#include -#include -#include - -#include "OccluderAreaComponentBus.h" - -namespace Visibility -{ - class OccluderAreaConfiguration - { - public: - AZ_TYPE_INFO(OccluderAreaConfiguration, "{F024EC7E-717F-576C-8C22-09CAFEFEAF29}"); - AZ_CLASS_ALLOCATOR(OccluderAreaConfiguration, AZ::SystemAllocator, 0); - - virtual ~OccluderAreaConfiguration() = default; - - static void Reflect(AZ::ReflectContext* context); - - bool m_displayFilled = true; - float m_cullDistRatio = 100.0f; - bool m_useInIndoors = false; - bool m_doubleSide = true; - - AZStd::array m_vertices = - AZStd::array { { - AZ::Vector3(-1.0f, -1.0f, 0.0f), - AZ::Vector3( 1.0f, -1.0f, 0.0f), - AZ::Vector3( 1.0f, 1.0f, 0.0f), - AZ::Vector3(-1.0f, 1.0f, 0.0f) - } }; - - virtual void OnChange() {} - virtual void OnVerticesChange() {} - }; - - class OccluderAreaComponent - : public AZ::Component - , private OccluderAreaRequestBus::Handler - , public AZ::TransformNotificationBus::Handler - { - public: - AZ_COMPONENT(OccluderAreaComponent, "{B3C90C5F-0F9B-5D4F-ABAE-6D16CB45CB5A}", AZ::Component); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires); - static void Reflect(AZ::ReflectContext* context); - - OccluderAreaComponent() = default; - explicit OccluderAreaComponent(const OccluderAreaConfiguration& params); - - // AZ::Component - void Activate() override; - void Deactivate() override; - - // OccluderAreaRequestBus - bool GetDisplayFilled() override; - float GetCullDistRatio() override; - bool GetUseInIndoors() override; - bool GetDoubleSide() override; - - protected: - // Reflected Data - OccluderAreaConfiguration m_config; - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/PortalComponent.cpp b/Gems/Visibility/Code/Source/PortalComponent.cpp deleted file mode 100644 index 9f1f618607..0000000000 --- a/Gems/Visibility/Code/Source/PortalComponent.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "Visibility_precompiled.h" -#include "PortalComponent.h" - -#include -#include - -namespace Visibility -{ - void PortalComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides) - { - provides.push_back(AZ::Crc32("PortalService")); - } - - void PortalComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires) - { - requires.push_back(AZ::Crc32("TransformService")); - } - - void PortalConfiguration::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("Height", &PortalConfiguration::m_height) - ->Field("DisplayFilled", &PortalConfiguration::m_displayFilled) - ->Field("AffectedBySun", &PortalConfiguration::m_affectedBySun) - ->Field("ViewDistRatio", &PortalConfiguration::m_viewDistRatio) - ->Field("SkyOnly", &PortalConfiguration::m_skyOnly) - ->Field("OceanIsVisible", &PortalConfiguration::m_oceanIsVisible) - ->Field("UseDeepness", &PortalConfiguration::m_useDeepness) - ->Field("DoubleSide", &PortalConfiguration::m_doubleSide) - ->Field("LightBlending", &PortalConfiguration::m_lightBlending) - ->Field("LightBlendValue", &PortalConfiguration::m_lightBlendValue) - ->Field("vertices", &PortalConfiguration::m_vertices) - ; - } - - if (auto* behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("PortalRequestBus") - ->Event("GetHeight", &PortalRequestBus::Events::GetHeight) - ->VirtualProperty("Height", "GetHeight", nullptr) - - ->Event("GetDisplayFilled", &PortalRequestBus::Events::GetDisplayFilled) - ->VirtualProperty("DisplayFilled", "GetDisplayFilled", nullptr) - - ->Event("GetAffectedBySun", &PortalRequestBus::Events::GetAffectedBySun) - ->VirtualProperty("AffectedBySun", "GetAffectedBySun", nullptr) - - ->Event("GetViewDistRatio", &PortalRequestBus::Events::GetViewDistRatio) - ->VirtualProperty("ViewDistRatio", "GetViewDistRatio", nullptr) - - ->Event("GetSkyOnly", &PortalRequestBus::Events::GetSkyOnly) - ->VirtualProperty("SkyOnly", "GetSkyOnly", nullptr) - - ->Event("GetOceanIsVisible", &PortalRequestBus::Events::GetOceanIsVisible) - ->VirtualProperty("OceanIsVisible", "GetOceanIsVisible", nullptr) - - ->Event("GetUseDeepness", &PortalRequestBus::Events::GetUseDeepness) - ->VirtualProperty("UseDeepness", "GetUseDeepness", nullptr) - - ->Event("GetDoubleSide", &PortalRequestBus::Events::GetDoubleSide) - ->VirtualProperty("DoubleSide", "GetDoubleSide", nullptr) - - ->Event("GetLightBlending", &PortalRequestBus::Events::GetLightBlending) - ->VirtualProperty("LightBlending", "GetLightBlending", nullptr) - - ->Event("GetLightBlendValue", &PortalRequestBus::Events::GetLightBlendValue) - ->VirtualProperty("LightBlendValue", "GetLightBlendValue", nullptr) - ; - - behaviorContext->Class()->RequestBus("PortalRequestBus"); - } - } - - bool PortalConfiguration::VersionConverter( - [[maybe_unused]] AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) - { - // conversion from version 1: - // - Remove IgnoreSkyColor - // - Remove IgnoreGI - if (classElement.GetVersion() <= 1) - { - classElement.RemoveElementByName(AZ_CRC("IgnoreSkyColor")); - classElement.RemoveElementByName(AZ_CRC("IgnoreGI")); - } - - return true; - } - - void PortalComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("m_config", &PortalComponent::m_config) - ; - } - - PortalConfiguration::Reflect(context); - } - - PortalComponent::PortalComponent(const PortalConfiguration& params) - : m_config(params) - { - } - - void PortalComponent::Activate() - { - PortalRequestBus::Handler::BusConnect(GetEntityId()); - } - - void PortalComponent::Deactivate() - { - PortalRequestBus::Handler::BusDisconnect(GetEntityId()); - } - - float PortalComponent::GetHeight() - { - return m_config.m_height; - } - - bool PortalComponent::GetDisplayFilled() - { - return m_config.m_displayFilled; - } - - bool PortalComponent::GetAffectedBySun() - { - return m_config.m_affectedBySun; - } - - float PortalComponent::GetViewDistRatio() - { - return m_config.m_viewDistRatio; - } - - bool PortalComponent::GetSkyOnly() - { - return m_config.m_skyOnly; - } - - bool PortalComponent::GetOceanIsVisible() - { - return m_config.m_oceanIsVisible; - } - - bool PortalComponent::GetUseDeepness() - { - return m_config.m_useDeepness; - } - - bool PortalComponent::GetDoubleSide() - { - return m_config.m_doubleSide; - } - - bool PortalComponent::GetLightBlending() - { - return m_config.m_lightBlending; - } - - float PortalComponent::GetLightBlendValue() - { - return m_config.m_lightBlendValue; - } - -} //namespace Visibility diff --git a/Gems/Visibility/Code/Source/PortalComponent.h b/Gems/Visibility/Code/Source/PortalComponent.h deleted file mode 100644 index fd6ce4ab77..0000000000 --- a/Gems/Visibility/Code/Source/PortalComponent.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include - -#include "PortalComponentBus.h" - -namespace Visibility -{ - class PortalConfiguration - { - public: - AZ_TYPE_INFO(PortalConfiguration, "{B9BDF017-DF8B-5DBE-8A92-5F62B7AECC1C}"); - AZ_CLASS_ALLOCATOR(PortalConfiguration, AZ::SystemAllocator,0); - - virtual ~PortalConfiguration() = default; - - static void Reflect(AZ::ReflectContext* context); - static bool VersionConverter( - AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); - - float m_height = 1.0f; - bool m_displayFilled = false; - bool m_affectedBySun = false; - float m_viewDistRatio = 100.0f; - bool m_skyOnly = false; - bool m_oceanIsVisible = false; - bool m_useDeepness = true; - bool m_doubleSide = true; - bool m_lightBlending = true; - float m_lightBlendValue = 0.5f; - - AZStd::array m_vertices = - AZStd::array { { - AZ::Vector3(-1.0f, -1.0f, 0.0f), - AZ::Vector3( 1.0f, -1.0f, 0.0f), - AZ::Vector3( 1.0f, 1.0f, 0.0f), - AZ::Vector3(-1.0f, 1.0f, 0.0f) - } }; - - virtual void OnChange() {} - virtual void OnVerticesChange() {} - }; - - class PortalComponent - : public AZ::Component - , private PortalRequestBus::Handler - { - public: - AZ_COMPONENT(PortalComponent, "{89F1DD88-4445-5A9D-9223-6D4D8D44E6AC}", AZ::Component); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires); - static void Reflect(AZ::ReflectContext* context); - - PortalComponent() = default; - explicit PortalComponent(const PortalConfiguration& params); - - // AZ::Component - void Activate() override; - void Deactivate() override; - - // PortalRequestBus - float GetHeight() override; - bool GetDisplayFilled() override; - bool GetAffectedBySun() override; - float GetViewDistRatio() override; - bool GetSkyOnly() override; - bool GetOceanIsVisible() override; - bool GetUseDeepness() override; - bool GetDoubleSide() override; - bool GetLightBlending() override; - float GetLightBlendValue() override; - - protected: - // Reflected Data - PortalConfiguration m_config; - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/VisAreaComponent.cpp b/Gems/Visibility/Code/Source/VisAreaComponent.cpp deleted file mode 100644 index 7db60f1688..0000000000 --- a/Gems/Visibility/Code/Source/VisAreaComponent.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "Visibility_precompiled.h" -#include "VisAreaComponent.h" - -#include -#include - -namespace Visibility -{ - void VisAreaComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides) - { - provides.push_back(AZ::Crc32("VisAreaService")); - } - - void VisAreaComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires) - { - requires.push_back(AZ::Crc32("TransformService")); - } - - void VisAreaConfiguration::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(2, &VersionConverter) - ->Field("m_Height", &VisAreaConfiguration::m_height) - ->Field("m_DisplayFilled", &VisAreaConfiguration::m_displayFilled) - ->Field("m_AffectedBySun", &VisAreaConfiguration::m_affectedBySun) - ->Field("m_ViewDistRatio", &VisAreaConfiguration::m_viewDistRatio) - ->Field("m_OceanIsVisible", &VisAreaConfiguration::m_oceanIsVisible) - ->Field("m_vertexContainer", &VisAreaConfiguration::m_vertexContainer) - ; - } - - if (auto behaviorContext = azrtti_cast(context)) - { - behaviorContext->EBus("VisAreaComponentRequestBus") - ->Event("GetHeight", &VisAreaComponentRequestBus::Events::GetHeight) - ->VirtualProperty("Height", "GetHeight", nullptr) - - ->Event("GetDisplayFilled", &VisAreaComponentRequestBus::Events::GetDisplayFilled) - ->VirtualProperty("DisplayFilled", "GetDisplayFilled", nullptr) - - ->Event("GetAffectedBySun", &VisAreaComponentRequestBus::Events::GetAffectedBySun) - ->VirtualProperty("AffectedBySun", "GetAffectedBySun", nullptr) - - ->Event("GetViewDistRatio", &VisAreaComponentRequestBus::Events::GetViewDistRatio) - ->VirtualProperty("ViewDistRatio", "GetViewDistRatio", nullptr) - - ->Event("GetOceanIsVisible", &VisAreaComponentRequestBus::Events::GetOceanIsVisible) - ->VirtualProperty("OceanIsVisible", "GetOceanIsVisible", nullptr) - ; - - behaviorContext->Class()->RequestBus("VisAreaComponentRequestBus"); - } - } - - bool VisAreaConfiguration::VersionConverter([[maybe_unused]] AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) - { - // conversion from version 1: - // - Remove IgnoreSkyColor - // - Remove IgnoreGI - // - Remove SkyOnly - if (classElement.GetVersion() <= 1) - { - classElement.RemoveElementByName(AZ_CRC("IgnoreSkyColor")); - classElement.RemoveElementByName(AZ_CRC("IgnoreGI")); - classElement.RemoveElementByName(AZ_CRC("SkyOnly")); - } - - return true; - } - - void VisAreaComponent::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(1) - ->Field("m_config", &VisAreaComponent::m_config) - ; - } - - VisAreaConfiguration::Reflect(context); - } - - VisAreaComponent::VisAreaComponent(const VisAreaConfiguration& params) - : m_config(params) - { - } - - void VisAreaComponent::Activate() - { - VisAreaComponentRequestBus::Handler::BusConnect(GetEntityId()); - } - - void VisAreaComponent::Deactivate() - { - VisAreaComponentRequestBus::Handler::BusDisconnect(GetEntityId()); - } - - float VisAreaComponent::GetHeight() - { - return m_config.m_height; - } - - bool VisAreaComponent::GetDisplayFilled() - { - return m_config.m_displayFilled; - } - - bool VisAreaComponent::GetAffectedBySun() - { - return m_config.m_affectedBySun; - } - - float VisAreaComponent::GetViewDistRatio() - { - return m_config.m_viewDistRatio; - } - - bool VisAreaComponent::GetOceanIsVisible() - { - return m_config.m_oceanIsVisible; - } -} //namespace Visibility diff --git a/Gems/Visibility/Code/Source/VisAreaComponent.h b/Gems/Visibility/Code/Source/VisAreaComponent.h deleted file mode 100644 index f2efe7167d..0000000000 --- a/Gems/Visibility/Code/Source/VisAreaComponent.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include -#include -#include - -#include "VisAreaComponentBus.h" - -namespace Visibility -{ - class VisAreaConfiguration - { - public: - AZ_TYPE_INFO(VisAreaConfiguration, "{160D9FC2-936F-59BB-827C-DEF89671E4DC}"); - AZ_CLASS_ALLOCATOR(VisAreaConfiguration, AZ::SystemAllocator,0); - - virtual ~VisAreaConfiguration() = default; - - static void Reflect(AZ::ReflectContext* context); - static bool VersionConverter( - AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement); - - float m_height = 5.0f; - bool m_displayFilled = false; - bool m_affectedBySun = false; - float m_viewDistRatio = 100.0f; - bool m_oceanIsVisible = false; - AZ::VertexContainer m_vertexContainer; - - virtual void ChangeHeight() {} - virtual void ChangeDisplayFilled() {} - virtual void ChangeAffectedBySun() {} - virtual void ChangeViewDistRatio() {} - virtual void ChangeOceanIsVisible() {} - virtual void ChangeVertexContainer() {} - }; - - class VisAreaComponent - : public AZ::Component - , private VisAreaComponentRequestBus::Handler - { - public: - AZ_COMPONENT(VisAreaComponent, "{ACAB60F8-100E-5EAF-BE2B-D60F79312404}", AZ::Component); - - static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provides); - static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& requires); - static void Reflect(AZ::ReflectContext* context); - - VisAreaComponent() = default; - explicit VisAreaComponent(const VisAreaConfiguration& params); - - // AZ::Component - void Activate() override; - void Deactivate() override; - - // VisAreaComponentRequestBus - float GetHeight() override; - bool GetDisplayFilled() override; - bool GetAffectedBySun() override; - float GetViewDistRatio() override; - bool GetOceanIsVisible() override; - - private: - VisAreaConfiguration m_config; ///< Reflected configuration. - }; -} // namespace Visibility diff --git a/Gems/Visibility/Code/Source/VisibilityGem.cpp b/Gems/Visibility/Code/Source/VisibilityGem.cpp deleted file mode 100644 index 37d31a56f6..0000000000 --- a/Gems/Visibility/Code/Source/VisibilityGem.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "Visibility_precompiled.h" - -#include "VisibilityGem.h" - -#include "OccluderAreaComponent.h" -#include "PortalComponent.h" -#include "VisAreaComponent.h" - -#ifdef VISIBILITY_EDITOR -#include "EditorOccluderAreaComponent.h" -#include "EditorPortalComponent.h" -#include "EditorVisAreaComponent.h" -#endif //VISIBILITY_EDITOR - -VisibilityGem::VisibilityGem() -{ - m_descriptors.push_back(Visibility::OccluderAreaComponent::CreateDescriptor()); - m_descriptors.push_back(Visibility::PortalComponent::CreateDescriptor()); - m_descriptors.push_back(Visibility::VisAreaComponent::CreateDescriptor()); - -#ifdef VISIBILITY_EDITOR - m_descriptors.push_back(Visibility::EditorOccluderAreaComponent::CreateDescriptor()); - m_descriptors.push_back(Visibility::EditorPortalComponent::CreateDescriptor()); - m_descriptors.push_back(Visibility::EditorVisAreaComponent::CreateDescriptor()); -#endif //VISIBILITY_EDITOR -} - -AZ_DECLARE_MODULE_CLASS(Gem_Visibility, VisibilityGem) diff --git a/Gems/Visibility/Code/Source/Visibility_precompiled.cpp b/Gems/Visibility/Code/Source/Visibility_precompiled.cpp deleted file mode 100644 index 6d32d0ea69..0000000000 --- a/Gems/Visibility/Code/Source/Visibility_precompiled.cpp +++ /dev/null @@ -1,12 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "Visibility_precompiled.h" diff --git a/Gems/Visibility/Code/Tests/VisibilityTest.cpp b/Gems/Visibility/Code/Tests/VisibilityTest.cpp deleted file mode 100644 index 406cef86a4..0000000000 --- a/Gems/Visibility/Code/Tests/VisibilityTest.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "Visibility_precompiled.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -class VisibilityTest - : public ::testing::Test -{ -protected: - - void SetUp() override - { - AZ::ComponentApplication::Descriptor appDesc; - appDesc.m_memoryBlocksByteSize = 10 * 1024 * 1024; - appDesc.m_recordingMode = AZ::Debug::AllocationRecords::RECORD_FULL; - - AZ::ComponentApplication::StartupParameters appStartup; - appStartup.m_createStaticModulesCallback = - [](AZStd::vector& modules) - { - modules.emplace_back(new VisibilityGem); - }; - - m_systemEntity = m_application.Create(appDesc, appStartup); - m_systemEntity->Init(); - m_systemEntity->Activate(); - - m_application.RegisterComponentDescriptor(AzFramework::TransformComponent::CreateDescriptor()); - m_application.RegisterComponentDescriptor(Visibility::OccluderAreaComponent::CreateDescriptor()); - m_application.RegisterComponentDescriptor(Visibility::PortalComponent::CreateDescriptor()); - m_application.RegisterComponentDescriptor(Visibility::VisAreaComponent::CreateDescriptor()); - } - - void TearDown() override - { - m_application.Destroy(); - } - - AZ::ComponentApplication m_application; - AZ::Entity* m_systemEntity; -}; - -#include -#include -#include - -TEST_F(VisibilityTest, Occluder_TestIntersect) -{ - AZ::Entity* testEntity = aznew AZ::Entity(); - ASSERT_TRUE(testEntity != nullptr); - - testEntity->CreateComponent(); - testEntity->CreateComponent(); - - Visibility::EditorOccluderAreaComponent* oaComp = testEntity->FindComponent(); - ASSERT_TRUE(oaComp != nullptr); - testEntity->Init(); - testEntity->Activate(); - - // Test CCW tri intersection test - const AZ::Vector3 src(0, 0, 10); - const AZ::Vector3 dir(0, 0, -1); - float distance; - - // Visibility Components do not make use of the ViewportInfo to determine - // camera position etc. - AzFramework::ViewportInfo viewportInfo{}; - - bool didHit = oaComp->EditorSelectionIntersectRayViewport(viewportInfo, src, dir, distance); - ASSERT_TRUE(didHit); - ASSERT_NEAR(distance, 10, 0.1f); // Occluder is a flat plane - - // Test CW tri intersection test - const AZ::Vector3 srcNeg(0, 0, -10); - const AZ::Vector3 dirNeg(0, 0, 1); - - didHit = oaComp->EditorSelectionIntersectRayViewport(viewportInfo, srcNeg, dirNeg, distance); - ASSERT_TRUE(didHit); - ASSERT_NEAR(distance, 10, 0.1f); // Occluder is a flat plane - - // Test intersect failure - const AZ::Vector3 badDir(100, 100, -1); - didHit = oaComp->EditorSelectionIntersectRayViewport(viewportInfo, src, badDir, distance); - ASSERT_FALSE(didHit); -} - -TEST_F(VisibilityTest, Portal_TestIntersect) -{ - AZ::Entity* testEntity = aznew AZ::Entity(); - ASSERT_TRUE(testEntity != nullptr); - - testEntity->CreateComponent(); - testEntity->CreateComponent(); - - Visibility::EditorPortalComponent* pComp = testEntity->FindComponent(); - ASSERT_TRUE(pComp != nullptr); - testEntity->Init(); - testEntity->Activate(); - - const AZ::Vector3 src(0, 0, 10); - const AZ::Vector3 dir(0, 0, -1); - float distance; - - // Visibility Components do not make use of the ViewportInfo to determine - // camera position etc. - AzFramework::ViewportInfo viewportInfo{}; - - // Test intersect - bool didHit = pComp->EditorSelectionIntersectRayViewport(viewportInfo, src, dir, distance); - ASSERT_TRUE(didHit); - ASSERT_NEAR(distance, 9, 0.1f); // Portal has a default height of 1 - - // Test casting a ray from inside the geom - const AZ::Vector3 internalSrc(0, 0, 0.5f); - didHit = pComp->EditorSelectionIntersectRayViewport(viewportInfo, internalSrc, dir, distance); - ASSERT_FALSE(didHit); - - // Test intersect failure - const AZ::Vector3 badDir(100, 100, -1); - didHit = pComp->EditorSelectionIntersectRayViewport(viewportInfo, src, badDir, distance); - ASSERT_FALSE(didHit); -} - -TEST_F(VisibilityTest, VisArea_TestIntersect) -{ - AZ::Entity* testEntity = aznew AZ::Entity(); - ASSERT_TRUE(testEntity != nullptr); - - testEntity->CreateComponent(); - testEntity->CreateComponent(); - testEntity->Init(); - testEntity->Activate(); - - Visibility::EditorVisAreaComponent* vaComp = testEntity->FindComponent(); - ASSERT_TRUE(vaComp != nullptr); - - const AZ::Vector3 src(0, 0, 10); - const AZ::Vector3 dir(0, 0, -1); - float distance; - - // Visibility Components do not make use of the ViewportInfo to determine - // camera position etc. - AzFramework::ViewportInfo viewportInfo{}; - - bool didHit = vaComp->EditorSelectionIntersectRayViewport(viewportInfo, src, dir, distance); - ASSERT_TRUE(didHit); - ASSERT_NEAR(distance, 5, 0.1f); // VisArea has a default height of 5 - - const AZ::Vector3 badDir(100, 100, -1); - didHit = vaComp->EditorSelectionIntersectRayViewport(viewportInfo, src, badDir, distance); - ASSERT_FALSE(didHit); -} - -AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); diff --git a/Gems/Visibility/Code/visibility_editor_files.cmake b/Gems/Visibility/Code/visibility_editor_files.cmake deleted file mode 100644 index 9d17b92e27..0000000000 --- a/Gems/Visibility/Code/visibility_editor_files.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - Include/EditorOccluderAreaComponentBus.h - Include/EditorPortalComponentBus.h - Include/EditorVisAreaComponentBus.h - Source/EditorOccluderAreaComponentMode.h - Source/EditorOccluderAreaComponentMode.cpp - Source/EditorPortalComponentMode.h - Source/EditorPortalComponentMode.cpp - Source/EditorVisAreaComponentMode.h - Source/EditorVisAreaComponentMode.cpp -) diff --git a/Gems/Visibility/Code/visibility_editor_shared_files.cmake b/Gems/Visibility/Code/visibility_editor_shared_files.cmake deleted file mode 100644 index 1714fc1402..0000000000 --- a/Gems/Visibility/Code/visibility_editor_shared_files.cmake +++ /dev/null @@ -1,21 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - Source/VisibilityGem.h - Source/VisibilityGem.cpp - Source/EditorOccluderAreaComponent.h - Source/EditorOccluderAreaComponent.cpp - Source/EditorPortalComponent.h - Source/EditorPortalComponent.cpp - Source/EditorVisAreaComponent.h - Source/EditorVisAreaComponent.cpp -) diff --git a/Gems/Visibility/Code/visibility_editor_tests_files.cmake b/Gems/Visibility/Code/visibility_editor_tests_files.cmake deleted file mode 100644 index 52867e64af..0000000000 --- a/Gems/Visibility/Code/visibility_editor_tests_files.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - Tests/VisibilityTest.cpp - Source/VisibilityGem.h - Source/VisibilityGem.cpp - Source/EditorOccluderAreaComponent.h - Source/EditorOccluderAreaComponent.cpp - Source/EditorPortalComponent.h - Source/EditorPortalComponent.cpp - Source/EditorVisAreaComponent.h - Source/EditorVisAreaComponent.cpp -) diff --git a/Gems/Visibility/Code/visibility_files.cmake b/Gems/Visibility/Code/visibility_files.cmake deleted file mode 100644 index e58ac4fbba..0000000000 --- a/Gems/Visibility/Code/visibility_files.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - Source/Visibility_precompiled.cpp - Source/Visibility_precompiled.h - Include/OccluderAreaComponentBus.h - Include/PortalComponentBus.h - Include/VisAreaComponentBus.h - Source/OccluderAreaComponent.h - Source/OccluderAreaComponent.cpp - Source/PortalComponent.h - Source/PortalComponent.cpp - Source/VisAreaComponent.h - Source/VisAreaComponent.cpp -) diff --git a/Gems/Visibility/gem.json b/Gems/Visibility/gem.json deleted file mode 100644 index 3e8eca471b..0000000000 --- a/Gems/Visibility/gem.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "gem_name": "Visibility", - "GemFormatVersion": 3, - "Uuid": "3b4ab3f54c2749328934c5b864355a61", - "Name": "Visibility", - "DisplayName": "Visibility", - "Version": "0.1.0", - "LinkType": "Dynamic", - "Summary": "Provides components for defining visible regions of a scene", - "Tags": ["Untagged"], - "IconPath": "preview.png", - "EditorModule": true -} diff --git a/Gems/Visibility/preview.png b/Gems/Visibility/preview.png deleted file mode 100644 index f60ab5eebd..0000000000 --- a/Gems/Visibility/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8f1a3e838ba075704ee974a1289487d4007e7b7385eb855b8b2a09534b6cecd1 -size 1949 diff --git a/Gems/WhiteBox/Code/Source/WhiteBoxSystemComponent.cpp b/Gems/WhiteBox/Code/Source/WhiteBoxSystemComponent.cpp index 6f24d409c9..8dc37c94fe 100644 --- a/Gems/WhiteBox/Code/Source/WhiteBoxSystemComponent.cpp +++ b/Gems/WhiteBox/Code/Source/WhiteBoxSystemComponent.cpp @@ -19,7 +19,6 @@ #include #include -#include namespace WhiteBox { @@ -63,12 +62,7 @@ namespace WhiteBox SetRenderMeshInterfaceBuilder( []() -> AZStd::unique_ptr { - if (AZ::Interface::Get()) - { - return AZStd::make_unique(); - } - - return AZStd::make_unique(); + return AZStd::make_unique(); }); WhiteBoxRequestBus::Handler::BusConnect(); diff --git a/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp b/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp index 6b2ba9ae4b..013b05fc3c 100644 --- a/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp +++ b/Gems/WhiteBox/Code/Tests/WhiteBoxPhysicsTest.cpp @@ -53,7 +53,7 @@ namespace UnitTest void EditorWhiteBoxPhysicsTestEnvironment::AddGemsAndComponents() { - AddDynamicModulePaths({"PhysX.Editor"}); + AddDynamicModulePaths({"PhysX.Editor.Gem"}); AddComponentDescriptors( {AzToolsFramework::EditorEntityContextComponent::CreateDescriptor(), WhiteBox::EditorWhiteBoxComponent::CreateDescriptor(), WhiteBox::WhiteBoxComponent::CreateDescriptor(), diff --git a/README.md b/README.md index caed4b515c..333ca795e8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ It is highly recommended you check that you have a [credential manager installed ### Clone the repository ```shell -> git clone https://github.com/aws/o3de.git +> git clone https://github.com/aws-lumberyard/o3de.git Cloning into 'o3de'... # initial prompt for credentials to download the repository code diff --git a/Registry/application_options.setreg b/Registry/application_options.setreg new file mode 100644 index 0000000000..06ccdc9b41 --- /dev/null +++ b/Registry/application_options.setreg @@ -0,0 +1,17 @@ +{ + "O3DE" : { + "AzCore": { + "Application": { + "ValidCommandOptions": [ + "project-path", + "engine-path", + "project-cache-path", + "regset", + "regremove", + "regdump", + "regdumpall" + ] + } + } + } +} diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 7ccd118413..4056242a47 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -14,7 +14,7 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARG ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev7-multiplatform TARGETS assimplib PACKAGE_HASH def855c89d8210db3040f1cb6ec837141ab9b8e74c158eae7c03d50160fcf30b) +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev8-multiplatform TARGETS assimplib PACKAGE_HASH 21dce424eccf5a2626ff0841e72092fa4ff9407a64b851e5eed9895926ce309d) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) @@ -43,6 +43,6 @@ ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux TARGETS mikk ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-linux TARGETS googletest PACKAGE_HASH 7b7ad330f369450c316a4c4592d17fbb4c14c731c95bd8f37757203e8c2bbc1b) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-linux TARGETS GoogleBenchmark PACKAGE_HASH 4038878f337fc7e0274f0230f71851b385b2e0327c495fc3dd3d1c18a807928d) ly_associate_package(PACKAGE_NAME unwind-1.2.1-linux TARGETS unwind PACKAGE_HASH 3453265fb056e25432f611a61546a25f60388e315515ad39007b5925dd054a77) -ly_associate_package(PACKAGE_NAME qt-5.15.2-linux TARGETS Qt PACKAGE_HASH 3857fbb2fc5581cdb71d80a7f9298c83ef06073d4e1ccd86a32b4f88782b6f14) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev3-linux TARGETS Qt PACKAGE_HASH b7d9932647f4b138b3f0b124d70debd250d2a8a6dca52b04dcbe82c6369d48ca) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-linux TARGETS libsamplerate PACKAGE_HASH 41643c31bc6b7d037f895f89d8d8d6369e906b92eff42b0fe05ee6a100f06261) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-linux TARGETS OpenSSL PACKAGE_HASH b779426d1e9c5ddf71160d5ae2e639c3b956e0fb5e9fcaf9ce97c4526024e3bc) diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index bd2fd969eb..fbe24d382d 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages_linux.cmake - dyad_linux.cmake FbxSdk_linux.cmake Wwise_linux.cmake ) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index fb6b17fb72..e06eadcbea 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -14,7 +14,7 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev7-multiplatform TARGETS assimplib PACKAGE_HASH def855c89d8210db3040f1cb6ec837141ab9b8e74c158eae7c03d50160fcf30b) +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev8-multiplatform TARGETS assimplib PACKAGE_HASH 21dce424eccf5a2626ff0841e72092fa4ff9407a64b851e5eed9895926ce309d) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) @@ -47,5 +47,5 @@ ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac TARGETS mik ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-mac TARGETS googletest PACKAGE_HASH cbf020d5ef976c5db8b6e894c6c63151ade85ed98e7c502729dd20172acae5a8) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-mac TARGETS GoogleBenchmark PACKAGE_HASH ad25de0146769c91e179953d845de2bec8ed4a691f973f47e3eb37639381f665) ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-mac TARGETS OpenSSL PACKAGE_HASH 28adc1c0616ac0482b2a9d7b4a3a3635a1020e87b163f8aba687c501cf35f96c) -ly_associate_package(PACKAGE_NAME qt-5.15.2-mac TARGETS Qt PACKAGE_HASH ac248833d65838e4bcef50f30c9ff02ba9464ff64b9ada52de2ad6045d38baec) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev3-mac TARGETS Qt PACKAGE_HASH 29966f22ec253dc9904e88ad48fe6b6a669302b2dc7049f2e2bbd4949e79e595) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac TARGETS libsamplerate PACKAGE_HASH b912af40c0ac197af9c43d85004395ba92a6a859a24b7eacd920fed5854a97fe) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index e8c1361b3f..939948d501 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -14,7 +14,7 @@ ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev7-multiplatform TARGETS assimplib PACKAGE_HASH def855c89d8210db3040f1cb6ec837141ab9b8e74c158eae7c03d50160fcf30b) +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev8-multiplatform TARGETS assimplib PACKAGE_HASH 21dce424eccf5a2626ff0841e72092fa4ff9407a64b851e5eed9895926ce309d) ly_associate_package(PACKAGE_NAME squish-ccr-20150601-rev3-multiplatform TARGETS squish-ccr PACKAGE_HASH c878c6c0c705e78403c397d03f5aa7bc87e5978298710e14d09c9daf951a83b3) ly_associate_package(PACKAGE_NAME ASTCEncoder-2017_11_14-rev2-multiplatform TARGETS ASTCEncoder PACKAGE_HASH c240ffc12083ee39a5ce9dc241de44d116e513e1e3e4cc1d05305e7aa3bdc326) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) @@ -51,7 +51,7 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-windows TARGETS Goo ly_associate_package(PACKAGE_NAME d3dx12-headers-rev1-windows TARGETS d3dx12 PACKAGE_HASH 088c637159fba4a3e4c0cf08fb4921906fd4cca498939bd239db7c54b5b2f804) ly_associate_package(PACKAGE_NAME pyside2-qt-5.15.1-rev2-windows TARGETS pyside2 PACKAGE_HASH c90f3efcc7c10e79b22a33467855ad861f9dbd2e909df27a5cba9db9fa3edd0f) ly_associate_package(PACKAGE_NAME openimageio-2.1.16.0-rev2-windows TARGETS OpenImageIO PACKAGE_HASH 85a2a6cf35cbc4c967c56ca8074babf0955c5b490c90c6e6fd23c78db99fc282) -ly_associate_package(PACKAGE_NAME qt-5.15.2-windows TARGETS Qt PACKAGE_HASH edaf954c647c99727bfd313dab2959803d2df0873914bb96368c3d8286eed6d9) +ly_associate_package(PACKAGE_NAME qt-5.15.2-rev2-windows TARGETS Qt PACKAGE_HASH 29966f22ec253dc9904e88ad48fe6b6a669302b2dc7049f2e2bbd4949e79e595) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-windows TARGETS libsamplerate PACKAGE_HASH dcf3c11a96f212a52e2c9241abde5c364ee90b0f32fe6eeb6dcdca01d491829f) ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows TARGETS OpenMesh PACKAGE_HASH 1c1df639358526c368e790dfce40c45cbdfcfb1c9a041b9d7054a8949d88ee77) ly_associate_package(PACKAGE_NAME civetweb-1.8-rev1-windows TARGETS civetweb PACKAGE_HASH 36d0e58a59bcdb4dd70493fb1b177aa0354c945b06c30416348fd326cf323dd4) diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 57dc8ed604..64d58e912f 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages_windows.cmake - dyad_windows.cmake FbxSdk_windows.cmake Wwise_windows.cmake ) diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index a4737b7020..80e1ae426a 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -12,7 +12,6 @@ set(FILES BuiltInPackages.cmake FindClang.cmake - Finddyad.cmake FindFbxSdk.cmake FindOpenGLInterface.cmake FindRadTelemetry.cmake diff --git a/cmake/CPack.cmake b/cmake/Packaging.cmake similarity index 100% rename from cmake/CPack.cmake rename to cmake/Packaging.cmake diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index fb3a7b1b09..8fe2fe2c1c 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -286,7 +286,7 @@ endfunction() function(ly_setup_others) # List of directories we want to install relative to engine root - set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole scripts) + set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole) foreach(dir ${DIRECTORIES_TO_INSTALL}) get_filename_component(install_path ${dir} DIRECTORY) @@ -301,6 +301,24 @@ function(ly_setup_others) endforeach() + # Scripts + file(GLOB o3de_scripts "${CMAKE_SOURCE_DIR}/scripts/o3de.*") + install(FILES + ${o3de_scripts} + DESTINATION ./scripts + COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} + ) + + install(DIRECTORY + ${CMAKE_SOURCE_DIR}/scripts/bundler + ${CMAKE_SOURCE_DIR}/scripts/project_manager + DESTINATION ./scripts + COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} + PATTERN "__pycache__" EXCLUDE + PATTERN "CMakeLists.txt" EXCLUDE + PATTERN "tests" EXCLUDE + ) + install(DIRECTORY "${CMAKE_SOURCE_DIR}/python" DESTINATION . COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} @@ -311,7 +329,7 @@ function(ly_setup_others) # Registry install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin/$/Registry - DESTINATION ./bin/$ + DESTINATION ./bin/${PAL_PLATFORM_NAME}/$ COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} ) install(DIRECTORY @@ -350,16 +368,14 @@ function(ly_setup_others) endif() endforeach() - # Qt Binaries - set(QT_BIN_DIRS bearer iconengines imageformats platforms styles translations) - foreach(qt_dir ${QT_BIN_DIRS}) - install(DIRECTORY - ${CMAKE_CURRENT_BINARY_DIR}/bin/$/${qt_dir} - DESTINATION ./bin/$ - COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} - ) - endforeach() + set(QT_DIRS bearer iconengines imageformats platforms styles translations) + list(TRANSFORM QT_DIRS PREPEND "${CMAKE_CURRENT_BINARY_DIR}/bin/$/" OUTPUT_VARIABLE QT_BIN_DIRS) + install(DIRECTORY + ${QT_BIN_DIRS} + DESTINATION ./bin/${PAL_PLATFORM_NAME}/$ + COMPONENT ${LY_DEFAULT_INSTALL_COMPONENT} + ) # Templates install(DIRECTORY diff --git a/cmake/Platform/iOS/Configurations_ios.cmake b/cmake/Platform/iOS/Configurations_ios.cmake index aa935c853f..6522c6a098 100644 --- a/cmake/Platform/iOS/Configurations_ios.cmake +++ b/cmake/Platform/iOS/Configurations_ios.cmake @@ -41,6 +41,11 @@ endif() # Signing ly_set(CMAKE_XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS --deep) +# Symbol Stripping +ly_set(CMAKE_XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=debug] "NO") +ly_set(CMAKE_XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=profile] "NO") +ly_set(CMAKE_XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=release] "YES") + # Generate scheme files for Xcode ly_set(CMAKE_XCODE_GENERATE_SCHEME TRUE) diff --git a/cmake/Platform/iOS/LYWrappers_ios.cmake b/cmake/Platform/iOS/LYWrappers_ios.cmake index 53783e5c0a..8da421ad5c 100644 --- a/cmake/Platform/iOS/LYWrappers_ios.cmake +++ b/cmake/Platform/iOS/LYWrappers_ios.cmake @@ -14,11 +14,6 @@ include(cmake/Platform/Common/LYWrappers_default.cmake) function(ly_apply_platform_properties target) get_target_property(target_type ${target} TYPE) - set_target_properties(${target} - PROPERTIES - XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING "YES" - ) - if(${target_type} STREQUAL "SHARED_LIBRARY") # Some projects use an "_" in their target name which is not allowed in a bundle identifier get_target_property(target_name ${target} NAME) diff --git a/cmake/cmake_files.cmake b/cmake/cmake_files.cmake index 5045a42cbe..e423eb0dbc 100644 --- a/cmake/cmake_files.cmake +++ b/cmake/cmake_files.cmake @@ -14,7 +14,6 @@ set(FILES 3rdPartyPackages.cmake CommandExecution.cmake Configurations.cmake - CPack.cmake Dependencies.cmake Deployment.cmake EngineFinder.cmake @@ -27,6 +26,7 @@ set(FILES LYPython.cmake LYWrappers.cmake Monolithic.cmake + Packaging.cmake PAL.cmake PALTools.cmake Projects.cmake diff --git a/scripts/scrubbing/validator.py b/scripts/scrubbing/validator.py index e442e443c8..ac7c45554f 100755 --- a/scripts/scrubbing/validator.py +++ b/scripts/scrubbing/validator.py @@ -312,7 +312,7 @@ class Validator(object): # Once we split the repos we will have to worry about multiple root points etc. but that is a problem for future us. # All the packaging safelist stuff goes away once repo is split for platforms this_path = Path(__file__).resolve() - root_folder = this_path.parents[5] + root_folder = this_path.parents[2] relative_folder = os.path.relpath(this_path.parent, root_folder) canary_file = os.path.join(root_folder, 'restricted', platform, relative_folder, platform.lower() + '_canary.txt') try: