Merge branch 'upstream/development' into LYN-6770_AutomatedTestNetInputs

This commit is contained in:
Gene Walters
2021-11-01 20:23:27 -07:00
262 changed files with 4009 additions and 1485 deletions
@@ -70,8 +70,6 @@ def AtomEditorComponents_postfx_layer_AddedToEntity():
:return: None
"""
import os
import azlmbr.legacy.general as general
from editor_python_test_tools.editor_entity_utils import EditorEntity
@@ -107,6 +107,19 @@ class EditorComponent:
return type_ids
def convert_to_azvector3(xyz) -> azlmbr.math.Vector3:
"""
Converts a vector3-like element into a azlmbr.math.Vector3
"""
if isinstance(xyz, Tuple) or isinstance(xyz, List):
assert len(xyz) == 3, ValueError("vector must be a 3 element list/tuple or azlmbr.math.Vector3")
return math.Vector3(float(xyz[0]), float(xyz[1]), float(xyz[2]))
elif isinstance(xyz, type(math.Vector3())):
return xyz
else:
raise ValueError("vector must be a 3 element list/tuple or azlmbr.math.Vector3")
class EditorEntity:
"""
Entity class is used to create and interact with Editor Entities.
@@ -183,15 +196,6 @@ class EditorEntity:
:return: EditorEntity class object
"""
def convert_to_azvector3(xyz) -> math.Vector3:
if isinstance(xyz, Tuple) or isinstance(xyz, List):
assert len(xyz) == 3, ValueError("vector must be a 3 element list/tuple or azlmbr.math.Vector3")
return math.Vector3(*xyz)
elif isinstance(xyz, type(math.Vector3())):
return xyz
else:
raise ValueError("vector must be a 3 element list/tuple or azlmbr.math.Vector3")
if parent_id is None:
parent_id = azlmbr.entity.EntityId()
@@ -206,7 +210,7 @@ class EditorEntity:
return entity
# Methods
def set_name(self, entity_name: str):
def set_name(self, entity_name: str) -> None:
"""
Given entity_name, sets name to Entity
:param: entity_name: Name of the entity to set
@@ -324,7 +328,7 @@ class EditorEntity:
self.start_status = status
return status
def set_start_status(self, desired_start_status: str):
def set_start_status(self, desired_start_status: str) -> None:
"""
Set an entity as active/inactive at beginning of runtime or it is editor-only,
given its entity id and the start status then return set success
@@ -382,18 +386,75 @@ class EditorEntity:
"""
return editor.EditorEntityInfoRequestBus(bus.Event, "IsVisible", self.id)
# World Transform Functions
def get_world_translation(self) -> azlmbr.math.Vector3:
"""
Gets the world translation of the entity
"""
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", self.id)
def set_world_translation(self, new_translation) -> None:
"""
Sets the new world translation of the current entity
"""
new_translation = convert_to_azvector3(new_translation)
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetWorldTranslation", self.id, new_translation)
def get_world_rotation(self) -> azlmbr.math.Quaternion:
"""
Gets the world rotation of the entity
"""
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldRotation", self.id)
def set_world_rotation(self, new_rotation):
"""
Sets the new world rotation of the current entity
"""
new_rotation = convert_to_azvector3(new_rotation)
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetWorldRotation", self.id, new_rotation)
# Local Transform Functions
def get_local_uniform_scale(self) -> float:
"""
Gets the local uniform scale of the entity
"""
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetLocalUniformScale", self.id)
def set_local_uniform_scale(self, scale_float) -> None:
"""
Sets the "SetLocalUniformScale" value on the entity.
Sets the local uniform scale value(relative to the parent) on the entity.
:param scale_float: value for "SetLocalUniformScale" to set to.
:return: None
"""
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalUniformScale", self.id, scale_float)
def set_local_rotation(self, vector3_rotation) -> None:
def get_local_rotation(self) -> azlmbr.math.Quaternion:
"""
Sets the "SetLocalRotation" value on the entity.
Gets the local rotation of the entity
"""
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetLocalRotation", self.id)
def set_local_rotation(self, new_rotation) -> None:
"""
Sets the set the local rotation(relative to the parent) of the current entity.
:param vector3_rotation: The math.Vector3 value to use for rotation on the entity (uses radians).
:return: None
"""
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", self.id, vector3_rotation)
new_rotation = convert_to_azvector3(new_rotation)
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalRotation", self.id, new_rotation)
def get_local_translation(self) -> azlmbr.math.Vector3:
"""
Gets the local translation of the current entity.
:return: The math.Vector3 value of the local translation.
"""
return azlmbr.components.TransformBus(azlmbr.bus.Event, "GetLocalTranslation", self.id)
def set_local_translation(self, new_translation) -> None:
"""
Sets the local translation(relative to the parent) of the current entity.
:param vector3_translation: The math.Vector3 value to use for translation on the entity.
:return: None
"""
new_translation = convert_to_azvector3(new_translation)
azlmbr.components.TransformBus(azlmbr.bus.Event, "SetLocalTranslation", self.id, new_translation)
@@ -138,6 +138,14 @@ class PrefabInstance:
self.container_entity = reparented_container_entity
current_instance_prefab.instances.add(self)
def get_direct_child_entities(self):
"""
Returns the entities only contained in the current prefab instance.
This function does not return entities contained in other child instances
"""
return self.container_entity.get_children()
# This is a helper class which contains some of the useful information about a prefab template.
class Prefab:
@@ -53,6 +53,27 @@ class EditorSingleTest_WithFileOverrides(EditorSingleTest):
for f in original_file_list:
fm._restore_file(f, file_list[f])
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomationWithPrefabSystemEnabled(EditorTestSuite):
global_extra_cmdline_args = ['-BatchMode', '-autotest_mode',
'extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"]']
@staticmethod
def get_number_parallel_editors():
return 16
class C4982801_PhysXColliderShape_CanBeSelected(EditorSharedTest):
from .tests.collider import Collider_BoxShapeEditing as test_module
class C4982800_PhysXColliderShape_CanBeSelected(EditorSharedTest):
from .tests.collider import Collider_SphereShapeEditing as test_module
class C4982802_PhysXColliderShape_CanBeSelected(EditorSharedTest):
from .tests.collider import Collider_CapsuleShapeEditing as test_module
@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.")
@pytest.mark.SUITE_main
@@ -286,15 +307,6 @@ class TestAutomation(EditorTestSuite):
class C19723164_ShapeCollider_WontCrashEditor(EditorSharedTest):
from .tests.shape_collider import ShapeCollider_LargeNumberOfShapeCollidersWontCrashEditor as test_module
class C4982800_PhysXColliderShape_CanBeSelected(EditorSharedTest):
from .tests.collider import Collider_SphereShapeEditting as test_module
class C4982801_PhysXColliderShape_CanBeSelected(EditorSharedTest):
from .tests.collider import Collider_BoxShapeEditting as test_module
class C4982802_PhysXColliderShape_CanBeSelected(EditorSharedTest):
from .tests.collider import Collider_CapsuleShapeEditting as test_module
class C12905528_ForceRegion_WithNonTriggerCollider(EditorSharedTest):
from .tests.force_region import ForceRegion_WithNonTriggerColliderWarning as test_module
# Fixme: expected_lines = ["[Warning] (PhysX Force Region) - Please ensure collider component marked as trigger exists in entity"]
@@ -401,19 +401,22 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
def test_Collider_SphereShapeEditting(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_SphereShapeEditting as test_module
self._run_test(request, workspace, editor, test_module)
def test_Collider_SphereShapeEditing(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_SphereShapeEditing as test_module
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"])
@revert_physics_config
def test_Collider_BoxShapeEditting(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_BoxShapeEditting as test_module
self._run_test(request, workspace, editor, test_module)
def test_Collider_BoxShapeEditing(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_BoxShapeEditing as test_module
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"])
@revert_physics_config
def test_Collider_CapsuleShapeEditting(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_CapsuleShapeEditting as test_module
self._run_test(request, workspace, editor, test_module)
def test_Collider_CapsuleShapeEditing(self, request, workspace, editor, launcher_platform):
from .tests.collider import Collider_CapsuleShapeEditing as test_module
self._run_test(request, workspace, editor, test_module,
extra_cmdline_args=["--regset=/Amazon/Preferences/EnablePrefabSystem=true"])
def test_ForceRegion_WithNonTriggerColliderWarning(self, request, workspace, editor, launcher_platform):
from .tests.force_region import ForceRegion_WithNonTriggerColliderWarning as test_module
@@ -19,7 +19,7 @@ class Tests():
# fmt: on
def Collider_BoxShapeEditting():
def Collider_BoxShapeEditing():
"""
Summary:
Adding PhysX Collider and Shape components to test entity, then attempting to modify the shape's dimensions
@@ -73,7 +73,7 @@ def Collider_BoxShapeEditting():
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
helper.open_level("", "Base")
# 2) Create the test entity
test_entity = Entity.create_editor_entity("Test Entity")
@@ -102,4 +102,4 @@ def Collider_BoxShapeEditting():
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Collider_BoxShapeEditting)
Report.start_test(Collider_BoxShapeEditing)
@@ -19,7 +19,7 @@ class Tests():
# fmt: on
def Collider_CapsuleShapeEditting():
def Collider_CapsuleShapeEditing():
"""
Summary:
Adding PhysX Collider and Shape components to test entity, then attempting to modify the shape's dimensions
@@ -74,7 +74,7 @@ def Collider_CapsuleShapeEditting():
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
helper.open_level("", "Base")
# 2) Create the test entity
test_entity = Entity.create_editor_entity("Test Entity")
@@ -102,4 +102,4 @@ def Collider_CapsuleShapeEditting():
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Collider_CapsuleShapeEditting)
Report.start_test(Collider_CapsuleShapeEditing)
@@ -19,7 +19,7 @@ class Tests():
# fmt: on
def Collider_SphereShapeEditting():
def Collider_SphereShapeEditing():
"""
Summary:
Adding PhysX Collider and Shape components to test entity, then attempting to modify the shape's dimensions
@@ -57,7 +57,7 @@ def Collider_SphereShapeEditting():
helper.init_idle()
# 1) Load the empty level
helper.open_level("Physics", "Base")
helper.open_level("", "Base")
# 2) Create the test entity
test_entity = Entity.create_editor_entity("Test Entity")
@@ -90,4 +90,4 @@ def Collider_SphereShapeEditting():
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Collider_SphereShapeEditting)
Report.start_test(Collider_SphereShapeEditing)
@@ -55,3 +55,11 @@ class TestAutomation(TestAutomationBase):
def test_PrefabBasicWorkflow_CreateAndDuplicatePrefab(self, request, workspace, editor, launcher_platform):
from .tests import PrefabBasicWorkflow_CreateAndDuplicatePrefab as test_module
self._run_prefab_test(request, workspace, editor, test_module)
def test_PrefabComplexWorflow_CreatePrefabOfChildEntity(self, request, workspace, editor, launcher_platform):
from .tests import PrefabComplexWorflow_CreatePrefabOfChildEntity as test_module
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
def test_PrefabComplexWorflow_CreatePrefabInsidePrefab(self, request, workspace, editor, launcher_platform):
from .tests import PrefabComplexWorflow_CreatePrefabInsidePrefab as test_module
self._run_prefab_test(request, workspace, editor, test_module, autotest_mode=False)
@@ -0,0 +1,57 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
def PrefabComplexWorflow_CreatePrefabInsidePrefab():
"""
Test description:
- Creates an entity with a physx collider
- Creates a prefab "Outer_prefab" and an instance based of that entity
- Creates a prefab "Inner_prefab" inside "Outer_prefab" based the entity contained inside of it
Checks that the entity is correctly handlded by the prefab system checking the name and that it contains the physx collider
"""
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.prefab_utils import Prefab
import PrefabTestUtils as prefab_test_utils
prefab_test_utils.open_base_tests_level()
# Creates a new Entity at the root level
# Asserts if creation didn't succeed
entity = EditorEntity.create_editor_entity_at((100.0, 100.0, 100.0), name = "TestEntity")
assert entity.id.IsValid(), "Couldn't create entity"
entity.add_component("PhysX Collider")
assert entity.has_component("PhysX Collider"), "Attempted to add a PhysX Collider but no physx collider collider was found afterwards"
# Create a prefab based on that entity
outer_prefab, outer_instance = Prefab.create_prefab([entity], "Outer_prefab")
# The test should be now inside the outer prefab instance.
entity = outer_instance.get_direct_child_entities()[0]
# We track if that is the same entity by checking the name and if it still contains the component that we created before
assert entity.get_name() == "TestEntity", f"Entity name inside outer_prefab doesn't match the original name, original:'TestEntity' current:'{entity.get_name()}'"
assert entity.has_component("PhysX Collider"), "Entity name inside outer_prefab doesn't have the collider component it should"
# Now, create another prefab, based on the entity that is inside outer_prefab
inner_prefab, inner_instance = Prefab.create_prefab([entity], "Inner_prefab")
# The test entity should now be inside the inner prefab instance
entity = inner_instance.get_direct_child_entities()[0]
# We track if that is the same entity by checking the name and if it still contains the component that we created before
assert entity.get_name() == "TestEntity", f"Entity name inside inner_prefab doesn't match the original name, original:'TestEntity' current:'{entity.get_name()}'"
assert entity.has_component("PhysX Collider"), "Entity name inside inner_prefab doesn't have the collider component it should"
# Verify hierarchy of entities:
# Outer_prefab
# |- Inner_prefab
# | |- TestEntity
assert entity.get_parent_id() == inner_instance.container_entity.id
assert inner_instance.container_entity.get_parent_id() == outer_instance.container_entity.id
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(PrefabComplexWorflow_CreatePrefabInsidePrefab)
@@ -0,0 +1,52 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
def PrefabComplexWorflow_CreatePrefabOfChildEntity():
"""
Test description:
- Creates two entities, parent and child. Child entity has Parent entity as its parent.
- Creates a prefab of the child entity.
Test is successful if the new instanced prefab of the child has the parent entity id
"""
CAR_PREFAB_FILE_NAME = 'car_prefab'
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.prefab_utils import Prefab
import PrefabTestUtils as prefab_test_utils
prefab_test_utils.open_base_tests_level()
# Creates a new Entity at the root level
# Asserts if creation didn't succeed
parent_entity = EditorEntity.create_editor_entity_at((100.0, 100.0, 100.0))
assert parent_entity.id.IsValid(), "Couldn't create parent entity"
child_entity = EditorEntity.create_editor_entity(parent_id=parent_entity.id)
assert child_entity.id.IsValid(), "Couldn't create child entity"
assert child_entity.get_world_translation().IsClose(parent_entity.get_world_translation()), f"Child entity position{child_entity.get_world_translation().ToString()}" \
f" is not located at the same position as the parent{parent_entity.get_world_translation().ToString()}"
# Asserts if prefab creation doesn't succeed
child_prefab, child_instance = Prefab.create_prefab([child_entity], CAR_PREFAB_FILE_NAME)
child_entity_on_child_instance = child_instance.get_direct_child_entities()[0]
assert child_instance.container_entity.get_parent_id().IsValid(), "Newly instanced entity has no parent"
assert child_instance.container_entity.get_parent_id() == parent_entity.id, "Newly instanced entity parent does not match the expected parent"
assert child_instance.container_entity.get_world_translation().IsClose(parent_entity.get_world_translation()), "Newly instanced entity position is not located at the same position as the parent"
# Move the parent position, it should update the child position
parent_entity.set_world_translation((200.0, 200.0, 200.0))
child_instance_translation = child_instance.container_entity.get_world_translation()
assert child_instance_translation.IsClose(azlmbr.math.Vector3(200.0, 200.0, 200.0)), f"Instance position position{child_instance_translation.ToString()} didn't get updated" \
f" to the same position as the parent{parent_entity.get_world_translation().ToString()}"
child_translation = child_entity_on_child_instance.get_world_translation()
assert child_translation.IsClose(azlmbr.math.Vector3(200.0, 200.0, 200.0)), f"Entity position{child_translation.ToString()} of the instance didn't get updated" \
f" to the same position as the parent{parent_entity.get_world_translation().ToString()}"
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(PrefabComplexWorflow_CreatePrefabOfChildEntity)
@@ -23,7 +23,7 @@ def create_jobs(request):
jobDescriptorList = []
for platformInfo in request.enabledPlatforms:
jobDesc = azlmbr.asset.builder.JobDescriptor()
jobDesc.jobKey = jobKeyName
jobDesc.jobKey = f'{jobKeyName}-{platformInfo.identifier}'
jobDesc.set_platform_identifier(platformInfo.identifier)
jobDescriptorList.append(jobDesc)
@@ -38,7 +38,7 @@ def on_create_jobs(args):
return create_jobs(request)
except:
log_exception_traceback()
# returing back a default CreateJobsResponse() records an asset error
# returning back a default CreateJobsResponse() records an asset error
return azlmbr.asset.builder.CreateJobsResponse()
def process_file(request):
@@ -58,6 +58,7 @@ def process_file(request):
fileOutput = open(tempFilename, "w")
fileOutput.write('{}')
fileOutput.close()
print(f'Wrote mock asset file: {tempFilename}')
# generate a product asset file entry
subId = binascii.crc32(mockFilename.encode())
@@ -15,6 +15,7 @@ import sys
import importlib
import re
import ly_test_tools
from ly_test_tools import LAUNCHERS
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
@@ -25,8 +26,15 @@ import ly_test_tools.environment.process_utils as process_utils
import argparse, sys
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
def get_editor_launcher_platform():
if ly_test_tools.WINDOWS:
return "windows_editor"
elif ly_test_tools.LINUX:
return "linux_editor"
else:
return None
@pytest.mark.parametrize("launcher_platform", [get_editor_launcher_platform()])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestEditorTest:
@@ -69,7 +77,7 @@ class TestEditorTest:
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorTestSuite
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("launcher_platform", [{get_editor_launcher_platform()}])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
class test_single(EditorSingleTest):
@@ -123,7 +131,7 @@ class TestEditorTest:
from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorTestSuite
@pytest.mark.SUITE_main
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("launcher_platform", [{get_editor_launcher_platform()}])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
class TestAutomation(EditorTestSuite):
{module_class_code}
+53
View File
@@ -0,0 +1,53 @@
{
"ContainerEntity": {
"Id": "ContainerEntity",
"Name": "Base",
"Components": {
"Component_[10182366347512475253]": {
"$type": "EditorPrefabComponent",
"Id": 10182366347512475253
},
"Component_[12917798267488243668]": {
"$type": "EditorPendingCompositionComponent",
"Id": 12917798267488243668
},
"Component_[3261249813163778338]": {
"$type": "EditorOnlyEntityComponent",
"Id": 3261249813163778338
},
"Component_[3837204912784440039]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 3837204912784440039
},
"Component_[4272963378099646759]": {
"$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
"Id": 4272963378099646759,
"Parent Entity": ""
},
"Component_[4848458548047175816]": {
"$type": "EditorVisibilityComponent",
"Id": 4848458548047175816
},
"Component_[5787060997243919943]": {
"$type": "EditorInspectorComponent",
"Id": 5787060997243919943
},
"Component_[7804170251266531779]": {
"$type": "EditorLockComponent",
"Id": 7804170251266531779
},
"Component_[7874177159288365422]": {
"$type": "EditorEntitySortComponent",
"Id": 7874177159288365422
},
"Component_[8018146290632383969]": {
"$type": "EditorEntityIconComponent",
"Id": 8018146290632383969
},
"Component_[8452360690590857075]": {
"$type": "SelectionComponent",
"Id": 8452360690590857075
}
}
}
}
+3
View File
@@ -16,9 +16,12 @@
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/utils.h>
struct ICVar;
class CVarMenu
: public QMenu
{
Q_OBJECT
public:
// CVar that can be toggled on and off
struct CVarToggle
+87 -95
View File
@@ -19,10 +19,9 @@ namespace Config
CConfigGroup::~CConfigGroup()
{
for (TConfigVariables::const_iterator it = m_vars.begin();
it != m_vars.end(); ++it)
for (IConfigVar* var : m_vars)
{
delete (*it);
delete var;
}
}
@@ -31,17 +30,15 @@ namespace Config
m_vars.push_back(var);
}
uint32 CConfigGroup::GetVarCount()
AZ::u32 CConfigGroup::GetVarCount()
{
return static_cast<uint32>(m_vars.size());
return aznumeric_cast<AZ::u32>(m_vars.size());
}
IConfigVar* CConfigGroup::GetVar(const char* szName)
{
for (TConfigVariables::const_iterator it = m_vars.begin();
it != m_vars.end(); ++it)
for (IConfigVar* var : m_vars)
{
IConfigVar* var = (*it);
if (0 == _stricmp(szName, var->GetName().c_str()))
{
return var;
@@ -53,20 +50,19 @@ namespace Config
const IConfigVar* CConfigGroup::GetVar(const char* szName) const
{
for (TConfigVariables::const_iterator it = m_vars.begin();
it != m_vars.end(); ++it)
for (const IConfigVar* var : m_vars)
{
IConfigVar* var = (*it);
if (0 == _stricmp(szName, var->GetName().c_str()))
{
return var;
}
}
return nullptr;
}
IConfigVar* CConfigGroup::GetVar(uint index)
IConfigVar* CConfigGroup::GetVar(AZ::u32 index)
{
if (index < m_vars.size())
{
@@ -76,7 +72,7 @@ namespace Config
return nullptr;
}
const IConfigVar* CConfigGroup::GetVar(uint index) const
const IConfigVar* CConfigGroup::GetVar(AZ::u32 index) const
{
if (index < m_vars.size())
{
@@ -89,114 +85,110 @@ namespace Config
void CConfigGroup::SaveToXML(XmlNodeRef node)
{
// save only values that don't have default values
for (TConfigVariables::const_iterator it = m_vars.begin();
it != m_vars.end(); ++it)
for (const IConfigVar* var : m_vars)
{
IConfigVar* var = (*it);
if (!var->IsFlagSet(IConfigVar::eFlag_DoNotSave))
if (var->IsFlagSet(IConfigVar::eFlag_DoNotSave) || var->IsDefault())
{
if (!var->IsDefault())
{
const char* szName = var->GetName().c_str();
continue;
}
switch (var->GetType())
{
case IConfigVar::eType_BOOL:
{
bool currentValue = false;
var->Get(&currentValue);
node->setAttr(szName, currentValue);
break;
}
const char* szName = var->GetName().c_str();
case IConfigVar::eType_INT:
{
int currentValue = 0;
var->Get(&currentValue);
node->setAttr(szName, currentValue);
break;
}
switch (var->GetType())
{
case IConfigVar::eType_BOOL:
{
bool currentValue = false;
var->Get(&currentValue);
node->setAttr(szName, currentValue);
break;
}
case IConfigVar::eType_FLOAT:
{
float currentValue = 0;
var->Get(&currentValue);
node->setAttr(szName, currentValue);
break;
}
case IConfigVar::eType_INT:
{
int currentValue = 0;
var->Get(&currentValue);
node->setAttr(szName, currentValue);
break;
}
case IConfigVar::eType_STRING:
{
AZStd::string currentValue;
var->Get(&currentValue);
node->setAttr(szName, currentValue.c_str());
break;
}
}
}
case IConfigVar::eType_FLOAT:
{
float currentValue = 0;
var->Get(&currentValue);
node->setAttr(szName, currentValue);
break;
}
case IConfigVar::eType_STRING:
{
AZStd::string currentValue;
var->Get(&currentValue);
node->setAttr(szName, currentValue.c_str());
break;
}
}
}
}
void CConfigGroup::LoadFromXML(XmlNodeRef node)
{
// save only values that don't have default values
for (TConfigVariables::const_iterator it = m_vars.begin();
it != m_vars.end(); ++it)
// load values that are save-able
for (IConfigVar* var : m_vars)
{
IConfigVar* var = (*it);
if (!var->IsFlagSet(IConfigVar::eFlag_DoNotSave))
if (var->IsFlagSet(IConfigVar::eFlag_DoNotSave))
{
const char* szName = var->GetName().c_str();
continue;
}
const char* szName = var->GetName().c_str();
switch (var->GetType())
switch (var->GetType())
{
case IConfigVar::eType_BOOL:
{
bool currentValue = false;
var->GetDefault(&currentValue);
if (node->getAttr(szName, currentValue))
{
case IConfigVar::eType_BOOL:
{
bool currentValue = false;
var->GetDefault(&currentValue);
if (node->getAttr(szName, currentValue))
{
var->Set(&currentValue);
}
break;
var->Set(&currentValue);
}
break;
}
case IConfigVar::eType_INT:
case IConfigVar::eType_INT:
{
int currentValue = 0;
var->GetDefault(&currentValue);
if (node->getAttr(szName, currentValue))
{
int currentValue = 0;
var->GetDefault(&currentValue);
if (node->getAttr(szName, currentValue))
{
var->Set(&currentValue);
}
break;
var->Set(&currentValue);
}
break;
}
case IConfigVar::eType_FLOAT:
case IConfigVar::eType_FLOAT:
{
float currentValue = 0;
var->GetDefault(&currentValue);
if (node->getAttr(szName, currentValue))
{
float currentValue = 0;
var->GetDefault(&currentValue);
if (node->getAttr(szName, currentValue))
{
var->Set(&currentValue);
}
break;
var->Set(&currentValue);
}
break;
}
case IConfigVar::eType_STRING:
case IConfigVar::eType_STRING:
{
AZStd::string currentValue;
var->GetDefault(&currentValue);
QString readValue(currentValue.c_str());
if (node->getAttr(szName, readValue))
{
AZStd::string currentValue;
var->GetDefault(&currentValue);
QString readValue(currentValue.c_str());
if (node->getAttr(szName, readValue))
{
currentValue = readValue.toUtf8().data();
var->Set(&currentValue);
}
break;
}
currentValue = readValue.toUtf8().data();
var->Set(&currentValue);
}
break;
}
}
}
}
+21 -69
View File
@@ -8,8 +8,12 @@
#pragma once
#ifndef CRYINCLUDE_EDITOR_CONFIGGROUP_H
#define CRYINCLUDE_EDITOR_CONFIGGROUP_H
#include <AzCore/base.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
struct ICVar;
class XmlNodeRef;
namespace Config
{
@@ -32,7 +36,7 @@ namespace Config
eFlag_DoNotSave = 1 << 2,
};
IConfigVar(const char* szName, const char* szDescription, EType varType, uint8 flags)
IConfigVar(const char* szName, const char* szDescription, EType varType, AZ::u8 flags)
: m_name(szName)
, m_description(szDescription)
, m_type(varType)
@@ -42,22 +46,22 @@ namespace Config
virtual ~IConfigVar() = default;
ILINE EType GetType() const
AZ_FORCE_INLINE EType GetType() const
{
return m_type;
}
ILINE const AZStd::string& GetName() const
AZ_FORCE_INLINE const AZStd::string& GetName() const
{
return m_name;
}
ILINE const AZStd::string& GetDescription() const
AZ_FORCE_INLINE const AZStd::string& GetDescription() const
{
return m_description;
}
ILINE bool IsFlagSet(EFlags flag) const
AZ_FORCE_INLINE bool IsFlagSet(EFlags flag) const
{
return 0 != (m_flags & flag);
}
@@ -68,73 +72,28 @@ namespace Config
virtual void GetDefault(void* outPtr) const = 0;
virtual void Reset() = 0;
static EType TranslateType(const bool&) { return eType_BOOL; }
static EType TranslateType(const int&) { return eType_INT; }
static EType TranslateType(const float&) { return eType_FLOAT; }
static EType TranslateType(const AZStd::string&) { return eType_STRING; }
static constexpr EType TranslateType(const bool&) { return eType_BOOL; }
static constexpr EType TranslateType(const int&) { return eType_INT; }
static constexpr EType TranslateType(const float&) { return eType_FLOAT; }
static constexpr EType TranslateType(const AZStd::string&) { return eType_STRING; }
protected:
EType m_type;
uint8 m_flags;
AZ::u8 m_flags;
AZStd::string m_name;
AZStd::string m_description;
void* m_ptr;
ICVar* m_pCVar;
};
// Typed wrapper for config variable
template<class T>
class TConfigVar
: public IConfigVar
{
private:
T m_default;
public:
TConfigVar(const char* szName, const char* szDescription, uint8 flags, T& ptr, const T& defaultValue)
: IConfigVar(szName, szDescription, IConfigVar::TranslateType(ptr), flags)
, m_default(defaultValue)
{
m_ptr = &ptr;
// reset to default value on initializations
ptr = defaultValue;
}
virtual void Get(void* outPtr) const
{
*reinterpret_cast<T*>(outPtr) = *reinterpret_cast<const T*>(m_ptr);
}
virtual void Set(const void* ptr)
{
*reinterpret_cast<T*>(m_ptr) = *reinterpret_cast<const T*>(ptr);
}
virtual void Reset()
{
*reinterpret_cast<T*>(m_ptr) = m_default;
}
virtual void GetDefault(void* outPtr) const
{
*reinterpret_cast<T*>(outPtr) = m_default;
}
virtual bool IsDefault() const
{
return *reinterpret_cast<const T*>(m_ptr) == m_default;
}
};
// Group of configuration variables with optional mapping to CVars
class CConfigGroup
{
private:
typedef std::vector<IConfigVar*> TConfigVariables;
using TConfigVariables = AZStd::vector<IConfigVar*> ;
TConfigVariables m_vars;
typedef std::vector<ICVar*> TConsoleVariables;
using TConsoleVariables = AZStd::vector<ICVar*>;
TConsoleVariables m_consoleVars;
public:
@@ -142,20 +101,13 @@ namespace Config
virtual ~CConfigGroup();
void AddVar(IConfigVar* var);
uint32 GetVarCount();
AZ::u32 GetVarCount();
IConfigVar* GetVar(const char* szName);
IConfigVar* GetVar(uint index);
IConfigVar* GetVar(AZ::u32 index);
const IConfigVar* GetVar(const char* szName) const;
const IConfigVar* GetVar(uint index) const;
const IConfigVar* GetVar(AZ::u32 index) const;
void SaveToXML(XmlNodeRef node);
void LoadFromXML(XmlNodeRef node);
template<class T>
void AddVar(const char* szName, const char* szDescription, T& var, const T& defaultValue, uint8 flags = 0)
{
AddVar(new TConfigVar<T>(szName, szDescription, flags, var, defaultValue));
}
};
};
#endif // CRYINCLUDE_EDITOR_CONFIGGROUP_H
@@ -6,8 +6,6 @@
*
*/
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYMISCCTRL_H
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYMISCCTRL_H
#pragma once
#if !defined(Q_MOC_RUN)
@@ -53,6 +51,7 @@ private:
class UserPopupWidgetHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarUser, UserPropertyEditor>
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(UserPopupWidgetHandler, AZ::SystemAllocator, 0);
bool IsDefaultHandler() const override { return false; }
@@ -67,6 +66,7 @@ public:
class FloatCurveHandler : public QObject, public AzToolsFramework::PropertyHandler < CReflectedVarSpline, CSplineCtrl>
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(FloatCurveHandler, AZ::SystemAllocator, 0);
bool IsDefaultHandler() const override { return false; }
@@ -80,5 +80,3 @@ public:
void OnSplineChange(CSplineCtrl*);
};
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYMISCCTRL_H
@@ -58,17 +58,9 @@ private:
void OnClicked() override
{
QString tempValue("");
QString ext("");
if (m_path.isEmpty() == false)
if (!m_path.isEmpty() && !Path::GetExt(m_path).isEmpty())
{
if (Path::GetExt(m_path) == "")
{
tempValue = "";
}
else
{
tempValue = m_path;
}
tempValue = m_path;
}
AssetSelectionModel selection;
@@ -99,6 +99,7 @@ class FileResourceSelectorWidgetHandler
: QObject
, public AzToolsFramework::PropertyHandler < CReflectedVarResource, FileResourceSelectorWidget >
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(FileResourceSelectorWidgetHandler, AZ::SystemAllocator, 0);
@@ -446,41 +446,54 @@ void ReflectedVarUserAdapter::SetVariable(IVariable *pVariable)
m_reflectedVar.reset(new CReflectedVarUser( pVariable->GetHumanName().toUtf8().data()));
}
void ReflectedVarUserAdapter::SyncReflectedVarToIVar(IVariable *pVariable)
void ReflectedVarUserAdapter::SyncReflectedVarToIVar(IVariable* pVariable)
{
QString value;
pVariable->Get(value);
m_reflectedVar->m_value = value.toUtf8().data();
//extract the list of custom items from the IVariable user data
IVariable::IGetCustomItems* pGetCustomItems = static_cast<IVariable::IGetCustomItems*> (pVariable->GetUserData().value<void *>());
if (pGetCustomItems != nullptr)
{
std::vector<IVariable::IGetCustomItems::SItem> items;
QString dlgTitle;
// call the user supplied callback to fill-in items and get dialog title
bool bShowIt = pGetCustomItems->GetItems(pVariable, items, dlgTitle);
if (bShowIt) // if func didn't veto, show the dialog
{
m_reflectedVar->m_enableEdit = true;
m_reflectedVar->m_useTree = pGetCustomItems->UseTree();
m_reflectedVar->m_treeSeparator = pGetCustomItems->GetTreeSeparator();
m_reflectedVar->m_dialogTitle = dlgTitle.toUtf8().data();
m_reflectedVar->m_itemNames.resize(items.size());
m_reflectedVar->m_itemDescriptions.resize(items.size());
QByteArray ba;
int i = -1;
std::generate(m_reflectedVar->m_itemNames.begin(), m_reflectedVar->m_itemNames.end(), [&items, &i, &ba]() { ++i; ba = items[i].name.toUtf8(); return ba.data(); });
i = -1;
std::generate(m_reflectedVar->m_itemDescriptions.begin(), m_reflectedVar->m_itemDescriptions.end(), [&items, &i, &ba]() { ++i; ba = items[i].desc.toUtf8(); return ba.data(); });
}
}
else
// extract the list of custom items from the IVariable user data
IVariable::IGetCustomItems* pGetCustomItems = static_cast<IVariable::IGetCustomItems*>(pVariable->GetUserData().value<void*>());
if (pGetCustomItems == nullptr)
{
m_reflectedVar->m_enableEdit = false;
return;
}
std::vector<IVariable::IGetCustomItems::SItem> items;
QString dlgTitle;
// call the user supplied callback to fill-in items and get dialog title
bool bShowIt = pGetCustomItems->GetItems(pVariable, items, dlgTitle);
if (!bShowIt) // if func vetoed it, don't show the dialog
{
return;
}
m_reflectedVar->m_enableEdit = true;
m_reflectedVar->m_useTree = pGetCustomItems->UseTree();
m_reflectedVar->m_treeSeparator = pGetCustomItems->GetTreeSeparator();
m_reflectedVar->m_dialogTitle = dlgTitle.toUtf8().data();
m_reflectedVar->m_itemNames.resize(items.size());
m_reflectedVar->m_itemDescriptions.resize(items.size());
QByteArray ba;
int i = -1;
AZStd::generate(
m_reflectedVar->m_itemNames.begin(), m_reflectedVar->m_itemNames.end(),
[&items, &i, &ba]()
{
++i;
ba = items[i].name.toUtf8();
return ba.data();
});
i = -1;
AZStd::generate(
m_reflectedVar->m_itemDescriptions.begin(), m_reflectedVar->m_itemDescriptions.end(),
[&items, &i, &ba]()
{
++i;
ba = items[i].desc.toUtf8();
return ba.data();
});
}
void ReflectedVarUserAdapter::SyncIVarToReflectedVar(IVariable *pVariable)
-2
View File
@@ -126,7 +126,6 @@ void TimelineWidget::DrawTicks(QPainter* painter)
const QPen pOldPen = painter->pen();
const QPen ltgray(QColor(110, 110, 110));
const QPen black(palette().color(QPalette::Normal, QPalette::Text));
const QPen redpen(QColor(255, 0, 255));
// Draw time ticks every tick step seconds.
@@ -598,7 +597,6 @@ void TimelineWidget::DrawSecondTicks(QPainter* painter)
{
const QPen ltgray(QColor(110, 110, 110));
const QPen black(palette().color(QPalette::Normal, QPalette::Text));
const QPen redpen(QColor(255, 0, 255));
for (int gx = m_grid.firstGridLine.x(); gx < m_grid.firstGridLine.x() + m_grid.numGridLines.x() + 1; gx++)
{
+9 -1
View File
@@ -4137,7 +4137,15 @@ extern "C" int AZ_DLL_EXPORT CryEditMain(int argc, char* argv[])
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
Editor::EditorQtApplication* app = Editor::EditorQtApplication::newInstance(argc, argv);
if (app->arguments().contains("-autotest_mode"))
QStringList qArgs = app->arguments();
const bool is_automated_test = AZStd::any_of(qArgs.begin(), qArgs.end(),
[](const QString& elem)
{
return elem.endsWith("autotest_mode") || elem.endsWith("runpythontest");
}
);
if (is_automated_test)
{
// Nullroute all stdout to null for automated tests, this way we make sure
// that the test result output is not polluted with unrelated output data.
+1
View File
@@ -431,6 +431,7 @@ public:
class CCrySingleDocTemplate
: public QObject
{
Q_OBJECT
private:
explicit CCrySingleDocTemplate(const QMetaObject* pDocClass)
: QObject()
+1 -4
View File
@@ -12,8 +12,6 @@
// Notice : Refer to ViewportTitleDlg.cpp for a use case.
#ifndef CRYINCLUDE_EDITOR_CUSTOMRESOLUTIONDLG_H
#define CRYINCLUDE_EDITOR_CUSTOMRESOLUTIONDLG_H
#pragma once
#if !defined(Q_MOC_RUN)
@@ -28,6 +26,7 @@ namespace Ui
class CCustomResolutionDlg
: public QDialog
{
Q_OBJECT
public:
CCustomResolutionDlg(int w, int h, QWidget* pParent = nullptr);
~CCustomResolutionDlg();
@@ -42,5 +41,3 @@ protected:
QScopedPointer<Ui::CustomResolutionDlg> m_ui;
};
#endif // CRYINCLUDE_EDITOR_CUSTOMRESOLUTIONDLG_H
+3 -3
View File
@@ -211,9 +211,9 @@ public:
void Reset(QAction& action)
{
emit beginResetModel();
beginResetModel();
m_action = &action;
emit endResetModel();
endResetModel();
}
private:
@@ -266,7 +266,7 @@ QStringList CustomizeKeyboardDialog::BuildModels(QWidget* parent)
categories.append(category);
QMenu* menu = menuAction->menu();
m_menuActions[category] = GetAllActionsForMenu(menu, QStringLiteral(""));
m_menuActions[category] = GetAllActionsForMenu(menu, QString());
}
return categories;
+2 -2
View File
@@ -25,9 +25,9 @@ namespace SandboxEditor
connect(m_ui->okButton, &QPushButton::clicked, this, &ErrorDialog::OnOK);
connect(
m_ui->messages,
SIGNAL(itemSelectionChanged()),
&QTreeWidget::itemSelectionChanged,
this,
SLOT(MessageSelectionChanged()));
&ErrorDialog::MessageSelectionChanged);
}
ErrorDialog::~ErrorDialog()
@@ -240,7 +240,7 @@ QJsonObject KeyboardCustomizationSettings::ExportGroup()
void KeyboardCustomizationSettings::ImportFromFile(QWidget* parent)
{
QString fileName = QFileDialog::getOpenFileName(parent, QObject::tr("Export Keyboard Shortcuts"), QStringLiteral(""), QObject::tr("Keyboard Settings (*.keys)"));
QString fileName = QFileDialog::getOpenFileName(parent, QObject::tr("Export Keyboard Shortcuts"), QString(), QObject::tr("Keyboard Settings (*.keys)"));
if (fileName.isEmpty())
{
return;
+1 -1
View File
@@ -419,7 +419,7 @@ void MemoryStatusItem::updateStatus()
GeneralStatusItem::GeneralStatusItem(QString name, MainStatusBar* parent)
: StatusBarItem(name, parent)
{
connect(parent, SIGNAL(messageChanged(QString)), this, SLOT(update()));
connect(parent, &MainStatusBar::messageChanged, this, [this](const QString&) { update(); });
}
QString GeneralStatusItem::CurrentText() const
+4 -3
View File
@@ -100,9 +100,10 @@ CNewLevelDialog::CNewLevelDialog(QWidget* pParent /*=nullptr*/)
m_level = "";
// First of all, keyboard focus is related to widget tab order, and the default tab order is based on the order in which
// widgets are constructed. Therefore, creating more widgets changes the keyboard focus. That is why setFocus() is called last.
// Secondly, using singleShot() allows setFocus() slot of the QLineEdit instance to be invoked right after the event system
// is ready to do so. Therefore, it is better to use singleShot() than directly call setFocus().
QTimer::singleShot(0, ui->LEVEL, SLOT(OnStartup()));
// in OnStartup()
// Secondly, using singleShot() allows OnStartup() slot of the QLineEdit instance to be invoked right after the event system
// is ready to do so. Therefore, it is better to use singleShot() than directly call OnStartup().
QTimer::singleShot(0, this, &CNewLevelDialog::OnStartup);
ReloadLevelFolder();
}
@@ -197,48 +197,46 @@ AssetCatalogModel::~AssetCatalogModel()
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
}
AZ::Data::AssetType AssetCatalogModel::GetAssetType(QString filename) const
AZ::Data::AssetType AssetCatalogModel::GetAssetType(const QString &filename) const
{
AZ::Data::AssetType returnType = AZ::Uuid::CreateNull();
// Compare file extensions with the map created from the asset database.
int dotIndex = filename.lastIndexOf('.');
if (dotIndex >= 0)
if (dotIndex < 0)
{
QString extension = filename.mid(dotIndex);
for (auto pair : m_extensionToAssetType)
{
QString qExtensions = pair.first.c_str();
if (qExtensions.indexOf(extension) >= 0)
{
if (pair.second.size() > 1)
{
// There are multiple types with this extension. Check each handler to see if they can handle this data type.
AZStd::string azFilename = filename.toStdString().c_str();
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, MakePathAssetRootRelative, azFilename);
AZ::Data::AssetId assetId;
EBUS_EVENT_RESULT(assetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, azFilename.c_str(), AZ::Data::s_invalidAssetType, false);
return AZ::Uuid::CreateNull();
}
for (AZ::Uuid type : pair.second)
{
const AZ::Data::AssetHandler* handler = AZ::Data::AssetManager::Instance().GetHandler(type);
if (handler && handler->CanHandleAsset(assetId))
{
returnType = type;
break;
}
}
}
else
{
returnType = pair.second[0];
break;
}
QStringRef extension = filename.midRef(dotIndex);
for (const auto& pair : m_extensionToAssetType)
{
QString qExtensions = pair.first.c_str();
if (qExtensions.indexOf(extension) < 0 || pair.second.empty())
{
continue;
}
if (pair.second.size() == 1)
{
return pair.second[0];
}
// There are multiple types with this extension. Search for a handler that can handle this data type.
AZStd::string azFilename = filename.toStdString().c_str();
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, MakePathAssetRootRelative, azFilename);
AZ::Data::AssetId assetId;
EBUS_EVENT_RESULT(assetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, azFilename.c_str(), AZ::Data::s_invalidAssetType, false);
for (const AZ::Uuid& type : pair.second)
{
const AZ::Data::AssetHandler* handler = AZ::Data::AssetManager::Instance().GetHandler(type);
if (handler && handler->CanHandleAsset(assetId))
{
return type;
}
}
}
return returnType;
return AZ::Uuid::CreateNull();
}
QStandardItem* AssetCatalogModel::GetPath(QString& path, bool createIfNeeded, QStandardItem* parent)
@@ -419,7 +417,7 @@ AssetCatalogEntry* AssetCatalogModel::AddAsset(QString assetPath, AZ::Data::Asse
// icons' memory being reclaimed and crashing the Editor.
QSize size = fileIcon.actualSize(QSize(16, 16));
QIcon deepCopy = fileIcon.pixmap(size).copy(0, 0, size.width(), size.height());
if (!fileIcon.isNull())
{
m_assetTypeToIcon[assetType] = deepCopy;
@@ -110,7 +110,7 @@ protected:
void SetFilterRegExp(const AZStd::string& filterType, const QRegExp& regExp);
void ClearFilterRegExp(const AZStd::string& filterType = AZStd::string());
AZ::Data::AssetType GetAssetType(QString filename) const;
AZ::Data::AssetType GetAssetType(const QString &filename) const;
QStandardItem* GetPath(QString& path, bool createIfNeeded, QStandardItem* parent = nullptr);
void ApplyFilter(QStandardItem* parent);
@@ -215,11 +215,6 @@ namespace AZ
m_oldProjectPath = newProjectPath;
// Merge the project.json file into settings registry under ProjectSettingsRootKey path.
AZ::IO::FixedMaxPath projectMetadataFile{ AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath };
projectMetadataFile /= "project.json";
m_registry.MergeSettingsFile(projectMetadataFile.Native(),
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
// Update all the runtime file paths based on the new "project_path" value.
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
}
@@ -168,6 +168,11 @@ namespace AZ
//! Rotation modifiers
//! @{
//! Set the world rotation matrix using the composition of rotations around
//! the principle axes in the order of z-axis first and y-axis and then x-axis.
//! @param eulerRadianAngles A Vector3 denoting radian angles of the rotations around each principle axis.
virtual void SetWorldRotation([[maybe_unused]] const AZ::Vector3& eulerAnglesRadian) {}
//! Sets the entity's rotation in the world in quaternion notation.
//! The origin of the axes is the entity's position in world space.
//! @param quaternion A quaternion that represents the rotation to use for the entity.
@@ -634,12 +634,18 @@ namespace AZ::SettingsRegistryMergeUtils
}
// Project name - if it was set via merging project.json use that value, otherwise use the project path's folder name.
auto projectNameKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
constexpr auto projectNameKey =
FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
+ "/project_name";
AZ::SettingsRegistryInterface::FixedValueString projectName;
if (!registry.Get(projectName, projectNameKey))
// Read the project name from the project.json file if it exists
if (AZ::IO::FixedMaxPath projectJsonPath = normalizedProjectPath / "project.json";
AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
{
registry.MergeSettingsFile(projectJsonPath.Native(),
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
}
if (FixedValueString projectName; !registry.Get(projectName, projectNameKey))
{
projectName = path.Filename().Native();
registry.Set(projectNameKey, projectName);
@@ -323,6 +323,13 @@ namespace AzFramework
return localZ;
}
void TransformComponent::SetWorldRotation(const AZ::Vector3& eulerAnglesRadian)
{
AZ::Transform newWorldTransform = m_worldTM;
newWorldTransform.SetRotation(AZ::Quaternion::CreateFromEulerAnglesRadians(eulerAnglesRadian));
SetWorldTM(newWorldTransform);
}
void TransformComponent::SetWorldRotationQuaternion(const AZ::Quaternion& quaternion)
{
AZ::Transform newWorldTransform = m_worldTM;
@@ -108,6 +108,7 @@ namespace AzFramework
float GetLocalZ() override;
// Rotation modifiers
void SetWorldRotation(const AZ::Vector3& eulerAnglesRadian) override;
void SetWorldRotationQuaternion(const AZ::Quaternion& quaternion) override;
AZ::Vector3 GetWorldRotation() override;
@@ -24,17 +24,17 @@ namespace AzFramework
IMatchmakingRequests() = default;
virtual ~IMatchmakingRequests() = default;
// Registers a player's acceptance or rejection of a proposed matchmaking.
// @param acceptMatchRequest The request of AcceptMatch operation
//! Registers a player's acceptance or rejection of a proposed matchmaking.
//! @param acceptMatchRequest The request of AcceptMatch operation
virtual void AcceptMatch(const AcceptMatchRequest& acceptMatchRequest) = 0;
// Create a game match for a group of players.
// @param startMatchmakingRequest The request of StartMatchmaking operation
// @return A unique identifier for a matchmaking ticket
//! Create a game match for a group of players.
//! @param startMatchmakingRequest The request of StartMatchmaking operation
//! @return A unique identifier for a matchmaking ticket
virtual AZStd::string StartMatchmaking(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
// Cancels a matchmaking ticket that is currently being processed.
// @param stopMatchmakingRequest The request of StopMatchmaking operation
//! Cancels a matchmaking ticket that is currently being processed.
//! @param stopMatchmakingRequest The request of StopMatchmaking operation
virtual void StopMatchmaking(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
};
@@ -48,16 +48,16 @@ namespace AzFramework
IMatchmakingAsyncRequests() = default;
virtual ~IMatchmakingAsyncRequests() = default;
// AcceptMatch Async
// @param acceptMatchRequest The request of AcceptMatch operation
//! AcceptMatch Async
//! @param acceptMatchRequest The request of AcceptMatch operation
virtual void AcceptMatchAsync(const AcceptMatchRequest& acceptMatchRequest) = 0;
// StartMatchmaking Async
// @param startMatchmakingRequest The request of StartMatchmaking operation
//! StartMatchmaking Async
//! @param startMatchmakingRequest The request of StartMatchmaking operation
virtual void StartMatchmakingAsync(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
// StopMatchmaking Async
// @param stopMatchmakingRequest The request of StopMatchmaking operation
//! StopMatchmaking Async
//! @param stopMatchmakingRequest The request of StopMatchmaking operation
virtual void StopMatchmakingAsync(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
};
@@ -76,14 +76,14 @@ namespace AzFramework
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
// OnAcceptMatchAsyncComplete is fired once AcceptMatchAsync completes
//! OnAcceptMatchAsyncComplete is fired once AcceptMatchAsync completes
virtual void OnAcceptMatchAsyncComplete() = 0;
// OnStartMatchmakingAsyncComplete is fired once StartMatchmakingAsync completes
// @param matchmakingTicketId The unique identifier for the matchmaking ticket
//! OnStartMatchmakingAsyncComplete is fired once StartMatchmakingAsync completes
//! @param matchmakingTicketId The unique identifier for the matchmaking ticket
virtual void OnStartMatchmakingAsyncComplete(const AZStd::string& matchmakingTicketId) = 0;
// OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
//! OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
virtual void OnStopMatchmakingAsyncComplete() = 0;
};
using MatchmakingAsyncRequestNotificationBus = AZ::EBus<MatchmakingAsyncRequestNotifications>;
@@ -29,17 +29,17 @@ namespace AzFramework
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
// OnMatchAcceptance is fired when match is found and pending on acceptance
// Use this notification to accept found match
//! OnMatchAcceptance is fired when match is found and pending on acceptance
//! Use this notification to accept found match
virtual void OnMatchAcceptance() = 0;
// OnMatchComplete is fired when match is complete
//! OnMatchComplete is fired when match is complete
virtual void OnMatchComplete() = 0;
// OnMatchError is fired when match is processed with error
//! OnMatchError is fired when match is processed with error
virtual void OnMatchError() = 0;
// OnMatchFailure is fired when match is failed to complete
//! OnMatchFailure is fired when match is failed to complete
virtual void OnMatchFailure() = 0;
};
using MatchmakingNotificationBus = AZ::EBus<MatchmakingNotifications>;
@@ -29,11 +29,11 @@ namespace AzFramework
AcceptMatchRequest() = default;
virtual ~AcceptMatchRequest() = default;
// Player response to accept or reject match
//! Player response to accept or reject match
bool m_acceptMatch;
// A list of unique identifiers for players delivering the response
//! A list of unique identifiers for players delivering the response
AZStd::vector<AZStd::string> m_playerIds;
// A unique identifier for a matchmaking ticket
//! A unique identifier for a matchmaking ticket
AZStd::string m_ticketId;
};
@@ -47,7 +47,7 @@ namespace AzFramework
StartMatchmakingRequest() = default;
virtual ~StartMatchmakingRequest() = default;
// A unique identifier for a matchmaking ticket
//! A unique identifier for a matchmaking ticket
AZStd::string m_ticketId;
};
@@ -61,7 +61,7 @@ namespace AzFramework
StopMatchmakingRequest() = default;
virtual ~StopMatchmakingRequest() = default;
// A unique identifier for a matchmaking ticket
//! A unique identifier for a matchmaking ticket
AZStd::string m_ticketId;
};
} // namespace AzFramework
@@ -10,6 +10,7 @@
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
namespace AzPhysics
{
@@ -28,6 +29,71 @@ namespace AzPhysics
->Field("ChildLocalPosition", &JointConfiguration::m_childLocalPosition)
->Field("StartSimulationEnabled", &JointConfiguration::m_startSimulationEnabled)
;
if (auto* editContext = serializeContext->GetEditContext())
{
editContext->Class<JointConfiguration>("Joint Configuration", "Joint configuration.")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &JointConfiguration::m_parentLocalRotation,
"Parent local rotation", "Parent joint frame relative to parent body.")
->Attribute(AZ::Edit::Attributes::Visibility, &JointConfiguration::GetParentLocalRotationVisibility)
->DataElement(AZ::Edit::UIHandlers::Default, &JointConfiguration::m_parentLocalPosition,
"Parent local position", "Joint position relative to parent body.")
->Attribute(AZ::Edit::Attributes::Visibility, &JointConfiguration::GetParentLocalPositionVisibility)
->DataElement(AZ::Edit::UIHandlers::Default, &JointConfiguration::m_childLocalRotation,
"Child local rotation", "Child joint frame relative to child body.")
->Attribute(AZ::Edit::Attributes::Visibility, &JointConfiguration::GetChildLocalRotationVisibility)
->DataElement(AZ::Edit::UIHandlers::Default, &JointConfiguration::m_childLocalPosition,
"Child local position", "Joint position relative to child body.")
->Attribute(AZ::Edit::Attributes::Visibility, &JointConfiguration::GetChildLocalPositionVisibility)
->DataElement(AZ::Edit::UIHandlers::Default, &JointConfiguration::m_startSimulationEnabled,
"Start simulation enabled", "When active, the joint will be enabled when the simulation begins.")
->Attribute(AZ::Edit::Attributes::Visibility, &JointConfiguration::GetStartSimulationEnabledVisibility)
;
}
}
}
}
AZ::Crc32 JointConfiguration::GetPropertyVisibility(JointConfiguration::PropertyVisibility property) const
{
return (m_propertyVisibilityFlags & property) != 0 ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
}
void JointConfiguration::SetPropertyVisibility(JointConfiguration::PropertyVisibility property, bool isVisible)
{
if (isVisible)
{
m_propertyVisibilityFlags |= property;
}
else
{
m_propertyVisibilityFlags &= ~property;
}
}
AZ::Crc32 JointConfiguration::GetParentLocalRotationVisibility() const
{
return GetPropertyVisibility(JointConfiguration::PropertyVisibility::ParentLocalRotation);
}
AZ::Crc32 JointConfiguration::GetParentLocalPositionVisibility() const
{
return GetPropertyVisibility(JointConfiguration::PropertyVisibility::ParentLocalPosition);
}
AZ::Crc32 JointConfiguration::GetChildLocalRotationVisibility() const
{
return GetPropertyVisibility(JointConfiguration::PropertyVisibility::ChildLocalRotation);
}
AZ::Crc32 JointConfiguration::GetChildLocalPositionVisibility() const
{
return GetPropertyVisibility(JointConfiguration::PropertyVisibility::ChildLocalPosition);
}
AZ::Crc32 JointConfiguration::GetStartSimulationEnabledVisibility() const
{
return GetPropertyVisibility(JointConfiguration::PropertyVisibility::StartSimulationEnabled);
}
} // namespace AzPhysics
@@ -31,6 +31,25 @@ namespace AzPhysics
JointConfiguration() = default;
virtual ~JointConfiguration() = default;
// Visibility helpers for use in the Editor when reflected.
enum PropertyVisibility : AZ::u8
{
ParentLocalRotation = 1 << 0, //!< Whether the parent local rotation is visible.
ParentLocalPosition = 1 << 1, //!< Whether the parent local position is visible.
ChildLocalRotation = 1 << 2, //!< Whether the child local rotation is visible.
ChildLocalPosition = 1 << 3, //!< Whether the child local position is visible.
StartSimulationEnabled = 1 << 4 //!< Whether the start simulation enabled setting is visible.
};
AZ::Crc32 GetPropertyVisibility(PropertyVisibility property) const;
void SetPropertyVisibility(PropertyVisibility property, bool isVisible);
AZ::Crc32 GetParentLocalRotationVisibility() const;
AZ::Crc32 GetParentLocalPositionVisibility() const;
AZ::Crc32 GetChildLocalRotationVisibility() const;
AZ::Crc32 GetChildLocalPositionVisibility() const;
AZ::Crc32 GetStartSimulationEnabledVisibility() const;
// Entity/object association.
void* m_customUserData = nullptr;
@@ -40,8 +59,11 @@ namespace AzPhysics
AZ::Quaternion m_childLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Child joint frame relative to child body.
AZ::Vector3 m_childLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to child body.
bool m_startSimulationEnabled = true;
// For debugging/tracking purposes only.
AZStd::string m_debugName;
// Default all visibility settings to invisible, since most joint configurations don't need to display these.
AZ::u8 m_propertyVisibilityFlags = 0;
};
}
@@ -18,16 +18,16 @@ namespace AzFramework
//! The properties for handling join session request.
struct SessionConnectionConfig
{
// A unique identifier for registered player in session.
//! A unique identifier for registered player in session.
AZStd::string m_playerSessionId;
// The DNS identifier assigned to the instance that is running the session.
//! The DNS identifier assigned to the instance that is running the session.
AZStd::string m_dnsName;
// The IP address of the session.
//! The IP address of the session.
AZStd::string m_ipAddress;
// The port number for the session.
//! The port number for the session.
uint16_t m_port = 0;
};
@@ -35,10 +35,10 @@ namespace AzFramework
//! The properties for handling player connect/disconnect
struct PlayerConnectionConfig
{
// A unique identifier for player connection.
//! A unique identifier for player connection.
uint32_t m_playerConnectionId = 0;
// A unique identifier for registered player in session.
//! A unique identifier for registered player in session.
AZStd::string m_playerSessionId;
};
@@ -51,12 +51,12 @@ namespace AzFramework
ISessionHandlingClientRequests() = default;
virtual ~ISessionHandlingClientRequests() = default;
// Request the player join session
// @param sessionConnectionConfig The required properties to handle the player join session process
// @return The result of player join session process
//! Request the player join session
//! @param sessionConnectionConfig The required properties to handle the player join session process
//! @return The result of player join session process
virtual bool RequestPlayerJoinSession(const SessionConnectionConfig& sessionConnectionConfig) = 0;
// Request the connected player leave session
//! Request the connected player leave session
virtual void RequestPlayerLeaveSession() = 0;
};
@@ -69,26 +69,26 @@ namespace AzFramework
ISessionHandlingProviderRequests() = default;
virtual ~ISessionHandlingProviderRequests() = default;
// Handle the destroy session process
//! Handle the destroy session process
virtual void HandleDestroySession() = 0;
// Validate the player join session process
// @param playerConnectionConfig The required properties to validate the player join session process
// @return The result of player join session validation
//! Validate the player join session process
//! @param playerConnectionConfig The required properties to validate the player join session process
//! @return The result of player join session validation
virtual bool ValidatePlayerJoinSession(const PlayerConnectionConfig& playerConnectionConfig) = 0;
// Handle the player leave session process
// @param playerConnectionConfig The required properties to handle the player leave session process
//! Handle the player leave session process
//! @param playerConnectionConfig The required properties to handle the player leave session process
virtual void HandlePlayerLeaveSession(const PlayerConnectionConfig& playerConnectionConfig) = 0;
// Retrieves the file location of a pem-encoded TLS certificate for Client to Server communication
// @return If successful, returns the file location of TLS certificate file; if not successful, returns
// empty string.
//! Retrieves the file location of a pem-encoded TLS certificate for Client to Server communication
//! @return If successful, returns the file location of TLS certificate file; if not successful, returns
//! empty string.
virtual AZ::IO::Path GetExternalSessionCertificate() = 0;
// Retrieves the file location of a pem-encoded TLS certificate for Server to Server communication
// @return If successful, returns the file location of TLS certificate file; if not successful, returns
// empty string.
//! Retrieves the file location of a pem-encoded TLS certificate for Server to Server communication
//! @return If successful, returns the file location of TLS certificate file; if not successful, returns
//! empty string.
virtual AZ::IO::Path GetInternalSessionCertificate() = 0;
};
} // namespace AzFramework
@@ -25,22 +25,22 @@ namespace AzFramework
ISessionRequests() = default;
virtual ~ISessionRequests() = default;
// Create a session for players to find and join.
// @param createSessionRequest The request of CreateSession operation
// @return The request id if session creation request succeeds; empty if it fails
//! Create a session for players to find and join.
//! @param createSessionRequest The request of CreateSession operation
//! @return The request id if session creation request succeeds; empty if it fails
virtual AZStd::string CreateSession(const CreateSessionRequest& createSessionRequest) = 0;
// Retrieve all active sessions that match the given search criteria and sorted in specific order.
// @param searchSessionsRequest The request of SearchSessions operation
// @return The response of SearchSessions operation
//! Retrieve all active sessions that match the given search criteria and sorted in specific order.
//! @param searchSessionsRequest The request of SearchSessions operation
//! @return The response of SearchSessions operation
virtual SearchSessionsResponse SearchSessions(const SearchSessionsRequest& searchSessionsRequest) const = 0;
// Reserve an open player slot in a session, and perform connection from client to server.
// @param joinSessionRequest The request of JoinSession operation
// @return True if joining session succeeds; False otherwise
//! Reserve an open player slot in a session, and perform connection from client to server.
//! @param joinSessionRequest The request of JoinSession operation
//! @return True if joining session succeeds; False otherwise
virtual bool JoinSession(const JoinSessionRequest& joinSessionRequest) = 0;
// Disconnect player from session.
//! Disconnect player from session.
virtual void LeaveSession() = 0;
};
@@ -54,19 +54,19 @@ namespace AzFramework
ISessionAsyncRequests() = default;
virtual ~ISessionAsyncRequests() = default;
// CreateSession Async
// @param createSessionRequest The request of CreateSession operation
//! CreateSession Async
//! @param createSessionRequest The request of CreateSession operation
virtual void CreateSessionAsync(const CreateSessionRequest& createSessionRequest) = 0;
// SearchSessions Async
// @param searchSessionsRequest The request of SearchSessions operation
//! SearchSessions Async
//! @param searchSessionsRequest The request of SearchSessions operation
virtual void SearchSessionsAsync(const SearchSessionsRequest& searchSessionsRequest) const = 0;
// JoinSession Async
// @param joinSessionRequest The request of JoinSession operation
//! JoinSession Async
//! @param joinSessionRequest The request of JoinSession operation
virtual void JoinSessionAsync(const JoinSessionRequest& joinSessionRequest) = 0;
// LeaveSession Async
//! LeaveSession Async
virtual void LeaveSessionAsync() = 0;
};
@@ -85,19 +85,19 @@ namespace AzFramework
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
// OnCreateSessionAsyncComplete is fired once CreateSessionAsync completes
// @param createSessionResponse The request id if session creation request succeeds; empty if it fails
//! OnCreateSessionAsyncComplete is fired once CreateSessionAsync completes
//! @param createSessionResponse The request id if session creation request succeeds; empty if it fails
virtual void OnCreateSessionAsyncComplete(const AZStd::string& createSessionReponse) = 0;
// OnSearchSessionsAsyncComplete is fired once SearchSessionsAsync completes
// @param searchSessionsResponse The response of SearchSessions call
//! OnSearchSessionsAsyncComplete is fired once SearchSessionsAsync completes
//! @param searchSessionsResponse The response of SearchSessions call
virtual void OnSearchSessionsAsyncComplete(const SearchSessionsResponse& searchSessionsResponse) = 0;
// OnJoinSessionAsyncComplete is fired once JoinSessionAsync completes
// @param joinSessionsResponse True if joining session succeeds; False otherwise
//! OnJoinSessionAsyncComplete is fired once JoinSessionAsync completes
//! @param joinSessionsResponse True if joining session succeeds; False otherwise
virtual void OnJoinSessionAsyncComplete(bool joinSessionsResponse) = 0;
// OnLeaveSessionAsyncComplete is fired once LeaveSessionAsync completes
//! OnLeaveSessionAsyncComplete is fired once LeaveSessionAsync completes
virtual void OnLeaveSessionAsyncComplete() = 0;
};
using SessionAsyncRequestNotificationBus = AZ::EBus<SessionAsyncRequestNotifications>;
@@ -24,46 +24,46 @@ namespace AzFramework
SessionConfig() = default;
virtual ~SessionConfig() = default;
// A time stamp indicating when this session was created. Format is a number expressed in Unix time as milliseconds.
//! A time stamp indicating when this session was created. Format is a number expressed in Unix time as milliseconds.
uint64_t m_creationTime = 0;
// A time stamp indicating when this data object was terminated. Same format as creation time.
//! A time stamp indicating when this data object was terminated. Same format as creation time.
uint64_t m_terminationTime = 0;
// A unique identifier for a player or entity creating the session.
//! A unique identifier for a player or entity creating the session.
AZStd::string m_creatorId;
// A collection of custom properties for a session.
//! A collection of custom properties for a session.
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
// The matchmaking process information that was used to create the session.
//! The matchmaking process information that was used to create the session.
AZStd::string m_matchmakingData;
// A unique identifier for the session.
//! A unique identifier for the session.
AZStd::string m_sessionId;
// A descriptive label that is associated with a session.
//! A descriptive label that is associated with a session.
AZStd::string m_sessionName;
// The DNS identifier assigned to the instance that is running the session.
//! The DNS identifier assigned to the instance that is running the session.
AZStd::string m_dnsName;
// The IP address of the session.
//! The IP address of the session.
AZStd::string m_ipAddress;
// The port number for the session.
//! The port number for the session.
uint16_t m_port = 0;
// The maximum number of players that can be connected simultaneously to the session.
//! The maximum number of players that can be connected simultaneously to the session.
uint64_t m_maxPlayer = 0;
// Number of players currently in the session.
//! Number of players currently in the session.
uint64_t m_currentPlayer = 0;
// Current status of the session.
//! Current status of the session.
AZStd::string m_status;
// Provides additional information about session status.
//! Provides additional information about session status.
AZStd::string m_statusReason;
};
} // namespace AzFramework
@@ -29,42 +29,42 @@ namespace AzFramework
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
// OnSessionHealthCheck is fired in health check process
// Use this notification to perform any custom health check
// @return True if OnSessionHealthCheck succeeds, false otherwise
//! OnSessionHealthCheck is fired in health check process
//! Use this notification to perform any custom health check
//! @return True if OnSessionHealthCheck succeeds, false otherwise
virtual bool OnSessionHealthCheck() = 0;
// OnCreateSessionBegin is fired at the beginning of session creation process
// Use this notification to perform any necessary configuration or initialization before
// creating session
// @param sessionConfig The properties to describe a session
// @return True if OnCreateSessionBegin succeeds, false otherwise
//! OnCreateSessionBegin is fired at the beginning of session creation process
//! Use this notification to perform any necessary configuration or initialization before
//! creating session
//! @param sessionConfig The properties to describe a session
//! @return True if OnCreateSessionBegin succeeds, false otherwise
virtual bool OnCreateSessionBegin(const SessionConfig& sessionConfig) = 0;
// OnCreateSessionEnd is fired at the end of session creation process
// Use this notification to perform any follow-up operation after session is created and active
//! OnCreateSessionEnd is fired at the end of session creation process
//! Use this notification to perform any follow-up operation after session is created and active
virtual void OnCreateSessionEnd() = 0;
// OnDestroySessionBegin is fired at the beginning of session termination process
// Use this notification to perform any cleanup operation before destroying session,
// like gracefully disconnect players, cleanup data, etc.
// @return True if OnDestroySessionBegin succeeds, false otherwise
//! OnDestroySessionBegin is fired at the beginning of session termination process
//! Use this notification to perform any cleanup operation before destroying session,
//! like gracefully disconnect players, cleanup data, etc.
//! @return True if OnDestroySessionBegin succeeds, false otherwise
virtual bool OnDestroySessionBegin() = 0;
// OnDestroySessionEnd is fired at the end of session termination process
// Use this notification to perform any follow-up operation after session is destroyed,
// like shutdown application process, etc.
//! OnDestroySessionEnd is fired at the end of session termination process
//! Use this notification to perform any follow-up operation after session is destroyed,
//! like shutdown application process, etc.
virtual void OnDestroySessionEnd() = 0;
// OnUpdateSessionBegin is fired at the beginning of session update process
// Use this notification to perform any configuration or initialization to handle
// the session settings changing
// @param sessionConfig The properties to describe a session
// @param updateReason The reason for session update
//! OnUpdateSessionBegin is fired at the beginning of session update process
//! Use this notification to perform any configuration or initialization to handle
//! the session settings changing
//! @param sessionConfig The properties to describe a session
//! @param updateReason The reason for session update
virtual void OnUpdateSessionBegin(const SessionConfig& sessionConfig, const AZStd::string& updateReason) = 0;
// OnUpdateSessionBegin is fired at the end of session update process
// Use this notification to perform any follow-up operations after session is updated
//! OnUpdateSessionBegin is fired at the end of session update process
//! Use this notification to perform any follow-up operations after session is updated
virtual void OnUpdateSessionEnd() = 0;
};
using SessionNotificationBus = AZ::EBus<SessionNotifications>;
@@ -31,16 +31,16 @@ namespace AzFramework
CreateSessionRequest() = default;
virtual ~CreateSessionRequest() = default;
// A unique identifier for a player or entity creating the session.
//! A unique identifier for a player or entity creating the session.
AZStd::string m_creatorId;
// A collection of custom properties for a session.
//! A collection of custom properties for a session.
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
// A descriptive label that is associated with a session.
//! A descriptive label that is associated with a session.
AZStd::string m_sessionName;
// The maximum number of players that can be connected simultaneously to the session.
//! The maximum number of players that can be connected simultaneously to the session.
uint64_t m_maxPlayer = 0;
};
@@ -54,17 +54,17 @@ namespace AzFramework
SearchSessionsRequest() = default;
virtual ~SearchSessionsRequest() = default;
// String containing the search criteria for the session search. If no filter expression is included, the request returns results
// for all active sessions.
//! String containing the search criteria for the session search. If no filter expression is included, the request returns results
//! for all active sessions.
AZStd::string m_filterExpression;
// Instructions on how to sort the search results. If no sort expression is included, the request returns results in random order.
//! Instructions on how to sort the search results. If no sort expression is included, the request returns results in random order.
AZStd::string m_sortExpression;
// The maximum number of results to return.
//! The maximum number of results to return.
uint8_t m_maxResult = 0;
// A token that indicates the start of the next sequential page of results.
//! A token that indicates the start of the next sequential page of results.
AZStd::string m_nextToken;
};
@@ -78,10 +78,10 @@ namespace AzFramework
SearchSessionsResponse() = default;
virtual ~SearchSessionsResponse() = default;
// A collection of sessions that match the search criteria and sorted in specific order.
//! A collection of sessions that match the search criteria and sorted in specific order.
AZStd::vector<SessionConfig> m_sessionConfigs;
// A token that indicates the start of the next sequential page of results.
//! A token that indicates the start of the next sequential page of results.
AZStd::string m_nextToken;
};
@@ -95,13 +95,13 @@ namespace AzFramework
JoinSessionRequest() = default;
virtual ~JoinSessionRequest() = default;
// A unique identifier for the session.
//! A unique identifier for the session.
AZStd::string m_sessionId;
// A unique identifier for a player. Player IDs are developer-defined.
//! A unique identifier for a player. Player IDs are developer-defined.
AZStd::string m_playerId;
// Developer-defined information related to a player.
//! Developer-defined information related to a player.
AZStd::string m_playerData;
};
} // namespace AzFramework
@@ -82,7 +82,7 @@ namespace AzGameFramework
// Used the lowercase the platform name since the bootstrap.game.<config>.<platform>.setreg is being loaded
// from the asset cache root where all the files are in lowercased from regardless of the filesystem case-sensitivity
static constexpr char filename[] = "bootstrap.game." AZ_BUILD_CONFIGURATION_TYPE "." AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER ".setreg";
static constexpr char filename[] = "bootstrap.game." AZ_BUILD_CONFIGURATION_TYPE ".setreg";
AZ::IO::FixedMaxPath cacheRootPath;
if (registry.Get(cacheRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
@@ -1387,7 +1387,10 @@ namespace AzToolsFramework
QDataStream stream(&pixmapBytes, QIODevice::ReadOnly);
QPixmap pixmap;
stream >> pixmap;
GUI->SetBrowseButtonIcon(pixmap);
if (!pixmap.isNull())
{
GUI->SetBrowseButtonIcon(pixmap);
}
}
}
}
@@ -1417,6 +1420,8 @@ namespace AzToolsFramework
}
else if (attrib == AZ_CRC_CE("ThumbnailIcon"))
{
GUI->SetCustomThumbnailEnabled(false);
AZStd::string iconPath;
if (attrValue->Read<AZStd::string>(iconPath) && !iconPath.empty())
{
@@ -1434,8 +1439,11 @@ namespace AzToolsFramework
QDataStream stream(&pixmapBytes, QIODevice::ReadOnly);
QPixmap pixmap;
stream >> pixmap;
GUI->SetCustomThumbnailEnabled(true);
GUI->SetCustomThumbnailPixmap(pixmap);
if (!pixmap.isNull())
{
GUI->SetCustomThumbnailEnabled(true);
GUI->SetCustomThumbnailPixmap(pixmap);
}
}
}
}
@@ -67,16 +67,9 @@ namespace AzToolsFramework
void ThumbnailPropertyCtrl::SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName)
{
if (m_customThumbnailEnabled)
{
ClearThumbnail();
}
else
{
m_key = key;
m_thumbnail->SetThumbnailKey(m_key, contextName);
m_thumbnailEnlarged->SetThumbnailKey(m_key, contextName);
}
m_key = key;
m_thumbnail->SetThumbnailKey(m_key, contextName);
m_thumbnailEnlarged->SetThumbnailKey(m_key, contextName);
UpdateVisibility();
}
@@ -301,6 +301,7 @@ namespace AzToolsFramework::ViewportUi::Internal
HighlightBorderSize + ViewportUiOverlayMargin, HighlightBorderSize + ViewportUiOverlayMargin);
m_componentModeBorderText.setVisible(true);
m_componentModeBorderText.setText(borderTitle.c_str());
UpdateUiOverlayGeometry();
}
void ViewportUiDisplay::RemoveViewportBorder()
@@ -60,13 +60,6 @@
#include <platform.h>
#if defined(WIN32) || defined(WIN64) || defined(APPLE) || defined(LINUX)
#if defined(DEDICATED_SERVER)
// enable/disable map load slicing functionality from the build
#define MAP_LOADING_SLICING
#endif
#endif
#ifdef WIN32
#include <AzCore/PlatformIncl.h>
#include <tlhelp32.h>
@@ -115,17 +115,20 @@ CViewSystem::CViewSystem(ISystem* pSystem)
, m_useDeferredViewSystemUpdate(false)
, m_bControlsAudioListeners(true)
{
#if !defined(_RELEASE) && !defined(DEDICATED_SERVER)
if (!s_debugCamera)
#if !defined(_RELEASE)
if (!gEnv->IsDedicated())
{
s_debugCamera = new DebugCamera;
}
if (!s_debugCamera)
{
s_debugCamera = new DebugCamera;
}
REGISTER_COMMAND("debugCameraToggle", ToggleDebugCamera, VF_DEV_ONLY, "Toggle the debug camera.\n");
REGISTER_COMMAND("debugCameraInvertY", ToggleDebugCameraInvertY, VF_DEV_ONLY, "Toggle debug camera Y-axis inversion.\n");
REGISTER_COMMAND("debugCameraMove", DebugCameraMove, VF_DEV_ONLY, "Move the debug camera the specified distance (x y z).\n");
gEnv->pConsole->CreateKeyBind("ctrl_keyboard_key_punctuation_backslash", "debugCameraToggle");
gEnv->pConsole->CreateKeyBind("alt_keyboard_key_punctuation_backslash", "debugCameraInvertY");
REGISTER_COMMAND("debugCameraToggle", ToggleDebugCamera, VF_DEV_ONLY, "Toggle the debug camera.\n");
REGISTER_COMMAND("debugCameraInvertY", ToggleDebugCameraInvertY, VF_DEV_ONLY, "Toggle debug camera Y-axis inversion.\n");
REGISTER_COMMAND("debugCameraMove", DebugCameraMove, VF_DEV_ONLY, "Move the debug camera the specified distance (x y z).\n");
gEnv->pConsole->CreateKeyBind("ctrl_keyboard_key_punctuation_backslash", "debugCameraToggle");
gEnv->pConsole->CreateKeyBind("alt_keyboard_key_punctuation_backslash", "debugCameraInvertY");
}
#endif
REGISTER_CVAR2("cl_camera_noise", &m_fCameraNoise, -1, 0,
@@ -167,6 +170,21 @@ CViewSystem::~CViewSystem()
{
m_pSystem->GetILevelSystem()->RemoveListener(this);
}
#if !defined(_RELEASE)
if (!gEnv->IsDedicated())
{
UNREGISTER_COMMAND("debugCameraToggle");
UNREGISTER_COMMAND("debugCameraInvertY");
UNREGISTER_COMMAND("debugCameraMove");
if (s_debugCamera)
{
delete s_debugCamera;
s_debugCamera = nullptr;
}
}
#endif
}
//------------------------------------------------------------------------
+8
View File
@@ -47,6 +47,10 @@ ly_add_target(
AZ::AssetBundlerBatch.Static
)
# Adds a specialized .setreg to identify gems enabled in the active project.
# This associates the AssetBundlerBatch target with the .Builders gem variants.
ly_set_gem_variant_to_load(TARGETS AssetBundlerBatch VARIANTS Builders)
# AssetBundler - Qt GUI Application
ly_add_target(
NAME AssetBundler ${PAL_TRAIT_BUILD_ASSETBUNDLER_APPLICATION_TYPE}
@@ -73,6 +77,10 @@ ly_add_target(
${additional_dependencies}
)
# Adds a specialized .setreg to identify gems enabled in the active project.
# This associates the AssetBundler target with the .Builders gem variants.
ly_set_gem_variant_to_load(TARGETS AssetBundler VARIANTS Builders)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_target(
@@ -54,7 +54,12 @@ namespace AssetBundler
bool ApplicationManager::Init()
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
Start(AzFramework::Application::Descriptor());
ComponentApplication::StartupParameters startupParameters;
// The AssetBundler does not need to load gems
startupParameters.m_loadDynamicModules = false;
Start(AzFramework::Application::Descriptor(), startupParameters);
AZ::SerializeContext* context;
EBUS_EVENT_RESULT(context, AZ::ComponentApplicationBus, GetSerializeContext);
AZ_Assert(context, "No serialize context");
@@ -71,7 +71,11 @@ namespace AssetBundler
m_data->m_applicationManager.reset(aznew MockApplicationManagerTest(0, 0));
m_data->m_applicationManager->Start(AzFramework::Application::Descriptor());
AZ::ComponentApplication::StartupParameters startupParameters;
// The AssetBundler does not need to load gems
startupParameters.m_loadDynamicModules = false;
m_data->m_applicationManager->Start(AzFramework::Application::Descriptor(), startupParameters);
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
@@ -259,6 +259,11 @@ namespace AssetProcessor
scratchBuffer.reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
AZStd::fixed_vector<AZStd::string_view, AzFramework::MaxPlatformCodeNames> platformCodes;
AzFramework::PlatformHelper::AppendPlatformCodeNames(platformCodes, request.m_platformInfo.m_identifier);
AZ_Assert(platformCodes.size() <= 1, "A one-to-one mapping of asset type platform identifier"
" to platform codename is required in the SettingsRegistryBuilder."
" The bootstrap.game is now only produced per build configuration and doesn't take into account"
" different platforms names");
const AZStd::string& assetPlatformIdentifier = request.m_jobDescription.GetPlatformIdentifier();
// Determines the suffix that will be used for the launcher based on processing server vs non-server assets
const char* launcherType = assetPlatformIdentifier != AzFramework::PlatformHelper::GetPlatformName(AzFramework::PlatformId::SERVER)
@@ -293,9 +298,10 @@ namespace AssetProcessor
outputBuffer.Reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
SettingsExporter exporter(outputBuffer, excludes);
for (AZStd::string_view platform : platformCodes)
if (!platformCodes.empty())
{
AZ::u32 productSubID = static_cast<AZ::u32>(AZStd::hash<AZStd::string_view>{}(platform)); // Deliberately ignoring half the bits.
AZStd::string_view platform = platformCodes.front();
constexpr AZ::u32 productSubID = 0;
for (size_t i = 0; i < AZStd::size(specializations); ++i)
{
const AZ::SettingsRegistryInterface::Specializations& specialization = specializations[i];
@@ -337,7 +343,7 @@ namespace AssetProcessor
// The purpose of this section is to copy the Gem's SourcePaths from the Global Settings Registry
// the local SettingsRegistry. The reason this is needed is so that the call to
// `MergeSettingsToRegistry_GemRegistries` below is able to locate each gem's "<gem-root>/Registry" folder
// that will be merged into the bootstrap.game.<configuration>.<platform>.setreg file
// that will be merged into the bootstrap.game.<configuration>.setreg file
// This is used by the GameLauncher applications to read from a single merged .setreg file
// containing the settings needed to run a game/simulation without have access to the source code base registry
AZStd::vector<AzFramework::GemInfo> gemInfos;
@@ -408,8 +414,6 @@ namespace AssetProcessor
}
outputPath += specialization.GetSpecialization(0); // Append configuration
outputPath += '.';
outputPath += platform;
outputPath += ".setreg";
AZ::IO::SystemFile file;
@@ -25,7 +25,7 @@ namespace AssetProcessor
: public ::testing::Test
{
protected:
UnitTestUtils::AssertAbsorber* m_errorAbsorber;
AZStd::unique_ptr<UnitTestUtils::AssertAbsorber> m_errorAbsorber{};
FileStatePassthrough m_fileStateCache;
void SetUp() override
@@ -40,7 +40,7 @@ namespace AssetProcessor
m_ownsSysAllocator = true;
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
}
m_errorAbsorber = new UnitTestUtils::AssertAbsorber();
m_errorAbsorber = AZStd::make_unique<UnitTestUtils::AssertAbsorber>();
m_application = AZStd::make_unique<AzFramework::Application>();
@@ -60,8 +60,8 @@ namespace AssetProcessor
AssetUtilities::ResetAssetRoot();
m_application.reset();
delete m_errorAbsorber;
m_errorAbsorber = nullptr;
m_errorAbsorber.reset();
if (m_ownsSysAllocator)
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
@@ -4447,7 +4447,9 @@ AssetBuilderSDK::AssetBuilderDesc MockBuilderInfoHandler::CreateBuilderDesc(cons
void FingerprintTest::SetUp()
{
AZ_Printf("FingerprintTest", "SetUp start");
AssetProcessorManagerTest::SetUp();
AZ_Printf("FingerprintTest", "SetUp self");
// We don't want the mock application manager to provide builder descriptors, mockBuilderInfoHandler will provide our own
m_mockApplicationManager->BusDisconnect();
@@ -4466,18 +4468,23 @@ void FingerprintTest::SetUp()
});
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(m_absolutePath, ""));
AZ_Printf("FingerprintTest", "SetUp end");
}
void FingerprintTest::TearDown()
{
AZ_Printf("FingerprintTest", "TearDown start");
m_jobResults = AZStd::vector<AssetProcessor::JobDetails>{};
m_mockBuilderInfoHandler = {};
AZ_Printf("FingerprintTest", "TearDown parent");
AssetProcessorManagerTest::TearDown();
AZ_Printf("FingerprintTest", "TearDown end");
}
void FingerprintTest::RunFingerprintTest(QString builderFingerprint, QString jobFingerprint, bool expectedResult)
{
AZ_Printf("FingerprintTest", "Fingerprint Test Start");
m_mockBuilderInfoHandler.m_builderDesc.m_analysisFingerprint = builderFingerprint.toUtf8().data();
m_mockBuilderInfoHandler.m_jobFingerprint = jobFingerprint;
QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, m_absolutePath));
@@ -4486,6 +4493,7 @@ void FingerprintTest::RunFingerprintTest(QString builderFingerprint, QString job
ASSERT_EQ(m_mockBuilderInfoHandler.m_createJobsCount, 1);
ASSERT_EQ(m_jobResults.size(), 1);
ASSERT_EQ(m_jobResults[0].m_autoFail, expectedResult);
AZ_Printf("FingerprintTest", "Fingerprint Test End");
}
TEST_F(FingerprintTest, FingerprintChecking_JobFingerprint_NoBuilderFingerprint)
@@ -21,6 +21,7 @@
#endif
#include <gtest/gtest.h>
#include <AzCore/UnitTest/UnitTest.h>
//! These macros can be used for checking your unit tests,
//! you can check AssetScannerUnitTest.cpp for usage
@@ -155,6 +156,7 @@ namespace UnitTestUtils
bool OnPreWarning([[maybe_unused]] const char* window, [[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) override
{
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
++m_numWarningsAbsorbed;
if (m_debugMessages)
{
@@ -165,6 +167,7 @@ namespace UnitTestUtils
bool OnPreAssert([[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) override
{
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
++m_numAssertsAbsorbed;
if (m_debugMessages)
{
@@ -175,6 +178,7 @@ namespace UnitTestUtils
bool OnPreError([[maybe_unused]] const char* window, [[maybe_unused]] const char* fileName, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* message) override
{
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
++m_numErrorsAbsorbed;
if (m_debugMessages)
{
@@ -183,8 +187,9 @@ namespace UnitTestUtils
return true; // I handled this, do not forward it
}
bool OnPrintf(const char* /*window*/, const char* /*message*/) override
bool OnPrintf(const char* /*window*/, const char* message) override
{
UnitTest::ColoredPrintf(UnitTest::COLOR_YELLOW, message);
++m_numMessagesAbsorbed;
return true;
}
@@ -21,8 +21,7 @@ namespace O3DE::ProjectManager
return AZ::Success(QStringList{ ProjectCMakeCommand,
"-B", targetBuildPath,
"-S", m_projectInfo.m_path,
QString("-DLY_3RDPARTY_PATH=").append(thirdPartyPath),
"-DLY_UNITY_BUILD=ON" } );
QString("-DLY_3RDPARTY_PATH=").append(thirdPartyPath) } );
}
AZ::Outcome<QStringList, QString> ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const
@@ -242,11 +242,15 @@ QTabBar::tab:focus {
/************** Project Settings **************/
#projectSettings {
margin-top:42px;
margin-top:30px;
}
#projectPreviewLabel {
margin: 10px 0 5px 0;
}
#projectTemplate {
margin: 55px 0 0 50px;
margin: 25px 0 0 50px;
}
#projectTemplateLabel {
font-size:16px;
@@ -11,19 +11,28 @@
#include <FormFolderBrowseEditWidget.h>
#include <PythonBindingsInterface.h>
#include <PathValidator.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QScrollArea>
namespace O3DE::ProjectManager
{
EngineSettingsScreen::EngineSettingsScreen(QWidget* parent)
: ScreenWidget(parent)
{
auto* layout = new QVBoxLayout();
QScrollArea* scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
QWidget* scrollWidget = new QWidget(this);
scrollArea->setWidget(scrollWidget);
QVBoxLayout* layout = new QVBoxLayout(scrollWidget);
layout->setAlignment(Qt::AlignTop);
scrollWidget->setLayout(layout);
setObjectName("engineSettingsScreen");
@@ -39,9 +48,18 @@ namespace O3DE::ProjectManager
formTitleLabel->setObjectName("formTitleLabel");
layout->addWidget(formTitleLabel);
m_engineVersion = new FormLineEditWidget(tr("Engine Version"), engineInfo.m_version, this);
m_engineVersion->lineEdit()->setReadOnly(true);
layout->addWidget(m_engineVersion);
FormLineEditWidget* engineName = new FormLineEditWidget(tr("Engine Name"), engineInfo.m_name, this);
engineName->lineEdit()->setReadOnly(true);
layout->addWidget(engineName);
FormLineEditWidget* engineVersion = new FormLineEditWidget(tr("Engine Version"), engineInfo.m_version, this);
engineVersion->lineEdit()->setReadOnly(true);
layout->addWidget(engineVersion);
FormBrowseEditWidget* engineFolder = new FormBrowseEditWidget(tr("Engine Folder"), engineInfo.m_path, this);
engineFolder->lineEdit()->setReadOnly(true);
connect( engineFolder, &FormBrowseEditWidget::OnBrowse, [engineInfo]{ AzQtComponents::ShowFileOnDesktop(engineInfo.m_path); });
layout->addWidget(engineFolder);
m_thirdParty = new FormFolderBrowseEditWidget(tr("3rd Party Software Folder"), engineInfo.m_thirdPartyPath, this);
m_thirdParty->lineEdit()->setValidator(new PathValidator(PathValidator::PathMode::ExistingFolder, this));
@@ -71,7 +89,11 @@ namespace O3DE::ProjectManager
connect(m_defaultProjectTemplates->lineEdit(), &QLineEdit::textChanged, this, &EngineSettingsScreen::OnTextChanged);
layout->addWidget(m_defaultProjectTemplates);
setLayout(layout);
QVBoxLayout* mainLayout = new QVBoxLayout();
mainLayout->setAlignment(Qt::AlignTop);
mainLayout->setMargin(0);
mainLayout->addWidget(scrollArea);
setLayout(mainLayout);
}
ProjectManagerScreen EngineSettingsScreen::GetScreenEnum()
@@ -29,7 +29,6 @@ namespace O3DE::ProjectManager
void OnTextChanged();
private:
FormLineEditWidget* m_engineVersion;
FormBrowseEditWidget* m_thirdParty;
FormBrowseEditWidget* m_defaultProjects;
FormBrowseEditWidget* m_defaultGems;
@@ -20,7 +20,8 @@ namespace O3DE::ProjectManager
setObjectName("formBrowseEditWidget");
QPushButton* browseButton = new QPushButton(this);
connect(browseButton, &QPushButton::pressed, this, &FormBrowseEditWidget::HandleBrowseButton);
connect( browseButton, &QPushButton::pressed, [this]{ emit OnBrowse(); });
connect( this, &FormBrowseEditWidget::OnBrowse, this, &FormBrowseEditWidget::HandleBrowseButton);
m_frameLayout->addWidget(browseButton);
}
@@ -34,7 +35,7 @@ namespace O3DE::ProjectManager
int key = event->key();
if (key == Qt::Key_Return || key == Qt::Key_Enter)
{
HandleBrowseButton();
emit OnBrowse();
}
}
@@ -24,10 +24,13 @@ namespace O3DE::ProjectManager
explicit FormBrowseEditWidget(const QString& labelText = "", QWidget* parent = nullptr);
~FormBrowseEditWidget() = default;
signals:
void OnBrowse();
protected:
void keyPressEvent(QKeyEvent* event) override;
protected slots:
virtual void HandleBrowseButton() = 0;
virtual void HandleBrowseButton() {};
};
} // namespace O3DE::ProjectManager
@@ -80,7 +80,7 @@ namespace O3DE::ProjectManager
void GemCatalogScreen::ReinitForProject(const QString& projectPath)
{
m_gemModel->clear();
m_gemModel->Clear();
m_gemsToRegisterWithProject.clear();
FillModel(projectPath);
@@ -145,10 +145,11 @@ namespace O3DE::ProjectManager
}
}
void GemCatalogScreen::OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies)
void GemCatalogScreen::OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies)
{
if (m_notificationsEnabled)
{
QModelIndex modelIndex = m_gemModel->FindIndexByNameString(gemName);
bool added = GemModel::IsAdded(modelIndex);
bool dependency = GemModel::IsAddedDependency(modelIndex);
@@ -233,7 +234,11 @@ namespace O3DE::ProjectManager
const QVector<GemInfo> allRepoGemInfos = allRepoGemInfosResult.GetValue();
for (const GemInfo& gemInfo : allRepoGemInfos)
{
m_gemModel->AddGem(gemInfo);
// do not add gems that have already been downloaded
if (!m_gemModel->FindIndexByNameString(gemInfo.m_name).isValid())
{
m_gemModel->AddGem(gemInfo);
}
}
}
else
@@ -257,7 +262,8 @@ namespace O3DE::ProjectManager
GemModel::SetWasPreviouslyAdded(*m_gemModel, modelIndex, true);
GemModel::SetIsAdded(*m_gemModel, modelIndex, true);
}
else
// ${Name} is a special name used in templates and is not really an error
else if (enabledGemName != "${Name}")
{
AZ_Warning("ProjectManager::GemCatalog", false,
"Cannot find entry for gem with name '%s'. The CMake target name probably does not match the specified name in the gem.json.",
@@ -46,7 +46,7 @@ namespace O3DE::ProjectManager
DownloadController* GetDownloadController() const { return m_downloadController; }
public slots:
void OnGemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies);
void OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies);
void OnAddGemClicked();
protected:
@@ -27,6 +27,14 @@ namespace O3DE::ProjectManager
void GemModel::AddGem(const GemInfo& gemInfo)
{
if (FindIndexByNameString(gemInfo.m_name).isValid())
{
// do not add gems with duplicate names
// this can happen by mistake or when a gem repo has a gem with the same name as a local gem
AZ_TracePrintf("GemModel", "Ignoring duplicate gem: %s", gemInfo.m_name.toUtf8().constData());
return;
}
QStandardItem* item = new QStandardItem();
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
@@ -60,6 +68,7 @@ namespace O3DE::ProjectManager
void GemModel::Clear()
{
clear();
m_nameToIndexMap.clear();
}
void GemModel::UpdateGemDependencies()
@@ -276,9 +285,11 @@ namespace O3DE::ProjectManager
void GemModel::SetIsAdded(QAbstractItemModel& model, const QModelIndex& modelIndex, bool isAdded)
{
// get the gemName first, because the modelIndex data change after adding because of filters
QString gemName = modelIndex.data(RoleName).toString();
model.setData(modelIndex, isAdded, RoleIsAdded);
UpdateDependencies(model, modelIndex);
UpdateDependencies(model, gemName, isAdded);
}
bool GemModel::HasDependentGems(const QModelIndex& modelIndex) const
@@ -294,15 +305,17 @@ namespace O3DE::ProjectManager
return false;
}
void GemModel::UpdateDependencies(QAbstractItemModel& model, const QModelIndex& modelIndex)
void GemModel::UpdateDependencies(QAbstractItemModel& model, const QString& gemName, bool isAdded)
{
GemModel* gemModel = GetSourceModel(&model);
AZ_Assert(gemModel, "Failed to obtain GemModel");
QModelIndex modelIndex = gemModel->FindIndexByNameString(gemName);
QVector<QModelIndex> dependencies = gemModel->GatherGemDependencies(modelIndex);
uint32_t numChangedDependencies = 0;
if (IsAdded(modelIndex))
if (isAdded)
{
for (const QModelIndex& dependency : dependencies)
{
@@ -324,7 +337,7 @@ namespace O3DE::ProjectManager
bool hasDependentGems = gemModel->HasDependentGems(modelIndex);
if (IsAddedDependency(modelIndex) != hasDependentGems)
{
SetIsAddedDependency(model, modelIndex, hasDependentGems);
SetIsAddedDependency(*gemModel, modelIndex, hasDependentGems);
}
for (const QModelIndex& dependency : dependencies)
@@ -343,7 +356,7 @@ namespace O3DE::ProjectManager
}
}
gemModel->emit gemStatusChanged(modelIndex, numChangedDependencies);
gemModel->emit gemStatusChanged(gemName, numChangedDependencies);
}
void GemModel::SetIsAddedDependency(QAbstractItemModel& model, const QModelIndex& modelIndex, bool isAdded)
@@ -64,7 +64,7 @@ namespace O3DE::ProjectManager
static bool NeedsToBeAdded(const QModelIndex& modelIndex, bool includeDependencies = false);
static bool NeedsToBeRemoved(const QModelIndex& modelIndex, bool includeDependencies = false);
static bool HasRequirement(const QModelIndex& modelIndex);
static void UpdateDependencies(QAbstractItemModel& model, const QModelIndex& modelIndex);
static void UpdateDependencies(QAbstractItemModel& model, const QString& gemName, bool isAdded);
static void SetDownloadStatus(QAbstractItemModel& model, const QModelIndex& modelIndex, GemInfo::DownloadStatus status);
bool DoGemsToBeAddedHaveRequirements() const;
@@ -78,7 +78,7 @@ namespace O3DE::ProjectManager
int TotalAddedGems(bool includeDependencies = false) const;
signals:
void gemStatusChanged(const QModelIndex& modelIndex, uint32_t numChangedDependencies);
void gemStatusChanged(const QString& gemName, uint32_t numChangedDependencies);
private:
void FindGemDisplayNamesByNameStrings(QStringList& inOutGemNames);
@@ -36,6 +36,7 @@ namespace O3DE::ProjectManager
QLabel* projectPreviewLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.")
.arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight)));
projectPreviewLabel->setObjectName("projectPreviewLabel");
previewExtrasLayout->addWidget(projectPreviewLabel);
m_projectPreviewImage = new QLabel(this);
@@ -25,11 +25,11 @@ namespace AWSGameLift
AWSGameLiftCreateSessionOnQueueRequest() = default;
virtual ~AWSGameLiftCreateSessionOnQueueRequest() = default;
// Name of the queue to use to place the new game session. You can use either the queue name or ARN value.
//! Name of the queue to use to place the new game session. You can use either the queue name or ARN value.
AZStd::string m_queueName;
// A unique identifier to assign to the new game session placement. This value is developer-defined.
// The value must be unique across all Regions and cannot be reused unless you are resubmitting a canceled or timed-out placement request.
//! A unique identifier to assign to the new game session placement. This value is developer-defined.
//! The value must be unique across all Regions and cannot be reused unless you are resubmitting a canceled or timed-out placement request.
AZStd::string m_placementId;
};
} // namespace AWSGameLift
@@ -25,14 +25,14 @@ namespace AWSGameLift
AWSGameLiftCreateSessionRequest() = default;
virtual ~AWSGameLiftCreateSessionRequest() = default;
// A unique identifier for the alias associated with the fleet to create a game session in.
//! A unique identifier for the alias associated with the fleet to create a game session in.
AZStd::string m_aliasId;
// A unique identifier for the fleet to create a game session in.
//! A unique identifier for the fleet to create a game session in.
AZStd::string m_fleetId;
// Custom string that uniquely identifies the new game session request.
// This is useful for ensuring that game session requests with the same idempotency token are processed only once.
//! Custom string that uniquely identifies the new game session request.
//! This is useful for ensuring that game session requests with the same idempotency token are processed only once.
AZStd::string m_idempotencyToken;
};
} // namespace AWSGameLift
@@ -25,13 +25,13 @@ namespace AWSGameLift
AWSGameLiftSearchSessionsRequest() = default;
virtual ~AWSGameLiftSearchSessionsRequest() = default;
// A unique identifier for the alias associated with the fleet to search for active game sessions.
//! A unique identifier for the alias associated with the fleet to search for active game sessions.
AZStd::string m_aliasId;
// A unique identifier for the fleet to search for active game sessions.
//! A unique identifier for the fleet to search for active game sessions.
AZStd::string m_fleetId;
// A fleet location to search for game sessions.
//! A fleet location to search for game sessions.
AZStd::string m_location;
};
} // namespace AWSGameLift
@@ -30,9 +30,10 @@ namespace AWSGameLift
AWSGameLiftStartMatchmakingRequest() = default;
virtual ~AWSGameLiftStartMatchmakingRequest() = default;
// Name of the matchmaking configuration to use for this request
//! Name of the matchmaking configuration to use for this request
AZStd::string m_configurationName;
// Information on each player to be matched
//! Information on each player to be matched
AZStd::vector<AWSGameLiftPlayer> m_players;
};
} // namespace AWSGameLift
@@ -259,6 +259,7 @@ namespace AZ
// Create and register a scene with all available feature processors
RPI::SceneDescriptor sceneDesc;
sceneDesc.m_nameId = AZ::Name("Main");
AZ::RPI::ScenePtr atomScene = RPI::Scene::CreateScene(sceneDesc);
atomScene->EnableAllFeatureProcessors();
atomScene->Activate();
@@ -78,5 +78,10 @@ namespace AZ
//! Find an assignment id corresponding to the lod and label substring filters
MaterialAssignmentId FindMaterialAssignmentIdInModel(
const Data::Instance<AZ::RPI::Model>& model, const MaterialAssignmentLodIndex lodFilter, const AZStd::string& labelFilter);
//! Special case handling to convert script values to supported types
AZ::RPI::MaterialPropertyValue ConvertMaterialPropertyValueFromScript(
const AZ::RPI::MaterialPropertyDescriptor* propertyDescriptor, const AZStd::any& value);
} // namespace Render
} // namespace AZ
@@ -12,7 +12,7 @@
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
#include <Atom/RPI.Public/Pass/PassFilter.h>
#include <Atom/RPI.Public/Pass/RenderPass.h>
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
#include <Atom/RPI.Public/Pass/Specific/SwapChainPass.h>
#include <Atom/RPI.Public/ViewportContextManager.h>
@@ -32,7 +32,7 @@ namespace AZ
{
if (m_rtPipeline)
{
AZ::RPI::RPISystemInterface::Get()->GetDefaultScene()->RemoveRenderPipeline(m_rtPipeline->GetId());
m_rtPipeline->RemoveFromScene();
m_rtPipeline = nullptr;
}
@@ -111,8 +111,12 @@ namespace AZ
parentPass->SetSourceTexture(m_texture, RHI::Format::R8G8B8A8_UNORM);
break;
}
AZ::RPI::RPISystemInterface::Get()->GetDefaultScene()->AddRenderPipeline(m_rtPipeline);
const auto mainScene = AZ::RPI::RPISystemInterface::Get()->GetSceneByName(AZ::Name("RPI"));
if (mainScene)
{
mainScene->AddRenderPipeline(m_rtPipeline);
}
}
bool LuxCoreTexture::IsIBLTexture()
@@ -143,28 +143,34 @@ namespace AZ
{
bool wasRenamed = false;
Name newName;
RPI::MaterialPropertyIndex materialPropertyIndex = m_materialInstance->FindPropertyIndex(propertyPair.first, &wasRenamed, &newName);
RPI::MaterialPropertyIndex materialPropertyIndex =
m_materialInstance->FindPropertyIndex(propertyPair.first, &wasRenamed, &newName);
// FindPropertyIndex will have already reported a message about what the old and new names are. Here we just add some extra info to help the user resolve it.
AZ_Warning("MaterialAssignment", !wasRenamed,
// FindPropertyIndex will have already reported a message about what the old and new names are. Here we just add
// some extra info to help the user resolve it.
AZ_Warning(
"MaterialAssignment", !wasRenamed,
"Consider running \"Apply Automatic Property Updates\" to use the latest property names.",
propertyPair.first.GetCStr(),
newName.GetCStr());
propertyPair.first.GetCStr(), newName.GetCStr());
if (wasRenamed && m_propertyOverrides.find(newName) != m_propertyOverrides.end())
{
materialPropertyIndex.Reset();
AZ_Warning("MaterialAssignment", false,
"Material property '%s' has been renamed to '%s', and a property override exists for both. The one with the old name will be ignored.",
propertyPair.first.GetCStr(),
newName.GetCStr());
AZ_Warning(
"MaterialAssignment", false,
"Material property '%s' has been renamed to '%s', and a property override exists for both. The one with "
"the old name will be ignored.",
propertyPair.first.GetCStr(), newName.GetCStr());
}
if (!materialPropertyIndex.IsNull())
{
const auto propertyDescriptor =
m_materialInstance->GetMaterialPropertiesLayout()->GetPropertyDescriptor(materialPropertyIndex);
m_materialInstance->SetPropertyValue(
materialPropertyIndex, AZ::RPI::MaterialPropertyValue::FromAny(propertyPair.second));
materialPropertyIndex, ConvertMaterialPropertyValueFromScript(propertyDescriptor, propertyPair.second));
}
}
}
@@ -284,5 +290,58 @@ namespace AZ
return MaterialAssignmentId();
}
template<typename T>
AZ::RPI::MaterialPropertyValue ConvertMaterialPropertyValueNumericType(const AZStd::any& value)
{
if (value.is<int32_t>())
{
return aznumeric_cast<T>(AZStd::any_cast<int32_t>(value));
}
if (value.is<uint32_t>())
{
return aznumeric_cast<T>(AZStd::any_cast<uint32_t>(value));
}
if (value.is<float>())
{
return aznumeric_cast<T>(AZStd::any_cast<float>(value));
}
if (value.is<double>())
{
return aznumeric_cast<T>(AZStd::any_cast<double>(value));
}
return AZ::RPI::MaterialPropertyValue::FromAny(value);
}
AZ::RPI::MaterialPropertyValue ConvertMaterialPropertyValueFromScript(
const AZ::RPI::MaterialPropertyDescriptor* propertyDescriptor, const AZStd::any& value)
{
switch (propertyDescriptor->GetDataType())
{
case AZ::RPI::MaterialPropertyDataType::Enum:
if (value.is<AZ::Name>())
{
return propertyDescriptor->GetEnumValue(AZStd::any_cast<AZ::Name>(value));
}
if (value.is<AZStd::string>())
{
return propertyDescriptor->GetEnumValue(AZ::Name(AZStd::any_cast<AZStd::string>(value)));
}
return ConvertMaterialPropertyValueNumericType<uint32_t>(value);
case AZ::RPI::MaterialPropertyDataType::Int:
return ConvertMaterialPropertyValueNumericType<int32_t>(value);
case AZ::RPI::MaterialPropertyDataType::UInt:
return ConvertMaterialPropertyValueNumericType<uint32_t>(value);
case AZ::RPI::MaterialPropertyDataType::Float:
return ConvertMaterialPropertyValueNumericType<float>(value);
case AZ::RPI::MaterialPropertyDataType::Bool:
return ConvertMaterialPropertyValueNumericType<bool>(value);
default:
break;
}
return AZ::RPI::MaterialPropertyValue::FromAny(value);
}
} // namespace Render
} // namespace AZ
+1 -2
View File
@@ -107,7 +107,7 @@ ly_add_target(
Gem::Atom_RHI.Reflect
Gem::Atom_RHI_DX12.Reflect
3rdParty::d3dx12
${AFTERMATH_BUILD_DEPENDENCY}
${AFTERMATH_BUILD_DEPENDENCY}
COMPILE_DEFINITIONS
PRIVATE
${USE_NSIGHT_AFTERMATH_DEFINE}
@@ -128,7 +128,6 @@ ly_add_target(
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
Gem::Atom_RHI.Reflect
Gem::Atom_RHI.Public
Gem::Atom_RHI_DX12.Reflect
@@ -12,6 +12,7 @@
#include <Atom/RPI.Public/GpuQuery/GpuQuerySystemInterface.h>
#include <Atom/RPI.Reflect/Image/Image.h>
#include <Atom/RPI.Public/Image/AttachmentImage.h>
#include <Atom/RPI.Public/Image/AttachmentImage.h>
#include <Atom/RPI.Public/Pass/PassAttachment.h>
#include <Atom/RPI.Public/Pass/PassDefines.h>
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
@@ -59,6 +60,7 @@ namespace AZ
struct PassRequest;
struct PassValidationResults;
class AttachmentReadback;
class ImageAttachmentCopy;
using SortedPipelineViewTags = AZStd::set<PipelineViewTag, AZNameSortAscending>;
using PassesByDrawList = AZStd::map<RHI::DrawListTag, const Pass*>;
@@ -94,6 +96,8 @@ namespace AZ
{
AZ_RPI_PASS(Pass);
friend class ImageAttachmentPreviewPass;
public:
using ChildPassIndex = RHI::Handle<uint32_t, class ChildPass>;
@@ -369,6 +373,9 @@ namespace AZ
void UpdateReadbackAttachment(FramePrepareParams params, bool beforeAddScopes);
// Setup ImageAttachmentCopy
void UpdateAttachmentCopy(FramePrepareParams params);
// --- Protected Members ---
const Name PassNameThis{"This"};
@@ -466,6 +473,9 @@ namespace AZ
AZStd::shared_ptr<AttachmentReadback> m_attachmentReadback;
PassAttachmentReadbackOption m_readbackOption;
// For image attachment preview
AZStd::weak_ptr<ImageAttachmentCopy> m_attachmentCopy;
private:
// Return the Timestamp result of this pass
virtual TimestampResult GetTimestampResultInternal() const;
@@ -77,6 +77,16 @@ namespace AZ
const AZStd::shared_ptr<PassTemplate> GetPassTemplate(const Name& name) const;
const AZStd::vector<Pass*>& GetPassesForTemplate(const Name& templateName) const;
//! Removes a PassTemplate by name, only if the following two conditions are met:
//! 1- The template was NOT created from an Asset. This means the template will be erasable
//! only if it was created at runtime with C++.
//! 2- The are no instantiated Passes referencing such template.
//! If the template exists but both conditions are not met then the function will assert.
//! If a template with the given name doesn't exist the function does nothing.
//! This function should be used judiciously, and under rare circumstances. For example,
//! Applications that iteratively create and need to delete templates at runtime.
void RemovePassTemplate(const Name& name);
//! Removes a pass from both it's associated template (if it has one) and from the pass name mapping
void RemovePassFromLibrary(Pass* pass);
@@ -94,6 +94,7 @@ namespace AZ
bool HasPassesForTemplateName(const Name& templateName) const override;
bool AddPassTemplate(const Name& name, const AZStd::shared_ptr<PassTemplate>& passTemplate) override;
const AZStd::shared_ptr<PassTemplate> GetPassTemplate(const Name& name) const override;
void RemovePassTemplate(const Name& name) override;
void RemovePassFromLibrary(Pass* pass) override;
void RegisterPass(Pass* pass) override;
void UnregisterPass(Pass* pass) override;
@@ -199,6 +199,9 @@ namespace AZ
//! Retrieves a PassTemplate from the library
virtual const AZStd::shared_ptr<PassTemplate> GetPassTemplate(const Name& name) const = 0;
//! See remarks in PassLibrary.h for the function with this name.
virtual void RemovePassTemplate(const Name& name) = 0;
//! Removes all references to the given pass from the pass library
virtual void RemovePassFromLibrary(Pass* pass) = 0;
@@ -13,9 +13,7 @@
#include <Atom/RHI/DrawList.h>
#include <Atom/RHI/ScopeProducer.h>
#include <Atom/RPI.Public/Pass/AttachmentReadback.h>
#include <Atom/RPI.Public/Pass/Pass.h>
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
namespace AZ
@@ -29,7 +27,6 @@ namespace AZ
namespace RPI
{
class ImageAttachmentCopy;
class RenderPass;
class Query;
@@ -41,8 +38,6 @@ namespace AZ
{
AZ_RPI_PASS(RenderPass);
friend class ImageAttachmentPreviewPass;
using ScopeQuery = AZStd::array<RHI::Ptr<Query>, static_cast<size_t>(ScopeQueryType::Count)>;
public:
@@ -143,8 +138,6 @@ namespace AZ
// Readback the results from the ScopeQueries
void ReadbackScopeQueryResults();
AZStd::weak_ptr<ImageAttachmentCopy> m_attachmentCopy;
// Readback results from the Timestamp queries
TimestampResult m_timestampResult;
// Readback results from the PipelineStatistics queries
@@ -78,7 +78,7 @@ namespace AZ
~ImageAttachmentPreviewPass();
//! Preview the PassAttachment of a pass' PassAttachmentBinding
void PreviewImageAttachmentForPass(RenderPass* pass, const PassAttachment* passAttachment);
void PreviewImageAttachmentForPass(Pass* pass, const PassAttachment* passAttachment);
//! Set the output color attachment for this pass
void SetOutputColorAttachment(RHI::Ptr<PassAttachment> outputImageAttachment);
@@ -70,7 +70,8 @@ namespace AZ
void InitializeSystemAssets() override;
void RegisterScene(ScenePtr scene) override;
void UnregisterScene(ScenePtr scene) override;
ScenePtr GetScene(const SceneId& sceneId) const override;
Scene* GetScene(const SceneId& sceneId) const override;
Scene* GetSceneByName(const AZ::Name& name) const override;
ScenePtr GetDefaultScene() const override;
RenderPipelinePtr GetRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle) override;
Data::Asset<ShaderAsset> GetCommonShaderAssetForSrgs() const override;
@@ -13,6 +13,7 @@
#include <Atom/RPI.Public/Base.h>
#include <AzCore/Name/Name.h>
#include <AzFramework/Windowing/WindowBus.h>
namespace AZ
@@ -46,11 +47,14 @@ namespace AZ
//! Unregister a scene from RPISystem. The scene won't be simulated or rendered.
virtual void UnregisterScene(ScenePtr scene) = 0;
// [GFX TODO] to be removed when we have scene setup in AZ Core
virtual ScenePtr GetDefaultScene() const = 0;
//! Deprecated. Use GetSceneByName(name), GetSceneForEntityContextId(entityContextId) or Scene::GetSceneForEntityId(AZ::EntityId entityId) instead
AZ_DEPRECATED(virtual ScenePtr GetDefaultScene() const = 0;, "This method has been deprecated. Please use GetSceneByName(name), GetSceneForEntityContextId(entityContextId) or Scene::GetSceneForEntityId(AZ::EntityId entityId) instead.");
//! Get scene by using scene id.
virtual ScenePtr GetScene(const SceneId& sceneId) const = 0;
virtual Scene* GetScene(const SceneId& sceneId) const = 0;
//! Get scene by using scene name.
virtual Scene* GetSceneByName(const AZ::Name& name) const = 0;
//! Get the render pipeline created for a window
virtual RenderPipelinePtr GetRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle) = 0;
@@ -80,6 +80,9 @@ namespace AZ
//! Gets the RPI::Scene for a given entityContextId.
//! May return nullptr if there is no RPI::Scene created for that entityContext.
static Scene* GetSceneForEntityContextId(AzFramework::EntityContextId entityContextId);
//! Gets the RPI::Scene for a given entityId.
static Scene* GetSceneForEntityId(AZ::EntityId entityId);
~Scene();
@@ -135,6 +138,8 @@ namespace AZ
const SceneId& GetId() const;
AZ::Name GetName() const;
//! Set default pipeline by render pipeline ID.
//! It returns true if the default render pipeline was set from the input ID.
//! If the specified render pipeline doesn't exist in this scene then it won't do anything and returns false.
@@ -245,6 +250,9 @@ namespace AZ
// The uuid to identify this scene.
SceneId m_id;
// Scene's name which is set at initialization. Can be empty
AZ::Name m_name;
bool m_activated = false;
bool m_taskGraphActive = false; // update during tick, to ensure it only changes on frame boundaries
@@ -286,13 +294,10 @@ namespace AZ
template<typename FeatureProcessorType>
FeatureProcessorType* Scene::GetFeatureProcessorForEntity(AZ::EntityId entityId)
{
// Find the entity context for the entity ID.
AzFramework::EntityContextId entityContextId = AzFramework::EntityContextId::CreateNull();
AzFramework::EntityIdContextQueryBus::EventResult(entityContextId, entityId, &AzFramework::EntityIdContextQueryBus::Events::GetOwningContextId);
if (!entityContextId.IsNull())
RPI::Scene* renderScene = GetSceneForEntityId(entityId);
if (renderScene)
{
return GetFeatureProcessorForEntityContextId<FeatureProcessorType>(entityContextId);
return renderScene->GetFeatureProcessor<FeatureProcessorType>();
}
return nullptr;
};
@@ -9,6 +9,7 @@
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Name/Name.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
@@ -25,6 +26,9 @@ namespace AZ
//! List of feature processors which the scene will initially enable.
AZStd::vector<AZStd::string> m_featureProcessorNames;
//! A name used as scene id. It can be used to search a registered scene via RPISystemInterface::GetScene()
AZ::Name m_nameId;
};
} // namespace RPI
} // namespace AZ
@@ -10,8 +10,8 @@
#include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <Atom/RPI.Reflect/Asset/AssetReference.h>
#include <Atom/RPI.Reflect/Pass/PassAsset.h>
@@ -33,11 +33,27 @@ namespace AZ
static const char* PassAssetExtension = "pass";
}
namespace PassBuilderNamespace
{
enum PassDependencies
{
Shader,
AttachmentImage,
Count
};
static const AZStd::tuple<const char*, const char*> DependencyExtensionJobKeyTable[PassDependencies::Count] =
{
{".shader", "Shader Asset"},
{".attimage", "Any Asset Builder"}
};
}
void PassBuilder::RegisterBuilder()
{
AssetBuilderSDK::AssetBuilderDesc builder;
builder.m_name = PassBuilderJobKey;
builder.m_version = 13; // antonmic: making .pass files declare dependency on shaders they reference
builder.m_version = 14; // making .pass files emit product dependencies for the shaders they reference so they are picked up by the asset bundler
builder.m_busId = azrtti_typeid<PassBuilder>();
builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
@@ -104,8 +120,27 @@ namespace AZ
}
}
bool SetJobKeyForExtension(const AZStd::string& filePath, FindPassReferenceAssetParams& params)
{
AZStd::string extension;
StringFunc::Path::GetExtension(filePath.c_str(), extension);
for (const auto& [dependencyExtension, jobKey] : PassBuilderNamespace::DependencyExtensionJobKeyTable)
{
if (extension == dependencyExtension)
{
params.jobKey = jobKey;
return true;
}
}
AZ_Error(PassBuilderName, false, "PassBuilder found a dependency with extension '%s', but does not know the corresponding job key. Add the job key for that extension to SetJobKeyForExtension in PassBuilder.cpp", extension.c_str());
params.jobKey = "Unknown";
return false;
}
// Helper function to find all assetId's and object references
bool FindReferencedAssets(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job)
bool FindReferencedAssets(
FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job, AZStd::vector<AssetBuilderSDK::ProductDependency>* productDependencies)
{
SerializeContext::ErrorHandler errorLogger;
errorLogger.Reset();
@@ -129,8 +164,8 @@ namespace AZ
if (job != nullptr) // Create Job Phase
{
params.dependencySourceFile = path;
bool dependencyAddedSuccessfully = AddDependency(params, job);
success = dependencyAddedSuccessfully && success;
success &= SetJobKeyForExtension(path, params);
success &= AddDependency(params, job);
}
else // Process Job Phase
{
@@ -139,6 +174,9 @@ namespace AZ
if (assetIdOutcome)
{
assetReference->m_assetId = assetIdOutcome.GetValue();
productDependencies->push_back(
AssetBuilderSDK::ProductDependency{assetReference->m_assetId, AZ::Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad)}
);
}
else
{
@@ -223,9 +261,9 @@ namespace AZ
params.passAssetSourceFile = request.m_sourceFile;
params.passAssetUuid = passAssetUuid;
params.serializeContext = serializeContext;
params.jobKey = "Shader Asset";
params.jobKey = "Unknown";
if (!FindReferencedAssets(params, &job))
if (!FindReferencedAssets(params, &job, nullptr))
{
return;
}
@@ -287,9 +325,10 @@ namespace AZ
params.passAssetSourceFile = request.m_sourceFile;
params.passAssetUuid = passAssetUuid;
params.serializeContext = serializeContext;
params.jobKey = "Shader Asset";
params.jobKey = "Unknown";
if (!FindReferencedAssets(params, nullptr))
AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
if (!FindReferencedAssets(params, nullptr, &productDependencies))
{
return;
}
@@ -313,6 +352,7 @@ namespace AZ
// --- Save output product(s) to response ---
AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0);
jobProduct.m_dependencies = productDependencies;
jobProduct.m_dependenciesHandled = true;
response.m_outputProducts.push_back(jobProduct);
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
@@ -699,9 +699,7 @@ namespace AZ
m_parentScene = parentScene;
AZ_Assert(m_visScene == nullptr, "IVisibilityScene already created for this RPI::Scene");
char sceneIdBuf[40] = "";
m_parentScene->GetId().ToString(sceneIdBuf);
AZ::Name visSceneName(AZStd::string::format("RenderCullScene[%s]", sceneIdBuf));
AZ::Name visSceneName(AZStd::string::format("RenderCullScene[%s]", m_parentScene->GetName().GetCStr()));
m_visScene = AZ::Interface<AzFramework::IVisibilitySystem>::Get()->CreateVisibilityScene(visSceneName);
#ifdef AZ_CULL_DEBUG_ENABLED
@@ -26,6 +26,7 @@
#include <Atom/RPI.Public/Pass/PassLibrary.h>
#include <Atom/RPI.Public/Pass/PassDefines.h>
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Reflect/Image/AttachmentImageAsset.h>
@@ -1215,6 +1216,12 @@ namespace AZ
m_queueState = PassQueueState::NoQueue;
InitializeInternal();
// Need to recreate the dest attachment because the source attachment might be changed
if (!m_attachmentCopy.expired())
{
m_attachmentCopy.lock()->InvalidateDestImage();
}
m_state = PassState::Initialized;
}
@@ -1301,6 +1308,9 @@ namespace AZ
// readback attachment with output state
UpdateReadbackAttachment(params, false);
// update attachment copy for preview
UpdateAttachmentCopy(params);
UpdateConnectedOutputBindings();
}
@@ -1489,6 +1499,14 @@ namespace AZ
}
}
void Pass::UpdateAttachmentCopy(FramePrepareParams params)
{
if (!m_attachmentCopy.expired())
{
m_attachmentCopy.lock()->FrameBegin(params);
}
}
bool Pass::IsTimestampQueryEnabled() const
{
return m_flags.m_timestampQueryEnabled;
@@ -236,6 +236,19 @@ namespace AZ
return true;
}
void PassLibrary::RemovePassTemplate(const Name& name)
{
auto itr = m_templateEntries.find(name);
if (itr != m_templateEntries.end())
{
AZ_Assert(itr->second.m_passes.empty(), "Can not delete PassTemplate '%s' because there are %zu Passes referencing it",
name.GetCStr(), itr->second.m_passes.size());
AZ_Assert(!itr->second.m_mappingAssetId.IsValid(), "Can not delete PassTemplate '%s' because it was created from an asset",
name.GetCStr());
m_templateEntries.erase(itr);
}
}
void PassLibrary::RemovePassFromLibrary(Pass* pass)
{
if (m_isShuttingDown)
@@ -466,6 +466,11 @@ namespace AZ
return m_passLibrary.GetPassTemplate(name);
}
void PassSystem::RemovePassTemplate(const Name& name)
{
m_passLibrary.RemovePassTemplate(name);
}
void PassSystem::RemovePassFromLibrary(Pass* pass)
{
m_passLibrary.RemovePassFromLibrary(pass);
@@ -177,12 +177,6 @@ namespace AZ
}
}
}
// Need to recreate the dest attachment because the source attachment might be changed
if (!m_attachmentCopy.expired())
{
m_attachmentCopy.lock()->InvalidateDestImage();
}
}
void RenderPass::FrameBeginInternal(FramePrepareParams params)
@@ -196,11 +190,7 @@ namespace AZ
// Read back the ScopeQueries submitted from previous frames
ReadbackScopeQueryResults();
if (!m_attachmentCopy.expired())
{
m_attachmentCopy.lock()->FrameBegin(params);
}
CollectSrgs();
PassSystemInterface::Get()->IncrementFrameRenderPassCount();
@@ -14,7 +14,7 @@
#include <Atom/RPI.Public/Buffer/Buffer.h>
#include <Atom/RPI.Public/Image/AttachmentImagePool.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <Atom/RPI.Public/Pass/RenderPass.h>
#include <Atom/RPI.Public/Pass/AttachmentReadback.h>
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
#include <Atom/RPI.Public/Pass/ParentPass.h>
#include <Atom/RPI.Public/RenderPipeline.h>
@@ -131,7 +131,7 @@ namespace AZ
Data::AssetBus::Handler::BusDisconnect();
}
void ImageAttachmentPreviewPass::PreviewImageAttachmentForPass(RenderPass* pass, const PassAttachment* passAttachment)
void ImageAttachmentPreviewPass::PreviewImageAttachmentForPass(Pass* pass, const PassAttachment* passAttachment)
{
if (passAttachment->GetAttachmentType() != RHI::AttachmentType::Image)
{
@@ -159,6 +159,11 @@ namespace AZ
AZ_Assert(false, "Scene was already registered");
return;
}
else if (!scene->GetName().IsEmpty() && scene->GetName() == sceneItem->GetName())
{
// only report a warning if there is a scene with duplicated name
AZ_Warning("RPISystem", false, "There is a registered scene with same name [%s]", scene->GetName().GetCStr());
}
}
m_scenes.push_back(scene);
@@ -177,11 +182,35 @@ namespace AZ
AZ_Assert(false, "Can't unregister scene which wasn't registered");
}
ScenePtr RPISystem::GetScene(const SceneId& sceneId) const
Scene* RPISystem::GetScene(const SceneId& sceneId) const
{
for (const auto& scene : m_scenes)
{
if (scene->GetId() == sceneId)
{
return scene.get();
}
}
return nullptr;
}
Scene* RPISystem::GetSceneByName(const AZ::Name& name) const
{
for (const auto& scene : m_scenes)
{
if (scene->GetName() == name)
{
return scene.get();
}
}
return nullptr;
}
ScenePtr RPISystem::GetDefaultScene() const
{
for (const auto& scene : m_scenes)
{
if (scene->GetName() == AZ::Name("Main"))
{
return scene;
}
@@ -189,16 +218,6 @@ namespace AZ
return nullptr;
}
ScenePtr RPISystem::GetDefaultScene() const
{
if (m_scenes.size() > 0)
{
return m_scenes[0];
}
return nullptr;
}
RenderPipelinePtr RPISystem::GetRenderPipelineForWindow(AzFramework::NativeWindowHandle windowHandle)
{
RenderPipelinePtr renderPipeline;
@@ -119,7 +119,12 @@ namespace AZ
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;
AzFramework::AssetSystemRequestBus::BroadcastResult(
status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, path);
AZ_Error("RPIUtils", status == AzFramework::AssetSystem::AssetStatus_Compiled, "Could not compile image at '%s'", path.data());
// When running with no Asset Processor (for example in release), CompileAssetSync will return AssetStatus_Unknown.
AZ_Error(
"RPIUtils",
status == AzFramework::AssetSystem::AssetStatus_Compiled || status == AzFramework::AssetSystem::AssetStatus_Unknown,
"Could not compile image at '%s'", path.data());
Data::AssetId streamingImageAssetId;
Data::AssetCatalogRequestBus::BroadcastResult(

Some files were not shown because too many files have changed in this diff Show More