Merge branch 'stabilization/2106' into Atom/gallowj/stabilization/2106

This commit is contained in:
Jonny Galloway
2021-06-17 11:42:30 -05:00
committed by GitHub
351 changed files with 5788 additions and 3873 deletions
@@ -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
@@ -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)
@@ -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"
}
}
}
}
}
}
@@ -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"
}
}
}
}
}
}
@@ -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(
@@ -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);
@@ -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))
@@ -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,
@@ -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)
{
+2 -9
View File
@@ -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");
}
+15 -5
View File
@@ -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])
+58 -5
View File
@@ -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"));
}
+14 -73
View File
@@ -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));
}
}
+35
View File
@@ -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
@@ -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;
@@ -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;
}
@@ -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
@@ -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