Merge branch 'stabilization/2106' into Atom/gallowj/stabilization/2106
This commit is contained in:
@@ -13,13 +13,6 @@ add_subdirectory(asset_processor_tests)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
## AP Python Tests ##
|
||||
ly_add_pytest(
|
||||
NAME AssetPipelineTests.AuxiliaryContent
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/auxiliary_content_tests/auxiliary_content_tests.py
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
TEST_SUITE periodic
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AssetPipelineTests.BankInfoParser
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/wwise_bank_dependency_tests/bank_info_parser_tests.py
|
||||
|
||||
-96
@@ -1,96 +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.
|
||||
|
||||
"""
|
||||
import pytest
|
||||
import ly_test_tools
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
import glob
|
||||
from ly_test_tools.builtin.helpers import *
|
||||
from ly_test_tools.environment.process_utils import *
|
||||
from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
project_list = ['AutomatedTesting']
|
||||
|
||||
@pytest.mark.system
|
||||
@pytest.mark.SUITE_periodic
|
||||
class TestAuxiliaryContent:
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project):
|
||||
path_to_dev = workspace.paths.engine_root()
|
||||
os.chdir(path_to_dev)
|
||||
auxiliaryContentDirName = str.lower(project) + f"_{ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]}_paks"
|
||||
self.auxiliaryContentPath = os.path.join(path_to_dev, auxiliaryContentDirName)
|
||||
|
||||
def teardown():
|
||||
if (os.path.exists(self.auxiliaryContentPath)):
|
||||
shutil.rmtree(self.auxiliaryContentPath)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@staticmethod
|
||||
def scanForLevelPak(path_toscan):
|
||||
files = glob.glob('{0}/**/level.pak'.format(path_toscan), recursive=True)
|
||||
return len(files)
|
||||
|
||||
@pytest.mark.parametrize('level', ['alldependencies'])
|
||||
@pytest.mark.parametrize('project', project_list)
|
||||
def test_CreateAuxiliaryContent_DontSkipLevelPaks(self, workspace, level):
|
||||
"""
|
||||
This test ensure that Auxiliary Content contain level.pak files
|
||||
|
||||
Test Steps:
|
||||
1. Run auxiliary content against project under test
|
||||
2. Validate auxiliary content exists
|
||||
3. Verifies that level.pak exists
|
||||
"""
|
||||
|
||||
path_to_dev = workspace.paths.engine_root()
|
||||
bin_path = workspace.paths.build_directory()
|
||||
|
||||
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
|
||||
subprocess.check_call(['python', auxiliaryContentScriptPath,
|
||||
"--buildFolder={0}".format(bin_path),
|
||||
"--platforms=pc",
|
||||
f"--project-path={workspace.project}"])
|
||||
|
||||
assert os.path.exists(self.auxiliaryContentPath)
|
||||
assert not self.scanForLevelPak(self.auxiliaryContentPath) == 0
|
||||
|
||||
@pytest.mark.parametrize('level', ['alldependencies'])
|
||||
@pytest.mark.parametrize('project', project_list)
|
||||
def test_CreateAuxiliaryContent_SkipLevelPaks(self, workspace, level):
|
||||
"""
|
||||
This test ensure that Auxiliary Content contain no level.pak file
|
||||
|
||||
Test Steps:
|
||||
1. Run auxiliary content against project under test with skiplevelPaks flag
|
||||
2. Validate auxiliary content exists
|
||||
3. Validate level.pak was added to auxiliary content
|
||||
"""
|
||||
|
||||
path_to_dev = workspace.paths.engine_root()
|
||||
bin_path = workspace.paths.build_directory()
|
||||
|
||||
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
|
||||
subprocess.check_call(['python', auxiliaryContentScriptPath,
|
||||
"--buildFolder={0}".format(bin_path),
|
||||
"--platforms=pc",
|
||||
"--skiplevelPaks",
|
||||
f"--project-path={workspace.project}"])
|
||||
assert os.path.exists(self.auxiliaryContentPath)
|
||||
|
||||
assert self.scanForLevelPak(self.auxiliaryContentPath) == 0
|
||||
@@ -49,7 +49,7 @@ class TestViewMenuOptions(EditorTestHelper):
|
||||
view_menu_options = [
|
||||
("Center on Selection",),
|
||||
("Show Quick Access Bar",),
|
||||
("Viewport", "Wireframe"),
|
||||
("Viewport", "Configure Layout"),
|
||||
("Viewport", "Go to Position"),
|
||||
("Viewport", "Center on Selection"),
|
||||
("Viewport", "Go to Location"),
|
||||
|
||||
@@ -89,7 +89,7 @@ class TestMenus(object):
|
||||
expected_lines = [
|
||||
"Center on Selection Action triggered",
|
||||
"Show Quick Access Bar Action triggered",
|
||||
"Wireframe Action triggered",
|
||||
"Configure Layout Action triggered",
|
||||
"Go to Position Action triggered",
|
||||
"Center on Selection Action triggered",
|
||||
"Go to Location Action triggered",
|
||||
|
||||
@@ -93,11 +93,13 @@ class TestAutomation(TestAutomationBase):
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@revert_physics_config
|
||||
@fm.file_override('physxsystemconfiguration.setreg','C4044457_Material_RestitutionCombine.setreg_override', 'AutomatedTesting/Registry')
|
||||
def test_C4044457_Material_RestitutionCombine(self, request, workspace, editor, launcher_platform):
|
||||
from . import C4044457_Material_RestitutionCombine as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@revert_physics_config
|
||||
@fm.file_override('physxsystemconfiguration.setreg','C4044456_Material_FrictionCombine.setreg_override', 'AutomatedTesting/Registry')
|
||||
def test_C4044456_Material_FrictionCombine(self, request, workspace, editor, launcher_platform):
|
||||
from . import C4044456_Material_FrictionCombine as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
@@ -194,6 +196,7 @@ class TestAutomation(TestAutomationBase):
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@revert_physics_config
|
||||
@fm.file_override('physxsystemconfiguration.setreg','C18981526_Material_RestitutionCombinePriority.setreg_override', 'AutomatedTesting/Registry')
|
||||
def test_C18981526_Material_RestitutionCombinePriority(self, request, workspace, editor, launcher_platform):
|
||||
from . import C18981526_Material_RestitutionCombinePriority as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
@@ -229,6 +232,7 @@ class TestAutomation(TestAutomationBase):
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@revert_physics_config
|
||||
@fm.file_override('physxsystemconfiguration.setreg','C18977601_Material_FrictionCombinePriority.setreg_override', 'AutomatedTesting/Registry')
|
||||
def test_C18977601_Material_FrictionCombinePriority(self, request, workspace, editor, launcher_platform):
|
||||
from . import C18977601_Material_FrictionCombinePriority as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
@@ -250,6 +254,7 @@ class TestAutomation(TestAutomationBase):
|
||||
@pytest.mark.xfail(
|
||||
reason="This test needs new physics asset with multiple materials to be more stable.")
|
||||
@revert_physics_config
|
||||
@fm.file_override('physxsystemconfiguration.setreg','C4044697_Material_PerfaceMaterialValidation.setreg_override', 'AutomatedTesting/Registry')
|
||||
def test_C4044697_Material_PerfaceMaterialValidation(self, request, workspace, editor, launcher_platform):
|
||||
from . import C4044697_Material_PerfaceMaterialValidation as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
@@ -282,6 +287,7 @@ class TestAutomation(TestAutomationBase):
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@revert_physics_config
|
||||
@fm.file_override('physxsystemconfiguration.setreg','C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.setreg_override', 'AutomatedTesting/Registry')
|
||||
def test_C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(self, request, workspace, editor, launcher_platform):
|
||||
from . import C15556261_PhysXMaterials_CharacterControllerMaterialAssignment as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
@@ -326,6 +332,7 @@ class TestAutomation(TestAutomationBase):
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
@revert_physics_config
|
||||
@fm.file_override('physxsystemconfiguration.setreg','C4044461_Material_Restitution.setreg_override', 'AutomatedTesting/Registry')
|
||||
def test_C4044461_Material_Restitution(self, request, workspace, editor, launcher_platform):
|
||||
from . import C4044461_Material_Restitution as test_module
|
||||
self._run_test(request, workspace, editor, test_module)
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"Gems": {
|
||||
"PhysX": {
|
||||
"PhysXSystemConfiguration": {
|
||||
"CollisionConfig": {
|
||||
"Layers": {
|
||||
"LayerNames": [
|
||||
"Default",
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
"TouchBend"
|
||||
]
|
||||
},
|
||||
"Groups": {
|
||||
"GroupPresets": [
|
||||
{
|
||||
"Name": "All",
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
|
||||
},
|
||||
"Name": "None",
|
||||
"Group": {
|
||||
"Mask": 0
|
||||
},
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
|
||||
},
|
||||
"Name": "All_NoTouchBend",
|
||||
"Group": {
|
||||
"Mask": 9223372036854775807
|
||||
},
|
||||
"ReadOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"MaterialLibrary": {
|
||||
"assetId": {
|
||||
"guid": "{70D4A444-AFD4-57C4-9885-63F25AC3C281}"
|
||||
},
|
||||
"loadBehavior": "QueueLoad",
|
||||
"assetHint": "levels/physics/c15556261_physxmaterials_charactercontrollermaterialassignment/library.physmaterial"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"Gems": {
|
||||
"PhysX": {
|
||||
"PhysXSystemConfiguration": {
|
||||
"CollisionConfig": {
|
||||
"Layers": {
|
||||
"LayerNames": [
|
||||
"Default",
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
"TouchBend"
|
||||
]
|
||||
},
|
||||
"Groups": {
|
||||
"GroupPresets": [
|
||||
{
|
||||
"Name": "All",
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
|
||||
},
|
||||
"Name": "None",
|
||||
"Group": {
|
||||
"Mask": 0
|
||||
},
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
|
||||
},
|
||||
"Name": "All_NoTouchBend",
|
||||
"Group": {
|
||||
"Mask": 9223372036854775807
|
||||
},
|
||||
"ReadOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"MaterialLibrary": {
|
||||
"assetId": {
|
||||
"guid": "{B8749DAB-15DA-5A61-B565-C853673604CD}"
|
||||
},
|
||||
"loadBehavior": "QueueLoad",
|
||||
"assetHint": "levels/physics/c18977601_material_frictioncombinepriority/friction_combine.physmaterial"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"Gems": {
|
||||
"PhysX": {
|
||||
"PhysXSystemConfiguration": {
|
||||
"CollisionConfig": {
|
||||
"Layers": {
|
||||
"LayerNames": [
|
||||
"Default",
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
"TouchBend"
|
||||
]
|
||||
},
|
||||
"Groups": {
|
||||
"GroupPresets": [
|
||||
{
|
||||
"Name": "All",
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
|
||||
},
|
||||
"Name": "None",
|
||||
"Group": {
|
||||
"Mask": 0
|
||||
},
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
|
||||
},
|
||||
"Name": "All_NoTouchBend",
|
||||
"Group": {
|
||||
"Mask": 9223372036854775807
|
||||
},
|
||||
"ReadOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"MaterialLibrary": {
|
||||
"assetId": {
|
||||
"guid": "{AED48B18-0F3F-5E59-A8FF-30DB134B307B}"
|
||||
},
|
||||
"loadBehavior": "QueueLoad",
|
||||
"assetHint": "levels/physics/c18981526_material_restitutioncombinepriority/restitution_combine.physmaterial"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"Gems": {
|
||||
"PhysX": {
|
||||
"PhysXSystemConfiguration": {
|
||||
"CollisionConfig": {
|
||||
"Layers": {
|
||||
"LayerNames": [
|
||||
"Default",
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
"TouchBend"
|
||||
]
|
||||
},
|
||||
"Groups": {
|
||||
"GroupPresets": [
|
||||
{
|
||||
"Name": "All",
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
|
||||
},
|
||||
"Name": "None",
|
||||
"Group": {
|
||||
"Mask": 0
|
||||
},
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
|
||||
},
|
||||
"Name": "All_NoTouchBend",
|
||||
"Group": {
|
||||
"Mask": 9223372036854775807
|
||||
},
|
||||
"ReadOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"MaterialLibrary": {
|
||||
"assetId": {
|
||||
"guid": "{8D2C4A29-E0FC-564F-82C9-24BBA30C5A90}"
|
||||
},
|
||||
"loadBehavior": "QueueLoad",
|
||||
"assetHint": "levels/physics/c4044456_material_frictioncombine/friction_combine.physmaterial"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"Gems": {
|
||||
"PhysX": {
|
||||
"PhysXSystemConfiguration": {
|
||||
"CollisionConfig": {
|
||||
"Layers": {
|
||||
"LayerNames": [
|
||||
"Default",
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
"TouchBend"
|
||||
]
|
||||
},
|
||||
"Groups": {
|
||||
"GroupPresets": [
|
||||
{
|
||||
"Name": "All",
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
|
||||
},
|
||||
"Name": "None",
|
||||
"Group": {
|
||||
"Mask": 0
|
||||
},
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
|
||||
},
|
||||
"Name": "All_NoTouchBend",
|
||||
"Group": {
|
||||
"Mask": 9223372036854775807
|
||||
},
|
||||
"ReadOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"MaterialLibrary": {
|
||||
"assetId": {
|
||||
"guid": "{D5D6A6DE-E636-5638-B30D-6CE2FDC321F8}"
|
||||
},
|
||||
"loadBehavior": "QueueLoad",
|
||||
"assetHint": "levels/physics/c4044457_material_restitutioncombine/restitution_combine.physmaterial"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"Gems": {
|
||||
"PhysX": {
|
||||
"PhysXSystemConfiguration": {
|
||||
"CollisionConfig": {
|
||||
"Layers": {
|
||||
"LayerNames": [
|
||||
"Default",
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
"TouchBend"
|
||||
]
|
||||
},
|
||||
"Groups": {
|
||||
"GroupPresets": [
|
||||
{
|
||||
"Name": "All",
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
|
||||
},
|
||||
"Name": "None",
|
||||
"Group": {
|
||||
"Mask": 0
|
||||
},
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
|
||||
},
|
||||
"Name": "All_NoTouchBend",
|
||||
"Group": {
|
||||
"Mask": 9223372036854775807
|
||||
},
|
||||
"ReadOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"MaterialLibrary": {
|
||||
"assetId": {
|
||||
"guid": "{E4117B5B-8D9A-5C1D-BA1E-C36542A6588D}"
|
||||
},
|
||||
"loadBehavior": "QueueLoad",
|
||||
"assetHint": "levels/physics/c4044461_material_restitution/restitution.physmaterial"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"Amazon": {
|
||||
"Gems": {
|
||||
"PhysX": {
|
||||
"PhysXSystemConfiguration": {
|
||||
"CollisionConfig": {
|
||||
"Layers": {
|
||||
"LayerNames": [
|
||||
"Default",
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
"TouchBend"
|
||||
]
|
||||
},
|
||||
"Groups": {
|
||||
"GroupPresets": [
|
||||
{
|
||||
"Name": "All",
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
|
||||
},
|
||||
"Name": "None",
|
||||
"Group": {
|
||||
"Mask": 0
|
||||
},
|
||||
"ReadOnly": true
|
||||
},
|
||||
{
|
||||
"Id": {
|
||||
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
|
||||
},
|
||||
"Name": "All_NoTouchBend",
|
||||
"Group": {
|
||||
"Mask": 9223372036854775807
|
||||
},
|
||||
"ReadOnly": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"MaterialLibrary": {
|
||||
"assetId": {
|
||||
"guid": "{2E85B457-ED19-5FE3-90B4-6EFFB4D0E682}"
|
||||
},
|
||||
"loadBehavior": "QueueLoad",
|
||||
"assetHint": "levels/physics/c4044697_material_perfacematerialvalidation/test_library.physmaterial"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,6 +406,7 @@ namespace AZ
|
||||
AZStd::vector<AZ::BehaviorParameter> eventParamsTypes{ AZStd::initializer_list<AZ::BehaviorParameter>{
|
||||
CreateBehaviorEventParameter<decay_array<T>>()... } };
|
||||
behaviorContext->Class<AZ::Event<T...>>()
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
|
||||
->Attribute(AZ::Script::Attributes::EventHandlerCreationFunction, createHandlerHolder)
|
||||
->Attribute(AZ::Script::Attributes::EventParameterTypes, eventParamsTypes)
|
||||
->Method("HasHandlerConnected", &AZ::Event<T...>::HasHandlerConnected)
|
||||
@@ -413,6 +414,7 @@ namespace AZ
|
||||
|
||||
behaviorContext->Class<AZ::EventHandler<T...>>()
|
||||
->Method("Disconnect", &AZ::EventHandler<T...>::Disconnect)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::ListOnly)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -607,10 +607,12 @@ namespace AZ
|
||||
}
|
||||
else if (source.Size() > target.Size())
|
||||
{
|
||||
rapidjson::SizeType sourceCount = source.Size();
|
||||
for (rapidjson::SizeType i = count; i < sourceCount; ++i)
|
||||
// Loop backwards through the removals so that each removal has a valid index when processing in order.
|
||||
for (rapidjson::SizeType i = source.Size(); i > count; --i)
|
||||
{
|
||||
ScopedStackedString entryName(element, i);
|
||||
// (We use "i - 1" here instead of in the loop to ensure we don't wrap around our unsigned numbers in the case
|
||||
// where count is 0.)
|
||||
ScopedStackedString entryName(element, i - 1);
|
||||
patch.PushBack(CreatePatchInternal_Remove(allocator, element), allocator);
|
||||
resultCode.Combine(settings.m_reporting("Removed member from array in JSON Patch.",
|
||||
ResultCode(Tasks::CreatePatch, Outcomes::Success), element));
|
||||
|
||||
@@ -175,4 +175,11 @@ namespace AZ::Utils
|
||||
path /= ".o3de";
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetO3deLogsDirectory()
|
||||
{
|
||||
AZ::IO::FixedMaxPath path = GetO3deManifestDirectory();
|
||||
path /= "Logs";
|
||||
return path.Native();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,9 @@ namespace AZ
|
||||
//! Retrieves the full path where the manifest file lives, i.e. "<userhome>/.o3de/o3de_manifest.json"
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath();
|
||||
|
||||
//! Retrieves the full directory to the O3DE logs directory, i.e. "<userhome>/.o3de/Logs"
|
||||
AZ::IO::FixedMaxPathString GetO3deLogsDirectory();
|
||||
|
||||
//! Retrieves the App root path to use on the current platform
|
||||
//! If the optional is not engaged the AppRootPath should be calculated based
|
||||
//! on the location of the bootstrap.cfg file
|
||||
|
||||
@@ -303,6 +303,29 @@ namespace JsonSerializationTests
|
||||
R"( { "foo": [ "bar", "baz" ] })");
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchRemoveArrayMembersInCorrectOrder_ReportsSuccess)
|
||||
{
|
||||
CheckApplyPatch(
|
||||
R"( { "foo": [ "bar", "qux", "baz" ] })",
|
||||
R"( [
|
||||
{ "op": "remove", "path": "/foo/2" },
|
||||
{ "op": "remove", "path": "/foo/1" }
|
||||
])",
|
||||
R"( { "foo": [ "bar" ] })");
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchRemoveArrayMembersInWrongOrder_ReportsError)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
CheckApplyPatchOutcome(
|
||||
R"( { "foo": [ "bar", "qux", "baz" ] })",
|
||||
R"( [
|
||||
{ "op": "remove", "path": "/foo/1" },
|
||||
{ "op": "remove", "path": "/foo/2" }
|
||||
])",
|
||||
Outcomes::Invalid, Processing::Halted);
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchRemoveOperationInvalidParent_ReportError)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
@@ -949,6 +972,27 @@ namespace JsonSerializationTests
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, CreatePatch_UseJsonPatchRemoveLastArrayEntries_MultipleOperationsInCorrectOrder)
|
||||
{
|
||||
CheckCreatePatch(
|
||||
R"( [ "foo", "hello", "bar" ])", R"( [ "foo" ])",
|
||||
R"( [
|
||||
{ "op": "remove", "path": "/2" },
|
||||
{ "op": "remove", "path": "/1" }
|
||||
])");
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, CreatePatch_UseJsonPatchRemoveAllArrayEntries_MultipleOperationsInCorrectOrder)
|
||||
{
|
||||
CheckCreatePatch(
|
||||
R"( [ "foo", "hello", "bar" ])", R"( [])",
|
||||
R"( [
|
||||
{ "op": "remove", "path": "/2" },
|
||||
{ "op": "remove", "path": "/1" },
|
||||
{ "op": "remove", "path": "/0" }
|
||||
])");
|
||||
}
|
||||
|
||||
TEST_F(JsonPatchingSerializationTests, CreatePatch_UseJsonPatchRemoveObjectFromArrayInMiddle_OperationToUpdateMember)
|
||||
{
|
||||
CheckCreatePatch(
|
||||
|
||||
+14
-3
@@ -159,12 +159,23 @@ namespace AzToolsFramework
|
||||
|
||||
void PrefabEditorEntityOwnershipService::GetNonPrefabEntities(EntityList& entities)
|
||||
{
|
||||
m_rootInstance->GetEntities(entities, false);
|
||||
m_rootInstance->GetEntities(
|
||||
[&entities](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
entities.emplace_back(entity.get());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool PrefabEditorEntityOwnershipService::GetAllEntities(EntityList& entities)
|
||||
{
|
||||
m_rootInstance->GetEntities(entities, true);
|
||||
m_rootInstance->GetAllEntitiesInHierarchy(
|
||||
[&entities](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
entities.emplace_back(entity.get());
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -551,7 +562,7 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
m_rootInstance->GetNestedEntities([this](AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
m_rootInstance->GetAllEntitiesInHierarchy([this](AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
AZ_Assert(entity, "Invalid entity found in root instance while starting play in editor.");
|
||||
if (entity->GetState() == AZ::Entity::State::Active)
|
||||
|
||||
@@ -373,17 +373,25 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::GetConstNestedEntities(const AZStd::function<bool(const AZ::Entity&)>& callback)
|
||||
bool Instance::GetEntities_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
|
||||
{
|
||||
GetConstEntities(callback);
|
||||
|
||||
for (const auto& [instanceAlias, instance] : m_nestedInstances)
|
||||
for (auto& [entityAlias, entity] : m_entities)
|
||||
{
|
||||
instance->GetConstNestedEntities(callback);
|
||||
if (!entity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!callback(entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Instance::GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback)
|
||||
bool Instance::GetConstEntities_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const
|
||||
{
|
||||
for (const auto& [entityAlias, entity] : m_entities)
|
||||
{
|
||||
@@ -394,19 +402,83 @@ namespace AzToolsFramework
|
||||
|
||||
if (!callback(*entity))
|
||||
{
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Instance::GetNestedEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
|
||||
bool Instance::GetAllEntitiesInHierarchy_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
|
||||
{
|
||||
GetEntities(callback);
|
||||
if (HasContainerEntity())
|
||||
{
|
||||
if (!callback(m_containerEntity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetEntities_Impl(callback))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& [instanceAlias, instance] : m_nestedInstances)
|
||||
{
|
||||
instance->GetNestedEntities(callback);
|
||||
if (!instance->GetAllEntitiesInHierarchy_Impl(callback))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Instance::GetAllEntitiesInHierarchyConst_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const
|
||||
{
|
||||
if (HasContainerEntity())
|
||||
{
|
||||
if (!callback(*m_containerEntity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GetConstEntities_Impl(callback))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& [instanceAlias, instance] : m_nestedInstances)
|
||||
{
|
||||
if (!instance->GetAllEntitiesInHierarchyConst_Impl(callback))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Instance::GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
|
||||
{
|
||||
GetEntities_Impl(callback);
|
||||
}
|
||||
|
||||
void Instance::GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback) const
|
||||
{
|
||||
GetConstEntities_Impl(callback);
|
||||
}
|
||||
|
||||
void Instance::GetAllEntitiesInHierarchy(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
|
||||
{
|
||||
GetAllEntitiesInHierarchy_Impl(callback);
|
||||
}
|
||||
|
||||
void Instance::GetAllEntitiesInHierarchyConst(const AZStd::function<bool(const AZ::Entity&)>& callback) const
|
||||
{
|
||||
GetAllEntitiesInHierarchyConst_Impl(callback);
|
||||
}
|
||||
|
||||
void Instance::GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback)
|
||||
@@ -417,44 +489,6 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback)
|
||||
{
|
||||
for (auto& [entityAlias, entity] : m_entities)
|
||||
{
|
||||
if (!callback(entity))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::GetEntities(EntityList& entities, bool includeNestedEntities)
|
||||
{
|
||||
// Non-recursive traversal of instances
|
||||
AZStd::vector<Instance*> instancesToTraverse = { this };
|
||||
while (!instancesToTraverse.empty())
|
||||
{
|
||||
Instance* currentInstance = instancesToTraverse.back();
|
||||
instancesToTraverse.pop_back();
|
||||
if (includeNestedEntities)
|
||||
{
|
||||
instancesToTraverse.reserve(instancesToTraverse.size() + currentInstance->m_nestedInstances.size());
|
||||
for (const auto& instanceByAlias : currentInstance->m_nestedInstances)
|
||||
{
|
||||
instancesToTraverse.push_back(instanceByAlias.second.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Size increases by 1 for each instance because we have to count the container entity also.
|
||||
entities.reserve(entities.size() + currentInstance->m_entities.size() + 1);
|
||||
entities.push_back(m_containerEntity.get());
|
||||
for (const auto& entityByAlias : currentInstance->m_entities)
|
||||
{
|
||||
entities.push_back(entityByAlias.second.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EntityAliasOptionalReference Instance::GetEntityAlias(const AZ::EntityId& id)
|
||||
{
|
||||
if (m_instanceToTemplateEntityIdMap.count(id))
|
||||
|
||||
@@ -121,10 +121,10 @@ namespace AzToolsFramework
|
||||
/**
|
||||
* Gets the entities in the Instance DOM. Can recursively trace all nested instances.
|
||||
*/
|
||||
void GetConstNestedEntities(const AZStd::function<bool(const AZ::Entity&)>& callback);
|
||||
void GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback);
|
||||
void GetNestedEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
|
||||
void GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
|
||||
void GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
|
||||
void GetAllEntitiesInHierarchy(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
|
||||
void GetAllEntitiesInHierarchyConst(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
|
||||
void GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback);
|
||||
|
||||
/**
|
||||
@@ -184,12 +184,6 @@ namespace AzToolsFramework
|
||||
|
||||
static InstanceAlias GenerateInstanceAlias();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Gets the entities owned by this instance
|
||||
*/
|
||||
void GetEntities(EntityList& entities, bool includeNestedEntities = false);
|
||||
|
||||
private:
|
||||
static constexpr const char s_aliasPathSeparator = '/';
|
||||
|
||||
@@ -197,6 +191,11 @@ namespace AzToolsFramework
|
||||
|
||||
void RemoveEntities(const AZStd::function<bool(const AZStd::unique_ptr<AZ::Entity>&)>& filter);
|
||||
|
||||
bool GetEntities_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
|
||||
bool GetConstEntities_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
|
||||
bool GetAllEntitiesInHierarchy_Impl(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback);
|
||||
bool GetAllEntitiesInHierarchyConst_Impl(const AZStd::function<bool(const AZ::Entity&)>& callback) const;
|
||||
|
||||
bool RegisterEntity(const AZ::EntityId& entityId, const EntityAlias& entityAlias);
|
||||
AZStd::unique_ptr<AZ::Entity> DetachEntity(const EntityAlias& entityAlias);
|
||||
|
||||
|
||||
+9
-24
@@ -62,25 +62,16 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::vector<AZ::Entity*> EditorInfoRemover::GetEntitiesFromInstance(AZStd::unique_ptr<Instance>& instance)
|
||||
void EditorInfoRemover::GetEntitiesFromInstance(
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities)
|
||||
{
|
||||
AZStd::vector<AZ::Entity*> result;
|
||||
|
||||
instance->GetNestedEntities(
|
||||
[&result](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
instance->GetAllEntitiesInHierarchy(
|
||||
[&hierarchyEntities](const AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
result.emplace_back(entity.get());
|
||||
hierarchyEntities.emplace_back(entity.get());
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
if (instance->HasContainerEntity())
|
||||
{
|
||||
auto containerEntityReference = instance->GetContainerEntity();
|
||||
result.emplace_back(&containerEntityReference->get());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void EditorInfoRemover::SetEditorOnlyEntityHandlerFromCandidates(const EntityList& entities)
|
||||
@@ -543,7 +534,9 @@ exportComponent, prefabProcessorContext);
|
||||
}
|
||||
|
||||
// grab all nested entities from the Instance as source entities.
|
||||
EntityList sourceEntities = GetEntitiesFromInstance(instance);
|
||||
EntityList sourceEntities;
|
||||
GetEntitiesFromInstance(instance, sourceEntities);
|
||||
|
||||
EntityList exportEntities;
|
||||
|
||||
// prepare for validation of component requirements.
|
||||
@@ -616,7 +609,7 @@ exportComponent, prefabProcessorContext);
|
||||
);
|
||||
|
||||
// replace entities of instance with exported ones.
|
||||
instance->GetNestedEntities(
|
||||
instance->GetAllEntitiesInHierarchy(
|
||||
[&exportEntitiesMap](AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
auto entityId = entity->GetId();
|
||||
@@ -625,14 +618,6 @@ exportComponent, prefabProcessorContext);
|
||||
}
|
||||
);
|
||||
|
||||
if (instance->HasContainerEntity())
|
||||
{
|
||||
if (auto found = exportEntitiesMap.find(instance->GetContainerEntityId()); found != exportEntitiesMap.end())
|
||||
{
|
||||
instance->SetContainerEntity(*found->second);
|
||||
}
|
||||
}
|
||||
|
||||
// save the final result in the target Prefab DOM.
|
||||
PrefabDom filteredPrefab;
|
||||
if (!PrefabDomUtils::StoreInstanceInPrefabDom(*instance, filteredPrefab))
|
||||
|
||||
+2
-2
@@ -55,8 +55,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
|
||||
|
||||
protected:
|
||||
using EntityList = AZStd::vector<AZ::Entity*>;
|
||||
static EntityList GetEntitiesFromInstance(
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance);
|
||||
static void GetEntitiesFromInstance(
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance>& instance, EntityList& hierarchyEntities);
|
||||
|
||||
static bool ReadComponentAttribute(
|
||||
AZ::Component* component,
|
||||
|
||||
+12
-6
@@ -29,15 +29,20 @@ namespace Benchmark
|
||||
{},
|
||||
m_pathString));
|
||||
|
||||
|
||||
auto& prefabDom = m_prefabSystemComponent->FindTemplateDom(instance->GetTemplateId());
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
|
||||
AzFramework::Spawnable spawnable;
|
||||
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(spawnable, prefabDom);
|
||||
|
||||
state.ResumeTiming();
|
||||
// Create a vector to store spawnables so that they don't get destroyed immediately after construction.
|
||||
AZStd::vector<AZStd::unique_ptr<AzFramework::Spawnable>> spawnables;
|
||||
spawnables.reserve(numSpawnables);
|
||||
|
||||
for (int spwanableCounter = 0; spwanableCounter < numSpawnables; ++spwanableCounter)
|
||||
{
|
||||
AZStd::unique_ptr<AzFramework::Spawnable> spawnable = AZStd::make_unique<AzFramework::Spawnable>();
|
||||
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(*spawnable, prefabDom);
|
||||
spawnables.push_back(AZStd::move(spawnable));
|
||||
}
|
||||
}
|
||||
|
||||
state.SetComplexityN(numSpawnables);
|
||||
@@ -50,3 +55,4 @@ namespace Benchmark
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace UnitTest
|
||||
|
||||
// Retrieve the entity pointer from the component application bus.
|
||||
AZ::Entity* wheelEntityUnderAxle = nullptr;
|
||||
axleInstance->GetNestedEntities([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
axleInstance->GetAllEntitiesInHierarchy([&wheelEntityUnderAxle, wheelEntityIdUnderAxle](AZStd::unique_ptr<AZ::Entity>& entity)
|
||||
{
|
||||
if (entity->GetId() == wheelEntityIdUnderAxle)
|
||||
{
|
||||
|
||||
@@ -2891,7 +2891,7 @@ void CCryEditApp::OpenProjectManager(const AZStd::string& screen)
|
||||
{
|
||||
// provide the current project path for in case we want to update the project
|
||||
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
|
||||
const AZStd::string commandLineOptions = AZStd::string::format(" --screen %s --project_path %s", screen.c_str(), projectPath.c_str());
|
||||
const AZStd::string commandLineOptions = AZStd::string::format(" --screen %s --project-path %s", screen.c_str(), projectPath.c_str());
|
||||
bool launchSuccess = AzFramework::ProjectManager::LaunchProjectManager(commandLineOptions);
|
||||
if (!launchSuccess)
|
||||
{
|
||||
@@ -4060,17 +4060,10 @@ void CCryEditApp::SetEditorWindowTitle(QString sTitleStr, QString sPreTitleStr,
|
||||
{
|
||||
if (MainWindow::instance() || m_pConsoleDialog)
|
||||
{
|
||||
QString platform = "";
|
||||
|
||||
#ifdef WIN64
|
||||
platform = "[x64]";
|
||||
#else
|
||||
platform = "[x86]";
|
||||
#endif //WIN64
|
||||
|
||||
if (sTitleStr.isEmpty())
|
||||
{
|
||||
sTitleStr = QObject::tr("Open 3D Engine Editor Beta %1 - Build %2").arg(platform).arg(LY_BUILD);
|
||||
sTitleStr = QObject::tr("O3DE Editor [Developer Preview]");
|
||||
}
|
||||
|
||||
if (!sPreTitleStr.isEmpty())
|
||||
|
||||
@@ -47,8 +47,6 @@ CEditorPreferencesPage_AWS::CEditorPreferencesPage_AWS()
|
||||
{
|
||||
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
|
||||
InitializeSettings();
|
||||
|
||||
// TODO Update with AWS svg.
|
||||
m_icon = QIcon(":/res/AWS_preferences_icon.svg");
|
||||
}
|
||||
|
||||
|
||||
@@ -514,18 +514,28 @@ void EditorViewportWidget::Update()
|
||||
// Disable rendering to avoid recursion into Update()
|
||||
PushDisableRendering();
|
||||
|
||||
|
||||
//get debug display interface for the viewport
|
||||
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
|
||||
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, GetViewportId());
|
||||
AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus.");
|
||||
|
||||
AzFramework::DebugDisplayRequests* debugDisplay =
|
||||
AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
|
||||
|
||||
|
||||
// draw debug visualizations
|
||||
if (m_debugDisplay)
|
||||
if (debugDisplay)
|
||||
{
|
||||
const AZ::u32 prevState = m_debugDisplay->GetState();
|
||||
m_debugDisplay->SetState(
|
||||
const AZ::u32 prevState = debugDisplay->GetState();
|
||||
debugDisplay->SetState(
|
||||
e_Mode3D | e_AlphaBlended | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn);
|
||||
|
||||
AzFramework::EntityDebugDisplayEventBus::Broadcast(
|
||||
&AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport,
|
||||
AzFramework::ViewportInfo{ GetViewportId() }, *m_debugDisplay);
|
||||
AzFramework::ViewportInfo{ GetViewportId() }, *debugDisplay);
|
||||
|
||||
m_debugDisplay->SetState(prevState);
|
||||
debugDisplay->SetState(prevState);
|
||||
}
|
||||
|
||||
QtViewport::Update();
|
||||
|
||||
@@ -154,11 +154,23 @@ SandboxIntegrationManager::SandboxIntegrationManager()
|
||||
{
|
||||
// Required to receive events from the Cry Engine undo system
|
||||
GetIEditor()->GetUndoManager()->AddListener(this);
|
||||
|
||||
// Only create the PrefabIntegrationManager if prefabs are enabled
|
||||
bool prefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
prefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (prefabSystemEnabled)
|
||||
{
|
||||
m_prefabIntegrationManager = aznew AzToolsFramework::Prefab::PrefabIntegrationManager();
|
||||
}
|
||||
}
|
||||
|
||||
SandboxIntegrationManager::~SandboxIntegrationManager()
|
||||
{
|
||||
GetIEditor()->GetUndoManager()->RemoveListener(this);
|
||||
|
||||
delete m_prefabIntegrationManager;
|
||||
m_prefabIntegrationManager = nullptr;
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::Setup()
|
||||
@@ -187,11 +199,16 @@ void SandboxIntegrationManager::Setup()
|
||||
AZ_Assert((m_editorEntityUiInterface != nullptr),
|
||||
"SandboxIntegrationManager requires a EditorEntityUiInterface instance to be present on Setup().");
|
||||
|
||||
m_prefabIntegrationInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabIntegrationInterface>::Get();
|
||||
|
||||
AZ_Assert(
|
||||
(m_prefabIntegrationInterface != nullptr),
|
||||
"SandboxIntegrationManager requires a PrefabIntegrationInterface instance to be present on Setup().");
|
||||
bool prefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
prefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (prefabSystemEnabled)
|
||||
{
|
||||
m_prefabIntegrationInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabIntegrationInterface>::Get();
|
||||
AZ_Assert(
|
||||
(m_prefabIntegrationInterface != nullptr),
|
||||
"SandboxIntegrationManager requires a PrefabIntegrationInterface instance to be present on Setup().");
|
||||
}
|
||||
|
||||
m_editorEntityAPI = AZ::Interface<AzToolsFramework::EditorEntityAPI>::Get();
|
||||
AZ_Assert(m_editorEntityAPI, "SandboxIntegrationManager requires an EditorEntityAPI instance to be present on Setup().");
|
||||
|
||||
@@ -305,7 +305,7 @@ private:
|
||||
|
||||
bool m_debugDisplayBusImplementationActive = false;
|
||||
|
||||
AzToolsFramework::Prefab::PrefabIntegrationManager m_prefabIntegrationManager;
|
||||
AzToolsFramework::Prefab::PrefabIntegrationManager* m_prefabIntegrationManager = nullptr;
|
||||
|
||||
AzToolsFramework::EditorEntityUiInterface* m_editorEntityUiInterface = nullptr;
|
||||
AzToolsFramework::Prefab::PrefabIntegrationInterface* m_prefabIntegrationInterface = nullptr;
|
||||
|
||||
@@ -19,6 +19,7 @@ set(FILES
|
||||
native/AssetManager/AssetRequestHandler.cpp
|
||||
native/AssetManager/AssetRequestHandler.h
|
||||
native/AssetManager/assetScanFolderInfo.h
|
||||
native/AssetManager/assetScanFolderInfo.cpp
|
||||
native/AssetManager/assetScanner.cpp
|
||||
native/AssetManager/assetScanner.h
|
||||
native/AssetManager/assetScannerWorker.cpp
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <native/AssetManager/assetScanFolderInfo.h>
|
||||
#include <native/utilities/assetUtils.h>
|
||||
|
||||
namespace AssetProcessor
|
||||
{
|
||||
ScanFolderInfo::ScanFolderInfo(
|
||||
QString path,
|
||||
QString displayName,
|
||||
QString portableKey,
|
||||
bool isRoot,
|
||||
bool recurseSubFolders,
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms,
|
||||
int order,
|
||||
AZ::s64 scanFolderID,
|
||||
bool canSaveNewAssets)
|
||||
: m_scanPath(path)
|
||||
, m_displayName(displayName)
|
||||
, m_portableKey (portableKey)
|
||||
, m_isRoot(isRoot)
|
||||
, m_recurseSubFolders(recurseSubFolders)
|
||||
, m_order(order)
|
||||
, m_scanFolderID(scanFolderID)
|
||||
, m_platforms(platforms)
|
||||
, m_canSaveNewAssets(canSaveNewAssets)
|
||||
{
|
||||
m_scanPath = AssetUtilities::NormalizeFilePath(m_scanPath);
|
||||
// note that m_scanFolderID is 0 unless its filled in from the DB.
|
||||
}
|
||||
|
||||
} // end namespace AssetProcessor
|
||||
@@ -33,19 +33,7 @@ namespace AssetProcessor
|
||||
AZStd::vector<AssetBuilderSDK::PlatformInfo> platforms = AZStd::vector<AssetBuilderSDK::PlatformInfo>{},
|
||||
int order = 0,
|
||||
AZ::s64 scanFolderID = 0,
|
||||
bool canSaveNewAssets = false)
|
||||
: m_scanPath(path)
|
||||
, m_displayName(displayName)
|
||||
, m_portableKey (portableKey)
|
||||
, m_isRoot(isRoot)
|
||||
, m_recurseSubFolders(recurseSubFolders)
|
||||
, m_order(order)
|
||||
, m_scanFolderID(scanFolderID)
|
||||
, m_platforms(platforms)
|
||||
, m_canSaveNewAssets(canSaveNewAssets)
|
||||
{
|
||||
// note that m_scanFolderID is 0 unless its filled in from the DB.
|
||||
}
|
||||
bool canSaveNewAssets = false);
|
||||
|
||||
ScanFolderInfo() = default;
|
||||
ScanFolderInfo(const ScanFolderInfo& other) = default;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "BuilderManager.h"
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <native/connection/connectionManager.h>
|
||||
@@ -186,10 +187,9 @@ namespace AssetProcessor
|
||||
QDir projectCacheRoot;
|
||||
AssetUtilities::ComputeProjectCacheRoot(projectCacheRoot);
|
||||
|
||||
QString gameName = AssetUtilities::ComputeProjectName();
|
||||
QString projectPath = AssetUtilities::ComputeProjectPath();
|
||||
QDir engineRoot;
|
||||
AssetUtilities::ComputeEngineRoot(engineRoot);
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectName = AZ::Utils::GetProjectName();
|
||||
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
|
||||
AZ::IO::FixedMaxPathString enginePath = AZ::Utils::GetEnginePath();
|
||||
|
||||
int portNumber = 0;
|
||||
ApplicationServerBus::BroadcastResult(portNumber, &ApplicationServerBus::Events::GetServerListeningPort);
|
||||
@@ -197,14 +197,14 @@ namespace AssetProcessor
|
||||
AZStd::string params;
|
||||
#if !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
params = AZStd::string::format(
|
||||
R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)", task,
|
||||
builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(),
|
||||
projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber);
|
||||
R"(-task=%s -id="%s" -project-name="%s" -project-cache-path="%s" -project-path="%s" -engine-path="%s" -port %d)",
|
||||
task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(),
|
||||
projectPath.c_str(), enginePath.c_str(), portNumber);
|
||||
#else
|
||||
params = AZStd::string::format(
|
||||
R"(-task=%s -id="%s" -project-name="\"%s\"" -project-cache-path="\"%s\"" -project-path="\"%s\"" -engine-path="\"%s\"" -port %d)",
|
||||
task, builderGuid.c_str(), gameName.toUtf8().constData(), projectCacheRoot.absolutePath().toUtf8().constData(),
|
||||
projectPath.toUtf8().constData(), engineRoot.absolutePath().toUtf8().constData(), portNumber);
|
||||
task, builderGuid.c_str(), projectName.c_str(), projectCacheRoot.absolutePath().toUtf8().constData(),
|
||||
projectPath.c_str(), enginePath.c_str(), portNumber);
|
||||
#endif // !AZ_TRAIT_OS_PLATFORM_APPLE && !AZ_TRAIT_OS_USE_WINDOWS_FILE_PATHS
|
||||
|
||||
if (moduleFilePath && moduleFilePath[0])
|
||||
|
||||
@@ -20,12 +20,11 @@ if (NOT python_package_name)
|
||||
message(WARNING "Python was not found in the package assocation list. Did someone call ly_associate_package(xxxxxxx Python) ?")
|
||||
endif()
|
||||
|
||||
|
||||
ly_add_target(
|
||||
NAME ProjectManager APPLICATION
|
||||
OUTPUT_NAME o3de
|
||||
NAME ProjectManager.Static STATIC
|
||||
NAMESPACE AZ
|
||||
AUTOMOC
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_files.cmake
|
||||
Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
@@ -47,6 +46,60 @@ ly_add_target(
|
||||
3rdParty::pybind11
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzToolsFramework
|
||||
AZ::AzQtComponents
|
||||
)
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME ProjectManager APPLICATION
|
||||
OUTPUT_NAME o3de
|
||||
NAMESPACE AZ
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_app_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Python
|
||||
3rdParty::pybind11
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzQtComponents
|
||||
AZ::ProjectManager.Static
|
||||
)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
ly_add_target(
|
||||
NAME ProjectManager.Tests EXECUTABLE
|
||||
NAMESPACE AZ
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_tests_files.cmake
|
||||
Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_tests_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
Platform/${PAL_PLATFORM_NAME}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Python
|
||||
3rdParty::pybind11
|
||||
AZ::AzTest
|
||||
AZ::AzFramework
|
||||
AZ::AzFrameworkTestShared
|
||||
AZ::ProjectManager.Static
|
||||
)
|
||||
|
||||
ly_add_googletest(
|
||||
NAME AZ::ProjectManager.Tests
|
||||
TEST_COMMAND $<TARGET_FILE:AZ::ProjectManager.Tests> --unittest
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -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(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Linux.h
|
||||
)
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS true
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Test_Traits_Linux.h>
|
||||
@@ -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(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Mac.h
|
||||
)
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Test_Traits_Mac.h>
|
||||
@@ -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(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Windows.h
|
||||
)
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ProjectManager_Test_Traits_Windows.h>
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false
|
||||
@@ -7,6 +7,11 @@ QMainWindow {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
#ScreensCtrl {
|
||||
min-width:1200px;
|
||||
min-height:800px;
|
||||
}
|
||||
|
||||
QPushButton:focus {
|
||||
outline: none;
|
||||
border:1px solid #1e70eb;
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 <Application.h>
|
||||
#include <ProjectUtils.h>
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzFramework/Logging/LoggingComponent.h>
|
||||
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
Application::~Application()
|
||||
{
|
||||
TearDown();
|
||||
}
|
||||
|
||||
bool Application::Init(bool interactive)
|
||||
{
|
||||
constexpr const char* applicationName { "O3DE" };
|
||||
|
||||
QApplication::setOrganizationName(applicationName);
|
||||
QApplication::setOrganizationDomain("o3de.org");
|
||||
|
||||
QCoreApplication::setApplicationName(applicationName);
|
||||
QCoreApplication::setApplicationVersion("1.0");
|
||||
|
||||
// Use the LogComponent for non-dev logging log
|
||||
RegisterComponentDescriptor(AzFramework::LogComponent::CreateDescriptor());
|
||||
|
||||
// set the log alias to .o3de/Logs instead of the default user/logs
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory();
|
||||
|
||||
// DevWriteStorage is where the event log is written during development
|
||||
m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_DevWriteStorage, path.LexicallyNormal().Native());
|
||||
|
||||
// Save event logs to .o3de/Logs/eventlogger/EventLogO3DE.azsl
|
||||
m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::BuildTargetNameKey, applicationName);
|
||||
|
||||
Start(AzFramework::Application::Descriptor());
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
|
||||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
|
||||
|
||||
// Create the actual Qt Application - this needs to happen before using QMessageBox
|
||||
m_app.reset(new QApplication(*GetArgC(), *GetArgV()));
|
||||
|
||||
if(!InitLog(applicationName))
|
||||
{
|
||||
AZ_Warning("ProjectManager", false, "Failed to init logging");
|
||||
}
|
||||
|
||||
m_pythonBindings = AZStd::make_unique<PythonBindings>(GetEngineRoot());
|
||||
if (!m_pythonBindings || !m_pythonBindings->PythonStarted())
|
||||
{
|
||||
if (interactive)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QObject::tr("Failed to start Python"),
|
||||
QObject::tr("This tool requires an O3DE engine with a Python runtime, "
|
||||
"but either Python is missing or mis-configured. Please rename "
|
||||
"your python/runtime folder to python/runtime_bak, then run "
|
||||
"python/get_python.bat to restore the Python runtime folder."));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::CommandLine* commandLine = GetCommandLine();
|
||||
AZ_Assert(commandLine, "Failed to get command line");
|
||||
|
||||
ProjectManagerScreen startScreen = ProjectManagerScreen::Projects;
|
||||
if (size_t screenSwitchCount = commandLine->GetNumSwitchValues("screen"); screenSwitchCount > 0)
|
||||
{
|
||||
QString screenOption = commandLine->GetSwitchValue("screen", screenSwitchCount - 1).c_str();
|
||||
ProjectManagerScreen screen = ProjectUtils::GetProjectManagerScreen(screenOption);
|
||||
if (screen != ProjectManagerScreen::Invalid)
|
||||
{
|
||||
startScreen = screen;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath projectPath;
|
||||
if (size_t projectSwitchCount = commandLine->GetNumSwitchValues("project-path"); projectSwitchCount > 0)
|
||||
{
|
||||
projectPath = commandLine->GetSwitchValue("project-path", projectSwitchCount - 1).c_str();
|
||||
}
|
||||
|
||||
m_mainWindow.reset(new ProjectManagerWindow(nullptr, projectPath, startScreen));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::InitLog(const char* logName)
|
||||
{
|
||||
if (!m_entity)
|
||||
{
|
||||
// override the log alias to the O3de Logs directory instead of the default project user/Logs folder
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory();
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(fileIO, "Failed to get FileIOBase instance");
|
||||
|
||||
fileIO->SetAlias("@log@", path.LexicallyNormal().Native().c_str());
|
||||
|
||||
// this entity exists because we need a home for LogComponent
|
||||
// and cannot use the system entity because we need to be able to call SetLogFileBaseName
|
||||
// so the log will be named O3DE.log
|
||||
m_entity = aznew AZ::Entity("Application Entity");
|
||||
if (m_entity)
|
||||
{
|
||||
AzFramework::LogComponent* logger = aznew AzFramework::LogComponent();
|
||||
AZ_Assert(logger, "Failed to create LogComponent");
|
||||
logger->SetLogFileBaseName(logName);
|
||||
m_entity->AddComponent(logger);
|
||||
m_entity->Init();
|
||||
m_entity->Activate();
|
||||
}
|
||||
}
|
||||
|
||||
return m_entity != nullptr;
|
||||
}
|
||||
|
||||
void Application::TearDown()
|
||||
{
|
||||
if (m_entity)
|
||||
{
|
||||
m_entity->Deactivate();
|
||||
delete m_entity;
|
||||
m_entity = nullptr;
|
||||
}
|
||||
|
||||
m_pythonBindings.reset();
|
||||
m_mainWindow.reset();
|
||||
m_app.reset();
|
||||
}
|
||||
|
||||
bool Application::Run()
|
||||
{
|
||||
// Set up the Style Manager
|
||||
AzQtComponents::StyleManager styleManager(qApp);
|
||||
styleManager.initialize(qApp, GetEngineRoot());
|
||||
|
||||
// setup stylesheets and hot reloading
|
||||
AZ::IO::FixedMaxPath engineRoot(GetEngineRoot());
|
||||
QDir rootDir(engineRoot.c_str());
|
||||
const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources");
|
||||
const auto qrcPath = QStringLiteral(":/ProjectManager/style");
|
||||
AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRoot);
|
||||
|
||||
// set stylesheet after creating the main window or their styles won't get updated
|
||||
AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:ProjectManager.qss"));
|
||||
|
||||
// the decoration wrapper is intended to remember window positioning and sizing
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper();
|
||||
wrapper->setGuest(m_mainWindow.data());
|
||||
wrapper->show();
|
||||
m_mainWindow->show();
|
||||
|
||||
qApp->setQuitOnLastWindowClosed(true);
|
||||
|
||||
// Run the application
|
||||
return qApp->exec();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 <AzFramework/Application/Application.h>
|
||||
#include <QCoreApplication>
|
||||
#include <PythonBindings.h>
|
||||
#include <ProjectManagerWindow.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Entity;
|
||||
}
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class Application
|
||||
: public AzFramework::Application
|
||||
{
|
||||
public:
|
||||
using AzFramework::Application::Application;
|
||||
virtual ~Application();
|
||||
|
||||
bool Init(bool interactive = true);
|
||||
bool Run();
|
||||
void TearDown();
|
||||
|
||||
private:
|
||||
bool InitLog(const char* logName);
|
||||
|
||||
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
||||
QSharedPointer<QCoreApplication> m_app;
|
||||
QSharedPointer<ProjectManagerWindow> m_mainWindow;
|
||||
|
||||
AZ::Entity* m_entity = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -77,6 +77,7 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::CreateProject;
|
||||
}
|
||||
|
||||
// Called when pressing "Create New Project"
|
||||
void CreateProjectCtrl::NotifyCurrentScreen()
|
||||
{
|
||||
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
|
||||
@@ -84,6 +85,11 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
currentScreen->NotifyCurrentScreen();
|
||||
}
|
||||
|
||||
// Gather the gems from the project template. When we will have multiple project templates, we need to re-gather them
|
||||
// on changing the template and let the user know that any further changes on top of the template will be lost.
|
||||
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
|
||||
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::HandleBackButton()
|
||||
@@ -151,9 +157,6 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
|
||||
|
||||
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
|
||||
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
|
||||
|
||||
Update();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace O3DE::ProjectManager
|
||||
EngineSettingsScreen::EngineSettingsScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
auto* layout = new QVBoxLayout();
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
|
||||
setObjectName("engineSettingsScreen");
|
||||
|
||||
@@ -82,6 +82,8 @@ namespace O3DE::ProjectManager
|
||||
|
||||
m_headerWidget->ReinitForProject();
|
||||
|
||||
connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
|
||||
|
||||
// Select the first entry after everything got correctly sized
|
||||
QTimer::singleShot(200, [=]{
|
||||
QModelIndex firstModelIndex = m_gemListView->model()->index(0,0);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace O3DE::ProjectManager
|
||||
const QVector<QString>& elementNames,
|
||||
const QVector<int>& elementCounts,
|
||||
bool showAllLessButton,
|
||||
bool collapsed,
|
||||
int defaultShowCount,
|
||||
QWidget* parent)
|
||||
: QWidget(parent)
|
||||
@@ -40,6 +41,7 @@ namespace O3DE::ProjectManager
|
||||
QHBoxLayout* collapseLayout = new QHBoxLayout();
|
||||
m_collapseButton = new QPushButton();
|
||||
m_collapseButton->setCheckable(true);
|
||||
m_collapseButton->setChecked(collapsed);
|
||||
m_collapseButton->setFlat(true);
|
||||
m_collapseButton->setFocusPolicy(Qt::NoFocus);
|
||||
m_collapseButton->setFixedWidth(s_collapseButtonSize);
|
||||
@@ -178,6 +180,11 @@ namespace O3DE::ProjectManager
|
||||
return m_buttonGroup;
|
||||
}
|
||||
|
||||
bool FilterCategoryWidget::IsCollapsed()
|
||||
{
|
||||
return m_collapseButton->isChecked();
|
||||
}
|
||||
|
||||
GemFilterWidget::GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent)
|
||||
: QScrollArea(parent)
|
||||
, m_filterProxyModel(filterProxyModel)
|
||||
@@ -193,20 +200,106 @@ namespace O3DE::ProjectManager
|
||||
QWidget* mainWidget = new QWidget();
|
||||
setWidget(mainWidget);
|
||||
|
||||
m_mainLayout = new QVBoxLayout();
|
||||
m_mainLayout->setAlignment(Qt::AlignTop);
|
||||
mainWidget->setLayout(m_mainLayout);
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout();
|
||||
mainLayout->setAlignment(Qt::AlignTop);
|
||||
mainWidget->setLayout(mainLayout);
|
||||
|
||||
QLabel* filterByLabel = new QLabel("Filter by");
|
||||
filterByLabel->setStyleSheet("font-size: 16px;");
|
||||
m_mainLayout->addWidget(filterByLabel);
|
||||
mainLayout->addWidget(filterByLabel);
|
||||
|
||||
QWidget* filterSection = new QWidget(this);
|
||||
mainLayout->addWidget(filterSection);
|
||||
|
||||
m_filterLayout = new QVBoxLayout();
|
||||
m_filterLayout->setAlignment(Qt::AlignTop);
|
||||
m_filterLayout->setContentsMargins(0, 0, 0, 0);
|
||||
filterSection->setLayout(m_filterLayout);
|
||||
|
||||
ResetGemStatusFilter();
|
||||
AddGemOriginFilter();
|
||||
AddTypeFilter();
|
||||
AddPlatformFilter();
|
||||
AddFeatureFilter();
|
||||
}
|
||||
|
||||
void GemFilterWidget::ResetGemStatusFilter()
|
||||
{
|
||||
QVector<QString> elementNames;
|
||||
QVector<int> elementCounts;
|
||||
const int totalGems = m_gemModel->rowCount();
|
||||
const int selectedGemTotal = m_gemModel->TotalAddedGems();
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Unselected));
|
||||
elementCounts.push_back(totalGems - selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Selected));
|
||||
elementCounts.push_back(selectedGemTotal);
|
||||
|
||||
bool wasCollapsed = false;
|
||||
if (m_statusFilter)
|
||||
{
|
||||
wasCollapsed = m_statusFilter->IsCollapsed();
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget =
|
||||
new FilterCategoryWidget("Status", elementNames, elementCounts, /*showAllLessButton=*/false, /*collapsed*/wasCollapsed);
|
||||
if (m_statusFilter)
|
||||
{
|
||||
m_filterLayout->replaceWidget(m_statusFilter, filterWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
}
|
||||
|
||||
m_statusFilter->deleteLater();
|
||||
m_statusFilter = filterWidget;
|
||||
|
||||
const GemSortFilterProxyModel::GemStatus currentFilterState = m_filterProxyModel->GetGemStatus();
|
||||
const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons();
|
||||
for (int statusFilterIndex = 0; statusFilterIndex < buttons.size(); ++statusFilterIndex)
|
||||
{
|
||||
const GemSortFilterProxyModel::GemStatus gemStatus = static_cast<GemSortFilterProxyModel::GemStatus>(statusFilterIndex);
|
||||
QAbstractButton* button = buttons[statusFilterIndex];
|
||||
|
||||
if (static_cast<GemSortFilterProxyModel::GemStatus>(statusFilterIndex) == currentFilterState)
|
||||
{
|
||||
button->setChecked(true);
|
||||
}
|
||||
|
||||
connect(
|
||||
button, &QAbstractButton::toggled, this,
|
||||
[=](bool checked)
|
||||
{
|
||||
GemSortFilterProxyModel::GemStatus filterStatus = m_filterProxyModel->GetGemStatus();
|
||||
if (checked)
|
||||
{
|
||||
if (filterStatus == GemSortFilterProxyModel::GemStatus::NoFilter)
|
||||
{
|
||||
filterStatus = gemStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filterStatus != gemStatus)
|
||||
{
|
||||
filterStatus = static_cast<GemSortFilterProxyModel::GemStatus>(!gemStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter;
|
||||
}
|
||||
}
|
||||
m_filterProxyModel->SetGemStatus(filterStatus);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void GemFilterWidget::AddGemOriginFilter()
|
||||
{
|
||||
QVector<QString> elementNames;
|
||||
@@ -233,7 +326,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Provider", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -283,7 +376,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Type", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -333,7 +426,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Supported Platforms", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -388,8 +481,8 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts,
|
||||
/*showAllLessButton=*/true, /*defaultShowCount=*/5);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
/*showAllLessButton=*/true, false, /*defaultShowCount=*/5);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
|
||||
@@ -37,11 +37,14 @@ namespace O3DE::ProjectManager
|
||||
const QVector<QString>& elementNames,
|
||||
const QVector<int>& elementCounts,
|
||||
bool showAllLessButton = true,
|
||||
bool collapsed = false,
|
||||
int defaultShowCount = 4,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
QButtonGroup* GetButtonGroup();
|
||||
|
||||
bool IsCollapsed();
|
||||
|
||||
private:
|
||||
void UpdateCollapseState();
|
||||
void UpdateSeeMoreLess();
|
||||
@@ -66,14 +69,18 @@ namespace O3DE::ProjectManager
|
||||
explicit GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr);
|
||||
~GemFilterWidget() = default;
|
||||
|
||||
public slots:
|
||||
void ResetGemStatusFilter();
|
||||
|
||||
private:
|
||||
void AddGemOriginFilter();
|
||||
void AddTypeFilter();
|
||||
void AddPlatformFilter();
|
||||
void AddFeatureFilter();
|
||||
|
||||
QVBoxLayout* m_mainLayout = nullptr;
|
||||
QVBoxLayout* m_filterLayout = nullptr;
|
||||
GemModel* m_gemModel = nullptr;
|
||||
GemSortFilterProxyModel* m_filterProxyModel = nullptr;
|
||||
FilterCategoryWidget* m_statusFilter = nullptr;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -204,7 +204,6 @@ namespace O3DE::ProjectManager
|
||||
painter->save();
|
||||
const QRect buttonRect = CalcButtonRect(contentRect);
|
||||
QPoint circleCenter;
|
||||
QString buttonText;
|
||||
|
||||
const bool isAdded = GemModel::IsAdded(modelIndex);
|
||||
if (isAdded)
|
||||
@@ -213,34 +212,15 @@ namespace O3DE::ProjectManager
|
||||
painter->setPen(m_buttonEnabledColor);
|
||||
|
||||
circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius + 1, 1);
|
||||
buttonText = "Added";
|
||||
}
|
||||
else
|
||||
{
|
||||
circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius, 1);
|
||||
buttonText = "Get";
|
||||
}
|
||||
|
||||
// Rounded rect
|
||||
painter->drawRoundedRect(buttonRect, s_buttonBorderRadius, s_buttonBorderRadius);
|
||||
|
||||
// Text
|
||||
QFont font;
|
||||
QRect textRect = GetTextRect(font, buttonText, s_buttonFontSize);
|
||||
if (isAdded)
|
||||
{
|
||||
textRect = QRect(buttonRect.left(), buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
textRect = QRect(buttonRect.left() + s_buttonCircleRadius * 2.0, buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height());
|
||||
}
|
||||
|
||||
font.setPixelSize(s_buttonFontSize);
|
||||
painter->setFont(font);
|
||||
painter->setPen(m_textColor);
|
||||
painter->drawText(textRect, Qt::AlignCenter, buttonText);
|
||||
|
||||
// Circle
|
||||
painter->setBrush(m_textColor);
|
||||
painter->drawEllipse(circleCenter, s_buttonCircleRadius, s_buttonCircleRadius);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <QStandardItemModel>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QSpacerItem>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
@@ -74,6 +75,15 @@ namespace O3DE::ProjectManager
|
||||
gemSummaryLabel->setStyleSheet("font-size: 12px;");
|
||||
columnHeaderLayout->addWidget(gemSummaryLabel);
|
||||
|
||||
QSpacerItem* horizontalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
columnHeaderLayout->addSpacerItem(horizontalSpacer);
|
||||
|
||||
QLabel* gemSelectedLabel = new QLabel(tr("Selected"));
|
||||
gemSelectedLabel->setStyleSheet("font-size: 12px;");
|
||||
columnHeaderLayout->addWidget(gemSelectedLabel);
|
||||
|
||||
columnHeaderLayout->addSpacing(60);
|
||||
|
||||
vLayout->addLayout(columnHeaderLayout);
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -235,4 +235,19 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int GemModel::TotalAddedGems() const
|
||||
{
|
||||
int result = 0;
|
||||
for (int row = 0; row < rowCount(); ++row)
|
||||
{
|
||||
const QModelIndex modelIndex = index(row, 0);
|
||||
if (IsAdded(modelIndex))
|
||||
{
|
||||
++result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace O3DE::ProjectManager
|
||||
QVector<QModelIndex> GatherGemsToBeAdded() const;
|
||||
QVector<QModelIndex> GatherGemsToBeRemoved() const;
|
||||
|
||||
int TotalAddedGems() const;
|
||||
|
||||
private:
|
||||
enum UserRole
|
||||
{
|
||||
|
||||
@@ -37,6 +37,16 @@ namespace O3DE::ProjectManager
|
||||
return false;
|
||||
}
|
||||
|
||||
// Gem status
|
||||
if (m_gemStatusFilter != GemStatus::NoFilter)
|
||||
{
|
||||
const GemStatus sourceGemStatus = static_cast<GemStatus>(GemModel::IsAdded(sourceIndex));
|
||||
if (m_gemStatusFilter != sourceGemStatus)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Gem origins
|
||||
if (m_gemOriginFilter)
|
||||
{
|
||||
@@ -125,6 +135,19 @@ namespace O3DE::ProjectManager
|
||||
return true;
|
||||
}
|
||||
|
||||
QString GemSortFilterProxyModel::GetGemStatusString(GemStatus status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case Unselected:
|
||||
return "Unselected";
|
||||
case Selected:
|
||||
return "Selected";
|
||||
default:
|
||||
return "<Unknown Gem Status>";
|
||||
}
|
||||
}
|
||||
|
||||
void GemSortFilterProxyModel::InvalidateFilter()
|
||||
{
|
||||
invalidate();
|
||||
|
||||
@@ -29,8 +29,17 @@ namespace O3DE::ProjectManager
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
enum GemStatus
|
||||
{
|
||||
NoFilter = -1,
|
||||
Unselected,
|
||||
Selected
|
||||
};
|
||||
|
||||
GemSortFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr);
|
||||
|
||||
static QString GetGemStatusString(GemStatus status);
|
||||
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
|
||||
|
||||
GemModel* GetSourceModel() const { return m_sourceModel; }
|
||||
@@ -38,6 +47,9 @@ namespace O3DE::ProjectManager
|
||||
|
||||
void SetSearchString(const QString& searchString) { m_searchString = searchString; InvalidateFilter(); }
|
||||
|
||||
GemStatus GetGemStatus() const { return m_gemStatusFilter; }
|
||||
void SetGemStatus(GemStatus gemStatus) { m_gemStatusFilter = gemStatus; InvalidateFilter(); }
|
||||
|
||||
GemInfo::GemOrigins GetGemOrigins() const { return m_gemOriginFilter; }
|
||||
void SetGemOrigins(const GemInfo::GemOrigins& gemOrigins) { m_gemOriginFilter = gemOrigins; InvalidateFilter(); }
|
||||
|
||||
@@ -61,6 +73,7 @@ namespace O3DE::ProjectManager
|
||||
AzQtComponents::SelectionProxyModel* m_selectionProxyModel = nullptr;
|
||||
|
||||
QString m_searchString;
|
||||
GemStatus m_gemStatusFilter = GemStatus::NoFilter;
|
||||
GemInfo::GemOrigins m_gemOriginFilter = {};
|
||||
GemInfo::Platforms m_platformFilter = {};
|
||||
GemInfo::Types m_typeFilter = {};
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
setObjectName("labelButton");
|
||||
|
||||
QVBoxLayout* vLayout = new QVBoxLayout(this);
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setContentsMargins(0, 0, 0, 0);
|
||||
vLayout->setSpacing(5);
|
||||
|
||||
|
||||
@@ -13,21 +13,11 @@
|
||||
#include <ProjectManagerWindow.h>
|
||||
#include <ScreensCtrl.h>
|
||||
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzFramework/CommandLine/CommandLine.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath, const AZ::IO::PathView& projectPath, ProjectManagerScreen startScreen)
|
||||
ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& projectPath, ProjectManagerScreen startScreen)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
m_pythonBindings = AZStd::make_unique<PythonBindings>(engineRootPath);
|
||||
|
||||
setWindowTitle(tr("O3DE Project Manager"));
|
||||
|
||||
ScreensCtrl* screensCtrl = new ScreensCtrl();
|
||||
@@ -44,15 +34,6 @@ namespace O3DE::ProjectManager
|
||||
|
||||
setCentralWidget(screensCtrl);
|
||||
|
||||
// setup stylesheets and hot reloading
|
||||
QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast<int>(engineRootPath.Native().size()));
|
||||
const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources");
|
||||
const auto qrcPath = QStringLiteral(":/ProjectManager/style");
|
||||
AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRootPath);
|
||||
|
||||
// set stylesheet after creating the screens or their styles won't get updated
|
||||
AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("style:ProjectManager.qss"));
|
||||
|
||||
// always push the projects screen first so we have something to come back to
|
||||
if (startScreen != ProjectManagerScreen::Projects)
|
||||
{
|
||||
@@ -66,10 +47,4 @@ namespace O3DE::ProjectManager
|
||||
emit screensCtrl->NotifyCurrentProject(path);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectManagerWindow::~ProjectManagerWindow()
|
||||
{
|
||||
m_pythonBindings.reset();
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QMainWindow>
|
||||
#include <PythonBindings.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <ScreenDefs.h>
|
||||
#endif
|
||||
|
||||
@@ -25,12 +25,8 @@ namespace O3DE::ProjectManager
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath, const AZ::IO::PathView& projectPath,
|
||||
explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& projectPath,
|
||||
ProjectManagerScreen startScreen = ProjectManagerScreen::Projects);
|
||||
~ProjectManagerWindow();
|
||||
|
||||
private:
|
||||
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace O3DE::ProjectManager
|
||||
// if we don't set this in a frame (just use a sub-layout) all the content will align incorrectly horizontally
|
||||
QFrame* projectSettingsFrame = new QFrame(this);
|
||||
projectSettingsFrame->setObjectName("projectSettings");
|
||||
m_verticalLayout = new QVBoxLayout(this);
|
||||
m_verticalLayout = new QVBoxLayout();
|
||||
|
||||
// you cannot remove content margins in qss
|
||||
m_verticalLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace O3DE::ProjectManager
|
||||
QFrame* frame = new QFrame(this);
|
||||
frame->setObjectName("firstTimeContent");
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
frame->setLayout(layout);
|
||||
@@ -100,7 +100,7 @@ namespace O3DE::ProjectManager
|
||||
"available by downloading our sample project."));
|
||||
layout->addWidget(introLabel);
|
||||
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout(this);
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout();
|
||||
buttonLayout->setAlignment(Qt::AlignLeft);
|
||||
buttonLayout->setSpacing(s_spacerSize);
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace O3DE::ProjectManager
|
||||
PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath)
|
||||
: m_enginePath(enginePath)
|
||||
{
|
||||
StartPython();
|
||||
m_pythonStarted = StartPython();
|
||||
}
|
||||
|
||||
PythonBindings::~PythonBindings()
|
||||
@@ -234,6 +234,11 @@ namespace O3DE::ProjectManager
|
||||
StopPython();
|
||||
}
|
||||
|
||||
bool PythonBindings::PythonStarted()
|
||||
{
|
||||
return m_pythonStarted && Py_IsInitialized();
|
||||
}
|
||||
|
||||
bool PythonBindings::StartPython()
|
||||
{
|
||||
if (Py_IsInitialized())
|
||||
@@ -246,7 +251,7 @@ namespace O3DE::ProjectManager
|
||||
AZStd::string pyBasePath = Platform::GetPythonHomePath(PY_PACKAGE, m_enginePath.c_str());
|
||||
if (!AZ::IO::SystemFile::Exists(pyBasePath.c_str()))
|
||||
{
|
||||
AZ_Assert(false, "Python home path must exist. path:%s", pyBasePath.c_str());
|
||||
AZ_Error("python", false, "Python home path does not exist: %s", pyBasePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -351,6 +356,11 @@ namespace O3DE::ProjectManager
|
||||
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::ExecuteWithLockErrorHandling(AZStd::function<void()> executionCallback)
|
||||
{
|
||||
if (!Py_IsInitialized())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Python is not initialized");
|
||||
}
|
||||
|
||||
AZStd::lock_guard<decltype(m_lock)> lock(m_lock);
|
||||
pybind11::gil_scoped_release release;
|
||||
pybind11::gil_scoped_acquire acquire;
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace O3DE::ProjectManager
|
||||
~PythonBindings() override;
|
||||
|
||||
// PythonBindings overrides
|
||||
bool PythonStarted() override;
|
||||
|
||||
// Engine
|
||||
AZ::Outcome<EngineInfo> GetEngineInfo() override;
|
||||
bool SetEngineInfo(const EngineInfo& engineInfo) override;
|
||||
@@ -70,6 +72,8 @@ namespace O3DE::ProjectManager
|
||||
bool StopPython();
|
||||
|
||||
|
||||
bool m_pythonStarted = false;
|
||||
|
||||
AZ::IO::FixedMaxPath m_enginePath;
|
||||
pybind11::handle m_engineTemplate;
|
||||
AZStd::recursive_mutex m_lock;
|
||||
|
||||
@@ -34,6 +34,12 @@ namespace O3DE::ProjectManager
|
||||
IPythonBindings() = default;
|
||||
virtual ~IPythonBindings() = default;
|
||||
|
||||
/**
|
||||
* Get whether Python was started or not. All Python functionality will fail if Python
|
||||
* failed to start.
|
||||
* @return true if Python was started successfully, false on failure
|
||||
*/
|
||||
virtual bool PythonStarted() = 0;
|
||||
|
||||
// Engine
|
||||
|
||||
|
||||
@@ -89,17 +89,18 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::UpdateProject;
|
||||
}
|
||||
|
||||
// Called when pressing "Edit Project Settings..."
|
||||
void UpdateProjectCtrl::NotifyCurrentScreen()
|
||||
{
|
||||
m_stack->setCurrentIndex(ScreenOrder::Settings);
|
||||
Update();
|
||||
|
||||
// Gather the available gems that will be shown in the gem catalog.
|
||||
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
|
||||
}
|
||||
|
||||
void UpdateProjectCtrl::HandleGemsButton()
|
||||
{
|
||||
// The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog.
|
||||
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
|
||||
|
||||
m_stack->setCurrentWidget(m_gemCatalogScreen);
|
||||
Update();
|
||||
}
|
||||
@@ -189,11 +190,13 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
if (m_stack->currentIndex() == ScreenOrder::Gems)
|
||||
{
|
||||
m_header->setSubTitle(QString(tr("Configure Gems for \"%1\"")).arg(m_projectInfo.m_projectName));
|
||||
m_nextButton->setText(tr("Confirm"));
|
||||
m_header->setTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.m_projectName));
|
||||
m_header->setSubTitle(QString(tr("Configure Gems")));
|
||||
m_nextButton->setText(tr("Finalize"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_header->setTitle("");
|
||||
m_header->setSubTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.m_projectName));
|
||||
m_nextButton->setText(tr("Save"));
|
||||
}
|
||||
|
||||
@@ -10,85 +10,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzFramework/CommandLine/CommandLine.h>
|
||||
|
||||
#include <ProjectManagerWindow.h>
|
||||
#include <ProjectUtils.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QGuiApplication>
|
||||
|
||||
using namespace O3DE::ProjectManager;
|
||||
#include <AzQtComponents/Utilities/QtPluginPaths.h>
|
||||
#include <Application.h>
|
||||
|
||||
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);
|
||||
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
|
||||
int runSuccess = 0;
|
||||
|
||||
// Call before using any Qt, or the app may not be able to locate Qt libs
|
||||
AzQtComponents::PrepareQtPaths();
|
||||
|
||||
O3DE::ProjectManager::Application application(&argc, &argv);
|
||||
if (!application.Init())
|
||||
{
|
||||
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);
|
||||
|
||||
// Get the initial start screen if one is provided via command line
|
||||
constexpr char optionPrefix[] = "--";
|
||||
AZ::CommandLine commandLine(optionPrefix);
|
||||
commandLine.Parse(argc, argv);
|
||||
|
||||
ProjectManagerScreen startScreen = ProjectManagerScreen::Projects;
|
||||
if(commandLine.HasSwitch("screen"))
|
||||
{
|
||||
QString screenOption = commandLine.GetSwitchValue("screen", 0).c_str();
|
||||
ProjectManagerScreen screen = ProjectUtils::GetProjectManagerScreen(screenOption);
|
||||
if (screen != ProjectManagerScreen::Invalid)
|
||||
{
|
||||
startScreen = screen;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath projectPath;
|
||||
if (commandLine.HasSwitch("project-path"))
|
||||
{
|
||||
projectPath = commandLine.GetSwitchValue("project-path", 0).c_str();
|
||||
}
|
||||
|
||||
ProjectManagerWindow window(nullptr, engineRootPath, projectPath, startScreen);
|
||||
window.show();
|
||||
|
||||
// somethings is preventing us from moving the window to the center of the
|
||||
// primary screen - likely an Az style or component helper
|
||||
constexpr int width = 1200;
|
||||
constexpr int height = 800;
|
||||
window.resize(width, height);
|
||||
|
||||
runSuccess = app.exec();
|
||||
AZ_Error("ProjectManager", false, "Failed to initialize");
|
||||
runSuccess = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
runSuccess = application.Run() ? 0 : 1;
|
||||
}
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
|
||||
|
||||
return runSuccess;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# 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
|
||||
Resources/ProjectManager.rc
|
||||
Resources/ProjectManager.qrc
|
||||
Resources/ProjectManager.qss
|
||||
Source/main.cpp
|
||||
)
|
||||
@@ -1,4 +1,5 @@
|
||||
#
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
@@ -10,10 +11,8 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Resources/ProjectManager.rc
|
||||
Resources/ProjectManager.qrc
|
||||
Resources/ProjectManager.qss
|
||||
Source/main.cpp
|
||||
Source/Application.h
|
||||
Source/Application.cpp
|
||||
Source/ScreenDefs.h
|
||||
Source/ScreenFactory.h
|
||||
Source/ScreenFactory.cpp
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# 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
|
||||
Resources/ProjectManager.qrc
|
||||
Resources/ProjectManager.qss
|
||||
tests/ApplicationTests.cpp
|
||||
tests/main.cpp
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <Application.h>
|
||||
#include <ProjectManager_Test_Traits_Platform.h>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ProjectManagerApplicationTests
|
||||
: public ::UnitTest::ScopedAllocatorSetupFixture
|
||||
{
|
||||
public:
|
||||
|
||||
ProjectManagerApplicationTests()
|
||||
{
|
||||
m_application = AZStd::make_unique<ProjectManager::Application>();
|
||||
}
|
||||
|
||||
~ProjectManagerApplicationTests()
|
||||
{
|
||||
m_application.reset();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<ProjectManager::Application> m_application;
|
||||
};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS
|
||||
TEST_F(ProjectManagerApplicationTests, DISABLED_Application_Init_Succeeds)
|
||||
#else
|
||||
TEST_F(ProjectManagerApplicationTests, Application_Init_Succeeds)
|
||||
#endif // !AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS
|
||||
{
|
||||
// we don't want to interact with actual GUI or display it
|
||||
EXPECT_TRUE(m_application->Init(/*interactive=*/false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 <AzTest/AzTest.h>
|
||||
|
||||
DECLARE_AZ_UNIT_TEST_MAIN();
|
||||
|
||||
int runDefaultRunner(int argc, char* argv[])
|
||||
{
|
||||
INVOKE_AZ_UNIT_TEST_MAIN(nullptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
// if no parameters are provided, add the --unittests parameter
|
||||
constexpr int defaultArgc = 2;
|
||||
char unittest_arg[] = "--unittests"; // Conversion from string literal to char* is not allowed per ISO C++11
|
||||
char* defaultArgv[defaultArgc] = { argv[0], unittest_arg };
|
||||
return runDefaultRunner(defaultArgc, defaultArgv);
|
||||
}
|
||||
INVOKE_AZ_UNIT_TEST_MAIN(nullptr);
|
||||
return 0;
|
||||
}
|
||||
@@ -77,6 +77,7 @@ namespace AZ
|
||||
{
|
||||
AZStd::string extension;
|
||||
StringFunc::Path::GetExtension(path.c_str(), extension);
|
||||
AZStd::to_lower(extension.begin(), extension.end());
|
||||
|
||||
if (!m_settings.m_supportedFileTypeExtensions.contains(extension))
|
||||
{
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace AZ
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<AssImpAnimationImporter, SceneCore::LoadingComponent>()->Version(4); // [LYN-3971] Bone pruning crash fix in AssImp SDK
|
||||
serializeContext->Class<AssImpAnimationImporter, SceneCore::LoadingComponent>()->Version(5); // [LYN-4226] Invert PostRotation matrix in animation chains
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,22 +46,69 @@ namespace AZ
|
||||
serializeContext->Class<AssImpTransformImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GetAllBones(const aiScene* scene, AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
|
||||
{
|
||||
for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
const aiMesh* mesh = scene->mMeshes[meshIndex];
|
||||
|
||||
for (unsigned boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
|
||||
{
|
||||
const aiBone* bone = mesh->mBones[boneIndex];
|
||||
|
||||
boneLookup[bone->mName.C_Str()] = bone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpTransformImporter::ImportTransform(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "transform");
|
||||
const aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
|
||||
if (currentNode == scene->mRootNode || IsPivotNode(currentNode->mName))
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
aiMatrix4x4 combinedTransform = GetConcatenatedLocalTransform(currentNode);
|
||||
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
|
||||
GetAllBones(scene, boneLookup);
|
||||
|
||||
auto boneIterator = boneLookup.find(currentNode->mName.C_Str());
|
||||
const bool isBone = boneIterator != boneLookup.end();
|
||||
|
||||
aiMatrix4x4 combinedTransform;
|
||||
|
||||
if (isBone)
|
||||
{
|
||||
auto parentNode = currentNode->mParent;
|
||||
|
||||
aiMatrix4x4 offsetMatrix = boneIterator->second->mOffsetMatrix;
|
||||
aiMatrix4x4 parentOffset {};
|
||||
|
||||
auto parentBoneIterator = boneLookup.find(parentNode->mName.C_Str());
|
||||
|
||||
if (parentNode && parentBoneIterator != boneLookup.end())
|
||||
{
|
||||
const auto& parentBone = parentBoneIterator->second;
|
||||
|
||||
parentOffset = parentBone->mOffsetMatrix;
|
||||
}
|
||||
|
||||
auto inverseOffset = offsetMatrix;
|
||||
inverseOffset.Inverse();
|
||||
|
||||
combinedTransform = parentOffset * inverseOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
combinedTransform = GetConcatenatedLocalTransform(currentNode);
|
||||
}
|
||||
|
||||
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform);
|
||||
|
||||
|
||||
context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform);
|
||||
context.m_sourceSceneSystem.ConvertUnit(localTransform);
|
||||
|
||||
@@ -105,9 +152,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
bool addedData = context.m_scene.GetGraph().SetContent(
|
||||
context.m_currentGraphPosition,
|
||||
transformData);
|
||||
bool addedData = context.m_scene.GetGraph().SetContent(context.m_currentGraphPosition, transformData);
|
||||
|
||||
AZ_Error(SceneAPI::Utilities::ErrorWindow, addedData, "Failed to add node data");
|
||||
return addedData ? Events::ProcessingResult::Success : Events::ProcessingResult::Failure;
|
||||
|
||||
@@ -69,13 +69,14 @@ namespace AZ
|
||||
// aiProcess_JoinIdenticalVertices is not enabled because O3DE has a mesh optimizer that also does this,
|
||||
// this flag is disabled to keep AssImp output similar to FBX SDK to reduce downstream bugs for the initial AssImp release.
|
||||
// There's currently a minimum of properties and flags set to maximize compatibility with the existing node graph.
|
||||
|
||||
// aiProcess_LimitBoneWeights is not enabled because it will remove bones which are not associated with a mesh.
|
||||
// This results in the loss of the offset matrix data for nodes without a mesh which is required for the Transform Importer.
|
||||
m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
|
||||
m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, false);
|
||||
m_sceneFileName = fileName;
|
||||
m_assImpScene = m_importer.ReadFile(fileName,
|
||||
aiProcess_Triangulate //Triangulates all faces of all meshes
|
||||
| aiProcess_LimitBoneWeights //Limits the number of bones that can affect a vertex to a maximum value
|
||||
//dropping the least important and re-normalizing
|
||||
| aiProcess_GenNormals); //Generate normals for meshes
|
||||
|
||||
#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
|
||||
|
||||
@@ -385,24 +385,36 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now, convert the nested slice to a prefab.
|
||||
bool nestedSliceResult = ConvertSliceFile(serializeContext, assetPath, isDryRun);
|
||||
if (!nestedSliceResult)
|
||||
{
|
||||
AZ_Warning("Convert-Slice", nestedSliceResult, " Nested slice '%s' could not be converted.", assetPath.c_str());
|
||||
return false;
|
||||
}
|
||||
// Check to see if we've already converted this slice at a higher level of slice nesting, or if this is our first
|
||||
// occurrence and we need to convert it now.
|
||||
|
||||
// Find the prefab template we created for the newly-created nested prefab.
|
||||
// To get the template, we need to take our absolute slice path and turn it into a project-relative prefab path.
|
||||
// First, take our absolute slice path and turn it into a project-relative prefab path.
|
||||
AZ::IO::Path nestedPrefabPath = assetPath;
|
||||
nestedPrefabPath.ReplaceExtension("prefab");
|
||||
|
||||
auto prefabLoaderInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
|
||||
nestedPrefabPath = prefabLoaderInterface->GenerateRelativePath(nestedPrefabPath);
|
||||
|
||||
// Now, see if we already have a template ID in memory for it.
|
||||
AzToolsFramework::Prefab::TemplateId nestedTemplateId =
|
||||
prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath);
|
||||
|
||||
// If we don't have a template ID yet, convert the nested slice to a prefab and get the template ID.
|
||||
if (nestedTemplateId == AzToolsFramework::Prefab::InvalidTemplateId)
|
||||
{
|
||||
bool nestedSliceResult = ConvertSliceFile(serializeContext, assetPath, isDryRun);
|
||||
if (!nestedSliceResult)
|
||||
{
|
||||
AZ_Warning("Convert-Slice", nestedSliceResult, " Nested slice '%s' could not be converted.", assetPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
nestedTemplateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath);
|
||||
AZ_Assert(nestedTemplateId != AzToolsFramework::Prefab::InvalidTemplateId,
|
||||
"Template ID for %s is invalid", nestedPrefabPath.c_str());
|
||||
}
|
||||
|
||||
// Get the nested prefab template.
|
||||
AzToolsFramework::Prefab::TemplateReference nestedTemplate =
|
||||
prefabSystemComponentInterface->FindTemplate(nestedTemplateId);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace AWSCore
|
||||
|
||||
bool UseAWSCredentials()
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Request body for the service API request.
|
||||
|
||||
@@ -25,20 +25,24 @@
|
||||
#include <AzCore/Module/ModuleManagerBus.h>
|
||||
#include <ResourceMapping/AWSResourceMappingUtils.h>
|
||||
|
||||
#include <QSysInfo>
|
||||
#include <QString>
|
||||
|
||||
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
static constexpr const char* EngineVersionJsonKey = "O3DEVersion";
|
||||
constexpr const char* EngineVersionJsonKey = "O3DEVersion";
|
||||
|
||||
constexpr char EditorAWSPreferencesFileName[] = "editor_aws_preferences.setreg";
|
||||
constexpr char AWSAttributionSettingsPrefixKey[] = "/Amazon/AWS/Preferences";
|
||||
constexpr char AWSAttributionEnabledKey[] = "/Amazon/AWS/Preferences/AWSAttributionEnabled";
|
||||
constexpr char AWSAttributionDelaySecondsKey[] = "/Amazon/AWS/Preferences/AWSAttributionDelaySeconds";
|
||||
constexpr char AWSAttributionLastTimeStampKey[] = "/Amazon/AWS/Preferences/AWSAttributionLastTimeStamp";
|
||||
constexpr char AWSAttributionApiId[] = "xbzx78kvbk";
|
||||
constexpr char AWSAttributionApiId[] = "2zxvvmv8d7";
|
||||
constexpr char AWSAttributionChinaApiId[] = "";
|
||||
constexpr char AWSAttributionApiStage[] = "prod";
|
||||
const int AWSAttributionDefaultDelayInDays = 7;
|
||||
|
||||
AWSAttributionManager::AWSAttributionManager()
|
||||
{
|
||||
@@ -58,12 +62,11 @@ namespace AWSCore
|
||||
{
|
||||
if (ShouldGenerateMetric())
|
||||
{
|
||||
// 1. Gather metadata and assemble metric
|
||||
// Gather metadata and assemble metric
|
||||
AttributionMetric metric;
|
||||
UpdateMetric(metric);
|
||||
// 2. Identify region and chose attribution endpoint
|
||||
|
||||
// 3. Post metric
|
||||
// Post metric
|
||||
SubmitMetric(metric);
|
||||
}
|
||||
}
|
||||
@@ -104,8 +107,7 @@ namespace AWSCore
|
||||
AZ::u64 delayInSeconds = 0;
|
||||
if (!m_settingsRegistry->Get(delayInSeconds, AWSAttributionDelaySecondsKey))
|
||||
{
|
||||
AZ_Warning("AWSAttributionManager", false, "AWSAttribution delay key not found. Defaulting to delay to day");
|
||||
delayInSeconds = 86400;
|
||||
delayInSeconds = 86400 * AWSAttributionDefaultDelayInDays;
|
||||
m_settingsRegistry->Set(AWSAttributionDelaySecondsKey, delayInSeconds);
|
||||
}
|
||||
|
||||
@@ -243,7 +245,8 @@ namespace AWSCore
|
||||
metric.SetO3DEVersion(engineVersion);
|
||||
|
||||
AZStd::string platform = this->GetPlatform();
|
||||
metric.SetPlatform(platform, "");
|
||||
QString productName = QSysInfo::prettyProductName();
|
||||
metric.SetPlatform(platform, productName.toStdString().c_str());
|
||||
|
||||
AZStd::vector<AZStd::string> gemNames;
|
||||
GetActiveAWSGems(gemNames);
|
||||
@@ -256,6 +259,7 @@ namespace AWSCore
|
||||
void AWSAttributionManager::SubmitMetric(AttributionMetric& metric)
|
||||
{
|
||||
AWSCore::ServiceAPI::AWSAttributionRequestJob::Config* config = ServiceAPI::AWSAttributionRequestJob::GetDefaultConfig();
|
||||
// Identify region and chose attribution endpoint
|
||||
SetApiEndpointAndRegion(config);
|
||||
|
||||
ServiceAPI::AWSAttributionRequestJob* requestJob = ServiceAPI::AWSAttributionRequestJob::Create(
|
||||
@@ -266,7 +270,12 @@ namespace AWSCore
|
||||
UpdateLastSend();
|
||||
AZ_Printf("AWSAttributionManager", "AWSAttribution metric submit success");
|
||||
|
||||
}, {}, config);
|
||||
},
|
||||
[this](ServiceAPI::AWSAttributionRequestJob* failJob)
|
||||
{
|
||||
AZ_Error("AWSAttributionManager", false, "Metrics send error: %s", failJob->error.message.c_str());
|
||||
},
|
||||
config);
|
||||
|
||||
requestJob->parameters.metric = metric;
|
||||
requestJob->Start();
|
||||
|
||||
@@ -19,14 +19,16 @@
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
constexpr char AWSAttributionMetricDefaultO3DEVersion[] = "1.1";
|
||||
|
||||
AttributionMetric::AttributionMetric(const AZStd::string& timestamp)
|
||||
: m_version("1.1")
|
||||
: m_version(AWSAttributionMetricDefaultO3DEVersion)
|
||||
, m_timestamp(timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
AttributionMetric::AttributionMetric()
|
||||
: m_version("1.1")
|
||||
: m_version(AWSAttributionMetricDefaultO3DEVersion)
|
||||
{
|
||||
m_timestamp = AttributionMetric::GenerateTimeStamp();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <AzCore/Module/ModuleManagerBus.h>
|
||||
|
||||
#include <TestFramework/AWSCoreFixture.h>
|
||||
#include <QSysInfo>
|
||||
#include <QString>
|
||||
|
||||
|
||||
using namespace AWSCore;
|
||||
@@ -405,6 +407,7 @@ namespace AWSAttributionUnitTest
|
||||
AZStd::string serializedMetricValue = metric.SerializeToJson();
|
||||
ASSERT_TRUE(serializedMetricValue.find("\"o3de_version\":\"1.0.0.0\"") != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find(AZ::GetPlatformName(AZ::g_currentPlatform)) != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find(QSysInfo::prettyProductName().toStdString().c_str()) != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find("AWSCore.Editor") != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find("AWSClientAuth") != AZStd::string::npos);
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ AlphaSource_Packed = 0
|
||||
AlphaSource_Split = 1
|
||||
AlphaSource_None = 2
|
||||
|
||||
ForwardPassIndex = 1
|
||||
|
||||
function ConfigureAlphaBlending(shaderItem)
|
||||
shaderItem:GetRenderStatesOverride():SetDepthEnabled(true)
|
||||
shaderItem:GetRenderStatesOverride():SetDepthWriteMask(DepthWriteMask_Zero)
|
||||
@@ -58,15 +56,17 @@ end
|
||||
function Process(context)
|
||||
local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode")
|
||||
|
||||
local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS")
|
||||
|
||||
if(opacityMode == OpacityMode_Blended) then
|
||||
ConfigureAlphaBlending(context:GetShader(ForwardPassIndex))
|
||||
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
|
||||
ConfigureAlphaBlending(forwardPassEDS)
|
||||
forwardPassEDS:SetDrawListTagOverride("transparent")
|
||||
elseif(opacityMode == OpacityMode_TintedTransparent) then
|
||||
ConfigureDualSourceBlending(context:GetShader(ForwardPassIndex))
|
||||
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
|
||||
ConfigureDualSourceBlending(forwardPassEDS)
|
||||
forwardPassEDS:SetDrawListTagOverride("transparent")
|
||||
else
|
||||
ResetAlphaBlending(context:GetShader(ForwardPassIndex))
|
||||
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("") -- reset to default draw list
|
||||
ResetAlphaBlending(forwardPassEDS)
|
||||
forwardPassEDS:SetDrawListTagOverride("") -- reset to default draw list
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -74,7 +74,9 @@ function Process(context)
|
||||
shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
|
||||
TrySetShaderEnabled(lowEndForwardEDS, (opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
|
||||
-- Only enable lowEndForwardEDS in Opaque mode, Transparent mode will be handled by forwardPassEDS. The transparent pass uses the "transparent" draw tag
|
||||
-- for both standard and low end pipelines, so this keeps both shaders from rendering to the transparent draw list.
|
||||
TrySetShaderEnabled(lowEndForwardEDS, opacityMode == OpacityMode_Opaque)
|
||||
TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout)
|
||||
end
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"MipLevels": "8",
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
},
|
||||
"GenerateFullMipChain": true
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "ReflectionScreenSpaceCompositePassTemplate",
|
||||
"PassClass": "FullScreenTriangle",
|
||||
"PassClass": "ReflectionScreenSpaceCompositePass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "TraceInput",
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
#include <Atom/Features/PBR/Lights/LightTypesCommon.azsli>
|
||||
#include <Atom/Features/Shadow/ProjectedShadow.azsli>
|
||||
|
||||
// The order should match m_pointShadowTransforms in PointLightFeatureProcessor.h/.cpp
|
||||
static const float3 PointLightShadowCubemapDirections[6] = {float3(-1,0,0), float3(1,0,0), float3(0,-1,0), float3(0,1,0), float3(0,0,-1), float3(0,0,1)};
|
||||
|
||||
int GetPointLightShadowCubemapFace(const float3 targetPos, const float3 lightPos)
|
||||
{
|
||||
const float3 toPoint = targetPos - lightPos;
|
||||
@@ -83,12 +80,13 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD
|
||||
{
|
||||
const int shadowCubemapFace = GetPointLightShadowCubemapFace(surface.position, light.m_position);
|
||||
const int shadowIndex = UnpackPointLightShadowIndex(light, shadowCubemapFace);
|
||||
|
||||
const float3 lightDir = normalize(light.m_position - surface.position);
|
||||
|
||||
litRatio *= ProjectedShadow::GetVisibility(
|
||||
shadowIndex,
|
||||
light.m_position,
|
||||
surface.position,
|
||||
PointLightShadowCubemapDirections[shadowCubemapFace],
|
||||
lightDir,
|
||||
surface.normal);
|
||||
|
||||
// Use backShadowRatio to carry thickness from shadow map for thick mode
|
||||
|
||||
+10
-6
@@ -226,7 +226,7 @@ float ProjectedShadow::GetVisibilityEsm()
|
||||
}
|
||||
|
||||
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
|
||||
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
|
||||
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
|
||||
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
|
||||
@@ -243,10 +243,12 @@ float ProjectedShadow::GetVisibilityEsm()
|
||||
const float depth = PerspectiveDepthToLinear(
|
||||
m_shadowPosition.z,
|
||||
coefficients);
|
||||
const float expDepthInShadowmap = expShadowmap.Sample(
|
||||
const float occluder = shadowmap.Sample(
|
||||
PassSrg::LinearSampler,
|
||||
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
|
||||
const float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
|
||||
|
||||
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
|
||||
const float ratio = exp(exponent);
|
||||
// pow() mitigates light bleeding to shadows from near shadow casters.
|
||||
return saturate( pow(ratio, 8) );
|
||||
}
|
||||
@@ -265,7 +267,7 @@ float ProjectedShadow::GetVisibilityEsmPcf()
|
||||
}
|
||||
|
||||
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
|
||||
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
|
||||
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
|
||||
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
|
||||
@@ -282,10 +284,12 @@ float ProjectedShadow::GetVisibilityEsmPcf()
|
||||
const float depth = PerspectiveDepthToLinear(
|
||||
m_shadowPosition.z,
|
||||
coefficients);
|
||||
const float expDepthInShadowmap = expShadowmap.Sample(
|
||||
const float occluder = shadowmap.Sample(
|
||||
PassSrg::LinearSampler,
|
||||
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
|
||||
float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
|
||||
|
||||
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
|
||||
float ratio = exp(exponent);
|
||||
|
||||
static const float pcfFallbackThreshold = 1.04;
|
||||
if (ratio > pcfFallbackThreshold)
|
||||
|
||||
@@ -92,6 +92,8 @@ partial ShaderResourceGroup ViewSrg
|
||||
uint m_filteringSampleCount;
|
||||
float2 m_unprojectConstants;
|
||||
float m_bias;
|
||||
float m_esmExponent;
|
||||
float3 m_padding;
|
||||
};
|
||||
|
||||
StructuredBuffer<ProjectedShadow> m_projectedShadows;
|
||||
|
||||
+4
-6
@@ -37,6 +37,9 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
// the max roughness mip level for sampling the previous frame image
|
||||
uint m_maxMipLevel;
|
||||
}
|
||||
|
||||
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
|
||||
@@ -69,10 +72,6 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
float4 positionWS = mul(ViewSrg::m_viewProjectionInverseMatrix, projectedPos);
|
||||
positionWS /= positionWS.w;
|
||||
|
||||
//float4 positionVS = mul(ViewSrg::m_projectionMatrixInverse, projectedPos);
|
||||
//positionVS /= positionVS.w;
|
||||
//float4 positionWS = mul(ViewSrg::m_viewMatrixInverse, positionVS);
|
||||
|
||||
// compute ray from camera to surface position
|
||||
float3 cameraToPositionWS = normalize(positionWS.xyz - ViewSrg::m_worldPosition);
|
||||
|
||||
@@ -103,8 +102,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
// compute the roughness mip to use in the previous frame image
|
||||
// remap the roughness mip into a lower range to more closely match the material roughness values
|
||||
const float MaxRoughness = 0.5f;
|
||||
const float MaxRoughnessMip = 7;
|
||||
float mip = saturate(roughness / MaxRoughness) * MaxRoughnessMip;
|
||||
float mip = saturate(roughness / MaxRoughness) * PassSrg::m_maxMipLevel;
|
||||
|
||||
// sample reflection value from the roughness mip
|
||||
float4 reflectionColor = float4(PassSrg::m_previousFrame.SampleLevel(PassSrg::LinearSampler, tracePrevUV, mip).rgb, 1.0f);
|
||||
|
||||
@@ -56,7 +56,6 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
|
||||
return; // Early return if filter is disabled.
|
||||
}
|
||||
|
||||
float depth = 0.;
|
||||
switch (o_shadowmapLightType)
|
||||
{
|
||||
case ShadowmapLightType::Directional:
|
||||
@@ -68,9 +67,15 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
|
||||
// and it often causes light bleeding with ESM.
|
||||
// So this converts it to "depth" to emphasize the difference
|
||||
// within the frustum.
|
||||
depth = (depthInClip - distanceMin) / (1. - distanceMin);
|
||||
}
|
||||
const float depth = (depthInClip - distanceMin) / (1. - distanceMin);
|
||||
|
||||
// Todo: Expose Esm exponent slider for directional lights
|
||||
// This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli
|
||||
// ATOM-15775
|
||||
const float outValue = exp(EsmExponentialShift * depth);
|
||||
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
|
||||
break;
|
||||
}
|
||||
case ShadowmapLightType::Spot:
|
||||
{
|
||||
const float3 coefficients = float3(
|
||||
@@ -84,12 +89,9 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
|
||||
// and it often causes light bleeding with ESM.
|
||||
// So this converts it to a linear depth to emphasize the
|
||||
// difference like a orthogonal depth.
|
||||
depth = PerspectiveDepthToLinear(depthInClip, coefficients);
|
||||
}
|
||||
PassSrg::m_outputShadowmap[dispatchId].r = PerspectiveDepthToLinear(depthInClip, coefficients);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const float outValue = exp(EsmExponentialShift * depth);
|
||||
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -100,10 +100,13 @@ namespace AZ
|
||||
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
|
||||
//! Sets the shadowmap Pcf (percentage closer filtering) method.
|
||||
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
|
||||
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
|
||||
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
|
||||
|
||||
//! Sets all of the the disk data for the provided LightHandle.
|
||||
virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0;
|
||||
|
||||
|
||||
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+2
@@ -82,6 +82,8 @@ namespace AZ
|
||||
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
|
||||
//! Sets the shadowmap Pcf (percentage closer filtering) method.
|
||||
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
|
||||
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
|
||||
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
|
||||
//! Sets all of the the point data for the provided LightHandle.
|
||||
virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0;
|
||||
};
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
#include <DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionCopyFrameBufferPass.h>
|
||||
#include <OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.h>
|
||||
|
||||
@@ -283,6 +284,7 @@ namespace AZ
|
||||
// Add Reflection passes
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurPass"), &Render::ReflectionScreenSpaceBlurPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceCompositePass"), &Render::ReflectionScreenSpaceCompositePass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create);
|
||||
|
||||
// Add RayTracing pas
|
||||
|
||||
@@ -343,6 +343,11 @@ namespace AZ
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
|
||||
}
|
||||
|
||||
void DiskLightFeatureProcessor::SetEsmExponent(LightHandle handle, float exponent)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, exponent);
|
||||
}
|
||||
|
||||
void DiskLightFeatureProcessor::UpdateShadow(LightHandle handle)
|
||||
{
|
||||
const DiskLightData& diskLight = m_diskLightData.GetData(handle.GetIndex());
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace AZ
|
||||
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
|
||||
void SetEsmExponent(LightHandle handle, float esmExponent) override;
|
||||
|
||||
void SetDiskData(LightHandle handle, const DiskLightData& data) override;
|
||||
|
||||
|
||||
@@ -192,9 +192,7 @@ namespace AZ
|
||||
OnShaderReloaded();
|
||||
}
|
||||
|
||||
void LightCullingTilePreparePass::OnShaderVariantReinitialized(
|
||||
const AZ::RPI::Shader&, const AZ::RPI::ShaderVariantId&,
|
||||
AZ::RPI::ShaderVariantStableId)
|
||||
void LightCullingTilePreparePass::OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant&)
|
||||
{
|
||||
OnShaderReloaded();
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus overrides...
|
||||
void OnShaderReinitialized(const AZ::RPI::Shader& shader) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const AZ::RPI::Shader& shader, const AZ::RPI::ShaderVariantId& shaderVariantId, AZ::RPI::ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override;
|
||||
|
||||
// Scope producer functions...
|
||||
void CompileResources(const RHI::FrameGraphCompileContext& context) override;
|
||||
|
||||
@@ -312,5 +312,10 @@ namespace AZ
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetEsmExponent(LightHandle handle, float esmExponent)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent);
|
||||
}
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace AZ
|
||||
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
|
||||
void SetEsmExponent(LightHandle handle, float esmExponent) override;
|
||||
void SetPointData(LightHandle handle, const PointLightData& data) override;
|
||||
|
||||
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset)
|
||||
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<RPI::ShaderAsset>& shaderAsset)
|
||||
{
|
||||
if (!Init())
|
||||
{
|
||||
@@ -207,7 +207,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void MorphTargetDispatchItem::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
|
||||
void MorphTargetDispatchItem::OnShaderVariantReinitialized(const RPI::ShaderVariant&)
|
||||
{
|
||||
if (!Init())
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user