merge from development

Signed-off-by: greerdv <greerdv@amazon.com>
This commit is contained in:
greerdv
2021-10-18 11:25:57 +01:00
236 changed files with 5045 additions and 3845 deletions
@@ -74,6 +74,7 @@ def update_manifest(scene):
source_filename_only = os.path.basename(clean_filename)
created_entities = []
previous_entity_id = azlmbr.entity.InvalidEntityId
# Loop every mesh node in the scene
for activeMeshIndex in range(len(mesh_name_list)):
@@ -102,14 +103,33 @@ def update_manifest(scene):
# The MeshGroup we created will be output as a product in the asset's path named mesh_group_name.azmodel
# The assetHint will be converted to an AssetId later during prefab loading
json_update = json.dumps({
"Controller": { "Configuration": { "ModelAsset": {
"assetHint": os.path.join(source_relative_path, mesh_group_name) + ".azmodel" }}}
});
"Controller": { "Configuration": { "ModelAsset": {
"assetHint": os.path.join(source_relative_path, mesh_group_name) + ".azmodel" }}}
});
# Apply the JSON above to the component we created
result = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "UpdateComponentForEntity", entity_id, editor_mesh_component, json_update)
if not result:
raise RuntimeError("UpdateComponentForEntity failed")
raise RuntimeError("UpdateComponentForEntity failed for Mesh component")
# Get the transform component
transform_component = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "GetOrAddComponentByTypeName", entity_id, "27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0")
# Set this entity to be a child of the last entity we created
# This is just an example of how to do parenting and isn't necessarily useful to parent everything like this
if previous_entity_id is not None:
transform_json = json.dumps({
"Parent Entity" : previous_entity_id.to_json()
});
# Apply the JSON update
result = azlmbr.entity.EntityUtilityBus(azlmbr.bus.Broadcast, "UpdateComponentForEntity", entity_id, transform_component, transform_json)
if not result:
raise RuntimeError("UpdateComponentForEntity failed for Transform component")
# Update the last entity id for next time
previous_entity_id = entity_id
# Keep track of the entity we set up, we'll add them all to the prefab we're creating later
created_entities.append(entity_id)
@@ -147,6 +167,8 @@ def on_update_manifest(args):
except RuntimeError as err:
print (f'ERROR - {err}')
log_exception_traceback()
except:
log_exception_traceback()
global sceneJobHandler
sceneJobHandler = None
@@ -71,5 +71,9 @@ class TestAutomation(EditorTestSuite):
class AtomEditorComponents_PostFXShapeWeightModifierAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded as test_module
@pytest.mark.test_case_id("C36525664")
class AtomEditorComponents_PostFXGradientWeightModifierAdded(EditorSharedTest):
from Atom.tests import hydra_AtomEditorComponents_PostFXGradientWeightModifierAdded as test_module
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest):
from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module
@@ -0,0 +1,179 @@
"""
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
"""
class Tests:
creation_undo = (
"UNDO Entity creation success",
"UNDO Entity creation failed")
creation_redo = (
"REDO Entity creation success",
"REDO Entity creation failed")
postfx_gradient_weight_creation = (
"PostFX Gradient Weight Modifier Entity successfully created",
"PostFX Gradient Weight Modifier Entity failed to be created")
postfx_gradient_weight_component = (
"Entity has a PostFX Gradient Weight Modifier component",
"Entity failed to find PostFX Gradient Weight Modifier component")
postfx_gradient_weight_disabled = (
"PostFX Gradient Weight Modifier component disabled",
"PostFX Gradient Weight Modifier component was not disabled.")
postfx_layer_component = (
"Entity has a PostFX Layer component",
"Entity did not have an PostFX Layer component")
postfx_gradient_weight_enabled = (
"PostFX Gradient Weight Modifier component enabled",
"PostFX Gradient Weight Modifier component was not enabled.")
enter_game_mode = (
"Entered game mode",
"Failed to enter game mode")
exit_game_mode = (
"Exited game mode",
"Couldn't exit game mode")
is_visible = (
"Entity is visible",
"Entity was not visible")
is_hidden = (
"Entity is hidden",
"Entity was not hidden")
entity_deleted = (
"Entity deleted",
"Entity was not deleted")
deletion_undo = (
"UNDO deletion success",
"UNDO deletion failed")
deletion_redo = (
"REDO deletion success",
"REDO deletion failed")
def AtomEditorComponents_PostFXGradientWeightModifier_AddedToEntity():
"""
Summary:
Tests the PostFX Gradient Weight Modifier component can be added to an entity and has the expected functionality.
Test setup:
- Wait for Editor idle loop.
- Open the "Base" level.
Expected Behavior:
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
Creation and deletion undo/redo should also work.
Test Steps:
1) Create a PostFX Gradient Weight Modifier entity with no components.
2) Add a PostFX Gradient Weight Modifier component to PostFX Gradient Weight Modifier entity.
3) UNDO the entity creation and component addition.
4) REDO the entity creation and component addition.
5) Verify PostFX Gradient Weight Modifier component not enabled.
6) Add PostFX Layer component since it is required by the PostFX Gradient Weight Modifier component.
7) Verify PostFX Gradient Weight Modifier component is enabled.
8) Enter/Exit game mode.
9) Test IsHidden.
10) Test IsVisible.
11) Delete PostFX Gradient Weight Modifier entity.
12) UNDO deletion.
13) REDO deletion.
14) Look for errors.
:return: None
"""
import azlmbr.legacy.general as general
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import Report, Tracer, TestHelper
with Tracer() as error_tracer:
# Test setup begins.
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
TestHelper.init_idle()
TestHelper.open_level("", "Base")
# Test steps begin.
# 1. Create a PostFX Gradient Weight Modifier entity with no components.
postfx_gradient_weight_name = "PostFX Gradient Weight Modifier"
postfx_gradient_weight_entity = EditorEntity.create_editor_entity(postfx_gradient_weight_name)
Report.critical_result(Tests.postfx_gradient_weight_creation, postfx_gradient_weight_entity.exists())
# 2. Add a PostFX Gradient Weight Modifier component to PostFX Gradient Weight Modifier entity.
postfx_gradient_weight_component = postfx_gradient_weight_entity.add_component(postfx_gradient_weight_name)
Report.critical_result(
Tests.postfx_gradient_weight_component,
postfx_gradient_weight_entity.has_component(postfx_gradient_weight_name))
# 3. UNDO the entity creation and component addition.
# -> UNDO component addition.
general.undo()
# -> UNDO naming entity.
general.undo()
# -> UNDO selecting entity.
general.undo()
# -> UNDO entity creation.
general.undo()
general.idle_wait_frames(1)
Report.result(Tests.creation_undo, not postfx_gradient_weight_entity.exists())
# 4. REDO the entity creation and component addition.
# -> REDO entity creation.
general.redo()
# -> REDO selecting entity.
general.redo()
# -> REDO naming entity.
general.redo()
# -> REDO component addition.
general.redo()
general.idle_wait_frames(1)
Report.result(Tests.creation_redo, postfx_gradient_weight_entity.exists())
# 5. Verify PostFX Gradient Weight Modifier component not enabled.
Report.result(Tests.postfx_gradient_weight_disabled, not postfx_gradient_weight_component.is_enabled())
# 6. Add PostFX Layer component since it is required by the PostFX Gradient Weight Modifier component.
postfx_layer_name = "PostFX Layer"
postfx_gradient_weight_entity.add_component(postfx_layer_name)
Report.result(Tests.postfx_layer_component, postfx_gradient_weight_entity.has_component(postfx_layer_name))
# 7. Verify PostFX Gradient Weight Modifier component is enabled.
Report.result(Tests.postfx_gradient_weight_enabled, postfx_gradient_weight_component.is_enabled())
# 8. Enter/Exit game mode.
TestHelper.enter_game_mode(Tests.enter_game_mode)
general.idle_wait_frames(1)
TestHelper.exit_game_mode(Tests.exit_game_mode)
# 9. Test IsHidden.
postfx_gradient_weight_entity.set_visibility_state(False)
Report.result(Tests.is_hidden, postfx_gradient_weight_entity.is_hidden() is True)
# 10. Test IsVisible.
postfx_gradient_weight_entity.set_visibility_state(True)
general.idle_wait_frames(1)
Report.result(Tests.is_visible, postfx_gradient_weight_entity.is_visible() is True)
# 11. Delete PostFX Gradient Weight Modifier entity.
postfx_gradient_weight_entity.delete()
Report.result(Tests.entity_deleted, not postfx_gradient_weight_entity.exists())
# 12. UNDO deletion.
general.undo()
Report.result(Tests.deletion_undo, postfx_gradient_weight_entity.exists())
# 13. REDO deletion.
general.redo()
Report.result(Tests.deletion_redo, not postfx_gradient_weight_entity.exists())
# 14. Look for errors or asserts.
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
for error_info in error_tracer.errors:
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
for assert_info in error_tracer.asserts:
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(AtomEditorComponents_PostFXGradientWeightModifier_AddedToEntity)
@@ -19,10 +19,16 @@ namespace Editor
if (GetIEditor()->IsInGameMode())
{
#ifdef PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
AzFramework::XcbEventHandlerBus::Broadcast(&AzFramework::XcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
// We need to handle RAW Input events in a separate loop. This is a workaround to enable XInput2 RAW Inputs using Editor mode.
// TODO To have this call here might be not be perfect.
AzFramework::XcbEventHandlerBus::Broadcast(&AzFramework::XcbEventHandler::PollSpecialEvents);
// Now handle the rest of the events.
AzFramework::XcbEventHandlerBus::Broadcast(
&AzFramework::XcbEventHandler::HandleXcbEvent, static_cast<xcb_generic_event_t*>(message));
#endif
return true;
}
return false;
}
}
} // namespace Editor
+3
View File
@@ -264,6 +264,9 @@ void EditorPreferencesDialog::SetFilter(const QString& filter)
else if (m_currentPageItem)
{
m_currentPageItem->UpdateEditorFilter(ui->propertyEditor, m_filter);
// Refresh the Stylesheet - when using search functionality.
AzQtComponents::StyleManager::repolishStyleSheet(this);
}
}
-35
View File
@@ -108,15 +108,11 @@ CObjectManager::CObjectManager()
m_objectsByName.reserve(1024);
LoadRegistry();
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
}
//////////////////////////////////////////////////////////////////////////
CObjectManager::~CObjectManager()
{
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
m_bExiting = true;
SaveRegistry();
DeleteAllObjects();
@@ -2307,37 +2303,6 @@ void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitC
}
}
void CObjectManager::OnEditorModeActivated(
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
if (mode == AzToolsFramework::ViewportEditorMode::Component)
{
// hide current gizmo for entity (translate/rotate/scale)
IGizmoManager* gizmoManager = GetGizmoManager();
const size_t gizmoCount = static_cast<size_t>(gizmoManager->GetGizmoCount());
for (size_t i = 0; i < gizmoCount; ++i)
{
gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast<int>(i)));
}
}
}
void CObjectManager::OnEditorModeDeactivated(
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
{
if (mode == AzToolsFramework::ViewportEditorMode::Component)
{
// show translate/rotate/scale gizmo again
if (IGizmoManager* gizmoManager = GetGizmoManager())
{
if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
{
gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
}
}
}
}
//////////////////////////////////////////////////////////////////////////
namespace
{
-8
View File
@@ -20,7 +20,6 @@
#include "ObjectManagerEventBus.h"
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
#include <AzCore/EBus/EBus.h>
#include <AzCore/Component/Component.h>
#include <Include/SandboxAPI.h>
@@ -59,7 +58,6 @@ public:
*/
class CObjectManager
: public IObjectManager
, private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
{
public:
//! Selection functor callback.
@@ -330,12 +328,6 @@ private:
void FindDisplayableObjects(DisplayContext& dc, bool bDisplay);
// ViewportEditorModeNotificationsBus overrides ...
void OnEditorModeActivated(
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
void OnEditorModeDeactivated(
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
private:
typedef std::map<GUID, CBaseObjectPtr, guid_less_predicate> Objects;
Objects m_objects;
@@ -225,8 +225,16 @@ namespace AZ
ConsoleCommandContainer commandSubset;
for (ConsoleFunctorBase* curr = m_head; curr != nullptr; curr = curr->m_next)
for (const auto& functor : m_commands)
{
if (functor.second.empty())
{
continue;
}
// Filter functors registered with the same name
const ConsoleFunctorBase* curr = functor.second.front();
if ((curr->GetFlags() & ConsoleFunctorFlags::IsInvisible) == ConsoleFunctorFlags::IsInvisible)
{
// Filter functors marked as invisible
@@ -236,7 +244,12 @@ namespace AZ
if (StringFunc::StartsWith(curr->m_name, command, false))
{
AZLOG_INFO("- %s : %s\n", curr->m_name, curr->m_desc);
commandSubset.push_back(curr->m_name);
if (commandSubset.size() < MaxConsoleCommandPlusArgsLength)
{
commandSubset.push_back(curr->m_name);
}
if (matches)
{
matches->push_back(curr->m_name);
@@ -271,7 +284,10 @@ namespace AZ
{
for (auto& curr : m_commands)
{
visitor(curr.second.front());
if (!curr.second.empty())
{
visitor(curr.second.front());
}
}
}
@@ -336,6 +352,11 @@ namespace AZ
{
iter->second.erase(iter2);
}
if (iter->second.empty())
{
m_commands.erase(iter);
}
}
functor->Unlink(m_head);
functor->m_console = nullptr;
@@ -40,6 +40,12 @@ namespace AZ
static unsigned int Record(StackFrame* frames, unsigned int maxNumOfFrames, unsigned int suppressCount = 0, void* nativeThread = 0);
};
class StackConverter
{
public:
static unsigned int FromNative(StackFrame* frames, unsigned int maxNumOfFrames, void* nativeContext);
};
class SymbolStorage
{
public:
+10 -6
View File
@@ -31,6 +31,8 @@ namespace AZ
{
namespace Debug
{
struct StackFrame;
namespace Platform
{
#if defined(AZ_ENABLE_DEBUG_TOOLS)
@@ -551,17 +553,19 @@ namespace AZ
{
StackFrame frames[25];
// Without StackFrame explicit alignment frames array is aligned to 4 bytes
// which causes the stack tracing to fail.
//size_t bla = AZStd::alignment_of<StackFrame>::value;
//printf("Alignment value %d address 0x%08x : 0x%08x\n",bla,frames);
SymbolStorage::StackLine lines[AZ_ARRAY_SIZE(frames)];
unsigned int numFrames = 0;
if (!nativeContext)
{
suppressCount += 1; /// If we don't provide a context we will capture in the RecordFunction, so skip us (Trace::PrinCallstack).
suppressCount += 1; /// If we don't provide a context we will capture in the RecordFunction, so skip us (Trace::PrintCallstack).
numFrames = StackRecorder::Record(frames, AZ_ARRAY_SIZE(frames), suppressCount);
}
unsigned int numFrames = StackRecorder::Record(frames, AZ_ARRAY_SIZE(frames), suppressCount, nativeContext);
else
{
numFrames = StackConverter::FromNative(frames, AZ_ARRAY_SIZE(frames), nativeContext);
}
if (numFrames)
{
SymbolStorage::DecodeFrames(frames, numFrames, lines);
@@ -17,6 +17,11 @@ namespace AZ
return false;
}
unsigned int StackConverter::FromNative(StackFrame*, unsigned int, void*)
{
return 0;
}
void SymbolStorage::LoadModuleData(const void*, unsigned int)
{}
@@ -78,6 +78,12 @@ StackRecorder::Record(StackFrame* frames, unsigned int maxNumOfFrames, unsigned
return count;
}
unsigned int StackConverter::FromNative([[maybe_unused]] StackFrame* frames, [[maybe_unused]] unsigned int maxNumOfFrames, [[maybe_unused]] void* nativeContext)
{
AZ_Assert(false, "StackConverter::FromNative() is not supported for UnixLike platform yet");
return 0;
}
void
SymbolStorage::DecodeFrames(const StackFrame* frames, unsigned int numFrames, StackLine* textLines)
{
@@ -1048,9 +1048,9 @@ cleanup:
unsigned int
StackRecorder::Record(StackFrame* frames, unsigned int maxNumOfFrames, unsigned int suppressCount, void* nativeThread)
{
#if defined(AZ_ENABLE_DEBUG_TOOLS)
unsigned int numFrames = 0;
#if defined(AZ_ENABLE_DEBUG_TOOLS)
if (nativeThread == NULL)
{
++suppressCount; // Skip current call
@@ -1079,9 +1079,8 @@ cleanup:
STACKFRAME64 sf;
memset(&sf, 0, sizeof(STACKFRAME64));
DWORD imageType;
DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
imageType = IMAGE_FILE_MACHINE_AMD64;
sf.AddrPC.Offset = context.Rip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrFrame.Offset = context.Rsp;
@@ -1090,8 +1089,7 @@ cleanup:
sf.AddrStack.Mode = AddrModeFlat;
EnterCriticalSection(&g_csDbgHelpDll);
s32 frame = -(s32)suppressCount;
for (; frame < (s32)maxNumOfFrames; ++frame)
for (s32 frame = -static_cast<s32>(suppressCount); frame < static_cast<s32>(maxNumOfFrames); ++frame)
{
if (!g_StackWalk64(imageType, g_currentProcess, hThread, &sf, &context, 0, g_SymFunctionTableAccess64, g_SymGetModuleBase64, 0))
{
@@ -1111,15 +1109,68 @@ cleanup:
}
LeaveCriticalSection(&g_csDbgHelpDll);
}
return numFrames;
}
#else
(void)frames;
(void)maxNumOfFrames;
(void)suppressCount;
(void)nativeThread;
return 0;
AZ_UNUSED(frames);
AZ_UNUSED(maxNumOfFrames);
AZ_UNUSED(suppressCount);
AZ_UNUSED(nativeThread);
#endif // AZ_ENABLE_DEBUG_TOOLS
return numFrames;
}
unsigned int StackConverter::FromNative(StackFrame* frames, unsigned int maxNumOfFrames, void* nativeContext)
{
unsigned int numFrames = 0;
#if defined(AZ_ENABLE_DEBUG_TOOLS)
if (!g_dbgHelpLoaded)
{
LoadDbgHelp();
}
HANDLE hThread;
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hThread, 0, false, DUPLICATE_SAME_ACCESS);
PCONTEXT nativeContextType = reinterpret_cast<PCONTEXT>(nativeContext);
STACKFRAME64 sf;
memset(&sf, 0, sizeof(STACKFRAME64));
DWORD imageType = IMAGE_FILE_MACHINE_AMD64;
sf.AddrPC.Offset = nativeContextType->Rip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrFrame.Offset = nativeContextType->Rsp;
sf.AddrFrame.Mode = AddrModeFlat;
sf.AddrStack.Offset = nativeContextType->Rsp;
sf.AddrStack.Mode = AddrModeFlat;
EnterCriticalSection(&g_csDbgHelpDll);
for (unsigned int frame = 0; frame < maxNumOfFrames; ++frame)
{
if (!g_StackWalk64(imageType, g_currentProcess, hThread, &sf, nativeContext, 0, g_SymFunctionTableAccess64, g_SymGetModuleBase64, 0))
{
break;
}
if (sf.AddrPC.Offset == sf.AddrReturn.Offset)
{
// "StackWalk64-Endless-Callstack!"
break;
}
frames[numFrames++].m_programCounter = sf.AddrPC.Offset;
}
LeaveCriticalSection(&g_csDbgHelpDll);
#else
AZ_UNUSED(frames);
AZ_UNUSED(maxNumOfFrames);
AZ_UNUSED(nativeContext);
#endif
return numFrames;
}
//////////////////////////////////////////////////////////////////////////
+4 -4
View File
@@ -1413,7 +1413,7 @@ namespace UnitTest
>;
TYPED_TEST_CASE(HashedSetDifferentAllocatorFixture, SetTemplateConfigs);
#if GTEST_OS_SUPPORTS_DEATH_TEST
#if GTEST_HAS_DEATH_TEST
TYPED_TEST(HashedSetDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
{
using ContainerType = typename TypeParam::ContainerType;
@@ -1435,7 +1435,7 @@ namespace UnitTest
}
}, ".*");
}
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
#endif // GTEST_HAS_DEATH_TEST
template<typename ContainerType>
class HashedMapContainers
@@ -1811,7 +1811,7 @@ namespace UnitTest
>;
TYPED_TEST_CASE(HashedMapDifferentAllocatorFixture, MapTemplateConfigs);
#if GTEST_OS_SUPPORTS_DEATH_TEST
#if GTEST_HAS_DEATH_TEST
TYPED_TEST(HashedMapDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
{
using ContainerType = typename TypeParam::ContainerType;
@@ -1833,7 +1833,7 @@ namespace UnitTest
}
} , ".*");
}
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
#endif // GTEST_HAS_DEATH_TEST
namespace HashedContainerTransparentTestInternal
{
@@ -1095,7 +1095,7 @@ namespace UnitTest
>;
TYPED_TEST_CASE(TreeSetDifferentAllocatorFixture, SetTemplateConfigs);
#if GTEST_OS_SUPPORTS_DEATH_TEST
#if GTEST_HAS_DEATH_TEST
TYPED_TEST(TreeSetDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
{
using ContainerType = typename TypeParam::ContainerType;
@@ -1117,7 +1117,7 @@ namespace UnitTest
}
}, ".*");
}
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
#endif // GTEST_HAS_DEATH_TEST
TYPED_TEST(TreeSetDifferentAllocatorFixture, SwapMovesElementsWhenAllocatorsDiffer)
{
@@ -1516,7 +1516,7 @@ namespace UnitTest
>;
TYPED_TEST_CASE(TreeMapDifferentAllocatorFixture, MapTemplateConfigs);
#if GTEST_OS_SUPPORTS_DEATH_TEST
#if GTEST_HAS_DEATH_TEST
TYPED_TEST(TreeMapDifferentAllocatorFixture, InsertNodeHandleWithDifferentAllocatorsLogsTraceMessages)
{
using ContainerType = typename TypeParam::ContainerType;
@@ -1538,7 +1538,7 @@ namespace UnitTest
}
}, ".*");
}
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
#endif // GTEST_HAS_DEATH_TEST
TYPED_TEST(TreeMapDifferentAllocatorFixture, SwapMovesElementsWhenAllocatorsDiffer)
{
@@ -1595,7 +1595,7 @@ namespace UnitTest
}
};
#if GTEST_OS_SUPPORTS_DEATH_TEST
#if GTEST_HAS_DEATH_TEST
TEST_F(ThreadEventsDeathTest, UsingClientBus_AvoidsDeadlock)
{
EXPECT_EXIT(
@@ -1608,5 +1608,5 @@ namespace UnitTest
, ::testing::ExitedWithCode(0),".*");
}
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
#endif // GTEST_HAS_DEATH_TEST
}
@@ -736,7 +736,10 @@ namespace UnitTest
auto& assetManager = AssetManager::Instance();
AssetBusCallbacks callbacks{};
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
callbacks.SetOnAssetReadyCallback([&, AssetNoRefB](const Asset<AssetData>&, AssetBusCallbacks&)
AZ_POP_DISABLE_WARNING
{
// This callback should run inside the "main thread" dispatch events loop
auto loadAsset = assetManager.GetAsset<AssetWithSerializedData>(AZ::Uuid(AssetNoRefB), AssetLoadBehavior::Default);
@@ -288,6 +288,21 @@ namespace AZ
AZStd::string completeCommand = console->AutoCompleteCommand("testVec3");
AZ_TEST_ASSERT(completeCommand == "testVec3");
}
// Duplicate names
{
// Register two cvars with the same name
auto id = AZ::TypeId();
auto flag = AZ::ConsoleFunctorFlags::Null;
auto signature = AZ::ConsoleFunctor<void, false>::FunctorSignature();
AZ::ConsoleFunctor<void, false> cvarOne(*console, "testAutoCompleteDuplication", "", flag, id, signature);
AZ::ConsoleFunctor<void, false> cvarTwo(*console, "testAutoCompleteDuplication", "", flag, id, signature);
// Autocomplete given name expecting one match (not two)
AZStd::vector<AZStd::string> matches;
AZStd::string completeCommand = console->AutoCompleteCommand("testAutoCompleteD", &matches);
AZ_TEST_ASSERT(matches.size() == 1 && completeCommand == "testAutoCompleteDuplication");
}
}
TEST_F(ConsoleTests, ConsoleFunctor_FreeFunctorExecutionTest)
@@ -109,7 +109,10 @@ namespace AZ::Debug
AZStd::thread threads[totalThreads];
for (size_t threadIndex = 0; threadIndex < totalThreads; ++threadIndex)
{
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
threads[threadIndex] = AZStd::thread([&startLogging, &messages]()
AZ_POP_DISABLE_WARNING
{
while (!startLogging)
{
@@ -226,7 +229,10 @@ namespace AZ::Debug
AZStd::thread threads[totalThreads];
for (size_t threadIndex = 0; threadIndex < totalThreads; ++threadIndex)
{
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
threads[threadIndex] = AZStd::thread([&startLogging, &message, &totalRecordsWritten]()
AZ_POP_DISABLE_WARNING
{
AZ_UNUSED(message);
@@ -0,0 +1,31 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/TestTypes.h>
namespace UnitTest
{
class UnhandledExceptions
: public ScopedAllocatorSetupFixture
{
public:
void causeAccessViolation()
{
int* someVariable = reinterpret_cast<int*>(0);
*someVariable = 0;
}
};
#if GTEST_HAS_DEATH_TEST
TEST_F(UnhandledExceptions, Handle)
{
EXPECT_DEATH(causeAccessViolation(), "");
}
#endif
}
@@ -144,14 +144,13 @@ namespace UnitTest
}
};
#if GTEST_OS_SUPPORTS_DEATH_TEST
// SPEC-2669: Disabled since it is causing hangs on Linux
#if GTEST_HAS_DEATH_TEST
TEST_F(AllocatorsTestFixtureLeakDetectionDeathTest_SKIPCODECOVERAGE, AllocatorLeak)
{
// testing that the TraceBusHook will fail on cause the test to die
EXPECT_DEATH(TestAllocatorLeak(), "");
}
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
#endif // GTEST_HAS_DEATH_TEST
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Testing ScopedAllocatorSetupFixture. Testing that detects leaks
@@ -597,7 +597,10 @@ namespace AZ::IO
path.InitFromAbsolutePath(m_dummyFilepath);
request->CreateRead(nullptr, buffer.get(), fileSize, path, 0, fileSize);
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback = [&fileSize, this](const FileRequest& request)
AZ_POP_DISABLE_WARNING
{
EXPECT_EQ(request.GetStatus(), AZ::IO::IStreamerTypes::RequestStatus::Completed);
auto& readRequest = AZStd::get<AZ::IO::FileRequest::ReadData>(request.GetCommand());
@@ -639,7 +642,10 @@ namespace AZ::IO
path.InitFromAbsolutePath(m_dummyFilepath);
request->CreateRead(nullptr, buffer, unalignedSize + 4, path, unalignedOffset, unalignedSize);
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback = [unalignedOffset, unalignedSize, this](const FileRequest& request)
AZ_POP_DISABLE_WARNING
{
EXPECT_EQ(request.GetStatus(), AZ::IO::IStreamerTypes::RequestStatus::Completed);
auto& readRequest = AZStd::get<AZ::IO::FileRequest::ReadData>(request.GetCommand());
@@ -784,7 +790,10 @@ namespace AZ::IO
requests[i] = m_context->GetNewInternalRequest();
requests[i]->CreateRead(nullptr, buffers[i].get(), chunkSize, path, i * chunkSize, chunkSize);
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback = [chunkSize, i](const FileRequest& request)
AZ_POP_DISABLE_WARNING
{
EXPECT_EQ(request.GetStatus(), AZ::IO::IStreamerTypes::RequestStatus::Completed);
auto& readRequest = AZStd::get<AZ::IO::FileRequest::ReadData>(request.GetCommand());
@@ -970,7 +979,10 @@ namespace AZ::IO
i * chunkSize
));
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback = [numChunks, &numCallbacks, &waitForReads](FileRequestHandle request)
AZ_POP_DISABLE_WARNING
{
IStreamer* streamer = Interface<IStreamer>::Get();
if (streamer)
@@ -1038,7 +1050,10 @@ namespace AZ::IO
i * chunkSize
));
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback = [numChunks, &waitForReads, &waitForSingleRead, &numReadCallbacks]([[maybe_unused]] FileRequestHandle request)
AZ_POP_DISABLE_WARNING
{
numReadCallbacks++;
if (numReadCallbacks == 1)
@@ -1059,7 +1074,10 @@ namespace AZ::IO
for (size_t i = 0; i < numChunks; ++i)
{
cancels.push_back(m_streamer->Cancel(requests[numChunks - i - 1]));
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback = [&numCancelCallbacks, &waitForCancels, numChunks](FileRequestHandle request)
AZ_POP_DISABLE_WARNING
{
auto result = Interface<IStreamer>::Get()->GetRequestStatus(request);
EXPECT_EQ(result, IStreamerTypes::RequestStatus::Completed);
@@ -327,7 +327,7 @@ namespace JsonSerializationTests
SerializerWithOneType::Unreflect(m_jsonRegistrationContext.get());
}
#if GTEST_OS_SUPPORTS_DEATH_TEST
#if GTEST_HAS_DEATH_TEST
using JsonSerializationDeathTests = JsonRegistrationContextTests;
TEST_F(JsonSerializationDeathTests, DoubleUnregisterSerializer_Asserts)
{
@@ -338,5 +338,6 @@ namespace JsonSerializationTests
}, ".*"
);
}
#endif // GTEST_OS_SUPPORTS_DEATH_TEST
#endif // GTEST_HAS_DEATH_TEST
} //namespace JsonSerializationTests
@@ -363,7 +363,10 @@ namespace AZ
{
constexpr AZStd::array visitTokens = { "Hello", "World", "", "More", "", "", "Tokens" };
size_t visitIndex{};
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto visitor = [&visitIndex, &visitTokens](AZStd::string_view token)
AZ_POP_DISABLE_WARNING
{
if (visitIndex > visitTokens.size())
{
@@ -389,7 +392,10 @@ namespace AZ
{
constexpr AZStd::array visitTokens = { "Hello", "World", "", "More", "", "", "Tokens" };
size_t visitIndex = visitTokens.size() - 1;
AZ_PUSH_DISABLE_WARNING(5233, "-Wunknown-warning-option") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto visitor = [&visitIndex, &visitTokens](AZStd::string_view token)
AZ_POP_DISABLE_WARNING
{
if (visitIndex > visitTokens.size())
{
@@ -72,6 +72,7 @@ set(FILES
Debug/AssetTracking.cpp
Debug/LocalFileEventLoggerTests.cpp
Debug/Trace.cpp
Debug/UnhandledExceptions.cpp
Name/NameJsonSerializerTests.cpp
Name/NameTests.cpp
RTTI/TypeSafeIntegralTests.cpp
@@ -23,10 +23,12 @@ namespace AzFramework
virtual ~XcbEventHandler() = default;
virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0;
// ATTN This is used as a workaround for RAW Input events when using the Editor.
virtual void PollSpecialEvents(){};
};
class XcbEventHandlerBusTraits
: public AZ::EBusTraits
class XcbEventHandlerBusTraits : public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,652 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/std/typetraits/integral_constant.h>
#include <AzFramework/API/ApplicationAPI_Linux.h>
#include <AzFramework/XcbConnectionManager.h>
#include <AzFramework/XcbInputDeviceMouse.h>
namespace AzFramework
{
xcb_window_t GetSystemCursorFocusWindow()
{
void* systemCursorFocusWindow = nullptr;
AzFramework::InputSystemCursorConstraintRequestBus::BroadcastResult(
systemCursorFocusWindow, &AzFramework::InputSystemCursorConstraintRequests::GetSystemCursorConstraintWindow);
if (!systemCursorFocusWindow)
{
return XCB_NONE;
}
// TODO Clang compile error because cast .... loses information. On GNU/Linux HWND is void* and on 64-bit
// machines its obviously 64 bit but we receive the window id from m_renderOverlay.winId() which is xcb_window_t 32-bit.
return static_cast<xcb_window_t>(reinterpret_cast<uint64_t>(systemCursorFocusWindow));
}
xcb_connection_t* XcbInputDeviceMouse::s_xcbConnection = nullptr;
xcb_screen_t* XcbInputDeviceMouse::s_xcbScreen = nullptr;
bool XcbInputDeviceMouse::m_xfixesInitialized = false;
bool XcbInputDeviceMouse::m_xInputInitialized = false;
XcbInputDeviceMouse::XcbInputDeviceMouse(InputDeviceMouse& inputDevice)
: InputDeviceMouse::Implementation(inputDevice)
, m_systemCursorState(SystemCursorState::Unknown)
, m_systemCursorPositionNormalized(0.5f, 0.5f)
, m_prevConstraintWindow(XCB_NONE)
, m_focusWindow(XCB_NONE)
, m_cursorShown(true)
{
XcbEventHandlerBus::Handler::BusConnect();
SetSystemCursorState(SystemCursorState::Unknown);
}
XcbInputDeviceMouse::~XcbInputDeviceMouse()
{
XcbEventHandlerBus::Handler::BusDisconnect();
SetSystemCursorState(SystemCursorState::Unknown);
}
InputDeviceMouse::Implementation* XcbInputDeviceMouse::Create(InputDeviceMouse& inputDevice)
{
auto* interface = AzFramework::XcbConnectionManagerInterface::Get();
if (!interface)
{
AZ_Warning("XcbInput", false, "XCB interface not available");
return nullptr;
}
s_xcbConnection = AzFramework::XcbConnectionManagerInterface::Get()->GetXcbConnection();
if (!s_xcbConnection)
{
AZ_Warning("XcbInput", false, "XCB connection not available");
return nullptr;
}
const xcb_setup_t* xcbSetup = xcb_get_setup(s_xcbConnection);
s_xcbScreen = xcb_setup_roots_iterator(xcbSetup).data;
if (!s_xcbScreen)
{
AZ_Warning("XcbInput", false, "XCB screen not available");
return nullptr;
}
// Initialize XFixes extension which we use to create pointer barriers.
if (!InitializeXFixes())
{
AZ_Warning("XcbInput", false, "XCB XFixes initialization failed");
return nullptr;
}
// Initialize XInput extension which is used to get RAW Input events.
if (!InitializeXInput())
{
AZ_Warning("XcbInput", false, "XCB XInput initialization failed");
return nullptr;
}
return aznew XcbInputDeviceMouse(inputDevice);
}
bool XcbInputDeviceMouse::IsConnected() const
{
return true;
}
void XcbInputDeviceMouse::CreateBarriers(xcb_window_t window, bool create)
{
// Don't create any barriers if we are debugging. This will cause artifacts but better then
// a confined cursor during debugging.
if (AZ::Debug::Trace::IsDebuggerPresent())
{
AZ_Warning("XcbInput", false, "Debugger running. Barriers will not be created.");
return;
}
if (create)
{
// Destroy barriers if they are active already.
if (!m_activeBarriers.empty())
{
for (const auto& barrier : m_activeBarriers)
{
xcb_xfixes_delete_pointer_barrier_checked(s_xcbConnection, barrier.id);
}
m_activeBarriers.clear();
}
// Get window information.
const XcbStdFreePtr<xcb_get_geometry_reply_t> xcbGeometryReply{ xcb_get_geometry_reply(
s_xcbConnection, xcb_get_geometry(s_xcbConnection, window), NULL) };
if (!xcbGeometryReply)
{
return;
}
const xcb_translate_coordinates_cookie_t translate_coord =
xcb_translate_coordinates(s_xcbConnection, window, s_xcbScreen->root, 0, 0);
const XcbStdFreePtr<xcb_translate_coordinates_reply_t> xkbTranslateCoordReply{ xcb_translate_coordinates_reply(
s_xcbConnection, translate_coord, NULL) };
if (!xkbTranslateCoordReply)
{
return;
}
const int16_t x0 = xkbTranslateCoordReply->dst_x < 0 ? 0 : xkbTranslateCoordReply->dst_x;
const int16_t y0 = xkbTranslateCoordReply->dst_y < 0 ? 0 : xkbTranslateCoordReply->dst_y;
const int16_t x1 = xkbTranslateCoordReply->dst_x + xcbGeometryReply->width;
const int16_t y1 = xkbTranslateCoordReply->dst_y + xcbGeometryReply->height;
// ATTN For whatever reason, when making an exact rectangle the pointer will escape the top right corner in some cases. Adding
// an offset to the lines so that they cross each other prevents that.
const int16_t offset = 30;
// Create the left barrier info.
m_activeBarriers.push_back({ xcb_generate_id(s_xcbConnection), XCB_XFIXES_BARRIER_DIRECTIONS_POSITIVE_X, x0, Clamp(y0 - offset),
x0, Clamp(y1 + offset) });
// Create the right barrier info.
m_activeBarriers.push_back({ xcb_generate_id(s_xcbConnection), XCB_XFIXES_BARRIER_DIRECTIONS_NEGATIVE_X, x1, Clamp(y0 - offset),
x1, Clamp(y1 + offset) });
// Create the top barrier info.
m_activeBarriers.push_back({ xcb_generate_id(s_xcbConnection), XCB_XFIXES_BARRIER_DIRECTIONS_POSITIVE_Y, Clamp(x0 - offset), y0,
Clamp(x1 + offset), y0 });
// Create the bottom barrier info.
m_activeBarriers.push_back({ xcb_generate_id(s_xcbConnection), XCB_XFIXES_BARRIER_DIRECTIONS_NEGATIVE_Y, Clamp(x0 - offset), y1,
Clamp(x1 + offset), y1 });
// Create the xfixes barriers.
for (const auto& barrier : m_activeBarriers)
{
xcb_void_cookie_t cookie = xcb_xfixes_create_pointer_barrier_checked(
s_xcbConnection, barrier.id, window, barrier.x0, barrier.y0, barrier.x1, barrier.y1, barrier.direction, 0, NULL);
const XcbStdFreePtr<xcb_generic_error_t> xkbError{ xcb_request_check(s_xcbConnection, cookie) };
AZ_Warning(
"XcbInput", !xkbError, "XFixes, failed to create barrier %d at (%d %d %d %d)", barrier.id, barrier.x0, barrier.y0,
barrier.x1, barrier.y1);
}
}
else
{
for (const auto& barrier : m_activeBarriers)
{
xcb_xfixes_delete_pointer_barrier_checked(s_xcbConnection, barrier.id);
}
m_activeBarriers.clear();
}
xcb_flush(s_xcbConnection);
}
bool XcbInputDeviceMouse::InitializeXFixes()
{
m_xfixesInitialized = false;
// We don't have to free query_extension_reply according to xcb documentation.
const xcb_query_extension_reply_t* query_extension_reply = xcb_get_extension_data(s_xcbConnection, &xcb_xfixes_id);
if (!query_extension_reply || !query_extension_reply->present)
{
return m_xfixesInitialized;
}
const xcb_xfixes_query_version_cookie_t query_cookie = xcb_xfixes_query_version(s_xcbConnection, 5, 0);
xcb_generic_error_t* error = NULL;
const XcbStdFreePtr<xcb_xfixes_query_version_reply_t> xkbQueryRequestReply{ xcb_xfixes_query_version_reply(
s_xcbConnection, query_cookie, &error) };
if (!xkbQueryRequestReply || error)
{
if (error)
{
AZ_Warning("XcbInput", false, "Retrieving XFixes version failed : Error code %d", error->error_code);
free(error);
}
return m_xfixesInitialized;
}
else if (xkbQueryRequestReply->major_version < 5)
{
AZ_Warning("XcbInput", false, "XFixes version fails the minimum version check (%d<5)", xkbQueryRequestReply->major_version);
return m_xfixesInitialized;
}
m_xfixesInitialized = true;
return m_xfixesInitialized;
}
bool XcbInputDeviceMouse::InitializeXInput()
{
m_xInputInitialized = false;
// We don't have to free query_extension_reply according to xcb documentation.
const xcb_query_extension_reply_t* query_extension_reply = xcb_get_extension_data(s_xcbConnection, &xcb_input_id);
if (!query_extension_reply || !query_extension_reply->present)
{
return m_xInputInitialized;
}
const xcb_input_xi_query_version_cookie_t query_version_cookie = xcb_input_xi_query_version(s_xcbConnection, 2, 2);
xcb_generic_error_t* error = NULL;
const XcbStdFreePtr<xcb_input_xi_query_version_reply_t> xkbQueryRequestReply{ xcb_input_xi_query_version_reply(
s_xcbConnection, query_version_cookie, &error) };
if (!xkbQueryRequestReply || error)
{
if (error)
{
AZ_Warning("XcbInput", false, "Retrieving XInput version failed : Error code %d", error->error_code);
free(error);
}
return m_xInputInitialized;
}
else if (xkbQueryRequestReply->major_version < 2)
{
AZ_Warning("XcbInput", false, "XInput version fails the minimum version check (%d<5)", xkbQueryRequestReply->major_version);
return m_xInputInitialized;
}
m_xInputInitialized = true;
return m_xInputInitialized;
}
void XcbInputDeviceMouse::SetEnableXInput(bool enable)
{
struct
{
xcb_input_event_mask_t head;
int mask;
} mask;
mask.head.deviceid = XCB_INPUT_DEVICE_ALL;
mask.head.mask_len = 1;
if (enable)
{
mask.mask = XCB_INPUT_XI_EVENT_MASK_RAW_MOTION | XCB_INPUT_XI_EVENT_MASK_RAW_BUTTON_PRESS |
XCB_INPUT_XI_EVENT_MASK_RAW_BUTTON_RELEASE | XCB_INPUT_XI_EVENT_MASK_MOTION | XCB_INPUT_XI_EVENT_MASK_BUTTON_PRESS |
XCB_INPUT_XI_EVENT_MASK_BUTTON_RELEASE;
}
else
{
mask.mask = XCB_NONE;
}
xcb_input_xi_select_events(s_xcbConnection, s_xcbScreen->root, 1, &mask.head);
xcb_flush(s_xcbConnection);
}
void XcbInputDeviceMouse::SetSystemCursorState(SystemCursorState systemCursorState)
{
if (systemCursorState != m_systemCursorState)
{
m_systemCursorState = systemCursorState;
m_focusWindow = GetSystemCursorFocusWindow();
HandleCursorState(m_focusWindow, systemCursorState);
}
}
void XcbInputDeviceMouse::HandleCursorState(xcb_window_t window, SystemCursorState systemCursorState)
{
bool confined = false, cursorShown = true;
switch (systemCursorState)
{
case SystemCursorState::ConstrainedAndHidden:
{
//!< Constrained to the application's main window and hidden
confined = true;
cursorShown = false;
}
break;
case SystemCursorState::ConstrainedAndVisible:
{
//!< Constrained to the application's main window and visible
confined = true;
}
break;
case SystemCursorState::UnconstrainedAndHidden:
{
//!< Free to move outside the main window but hidden while inside
cursorShown = false;
}
break;
case SystemCursorState::UnconstrainedAndVisible:
{
//!< Free to move outside the application's main window and visible
}
case SystemCursorState::Unknown:
default:
break;
}
// ATTN GetSystemCursorFocusWindow when getting out of the play in editor will return XCB_NONE
// We need however the window id to reset the cursor.
if (XCB_NONE == window && (confined || cursorShown))
{
// Reuse the previous window to reset states.
window = m_prevConstraintWindow;
m_prevConstraintWindow = XCB_NONE;
}
else
{
// Remember the window we used to modify cursor and barrier states.
m_prevConstraintWindow = window;
}
SetEnableXInput(!cursorShown);
CreateBarriers(window, confined);
ShowCursor(window, cursorShown);
}
SystemCursorState XcbInputDeviceMouse::GetSystemCursorState() const
{
return m_systemCursorState;
}
void XcbInputDeviceMouse::SetSystemCursorPositionNormalizedInternal(xcb_window_t window, AZ::Vector2 positionNormalized)
{
// TODO Basically not done at all. Added only the basic functions needed.
const XcbStdFreePtr<xcb_get_geometry_reply_t> xkbGeometryReply{ xcb_get_geometry_reply(
s_xcbConnection, xcb_get_geometry(s_xcbConnection, window), NULL) };
if (!xkbGeometryReply)
{
return;
}
const int16_t x = static_cast<int16_t>(positionNormalized.GetX() * xkbGeometryReply->width);
const int16_t y = static_cast<int16_t>(positionNormalized.GetY() * xkbGeometryReply->height);
xcb_warp_pointer(s_xcbConnection, XCB_NONE, window, 0, 0, 0, 0, x, y);
xcb_flush(s_xcbConnection);
}
void XcbInputDeviceMouse::SetSystemCursorPositionNormalized(AZ::Vector2 positionNormalized)
{
const xcb_window_t window = GetSystemCursorFocusWindow();
if (XCB_NONE == window)
{
return;
}
SetSystemCursorPositionNormalizedInternal(window, positionNormalized);
}
AZ::Vector2 XcbInputDeviceMouse::GetSystemCursorPositionNormalizedInternal(xcb_window_t window) const
{
AZ::Vector2 position = AZ::Vector2::CreateZero();
const xcb_query_pointer_cookie_t pointer = xcb_query_pointer(s_xcbConnection, window);
const XcbStdFreePtr<xcb_query_pointer_reply_t> xkbQueryPointerReply{ xcb_query_pointer_reply(s_xcbConnection, pointer, NULL) };
if (!xkbQueryPointerReply)
{
return position;
}
const XcbStdFreePtr<xcb_get_geometry_reply_t> xkbGeometryReply{ xcb_get_geometry_reply(
s_xcbConnection, xcb_get_geometry(s_xcbConnection, window), NULL) };
if (!xkbGeometryReply)
{
return position;
}
AZ_Assert(xkbGeometryReply->width != 0, "xkbGeometry response width must be non-zero. (%d)", xkbGeometryReply->width);
const float normalizedCursorPostionX = static_cast<float>(xkbQueryPointerReply->win_x) / xkbGeometryReply->width;
AZ_Assert(xkbGeometryReply->height != 0, "xkbGeometry response height must be non-zero. (%d)", xkbGeometryReply->height);
const float normalizedCursorPostionY = static_cast<float>(xkbQueryPointerReply->win_y) / xkbGeometryReply->height;
position = AZ::Vector2(normalizedCursorPostionX, normalizedCursorPostionY);
return position;
}
AZ::Vector2 XcbInputDeviceMouse::GetSystemCursorPositionNormalized() const
{
const xcb_window_t window = GetSystemCursorFocusWindow();
if (XCB_NONE == window)
{
return AZ::Vector2::CreateZero();
}
return GetSystemCursorPositionNormalizedInternal(window);
}
void XcbInputDeviceMouse::TickInputDevice()
{
ProcessRawEventQueues();
}
void XcbInputDeviceMouse::ShowCursor(xcb_window_t window, bool show)
{
xcb_void_cookie_t cookie;
if (show)
{
cookie = xcb_xfixes_show_cursor_checked(s_xcbConnection, window);
}
else
{
cookie = xcb_xfixes_hide_cursor_checked(s_xcbConnection, window);
}
const XcbStdFreePtr<xcb_generic_error_t> xkbError{ xcb_request_check(s_xcbConnection, cookie) };
if (xkbError)
{
AZ_Warning("XcbInput", false, "ShowCursor failed: %d", xkbError->error_code);
return;
}
// ATTN In the following part we will when cursor gets hidden store the position of the cursor in screen space
// not window space. We use that to re-position when showing the cursor again. Is this the correct
// behavior?
const bool cursorWasHidden = !m_cursorShown;
m_cursorShown = show;
if (!m_cursorShown)
{
m_cursorHiddenPosition = GetSystemCursorPositionNormalizedInternal(s_xcbScreen->root);
SetSystemCursorPositionNormalized(AZ::Vector2(0.5f, 0.5f));
}
else if (cursorWasHidden)
{
SetSystemCursorPositionNormalizedInternal(s_xcbScreen->root, m_cursorHiddenPosition);
}
xcb_flush(s_xcbConnection);
}
void XcbInputDeviceMouse::HandleButtonPressEvents(uint32_t detail, bool pressed)
{
bool isWheel;
float wheelDirection;
const auto* button = InputChannelFromMouseEvent(detail, isWheel, wheelDirection);
if (button)
{
QueueRawButtonEvent(*button, pressed);
}
if (isWheel)
{
float axisValue = MAX_XI_WHEEL_SENSITIVITY * wheelDirection;
QueueRawMovementEvent(InputDeviceMouse::Movement::Z, axisValue);
}
}
void XcbInputDeviceMouse::HandlePointerMotionEvents(const xcb_generic_event_t* event)
{
const xcb_input_motion_event_t* mouseMotionEvent = reinterpret_cast<const xcb_input_motion_event_t*>(event);
m_systemCursorPosition[0] = mouseMotionEvent->event_x;
m_systemCursorPosition[1] = mouseMotionEvent->event_y;
}
void XcbInputDeviceMouse::HandleRawInputEvents(const xcb_ge_generic_event_t* event)
{
const xcb_ge_generic_event_t* genericEvent = reinterpret_cast<const xcb_ge_generic_event_t*>(event);
switch (genericEvent->event_type)
{
case XCB_INPUT_RAW_BUTTON_PRESS:
{
const xcb_input_raw_button_press_event_t* mouseButtonEvent =
reinterpret_cast<const xcb_input_raw_button_press_event_t*>(event);
HandleButtonPressEvents(mouseButtonEvent->detail, true);
}
break;
case XCB_INPUT_RAW_BUTTON_RELEASE:
{
const xcb_input_raw_button_release_event_t* mouseButtonEvent =
reinterpret_cast<const xcb_input_raw_button_release_event_t*>(event);
HandleButtonPressEvents(mouseButtonEvent->detail, false);
}
break;
case XCB_INPUT_RAW_MOTION:
{
const xcb_input_raw_motion_event_t* mouseMotionEvent = reinterpret_cast<const xcb_input_raw_motion_event_t*>(event);
int axisLen = xcb_input_raw_button_press_axisvalues_length(mouseMotionEvent);
const xcb_input_fp3232_t* axisvalues = xcb_input_raw_button_press_axisvalues_raw(mouseMotionEvent);
for (int i = 0; i < axisLen; ++i)
{
const float axisValue = fp3232ToFloat(axisvalues[i]);
switch (i)
{
case 0:
QueueRawMovementEvent(InputDeviceMouse::Movement::X, axisValue);
break;
case 1:
QueueRawMovementEvent(InputDeviceMouse::Movement::Y, axisValue);
break;
}
}
}
break;
}
}
void XcbInputDeviceMouse::PollSpecialEvents()
{
while (xcb_generic_event_t* genericEvent = xcb_poll_for_queued_event(s_xcbConnection))
{
// TODO Is the following correct? If we are showing the cursor, don't poll RAW Input events.
switch (genericEvent->response_type & ~0x80)
{
case XCB_GE_GENERIC:
{
const xcb_ge_generic_event_t* geGenericEvent = reinterpret_cast<const xcb_ge_generic_event_t*>(genericEvent);
// Only handle raw inputs if we have focus.
// Handle Raw Input events first.
if ((geGenericEvent->event_type == XCB_INPUT_RAW_BUTTON_PRESS) ||
(geGenericEvent->event_type == XCB_INPUT_RAW_BUTTON_RELEASE) ||
(geGenericEvent->event_type == XCB_INPUT_RAW_MOTION))
{
HandleRawInputEvents(geGenericEvent);
free(genericEvent);
}
}
break;
}
}
}
void XcbInputDeviceMouse::HandleXcbEvent(xcb_generic_event_t* event)
{
switch (event->response_type & ~0x80)
{
// QT5 is using by default XInput which means we do need to check for XCB_GE_GENERIC event to parse all mouse related events.
case XCB_GE_GENERIC:
{
const xcb_ge_generic_event_t* genericEvent = reinterpret_cast<const xcb_ge_generic_event_t*>(event);
// Handling RAW Inputs here works in GameMode but not in Editor mode because QT is
// not handling RAW input events and passing to.
if (!m_cursorShown)
{
// Handle Raw Input events first.
if ((genericEvent->event_type == XCB_INPUT_RAW_BUTTON_PRESS) ||
(genericEvent->event_type == XCB_INPUT_RAW_BUTTON_RELEASE) || (genericEvent->event_type == XCB_INPUT_RAW_MOTION))
{
HandleRawInputEvents(genericEvent);
}
}
else
{
switch (genericEvent->event_type)
{
case XCB_INPUT_BUTTON_PRESS:
{
const xcb_input_button_press_event_t* mouseButtonEvent =
reinterpret_cast<const xcb_input_button_press_event_t*>(genericEvent);
HandleButtonPressEvents(mouseButtonEvent->detail, true);
}
break;
case XCB_INPUT_BUTTON_RELEASE:
{
const xcb_input_button_release_event_t* mouseButtonEvent =
reinterpret_cast<const xcb_input_button_release_event_t*>(genericEvent);
HandleButtonPressEvents(mouseButtonEvent->detail, false);
}
break;
case XCB_INPUT_MOTION:
{
HandlePointerMotionEvents(event);
}
break;
}
}
}
break;
case XCB_FOCUS_IN:
{
const xcb_focus_in_event_t* focusInEvent = reinterpret_cast<const xcb_focus_in_event_t*>(event);
if (m_focusWindow != focusInEvent->event)
{
m_focusWindow = focusInEvent->event;
HandleCursorState(m_focusWindow, m_systemCursorState);
}
}
break;
case XCB_FOCUS_OUT:
{
const xcb_focus_out_event_t* focusOutEvent = reinterpret_cast<const xcb_focus_out_event_t*>(event);
HandleCursorState(focusOutEvent->event, SystemCursorState::UnconstrainedAndVisible);
ProcessRawEventQueues();
ResetInputChannelStates();
m_focusWindow = XCB_NONE;
}
break;
}
}
} // namespace AzFramework
@@ -0,0 +1,193 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/XcbConnectionManager.h>
#include <AzFramework/XcbEventHandler.h>
#include <AzFramework/XcbInterface.h>
#include <xcb/xfixes.h>
#include <xcb/xinput.h>
// The maximum number of raw input axis this mouse device supports.
constexpr uint32_t MAX_XI_RAW_AXIS = 2;
// The sensitivity of the wheel.
constexpr float MAX_XI_WHEEL_SENSITIVITY = 140.0f;
namespace AzFramework
{
class XcbInputDeviceMouse
: public InputDeviceMouse::Implementation
, public XcbEventHandlerBus::Handler
{
public:
AZ_CLASS_ALLOCATOR(XcbInputDeviceMouse, AZ::SystemAllocator, 0);
////////////////////////////////////////////////////////////////////////////////////////////
//! Constructor
//! \param[in] inputDevice Reference to the input device being implemented
XcbInputDeviceMouse(InputDeviceMouse& inputDevice);
////////////////////////////////////////////////////////////////////////////////////////////
//! Destructor
virtual ~XcbInputDeviceMouse();
static XcbInputDeviceMouse::Implementation* Create(InputDeviceMouse& inputDevice);
protected:
////////////////////////////////////////////////////////////////////////////////////////////
//! \ref AzFramework::InputDeviceMouse::Implementation::IsConnected
bool IsConnected() const override;
////////////////////////////////////////////////////////////////////////////////////////////
//! \ref AzFramework::InputDeviceMouse::Implementation::SetSystemCursorState
void SetSystemCursorState(SystemCursorState systemCursorState) override;
////////////////////////////////////////////////////////////////////////////////////////////
//! \ref AzFramework::InputDeviceMouse::Implementation::GetSystemCursorState
SystemCursorState GetSystemCursorState() const override;
////////////////////////////////////////////////////////////////////////////////////////////
//! \ref AzFramework::InputDeviceMouse::Implementation::SetSystemCursorPositionNormalized
void SetSystemCursorPositionNormalized(AZ::Vector2 positionNormalized) override;
////////////////////////////////////////////////////////////////////////////////////////////
//! \ref AzFramework::InputDeviceMouse::Implementation::GetSystemCursorPositionNormalized
AZ::Vector2 GetSystemCursorPositionNormalized() const override;
////////////////////////////////////////////////////////////////////////////////////////////
//! \ref AzFramework::InputDeviceMouse::Implementation::TickInputDevice
void TickInputDevice() override;
//! This method is called by the Editor to accommodate some events with the Editor. Never called in Game mode.
void PollSpecialEvents() override;
//! Handle X11 events.
void HandleXcbEvent(xcb_generic_event_t* event) override;
//! Initialize XFixes extension. Used for barriers.
static bool InitializeXFixes();
//! Initialize XInput extension. Used for raw input during confinement and showing/hiding the cursor.
static bool InitializeXInput();
//! Enables/Disables XInput Raw Input events.
void SetEnableXInput(bool enable);
//! Create barriers.
void CreateBarriers(xcb_window_t window, bool create);
//! Helper function.
void SystemCursorStateToLogic(SystemCursorState systemCursorState, bool& confined, bool& cursorShown);
//! Shows/Hides the cursor.
void ShowCursor(xcb_window_t window, bool show);
//! Get the normalized cursor position. The coordinates returned are relative to the specified window.
AZ::Vector2 GetSystemCursorPositionNormalizedInternal(xcb_window_t window) const;
//! Set the normalized cursor position. The normalized position will be relative to the specified window.
void SetSystemCursorPositionNormalizedInternal(xcb_window_t window, AZ::Vector2 positionNormalized);
//! Handle button press/release events.
void HandleButtonPressEvents(uint32_t detail, bool pressed);
//! Handle motion notify events.
void HandlePointerMotionEvents(const xcb_generic_event_t* event);
//! Will set cursor states and confinement modes.
void HandleCursorState(xcb_window_t window, SystemCursorState systemCursorState);
//! Will handle all raw input events.
void HandleRawInputEvents(const xcb_ge_generic_event_t* event);
//! Convert XInput fp1616 to float.
inline float fp1616ToFloat(xcb_input_fp1616_t value) const
{
return static_cast<float>((value >> 16) + (value & 0xffff) / 0xffff);
}
//! Convert XInput fp3232 to float.
inline float fp3232ToFloat(xcb_input_fp3232_t value) const
{
return static_cast<float>(value.integral) + static_cast<float>(value.frac / (float)(1ull << 32));
}
const InputChannelId* InputChannelFromMouseEvent(xcb_button_t button, bool& isWheel, float& direction) const
{
isWheel = false;
direction = 1.0f;
switch (button)
{
case XCB_BUTTON_INDEX_1:
return &InputDeviceMouse::Button::Left;
case XCB_BUTTON_INDEX_2:
return &InputDeviceMouse::Button::Right;
case XCB_BUTTON_INDEX_3:
return &InputDeviceMouse::Button::Middle;
case XCB_BUTTON_INDEX_4:
isWheel = true;
direction = 1.0f;
break;
case XCB_BUTTON_INDEX_5:
isWheel = true;
direction = -1.0f;
break;
default:
break;
}
return nullptr;
}
// Barriers work only with positive values. We clamp here to zero.
inline int16_t Clamp(int16_t value) const
{
return value < 0 ? 0 : value;
}
private:
//! The current system cursor state
SystemCursorState m_systemCursorState;
//! The cursor position before it got hidden.
AZ::Vector2 m_cursorHiddenPosition;
AZ::Vector2 m_systemCursorPositionNormalized;
uint32_t m_systemCursorPosition[MAX_XI_RAW_AXIS];
static xcb_connection_t* s_xcbConnection;
static xcb_screen_t* s_xcbScreen;
//! Will be true if the xfixes extension could be initialized.
static bool m_xfixesInitialized;
//! Will be true if the xinput2 extension could be initialized.
static bool m_xInputInitialized;
//! The window that had focus
xcb_window_t m_prevConstraintWindow;
//! The current window that has focus
xcb_window_t m_focusWindow;
//! Will be true if the cursor is shown else false.
bool m_cursorShown;
struct XFixesBarrierProperty
{
xcb_xfixes_barrier_t id;
uint32_t direction;
int16_t x0, y0, x1, y1;
};
//! Array that holds barrier information used to confine the cursor.
std::vector<XFixesBarrierProperty> m_activeBarriers;
};
} // namespace AzFramework
@@ -8,25 +8,31 @@
#include <AzFramework/Application/Application.h>
#include <AzFramework/Windowing/NativeWindow.h>
#include <AzFramework/XcbNativeWindow.h>
#include <AzFramework/XcbConnectionManager.h>
#include <AzFramework/XcbInterface.h>
#include <AzFramework/XcbNativeWindow.h>
#include <xcb/xcb.h>
namespace AzFramework
{
[[maybe_unused]] const char XcbErrorWindow[] = "XcbNativeWindow";
static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages
static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified
static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event
static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages
static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified
static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event
#define _NET_WM_STATE_REMOVE 0l
#define _NET_WM_STATE_ADD 1l
#define _NET_WM_STATE_TOGGLE 2l
////////////////////////////////////////////////////////////////////////////////////////////////
XcbNativeWindow::XcbNativeWindow()
XcbNativeWindow::XcbNativeWindow()
: NativeWindow::Implementation()
, m_xcbConnection(nullptr)
, m_xcbRootScreen(nullptr)
, m_xcbWindow(XCB_NONE)
{
if (auto xcbConnectionManager = AzFramework::XcbConnectionManagerInterface::Get();
xcbConnectionManager != nullptr)
if (auto xcbConnectionManager = AzFramework::XcbConnectionManagerInterface::Get(); xcbConnectionManager != nullptr)
{
m_xcbConnection = xcbConnectionManager->GetXcbConnection();
}
@@ -34,89 +40,184 @@ namespace AzFramework
}
////////////////////////////////////////////////////////////////////////////////////////////////
XcbNativeWindow::~XcbNativeWindow() = default;
XcbNativeWindow::~XcbNativeWindow()
{
if (XCB_NONE != m_xcbWindow)
{
xcb_destroy_window(m_xcbConnection, m_xcbWindow);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
void XcbNativeWindow::InitWindow(const AZStd::string& title,
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks)
void XcbNativeWindow::InitWindow(const AZStd::string& title, const WindowGeometry& geometry, const WindowStyleMasks& styleMasks)
{
// Get the parent window
// Get the parent window
const xcb_setup_t* xcbSetup = xcb_get_setup(m_xcbConnection);
xcb_screen_t* xcbRootScreen = xcb_setup_roots_iterator(xcbSetup).data;
xcb_window_t xcbParentWindow = xcbRootScreen->root;
m_xcbRootScreen = xcb_setup_roots_iterator(xcbSetup).data;
xcb_window_t xcbParentWindow = m_xcbRootScreen->root;
// Create an XCB window from the connection
m_xcbWindow = xcb_generate_id(m_xcbConnection);
uint16_t borderWidth = 0;
const uint32_t mask = styleMasks.m_platformAgnosticStyleMask;
if ((mask & WindowStyleMasks::WINDOW_STYLE_BORDERED) ||
(mask & WindowStyleMasks::WINDOW_STYLE_RESIZEABLE))
if ((mask & WindowStyleMasks::WINDOW_STYLE_BORDERED) || (mask & WindowStyleMasks::WINDOW_STYLE_RESIZEABLE))
{
borderWidth = s_DefaultXcbWindowBorderWidth;
}
uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
const uint32_t interestedEvents =
XCB_EVENT_MASK_STRUCTURE_NOTIFY
| XCB_EVENT_MASK_BUTTON_PRESS
| XCB_EVENT_MASK_BUTTON_RELEASE
| XCB_EVENT_MASK_KEY_PRESS
| XCB_EVENT_MASK_KEY_RELEASE
| XCB_EVENT_MASK_POINTER_MOTION
;
uint32_t valueList[] = { xcbRootScreen->black_pixel,
interestedEvents };
const uint32_t interestedEvents = XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE;
uint32_t valueList[] = { m_xcbRootScreen->black_pixel, interestedEvents };
xcb_void_cookie_t xcbCheckResult;
xcbCheckResult = xcb_create_window_checked(m_xcbConnection,
XCB_COPY_FROM_PARENT,
m_xcbWindow,
xcbParentWindow,
aznumeric_cast<int16_t>(geometry.m_posX),
aznumeric_cast<int16_t>(geometry.m_posY),
aznumeric_cast<int16_t>(geometry.m_width),
aznumeric_cast<int16_t>(geometry.m_height),
borderWidth,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
xcbRootScreen->root_visual,
eventMask,
valueList);
xcbCheckResult = xcb_create_window_checked(
m_xcbConnection, XCB_COPY_FROM_PARENT, m_xcbWindow, xcbParentWindow, aznumeric_cast<int16_t>(geometry.m_posX),
aznumeric_cast<int16_t>(geometry.m_posY), aznumeric_cast<int16_t>(geometry.m_width), aznumeric_cast<int16_t>(geometry.m_height),
borderWidth, XCB_WINDOW_CLASS_INPUT_OUTPUT, m_xcbRootScreen->root_visual, eventMask, valueList);
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to create xcb window.");
SetWindowTitle(title);
// Setup the window close event
const static char* wmProtocolString = "WM_PROTOCOLS";
xcb_intern_atom_cookie_t cookieProtocol = xcb_intern_atom(m_xcbConnection, 1, strlen(wmProtocolString), wmProtocolString);
xcb_intern_atom_reply_t* replyProtocol = xcb_intern_atom_reply(m_xcbConnection, cookieProtocol, nullptr);
AZ_Error(XcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString);
m_xcbAtomProtocols = replyProtocol->atom;
const static char* wmDeleteWindowString = "WM_DELETE_WINDOW";
xcb_intern_atom_cookie_t cookieDeleteWindow = xcb_intern_atom(m_xcbConnection, 0, strlen(wmDeleteWindowString), wmDeleteWindowString);
xcb_intern_atom_reply_t* replyDeleteWindow = xcb_intern_atom_reply(m_xcbConnection, cookieDeleteWindow, nullptr);
AZ_Error(XcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString);
m_xcbAtomDeleteWindow = replyDeleteWindow->atom;
xcbCheckResult = xcb_change_property_checked(m_xcbConnection,
XCB_PROP_MODE_REPLACE,
m_xcbWindow,
m_xcbAtomProtocols,
XCB_ATOM_ATOM,
s_XcbFormatDataSize,
1,
&m_xcbAtomDeleteWindow);
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to change the xcb atom property for WM_CLOSE event");
m_posX = geometry.m_posX;
m_posY = geometry.m_posY;
m_width = geometry.m_width;
m_height = geometry.m_height;
InitializeAtoms();
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.type = _NET_REQUEST_FRAME_EXTENTS;
event.window = m_xcbWindow;
event.format = 32;
event.sequence = 0;
event.data.data32[0] = 0l;
event.data.data32[1] = 0l;
event.data.data32[2] = 0l;
event.data.data32[3] = 0l;
event.data.data32[4] = 0l;
xcbCheckResult = xcb_send_event(
m_xcbConnection, 1, m_xcbRootScreen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
(const char*)&event);
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set _NET_REQUEST_FRAME_EXTENTS");
// The WM will be able to kill the application if it gets unresponsive.
int32_t pid = getpid();
xcb_change_property(m_xcbConnection, XCB_PROP_MODE_REPLACE, m_xcbWindow, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &pid);
xcb_flush(m_xcbConnection);
}
xcb_atom_t XcbNativeWindow::GetAtom(const char* atomName)
{
xcb_intern_atom_cookie_t intern_atom_cookie = xcb_intern_atom(m_xcbConnection, 0, strlen(atomName), atomName);
XcbStdFreePtr<xcb_intern_atom_reply_t> xkbinternAtom{ xcb_intern_atom_reply(m_xcbConnection, intern_atom_cookie, NULL) };
if (!xkbinternAtom)
{
AZ_Error(XcbErrorWindow, xkbinternAtom != nullptr, "Unable to query xcb '%s' atom", atomName);
return XCB_NONE;
}
return xkbinternAtom->atom;
}
int XcbNativeWindow::SetAtom(xcb_window_t window, xcb_atom_t atom, xcb_atom_t type, size_t len, void* data)
{
xcb_void_cookie_t cookie = xcb_change_property_checked(m_xcbConnection, XCB_PROP_MODE_REPLACE, window, atom, type, 32, len, data);
XcbStdFreePtr<xcb_generic_error_t> xkbError{ xcb_request_check(m_xcbConnection, cookie) };
if (!xkbError)
{
return 0;
}
return xkbError->error_code;
}
////////////////////////////////////////////////////////////////////////////////////////////////
void XcbNativeWindow::InitializeAtoms()
{
AZStd::vector<xcb_atom_t> Atoms;
_NET_ACTIVE_WINDOW = GetAtom("_NET_ACTIVE_WINDOW");
_NET_WM_BYPASS_COMPOSITOR = GetAtom("_NET_WM_BYPASS_COMPOSITOR");
// ---------------------------------------------------------------------
// Handle all WM Protocols atoms.
//
WM_PROTOCOLS = GetAtom("WM_PROTOCOLS");
// This atom is used to close a window. Emitted when user clicks the close button.
WM_DELETE_WINDOW = GetAtom("WM_DELETE_WINDOW");
Atoms.push_back(WM_DELETE_WINDOW);
xcb_change_property(
m_xcbConnection, XCB_PROP_MODE_REPLACE, m_xcbWindow, WM_PROTOCOLS, XCB_ATOM_ATOM, 32, Atoms.size(), Atoms.data());
xcb_flush(m_xcbConnection);
// ---------------------------------------------------------------------
// Handle all WM State atoms.
//
_NET_WM_STATE = GetAtom("_NET_WM_STATE");
_NET_WM_STATE_FULLSCREEN = GetAtom("_NET_WM_STATE_FULLSCREEN");
_NET_WM_STATE_MAXIMIZED_VERT = GetAtom("_NET_WM_STATE_MAXIMIZED_VERT");
_NET_WM_STATE_MAXIMIZED_HORZ = GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ");
_NET_MOVERESIZE_WINDOW = GetAtom("_NET_MOVERESIZE_WINDOW");
_NET_REQUEST_FRAME_EXTENTS = GetAtom("_NET_REQUEST_FRAME_EXTENTS");
_NET_FRAME_EXTENTS = GetAtom("_NET_FRAME_EXTENTS");
_NET_WM_PID = GetAtom("_NET_WM_PID");
}
void XcbNativeWindow::GetWMStates()
{
xcb_get_property_cookie_t cookie = xcb_get_property(m_xcbConnection, 0, m_xcbWindow, _NET_WM_STATE, XCB_ATOM_ATOM, 0, 1024);
xcb_generic_error_t* error = nullptr;
XcbStdFreePtr<xcb_get_property_reply_t> xkbGetPropertyReply{ xcb_get_property_reply(m_xcbConnection, cookie, &error) };
if (!xkbGetPropertyReply || error || !((xkbGetPropertyReply->format == 32) && (xkbGetPropertyReply->type == XCB_ATOM_ATOM)))
{
AZ_Warning("ApplicationLinux", false, "Acquiring _NET_WM_STATE information from the WM failed.");
if (error)
{
AZ_TracePrintf("Error", "Error code %d", error->error_code);
free(error);
}
return;
}
m_fullscreenState = false;
m_horizontalyMaximized = false;
m_verticallyMaximized = false;
const xcb_atom_t* states = static_cast<const xcb_atom_t*>(xcb_get_property_value(xkbGetPropertyReply.get()));
for (int i = 0; i < xkbGetPropertyReply->length; i++)
{
if (states[i] == _NET_WM_STATE_FULLSCREEN)
{
m_fullscreenState = true;
}
else if (states[i] == _NET_WM_STATE_MAXIMIZED_HORZ)
{
m_horizontalyMaximized = true;
}
else if (states[i] == _NET_WM_STATE_MAXIMIZED_VERT)
{
m_verticallyMaximized = true;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
@@ -146,7 +247,7 @@ namespace AzFramework
xcb_flush(m_xcbConnection);
}
XcbEventHandlerBus::Handler::BusDisconnect();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
NativeWindowHandle XcbNativeWindow::GetWindowHandle() const
@@ -158,14 +259,9 @@ namespace AzFramework
void XcbNativeWindow::SetWindowTitle(const AZStd::string& title)
{
xcb_void_cookie_t xcbCheckResult;
xcbCheckResult = xcb_change_property(m_xcbConnection,
XCB_PROP_MODE_REPLACE,
m_xcbWindow,
XCB_ATOM_WM_NAME,
XCB_ATOM_STRING,
8,
static_cast<uint32_t>(title.size()),
title.c_str());
xcbCheckResult = xcb_change_property(
m_xcbConnection, XCB_PROP_MODE_REPLACE, m_xcbWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, static_cast<uint32_t>(title.size()),
title.c_str());
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set window title.");
}
@@ -175,7 +271,7 @@ namespace AzFramework
const uint32_t values[] = { clientAreaSize.m_width, clientAreaSize.m_height };
xcb_configure_window(m_xcbConnection, m_xcbWindow, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
m_width = clientAreaSize.m_width;
m_height = clientAreaSize.m_height;
}
@@ -185,16 +281,77 @@ namespace AzFramework
{
// [GFX TODO][GHI - 2678]
// Using 60 for now until proper support is added
return 60;
}
bool XcbNativeWindow::GetFullScreenState() const
{
return m_fullscreenState;
}
void XcbNativeWindow::SetFullScreenState(bool fullScreenState)
{
// TODO This is a pretty basic full-screen implementation using WM's _NET_WM_STATE_FULLSCREEN state.
// Do we have to provide also the old way?
GetWMStates();
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.type = _NET_WM_STATE;
event.window = m_xcbWindow;
event.format = 32;
event.sequence = 0;
event.data.data32[0] = fullScreenState ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
event.data.data32[1] = _NET_WM_STATE_FULLSCREEN;
event.data.data32[2] = 0;
event.data.data32[3] = 1;
event.data.data32[4] = 0;
xcb_void_cookie_t xcbCheckResult = xcb_send_event(
m_xcbConnection, 1, m_xcbRootScreen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
(const char*)&event);
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set _NET_WM_STATE_FULLSCREEN");
// Also try to disable/enable the compositor if possible. Might help in some cases.
const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = m_fullscreenState ? 1 : 0;
SetAtom(m_xcbWindow, _NET_WM_BYPASS_COMPOSITOR, XCB_ATOM_CARDINAL, 32, (char*)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON);
if (!fullScreenState)
{
if (m_horizontalyMaximized || m_verticallyMaximized)
{
printf("Remove maximized state.\n");
xcb_client_message_event_t event;
event.response_type = XCB_CLIENT_MESSAGE;
event.type = _NET_WM_STATE;
event.window = m_xcbWindow;
event.format = 32;
event.sequence = 0;
event.data.data32[0] = _NET_WM_STATE_MAXIMIZED_VERT;
event.data.data32[1] = _NET_WM_STATE_MAXIMIZED_HORZ;
event.data.data32[2] = 0;
event.data.data32[3] = 0;
event.data.data32[4] = 0;
xcb_void_cookie_t xcbCheckResult = xcb_send_event(
m_xcbConnection, 1, m_xcbRootScreen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
(const char*)&event);
AZ_Assert(
ValidateXcbResult(xcbCheckResult), "Failed to remove _NET_WM_STATE_MAXIMIZED_VERT | _NET_WM_STATE_MAXIMIZED_HORZ");
}
}
xcb_flush(m_xcbConnection);
m_fullscreenState = fullScreenState;
}
////////////////////////////////////////////////////////////////////////////////////////////////
bool XcbNativeWindow::ValidateXcbResult(xcb_void_cookie_t cookie)
{
bool result = true;
if (xcb_generic_error_t* error = xcb_request_check(m_xcbConnection, cookie))
{
AZ_TracePrintf("Error","Error code %d", error->error_code);
AZ_TracePrintf("Error", "Error code %d", error->error_code);
result = false;
}
return result;
@@ -205,20 +362,20 @@ namespace AzFramework
{
switch (event->response_type & s_XcbResponseTypeMask)
{
case XCB_CONFIGURE_NOTIFY:
case XCB_CONFIGURE_NOTIFY:
{
xcb_configure_notify_event_t* cne = reinterpret_cast<xcb_configure_notify_event_t*>(event);
WindowSizeChanged(aznumeric_cast<uint32_t>(cne->width),
aznumeric_cast<uint32_t>(cne->height));
if ((cne->width != m_width) || (cne->height != m_height))
{
WindowSizeChanged(aznumeric_cast<uint32_t>(cne->width), aznumeric_cast<uint32_t>(cne->height));
}
break;
}
case XCB_CLIENT_MESSAGE:
case XCB_CLIENT_MESSAGE:
{
xcb_client_message_event_t* cme = reinterpret_cast<xcb_client_message_event_t*>(event);
if ((cme->type == m_xcbAtomProtocols) &&
(cme->format == s_XcbFormatDataSize) &&
(cme->data.data32[0] == m_xcbAtomDeleteWindow))
if ((cme->type == WM_PROTOCOLS) && (cme->format == s_XcbFormatDataSize) && (cme->data.data32[0] == WM_DELETE_WINDOW))
{
Deactivate();
@@ -239,7 +396,8 @@ namespace AzFramework
if (m_activated)
{
WindowNotificationBus::Event(reinterpret_cast<NativeWindowHandle>(m_xcbWindow), &WindowNotificationBus::Events::OnWindowResized, width, height);
WindowNotificationBus::Event(
reinterpret_cast<NativeWindowHandle>(m_xcbWindow), &WindowNotificationBus::Events::OnWindowResized, width, height);
}
}
}
@@ -27,15 +27,16 @@ namespace AzFramework
////////////////////////////////////////////////////////////////////////////////////////////
// NativeWindow::Implementation
void InitWindow(const AZStd::string& title,
const WindowGeometry& geometry,
const WindowStyleMasks& styleMasks) override;
void InitWindow(const AZStd::string& title, const WindowGeometry& geometry, const WindowStyleMasks& styleMasks) override;
void Activate() override;
void Deactivate() override;
NativeWindowHandle GetWindowHandle() const override;
void SetWindowTitle(const AZStd::string& title) override;
void ResizeClientArea(WindowSize clientAreaSize) override;
uint32_t GetDisplayRefreshRate() const override;
uint32_t GetDisplayRefreshRate() const override;
bool GetFullScreenState() const override;
void SetFullScreenState(bool fullScreenState) override;
////////////////////////////////////////////////////////////////////////////////////////////
// XcbEventHandlerBus::Handler
@@ -44,10 +45,46 @@ namespace AzFramework
private:
bool ValidateXcbResult(xcb_void_cookie_t cookie);
void WindowSizeChanged(const uint32_t width, const uint32_t height);
int SetAtom(xcb_window_t window, xcb_atom_t atom, xcb_atom_t type, size_t len, void* data);
xcb_connection_t* m_xcbConnection = nullptr;
xcb_window_t m_xcbWindow = 0;
xcb_atom_t m_xcbAtomProtocols;
xcb_atom_t m_xcbAtomDeleteWindow;
// Initialize one atom.
xcb_atom_t GetAtom(const char* atomName);
// Initialize all used atoms.
void InitializeAtoms();
void GetWMStates();
xcb_connection_t* m_xcbConnection = nullptr;
xcb_screen_t* m_xcbRootScreen = nullptr;
xcb_window_t m_xcbWindow = 0;
int32_t m_posX;
int32_t m_posY;
bool m_fullscreenState = false;
bool m_horizontalyMaximized = false;
bool m_verticallyMaximized = false;
// Use exact atom names for easy readability and usage.
xcb_atom_t WM_PROTOCOLS;
xcb_atom_t WM_DELETE_WINDOW;
// This atom is used to activate a window.
xcb_atom_t _NET_ACTIVE_WINDOW;
// This atom is use to bypass a compositor. Used during fullscreen mode.
xcb_atom_t _NET_WM_BYPASS_COMPOSITOR;
// This atom is used to change the state of a window using the WM.
xcb_atom_t _NET_WM_STATE;
// This atom is used to enable/disable fullscreen mode of a window.
xcb_atom_t _NET_WM_STATE_FULLSCREEN;
// This atom is used to extend the window to max vertically.
xcb_atom_t _NET_WM_STATE_MAXIMIZED_VERT;
// This atom is used to extend the window to max horizontally.
xcb_atom_t _NET_WM_STATE_MAXIMIZED_HORZ;
// This atom is used to position and resize a window.
xcb_atom_t _NET_MOVERESIZE_WINDOW;
// This atom is used to request the extent of the window.
xcb_atom_t _NET_REQUEST_FRAME_EXTENTS;
// This atom is used to identify the reply event for _NET_REQUEST_FRAME_EXTENTS
xcb_atom_t _NET_FRAME_EXTENTS;
// This atom is used to allow WM to kill app if not responsive anymore
xcb_atom_t _NET_WM_PID;
};
} // namespace AzFramework
@@ -12,6 +12,8 @@ set(FILES
AzFramework/XcbConnectionManager.h
AzFramework/XcbInputDeviceKeyboard.cpp
AzFramework/XcbInputDeviceKeyboard.h
AzFramework/XcbInputDeviceMouse.cpp
AzFramework/XcbInputDeviceMouse.h
AzFramework/XcbInterface.h
AzFramework/XcbNativeWindow.cpp
AzFramework/XcbNativeWindow.h
@@ -0,0 +1,27 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
#include <AzFramework/XcbInputDeviceMouse.h>
#endif
namespace AzFramework
{
InputDeviceMouse::Implementation* InputDeviceMouse::Implementation::Create(InputDeviceMouse& inputDevice)
{
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
return XcbInputDeviceMouse::Create(inputDevice);
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
#error "Linux Window Manager Wayland not supported."
return nullptr;
#else
#error "Linux Window Manager not recognized."
return nullptr;
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
}
} // namespace AzFramework
@@ -22,8 +22,10 @@ if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb")
PRIVATE
3rdParty::X11::xcb
3rdParty::X11::xcb_xkb
3rdParty::X11::xcb_xfixes
3rdParty::X11::xkbcommon
3rdParty::X11::xkbcommon_X11
xcb-xinput
)
elseif(PAL_TRAIT_LINUX_WINDOW_MANAGER STREQUAL "wayland")
@@ -22,8 +22,8 @@ set(FILES
AzFramework/Windowing/NativeWindow_Linux.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp
AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Linux.cpp
AzFramework/Input/Devices/Mouse/InputDeviceMouse_Linux.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Motion/InputDeviceMotion_Unimplemented.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Mouse/InputDeviceMouse_Unimplemented.cpp
../Common/Unimplemented/AzFramework/Input/Devices/Touch/InputDeviceTouch_Unimplemented.cpp
AzFramework/Input/User/LocalUserId_Platform.h
../Common/Default/AzFramework/Input/User/LocalUserId_Default.h
@@ -569,11 +569,12 @@ namespace UnitTest
FillSpawnable(NumEntities);
CreateEntityReferences(refScheme);
AZ_PUSH_DISABLE_WARNING(5233, "-Wunused-lambda-capture") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback =
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
AZ_POP_DISABLE_WARNING
{
AZ_UNUSED(refScheme);
AZ_UNUSED(NumEntities);
ValidateEntityReferences(refScheme, NumEntities, entities);
};
@@ -591,11 +592,12 @@ namespace UnitTest
FillSpawnable(NumEntities);
CreateEntityReferences(refScheme);
AZ_PUSH_DISABLE_WARNING(5233, "-Wunused-lambda-capture") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback =
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
AZ_POP_DISABLE_WARNING
{
AZ_UNUSED(refScheme);
AZ_UNUSED(NumEntities);
ValidateEntityReferences(refScheme, NumEntities, entities);
};
@@ -720,11 +722,12 @@ namespace UnitTest
FillSpawnable(NumEntities);
CreateEntityReferences(refScheme);
AZ_PUSH_DISABLE_WARNING(5233, "-Wunused-lambda-capture") // Older versions of MSVC toolchain require to pass constexpr in the
// capture. Newer versions issue unused warning
auto callback =
[this, refScheme, NumEntities](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableConstEntityContainerView entities)
AZ_POP_DISABLE_WARNING
{
AZ_UNUSED(refScheme);
AZ_UNUSED(NumEntities);
ValidateEntityReferences(refScheme, NumEntities, entities);
};
+6 -11
View File
@@ -90,19 +90,16 @@ namespace AZ
}
}
//! Filter out integration tests from the test run
void excludeIntegTests()
{
AddExcludeFilter("INTEG_*");
AddExcludeFilter("Integ_*");
}
void ApplyGlobalParameters(int* argc, char** argv)
{
// this is a hook that can be used to apply any other global non-google parameters
// that we use.
// this is a hook that can be used to apply any other global parameters that we use.
AZ_UNUSED(argc);
AZ_UNUSED(argv);
// Disable gtest catching unhandled exceptions, instead, AzTestRunner will do it through:
// AZ::Debug::Trace::HandleExceptions(true). This gives us a stack trace when the exception
// is thrown (googletest does not).
testing::FLAGS_gtest_catch_exceptions = false;
}
//! Print out parameters that are not used by the framework
@@ -160,7 +157,6 @@ namespace AZ
}
::testing::InitGoogleMock(&argc, argv);
AZ::Test::excludeIntegTests();
AZ::Test::ApplyGlobalParameters(&argc, argv);
AZ::Test::printUnusedParametersWarning(argc, argv);
AZ::Test::addTestEnvironments(m_envs);
@@ -281,7 +277,6 @@ namespace AZ
}
}
AZ::Test::excludeIntegTests();
AZ::Test::printUnusedParametersWarning(argc, argv);
return RUN_ALL_TESTS();
-2
View File
@@ -104,7 +104,6 @@ namespace AZ
void addTestEnvironment(ITestEnvironment* env);
void addTestEnvironments(std::vector<ITestEnvironment*> envs);
void excludeIntegTests();
//! A hook that can be used to read any other misc parameters and remove them before google sees them.
//! Note that this modifies argc and argv to delete the parameters it consumes.
@@ -266,7 +265,6 @@ namespace AZ
::testing::TestEventListeners& listeners = testing::UnitTest::GetInstance()->listeners(); \
listeners.Append(new AZ::Test::OutputEventListener); \
} \
AZ::Test::excludeIntegTests(); \
AZ::Test::ApplyGlobalParameters(&argc, argv); \
AZ::Test::printUnusedParametersWarning(argc, argv); \
AZ::Test::addTestEnvironments({TEST_ENV}); \
@@ -43,8 +43,7 @@ namespace AzToolsFramework
};
//! Provides a bus to notify when the different editor modes are entered/exit.
class ViewportEditorModeNotifications
: public AZ::EBusTraits
class ViewportEditorModeNotifications : public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
@@ -58,14 +57,17 @@ namespace AzToolsFramework
static void Reflect(AZ::ReflectContext* context);
//! Notifies subscribers of the a given viewport to the activation of the specified editor mode.
virtual void OnEditorModeActivated([[maybe_unused]] const ViewportEditorModesInterface& editorModeState, [[maybe_unused]] ViewportEditorMode mode)
virtual void OnEditorModeActivated(
[[maybe_unused]] const ViewportEditorModesInterface& editorModeState, [[maybe_unused]] ViewportEditorMode mode)
{
}
//! Notifies subscribers of the a given viewport to the deactivation of the specified editor mode.
virtual void OnEditorModeDeactivated([[maybe_unused]] const ViewportEditorModesInterface& editorModeState, [[maybe_unused]] ViewportEditorMode mode)
virtual void OnEditorModeDeactivated(
[[maybe_unused]] const ViewportEditorModesInterface& editorModeState, [[maybe_unused]] ViewportEditorMode mode)
{
}
};
using ViewportEditorModeNotificationsBus = AZ::EBus<ViewportEditorModeNotifications>;
} // namespace AzToolsFramework
@@ -137,6 +137,7 @@ namespace AzToolsFramework
if (componentTypeIt == m_activeComponentTypes.end())
{
m_activeComponentTypes.push_back(componentType);
m_viewportUiHandlers.emplace_back(componentType);
}
// see if we already have a ComponentModeBuilder for the specific component on this entity
@@ -225,6 +226,7 @@ namespace AzToolsFramework
if (!m_entitiesAndComponentModes.empty())
{
RefreshActions();
PopulateViewportUi();
}
// if entering ComponentMode not as an undo/redo step (an action was
@@ -285,6 +287,10 @@ namespace AzToolsFramework
componentModeCommand.release();
}
// remove the component mode viewport border
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::RemoveViewportBorder);
// notify listeners the editor has left ComponentMode - listeners may
// wish to modify state to indicate this (e.g. appearance, functionality etc.)
m_viewportEditorModeTracker->DeactivateMode({ GetEntityContextId() }, ViewportEditorMode::Component);
@@ -301,6 +307,7 @@ namespace AzToolsFramework
}
m_entitiesAndComponentModeBuilders.clear();
m_activeComponentTypes.clear();
m_viewportUiHandlers.clear();
m_componentMode = false;
m_selectedComponentModeIndex = 0;
@@ -385,6 +392,24 @@ namespace AzToolsFramework
return m_activeComponentTypes.size() > 1;
}
static ComponentModeViewportUi* FindViewportUiHandlerForType(
AZStd::vector<ComponentModeViewportUi>& viewportUiHandlers, const AZ::Uuid& componentType)
{
auto handler = AZStd::find_if(
viewportUiHandlers.begin(), viewportUiHandlers.end(),
[componentType](const ComponentModeViewportUi& handler)
{
return handler.GetComponentType() == componentType;
});
if (handler == viewportUiHandlers.end())
{
return nullptr;
}
return handler;
}
bool ComponentModeCollection::ActiveComponentModeChanged(const AZ::Uuid& previousComponentType)
{
if (m_activeComponentTypes[m_selectedComponentModeIndex] != previousComponentType)
@@ -410,6 +435,20 @@ namespace AzToolsFramework
// replace the current component mode by invoking the builder
// for the new 'active' component mode
componentMode.m_componentMode = componentModeBuilder->m_componentModeBuilder();
// populate the viewport UI with the new component mode
PopulateViewportUi();
// set the appropriate viewportUiHandler to active
if (auto viewportUiHandler =
FindViewportUiHandlerForType(m_viewportUiHandlers, m_activeComponentTypes[m_selectedComponentModeIndex]))
{
viewportUiHandler->SetComponentModeViewportUiActive(true);
}
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateViewportBorder,
componentMode.m_componentMode->GetComponentModeName().c_str());
}
RefreshActions();
@@ -519,5 +558,18 @@ namespace AzToolsFramework
}
}
void ComponentModeCollection::PopulateViewportUi()
{
// update viewport UI for new component type
if (m_selectedComponentModeIndex < m_activeComponentTypes.size())
{
// iterate over all entities and their active Component Mode, populate viewport UI for the new mode
for (auto& entityAndComponentMode : m_entitiesAndComponentModes)
{
// build viewport UI based on current state
entityAndComponentMode.m_componentMode->PopulateViewportUi();
}
}
}
} // namespace ComponentModeFramework
} // namespace AzToolsFramework
@@ -55,7 +55,7 @@ namespace AzToolsFramework
GetEntityComponentIdPair(), elementIdsToDisplay);
// create the component mode border with the specific name for this component mode
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateComponentModeBorder,
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateViewportBorder,
GetComponentModeName());
// set the EntityComponentId for this ComponentMode to active in the ComponentModeViewportUi system
ComponentModeViewportUiRequestBus::Event(
@@ -71,12 +71,7 @@ namespace AzToolsFramework
return;
}
AZ::EntityId previousFocusEntityId = m_focusRoot;
m_focusRoot = entityId;
FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, previousFocusEntityId, m_focusRoot);
if (auto tracker = AZ::Interface<ViewportEditorModeTrackerInterface>::Get();
tracker != nullptr)
if (auto tracker = AZ::Interface<ViewportEditorModeTrackerInterface>::Get())
{
if (!m_focusRoot.IsValid() && entityId.IsValid())
{
@@ -87,6 +82,10 @@ namespace AzToolsFramework
tracker->DeactivateMode({ GetEntityContextId() }, ViewportEditorMode::Focus);
}
}
AZ::EntityId previousFocusEntityId = m_focusRoot;
m_focusRoot = entityId;
FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, previousFocusEntityId, m_focusRoot);
}
void FocusModeSystemComponent::ClearFocusRoot([[maybe_unused]] AzFramework::EntityContextId entityContextId)
@@ -1052,10 +1052,10 @@ namespace AzToolsFramework
DuplicateNestedEntitiesInInstance(commonOwningInstance->get(),
entities, instanceDomAfter, duplicatedEntityAndInstanceIds, duplicateEntityAliasMap);
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity/Instance duplication");
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity/Instance duplication", false);
command->SetParent(undoBatch.GetUndoBatch());
command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId());
command->RedoBatched();
command->Redo();
DuplicateNestedInstancesInInstance(commonOwningInstance->get(),
instances, instanceDomAfter, duplicatedEntityAndInstanceIds, newInstanceAliasToOldInstanceMap);
@@ -1323,7 +1323,7 @@ namespace AzToolsFramework
Prefab::PrefabDom instanceDomAfter;
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomAfter, parentInstance);
PrefabUndoInstance* command = aznew PrefabUndoInstance("Instance detachment");
PrefabUndoInstance* command = aznew PrefabUndoInstance("Instance detachment", false);
command->Capture(instanceDomBefore, instanceDomAfter, parentTemplateId);
command->SetParent(undoBatch.GetUndoBatch());
{
@@ -6,11 +6,14 @@
*
*/
#include <API/ToolsApplicationAPI.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <Prefab/PrefabSystemComponentInterface.h>
#include <Prefab/PrefabSystemScriptingHandler.h>
#include <AzCore/Component/Entity.h>
#include <Prefab/EditorPrefabComponent.h>
#include <ToolsComponents/TransformComponent.h>
namespace AzToolsFramework::Prefab
{
@@ -61,9 +64,30 @@ namespace AzToolsFramework::Prefab
entities.push_back(entity);
}
}
auto prefab = m_prefabSystemComponentInterface->CreatePrefab(entities, {}, AZ::IO::PathView(AZStd::string_view(filePath)));
bool result = false;
[[maybe_unused]] AZ::EntityId commonRoot;
EntityList topLevelEntities;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(result, &AzToolsFramework::ToolsApplicationRequestBus::Events::FindCommonRootInactive,
entities, commonRoot, &topLevelEntities);
auto containerEntity = AZStd::make_unique<AZ::Entity>();
containerEntity->CreateComponent<Prefab::EditorPrefabComponent>();
for (AZ::Entity* entity : topLevelEntities)
{
AzToolsFramework::Components::TransformComponent* transformComponent =
entity->FindComponent<AzToolsFramework::Components::TransformComponent>();
if (transformComponent)
{
transformComponent->SetParent(containerEntity->GetId());
}
}
auto prefab = m_prefabSystemComponentInterface->CreatePrefab(
entities, {}, AZ::IO::PathView(AZStd::string_view(filePath)), AZStd::move(containerEntity));
if (!prefab)
{
AZ_Error("PrefabSystemComponenent", false, "Failed to create prefab %s", filePath.c_str());
@@ -17,17 +17,16 @@ namespace AzToolsFramework
{
PrefabUndoBase::PrefabUndoBase(const AZStd::string& undoOperationName)
: UndoSystem::URSequencePoint(undoOperationName)
, m_changed(true)
, m_templateId(InvalidTemplateId)
{
m_instanceToTemplateInterface = AZ::Interface<InstanceToTemplateInterface>::Get();
AZ_Assert(m_instanceToTemplateInterface, "Failed to grab instance to template interface");
}
//PrefabInstanceUndo
PrefabUndoInstance::PrefabUndoInstance(const AZStd::string& undoOperationName)
PrefabUndoInstance::PrefabUndoInstance(const AZStd::string& undoOperationName, const bool useImmediatePropagation)
: PrefabUndoBase(undoOperationName)
{
m_useImmediatePropagation = useImmediatePropagation;
}
void PrefabUndoInstance::Capture(
@@ -43,17 +42,12 @@ namespace AzToolsFramework
void PrefabUndoInstance::Undo()
{
m_instanceToTemplateInterface->PatchTemplate(m_undoPatch, m_templateId, true);
m_instanceToTemplateInterface->PatchTemplate(m_undoPatch, m_templateId, m_useImmediatePropagation);
}
void PrefabUndoInstance::Redo()
{
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, true);
}
void PrefabUndoInstance::RedoBatched()
{
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId);
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, m_useImmediatePropagation);
}
@@ -29,14 +29,15 @@ namespace AzToolsFramework
bool Changed() const override { return m_changed; }
protected:
TemplateId m_templateId;
TemplateId m_templateId = InvalidTemplateId;
PrefabDom m_redoPatch;
PrefabDom m_undoPatch;
InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr;
bool m_changed;
bool m_changed = true;
bool m_useImmediatePropagation = true;
};
//! handles the addition and removal of entities from instances
@@ -44,7 +45,7 @@ namespace AzToolsFramework
: public PrefabUndoBase
{
public:
explicit PrefabUndoInstance(const AZStd::string& undoOperationName);
explicit PrefabUndoInstance(const AZStd::string& undoOperationName, const bool useImmediatePropagation = true);
void Capture(
const PrefabDom& initialState,
@@ -53,7 +54,6 @@ namespace AzToolsFramework
void Undo() override;
void Redo() override;
void RedoBatched();
};
//! handles entity updates, such as when the values on an entity change
@@ -23,10 +23,10 @@ namespace AzToolsFramework
PrefabDom instanceDomAfterUpdate;
PrefabDomUtils::StoreInstanceInPrefabDom(instance, instanceDomAfterUpdate);
PrefabUndoInstance* state = aznew Prefab::PrefabUndoInstance(undoMessage);
PrefabUndoInstance* state = aznew Prefab::PrefabUndoInstance(undoMessage, false);
state->Capture(instanceDomBeforeUpdate, instanceDomAfterUpdate, instance.GetTemplateId());
state->SetParent(undoBatch);
state->RedoBatched();
state->Redo();
}
LinkId CreateLink(
@@ -9,6 +9,7 @@
#include "EditorHelpers.h"
#include <AzCore/Console/Console.h>
#include <AzCore/Math/VectorConversions.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Viewport/ViewportScreen.h>
@@ -114,6 +115,33 @@ namespace AzToolsFramework
}
}
CursorEntityIdQuery::CursorEntityIdQuery(AZ::EntityId entityId, AZ::EntityId rootEntityId)
: m_entityId(entityId)
, m_containerAncestorEntityId(rootEntityId)
{
}
AZ::EntityId CursorEntityIdQuery::EntityIdUnderCursor() const
{
return m_entityId;
}
AZ::EntityId CursorEntityIdQuery::ContainerAncestorEntityId() const
{
return m_containerAncestorEntityId;
}
bool CursorEntityIdQuery::HasContainerAncestorEntityId() const
{
if (m_entityId.IsValid())
{
return m_entityId != m_containerAncestorEntityId;
}
return false;
}
EditorHelpers::EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache)
: m_entityDataCache(entityDataCache)
{
@@ -123,9 +151,14 @@ namespace AzToolsFramework
"EditorHelpers - "
"Focus Mode Interface could not be found. "
"Check that it is being correctly initialized.");
AZStd::vector<AZStd::unique_ptr<InvalidClick>> invalidClicks;
invalidClicks.push_back(AZStd::make_unique<FadingText>("Not in focus"));
invalidClicks.push_back(AZStd::make_unique<ExpandingFadingCircles>());
m_invalidClicks = AZStd::make_unique<InvalidClicks>(AZStd::move(invalidClicks));
}
AZ::EntityId EditorHelpers::HandleMouseInteraction(
CursorEntityIdQuery EditorHelpers::FindEntityIdUnderCursor(
const AzFramework::CameraState& cameraState, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -186,20 +219,34 @@ namespace AzToolsFramework
}
}
// Verify if the entity Id corresponds to an entity that is focused; if not, halt selection.
if (!IsSelectableAccordingToFocusMode(entityIdUnderCursor))
// verify if the entity Id corresponds to an entity that is focused; if not, halt selection.
if (entityIdUnderCursor.IsValid() && !IsSelectableAccordingToFocusMode(entityIdUnderCursor))
{
return AZ::EntityId();
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down ||
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::DoubleClick)
{
m_invalidClicks->AddInvalidClick(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
}
return CursorEntityIdQuery(AZ::EntityId(), AZ::EntityId());
}
// Container Entity support - if the entity that is being selected is part of a closed container,
// container entity support - if the entity that is being selected is part of a closed container,
// change the selection to the container instead.
if (ContainerEntityInterface* containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get())
{
return containerEntityInterface->FindHighestSelectableEntity(entityIdUnderCursor);
const auto highestSelectableEntity = containerEntityInterface->FindHighestSelectableEntity(entityIdUnderCursor);
return CursorEntityIdQuery(entityIdUnderCursor, highestSelectableEntity);
}
return entityIdUnderCursor;
return CursorEntityIdQuery(entityIdUnderCursor, AZ::EntityId());
}
void EditorHelpers::Display2d(
[[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
m_invalidClicks->Display2d(viewportInfo, debugDisplay);
}
void EditorHelpers::DisplayHelpers(
@@ -263,19 +310,19 @@ namespace AzToolsFramework
}
}
bool EditorHelpers::IsSelectableInViewport(AZ::EntityId entityId)
bool EditorHelpers::IsSelectableInViewport(const AZ::EntityId entityId) const
{
return IsSelectableAccordingToFocusMode(entityId) && IsSelectableAccordingToContainerEntities(entityId);
}
bool EditorHelpers::IsSelectableAccordingToFocusMode(AZ::EntityId entityId)
bool EditorHelpers::IsSelectableAccordingToFocusMode(const AZ::EntityId entityId) const
{
return m_focusModeInterface->IsInFocusSubTree(entityId);
}
bool EditorHelpers::IsSelectableAccordingToContainerEntities(AZ::EntityId entityId)
bool EditorHelpers::IsSelectableAccordingToContainerEntities(const AZ::EntityId entityId) const
{
if (ContainerEntityInterface* containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get())
if (const auto* containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get())
{
return !containerEntityInterface->IsUnderClosedContainerEntity(entityId);
}
@@ -11,6 +11,9 @@
#include <AzCore/Component/EntityId.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/std/functional.h>
#include <AzCore/std/containers/vector.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzToolsFramework/ViewportSelection/InvalidClicks.h>
namespace AzFramework
{
@@ -29,6 +32,28 @@ namespace AzToolsFramework
struct MouseInteractionEvent;
}
//!< Represents the result of a query to find the id of the entity under the cursor (if any).
class CursorEntityIdQuery
{
public:
CursorEntityIdQuery(AZ::EntityId entityId, AZ::EntityId rootEntityId);
//! Returns the entity id under the cursor (if any).
//! @note In the case of no entity id under the cursor, an invalid entity id is returned.
AZ::EntityId EntityIdUnderCursor() const;
//! Returns the topmost container entity id in the hierarchy if the entity id under the cursor is inside a container entity, otherwise returns the entity id.
//! @note In the case of no entity id under the cursor, an invalid entity id is returned.
AZ::EntityId ContainerAncestorEntityId() const;
//! Returns true if the query has a container ancestor entity id, otherwise false.
bool HasContainerAncestorEntityId() const;
private:
AZ::EntityId m_entityId; //<! The entity id under the cursor.
AZ::EntityId m_containerAncestorEntityId; //<! For entities in container entities, the topmost container entity id in the hierarchy, otherwise the entity id under the cursor.
};
//! EditorHelpers are the visualizations that appear for entities
//! when 'Display Helpers' is toggled on inside the editor.
//! These include but are not limited to entity icons and shape visualizations.
@@ -44,9 +69,9 @@ namespace AzToolsFramework
EditorHelpers& operator=(const EditorHelpers&) = delete;
~EditorHelpers() = default;
//! Handle any mouse interaction with the EditorHelpers.
//! Finds the id of the entity under the cursor (if any). For entities in container entities, also finds the topmost container entity id in the hierarchy.
//! Used to check if a particular entity was selected.
AZ::EntityId HandleMouseInteraction(
CursorEntityIdQuery FindEntityIdUnderCursor(
const AzFramework::CameraState& cameraState, const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
//! Do the drawing responsible for the EditorHelpers.
@@ -58,20 +83,27 @@ namespace AzToolsFramework
AzFramework::DebugDisplayRequests& debugDisplay,
const AZStd::function<bool(AZ::EntityId)>& showIconCheck);
//! Handle 2d drawing for EditorHelper functionality.
void Display2d(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay);
//! Returns whether the entityId can be selected in the viewport according
//! to the current Editor Focus Mode and Container Entity setup.
bool IsSelectableInViewport(AZ::EntityId entityId);
bool IsSelectableInViewport(AZ::EntityId entityId) const;
private:
//! Returns whether the entityId can be selected in the viewport according
//! to the current Editor Focus Mode setup.
bool IsSelectableAccordingToFocusMode(AZ::EntityId entityId);
bool IsSelectableAccordingToFocusMode(AZ::EntityId entityId) const;
//! Returns whether the entityId can be selected in the viewport according
//! to the current Container Entityu setup.
bool IsSelectableAccordingToContainerEntities(AZ::EntityId entityId);
//! to the current Container Entity setup.
bool IsSelectableAccordingToContainerEntities(AZ::EntityId entityId) const;
AZStd::unique_ptr<InvalidClicks> m_invalidClicks; //!< Display for invalid click behavior.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
const FocusModeInterface* m_focusModeInterface = nullptr;
const FocusModeInterface* m_focusModeInterface = nullptr; //!< API to interact with focus mode functionality.
};
} // namespace AzToolsFramework
@@ -80,7 +80,7 @@ namespace AzToolsFramework
const AzFramework::CameraState cameraState = GetCameraState(viewportId);
m_cachedEntityIdUnderCursor = m_editorHelpers->HandleMouseInteraction(cameraState, mouseInteraction);
m_cachedEntityIdUnderCursor = m_editorHelpers->FindEntityIdUnderCursor(cameraState, mouseInteraction).ContainerAncestorEntityId();
// when left clicking, if we successfully clicked an entity, assign that
// to the entity field selected in the entity inspector (RPE)
@@ -27,6 +27,7 @@
#include <AzToolsFramework/Manipulators/ScaleManipulators.h>
#include <AzToolsFramework/Manipulators/TranslationManipulators.h>
#include <AzToolsFramework/Maths/TransformUtils.h>
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
#include <AzToolsFramework/ToolsComponents/EditorLockComponentBus.h>
#include <AzToolsFramework/ToolsComponents/EditorVisibilityBus.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
@@ -1799,7 +1800,8 @@ namespace AzToolsFramework
const AzFramework::ViewportId viewportId = mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId;
const AzFramework::CameraState cameraState = GetCameraState(viewportId);
m_cachedEntityIdUnderCursor = m_editorHelpers->HandleMouseInteraction(cameraState, mouseInteraction);
const auto cursorEntityIdQuery = m_editorHelpers->FindEntityIdUnderCursor(cameraState, mouseInteraction);
m_cachedEntityIdUnderCursor = cursorEntityIdQuery.ContainerAncestorEntityId();
const auto selectClickEvent = ClickDetectorEventFromViewportInteraction(mouseInteraction);
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
@@ -1825,8 +1827,6 @@ namespace AzToolsFramework
}
}
const AZ::EntityId entityIdUnderCursor = m_cachedEntityIdUnderCursor;
EditorContextMenuUpdate(m_contextMenu, mouseInteraction);
m_boxSelect.HandleMouseInteraction(mouseInteraction);
@@ -1842,6 +1842,21 @@ namespace AzToolsFramework
return true;
}
const AZ::EntityId entityIdUnderCursor = m_cachedEntityIdUnderCursor;
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::DoubleClick &&
mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
{
if (cursorEntityIdQuery.HasContainerAncestorEntityId())
{
if (auto prefabFocusInterface = AZ::Interface<Prefab::PrefabFocusInterface>::Get())
{
prefabFocusInterface->FocusOnPrefabInstanceOwningEntityId(cursorEntityIdQuery.ContainerAncestorEntityId());
return false;
}
}
}
bool stickySelect = false;
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
stickySelect, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::StickySelectEnabled);
@@ -3560,6 +3575,8 @@ namespace AzToolsFramework
DrawAxisGizmo(viewportInfo, debugDisplay);
m_boxSelect.Display2d(viewportInfo, debugDisplay);
m_editorHelpers->Display2d(viewportInfo, debugDisplay);
}
void EditorTransformComponentSelection::RefreshSelectedEntityIds()
@@ -3663,26 +3680,63 @@ namespace AzToolsFramework
void EditorTransformComponentSelection::OnEditorModeActivated(
[[maybe_unused]] const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode)
{
if (mode == ViewportEditorMode::Component)
switch (mode)
{
SetAllViewportUiVisible(false);
case ViewportEditorMode::Component:
{
SetAllViewportUiVisible(false);
EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterDisconnect();
ToolsApplicationNotificationBus::Handler::BusDisconnect();
EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterDisconnect();
ToolsApplicationNotificationBus::Handler::BusDisconnect();
}
break;
case ViewportEditorMode::Focus:
{
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateViewportBorder, "Focus Mode");
}
break;
case ViewportEditorMode::Default:
case ViewportEditorMode::Pick:
// noop
break;
}
}
void EditorTransformComponentSelection::OnEditorModeDeactivated(
[[maybe_unused]] const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode)
const ViewportEditorModesInterface& editorModeState, const ViewportEditorMode mode)
{
if (mode == ViewportEditorMode::Component)
switch (mode)
{
SetAllViewportUiVisible(true);
case ViewportEditorMode::Component:
{
SetAllViewportUiVisible(true);
ToolsApplicationNotificationBus::Handler::BusConnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterConnect();
EditorEntityLockComponentNotificationBus::Router::BusRouterConnect();
ToolsApplicationNotificationBus::Handler::BusConnect();
EditorEntityVisibilityNotificationBus::Router::BusRouterConnect();
EditorEntityLockComponentNotificationBus::Router::BusRouterConnect();
// note: when leaving component mode, we check if we're still in focus mode (i.e. component mode was
// started from within focus mode), if we are, ensure we create/update the viewport border (as leaving
// component mode will attempt to remove it)
if (editorModeState.IsModeActive(ViewportEditorMode::Focus))
{
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::CreateViewportBorder, "Focus Mode");
}
}
break;
case ViewportEditorMode::Focus:
{
ViewportUi::ViewportUiRequestBus::Event(
ViewportUi::DefaultViewportId, &ViewportUi::ViewportUiRequestBus::Events::RemoveViewportBorder);
}
break;
case ViewportEditorMode::Default:
case ViewportEditorMode::Pick:
// noop
break;
}
}
@@ -0,0 +1,142 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Console/Console.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/ViewportSelection/InvalidClicks.h>
AZ_CVAR(float, ed_invalidClickRadius, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum invalid click radius to expand to");
AZ_CVAR(float, ed_invalidClickDuration, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Duration to display the invalid click feedback");
AZ_CVAR(float, ed_invalidClickMessageSize, 0.8f, nullptr, AZ::ConsoleFunctorFlags::Null, "Size of text for invalid message");
AZ_CVAR(
float,
ed_invalidClickMessageVerticalOffset,
30.0f,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Vertical offset from cursor of invalid click message");
namespace AzToolsFramework
{
void ExpandingFadingCircles::Begin(const AzFramework::ScreenPoint& screenPoint)
{
FadingCircle fadingCircle;
fadingCircle.m_position = screenPoint;
fadingCircle.m_opacity = 1.0f;
fadingCircle.m_radius = 0.0f;
m_fadingCircles.push_back(fadingCircle);
}
void ExpandingFadingCircles::Update(const float deltaTime)
{
for (auto& fadingCircle : m_fadingCircles)
{
fadingCircle.m_opacity = AZStd::max(fadingCircle.m_opacity - (deltaTime / ed_invalidClickDuration), 0.0f);
fadingCircle.m_radius += deltaTime * ed_invalidClickRadius;
}
m_fadingCircles.erase(
AZStd::remove_if(
m_fadingCircles.begin(), m_fadingCircles.end(),
[](const FadingCircle& fadingCircle)
{
return fadingCircle.m_opacity <= 0.0f;
}),
m_fadingCircles.end());
}
bool ExpandingFadingCircles::Updating()
{
return !m_fadingCircles.empty();
}
void ExpandingFadingCircles::Display(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
const AZ::Vector2 viewportSize = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId).m_viewportSize;
for (const auto& fadingCircle : m_fadingCircles)
{
const auto position = AzFramework::Vector2FromScreenPoint(fadingCircle.m_position) / viewportSize;
debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, fadingCircle.m_opacity));
debugDisplay.DrawWireCircle2d(position, fadingCircle.m_radius * 0.005f, 0.0f);
}
}
void FadingText::Begin(const AzFramework::ScreenPoint& screenPoint)
{
m_opacity = 1.0f;
m_invalidClickPosition = screenPoint;
}
void FadingText::Update(const float deltaTime)
{
m_opacity -= deltaTime / ed_invalidClickDuration;
}
bool FadingText::Updating()
{
return m_opacity >= 0.0f;
}
void FadingText::Display(
[[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
if (constexpr float MinOpacity = 0.05f; m_opacity >= MinOpacity)
{
debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, m_opacity));
debugDisplay.Draw2dTextLabel(
aznumeric_cast<float>(m_invalidClickPosition.m_x),
aznumeric_cast<float>(m_invalidClickPosition.m_y) - ed_invalidClickMessageVerticalOffset, ed_invalidClickMessageSize,
m_message.c_str(), true);
}
}
void InvalidClicks::AddInvalidClick(const AzFramework::ScreenPoint& screenPoint)
{
AZ::TickBus::Handler::BusConnect();
for (auto& invalidClickBehavior : m_invalidClickBehaviors)
{
invalidClickBehavior->Begin(screenPoint);
}
}
void InvalidClicks::OnTick(const float deltaTime, [[maybe_unused]] const AZ::ScriptTimePoint time)
{
for (auto& invalidClickBehavior : m_invalidClickBehaviors)
{
invalidClickBehavior->Update(deltaTime);
}
const auto updating = AZStd::any_of(
m_invalidClickBehaviors.begin(), m_invalidClickBehaviors.end(),
[](const auto& invalidClickBehavior)
{
return invalidClickBehavior->Updating();
});
if (!updating && AZ::TickBus::Handler::BusIsConnected())
{
AZ::TickBus::Handler::BusDisconnect();
}
}
void InvalidClicks::Display2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
debugDisplay.DepthTestOff();
for (const auto& invalidClickBehavior : m_invalidClickBehaviors)
{
invalidClickBehavior->Display(viewportInfo, debugDisplay);
}
debugDisplay.DepthTestOn();
}
} // namespace AzToolsFramework
@@ -0,0 +1,108 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Component/TickBus.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
namespace AzFramework
{
class DebugDisplayRequests;
struct ViewportInfo;
} // namespace AzFramework
namespace AzToolsFramework
{
namespace ViewportInteraction
{
struct MouseInteractionEvent;
}
//! An interface to provide invalid click feedback in the editor viewport.
class InvalidClick
{
public:
virtual ~InvalidClick() = default;
//! Begin the feedback.
//! @param screenPoint The position of the click in screen coordinates.
virtual void Begin(const AzFramework::ScreenPoint& screenPoint) = 0;
//! Update the invalid click feedback
virtual void Update(float deltaTime) = 0;
//! Report if the click feedback is running or not (returning false will signal the TickBus can be disconnected from).
virtual bool Updating() = 0;
//! Display the click feedback in the viewport.
virtual void Display(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) = 0;
};
//! Display expanding fading circles for every click of the mouse that is invalid.
class ExpandingFadingCircles : public InvalidClick
{
public:
void Begin(const AzFramework::ScreenPoint& screenPoint) override;
void Update(float deltaTime) override;
bool Updating() override;
void Display(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
private:
//! Stores a circle representation with a lifetime to grow and fade out over time.
struct FadingCircle
{
AzFramework::ScreenPoint m_position;
float m_radius;
float m_opacity;
};
using FadingCircles = AZStd::vector<FadingCircle>;
FadingCircles m_fadingCircles; //!< Collection of fading circles to draw for clicks that have no effect.
};
//! Display fading text where an invalid click happened.
//! @note There is only one fading text, each click will update its position.
class FadingText : public InvalidClick
{
public:
explicit FadingText(AZStd::string message)
: m_message(AZStd::move(message))
{
}
void Begin(const AzFramework::ScreenPoint& screenPoint) override;
void Update(float deltaTime) override;
bool Updating() override;
void Display(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
private:
AZStd::string m_message; //!< Message to display for fading text.
float m_opacity = 1.0f; //!< The opacity of the invalid click message.
AzFramework::ScreenPoint m_invalidClickPosition; //!< The position to display the invalid click message.
};
//! Interface to begin invalid click feedback (will run all added InvalidClick behaviors).
class InvalidClicks : private AZ::TickBus::Handler
{
public:
explicit InvalidClicks(AZStd::vector<AZStd::unique_ptr<InvalidClick>> invalidClickBehaviors)
: m_invalidClickBehaviors(AZStd::move(invalidClickBehaviors))
{
}
//! Add an invalid click and activate one or more of the added invalid click behaviors.
void AddInvalidClick(const AzFramework::ScreenPoint& screenPoint);
//! Handle 2d drawing for EditorHelper functionality.
void Display2d(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay);
private:
//! AZ::TickBus overrides ...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
AZStd::vector<AZStd::unique_ptr<InvalidClick>> m_invalidClickBehaviors; //!< Invalid click behaviors to run.
};
} // namespace AzToolsFramework
@@ -290,9 +290,9 @@ namespace AzToolsFramework::ViewportUi::Internal
return false;
}
void ViewportUiDisplay::CreateComponentModeBorder(const AZStd::string& borderTitle)
void ViewportUiDisplay::CreateViewportBorder(const AZStd::string& borderTitle)
{
AZStd::string styleSheet = AZStd::string::format(
const AZStd::string styleSheet = AZStd::string::format(
"border: %dpx solid %s; border-top: %dpx solid %s;", HighlightBorderSize, HighlightBorderColor, TopHighlightBorderSize,
HighlightBorderColor);
m_uiOverlay.setStyleSheet(styleSheet.c_str());
@@ -303,7 +303,7 @@ namespace AzToolsFramework::ViewportUi::Internal
m_componentModeBorderText.setText(borderTitle.c_str());
}
void ViewportUiDisplay::RemoveComponentModeBorder()
void ViewportUiDisplay::RemoveViewportBorder()
{
m_componentModeBorderText.setVisible(false);
m_uiOverlay.setStyleSheet("border: none;");
@@ -420,6 +420,7 @@ namespace AzToolsFramework::ViewportUi::Internal
m_uiMainWindow.setVisible(true);
m_uiOverlay.setVisible(true);
}
m_uiMainWindow.setMask(region);
}
@@ -437,6 +438,7 @@ namespace AzToolsFramework::ViewportUi::Internal
{
return element->second;
}
return ViewportUiElementInfo{ nullptr, InvalidViewportUiElementId, false };
}
@@ -89,8 +89,8 @@ namespace AzToolsFramework::ViewportUi::Internal
AZStd::shared_ptr<QWidget> GetViewportUiElement(ViewportUiElementId elementId);
bool IsViewportUiElementVisible(ViewportUiElementId elementId);
void CreateComponentModeBorder(const AZStd::string& borderTitle);
void RemoveComponentModeBorder();
void CreateViewportBorder(const AZStd::string& borderTitle);
void RemoveViewportBorder();
private:
void PrepareWidgetForViewportUi(QPointer<QWidget> widget);
@@ -240,14 +240,14 @@ namespace AzToolsFramework::ViewportUi
}
}
void ViewportUiManager::CreateComponentModeBorder(const AZStd::string& borderTitle)
void ViewportUiManager::CreateViewportBorder(const AZStd::string& borderTitle)
{
m_viewportUi->CreateComponentModeBorder(borderTitle);
m_viewportUi->CreateViewportBorder(borderTitle);
}
void ViewportUiManager::RemoveComponentModeBorder()
void ViewportUiManager::RemoveViewportBorder()
{
m_viewportUi->RemoveComponentModeBorder();
m_viewportUi->RemoveViewportBorder();
}
void ViewportUiManager::PressButton(ClusterId clusterId, ButtonId buttonId)
@@ -50,8 +50,8 @@ namespace AzToolsFramework::ViewportUi
void RegisterTextFieldCallback(TextFieldId textFieldId, AZ::Event<AZStd::string>::Handler& handler) override;
void RemoveTextField(TextFieldId textFieldId) override;
void SetTextFieldVisible(TextFieldId textFieldId, bool visible) override;
void CreateComponentModeBorder(const AZStd::string& borderTitle) override;
void RemoveComponentModeBorder() override;
void CreateViewportBorder(const AZStd::string& borderTitle) override;
void RemoveViewportBorder() override;
void PressButton(ClusterId clusterId, ButtonId buttonId) override;
void PressButton(SwitcherId switcherId, ButtonId buttonId) override;
@@ -78,7 +78,7 @@ namespace AzToolsFramework::ViewportUi
virtual void RegisterSwitcherEventHandler(SwitcherId switcherId, AZ::Event<ButtonId>::Handler& handler) = 0;
//! Removes a cluster from the Viewport UI system.
virtual void RemoveCluster(ClusterId clusterId) = 0;
//!
//! Removes a switcher from the Viewport UI system.
virtual void RemoveSwitcher(SwitcherId switcherId) = 0;
//! Sets the visibility of the cluster.
virtual void SetClusterVisible(ClusterId clusterId, bool visible) = 0;
@@ -96,12 +96,12 @@ namespace AzToolsFramework::ViewportUi
//! Sets the visibility of the text field.
virtual void SetTextFieldVisible(TextFieldId textFieldId, bool visible) = 0;
//! Create the highlight border for Component Mode.
virtual void CreateComponentModeBorder(const AZStd::string& borderTitle) = 0;
virtual void CreateViewportBorder(const AZStd::string& borderTitle) = 0;
//! Remove the highlight border for Component Mode.
virtual void RemoveComponentModeBorder() = 0;
//! Invoke a button press in a cluster.
virtual void RemoveViewportBorder() = 0;
//! Invoke a button press on a cluster.
virtual void PressButton(ClusterId clusterId, ButtonId buttonId) = 0;
//!
//! Invoke a button press on a switcher.
virtual void PressButton(SwitcherId switcherId, ButtonId buttonId) = 0;
};
@@ -553,6 +553,8 @@ set(FILES
ViewportSelection/EditorTransformComponentSelectionRequestBus.cpp
ViewportSelection/EditorVisibleEntityDataCache.h
ViewportSelection/EditorVisibleEntityDataCache.cpp
ViewportSelection/InvalidClicks.h
ViewportSelection/InvalidClicks.cpp
ViewportSelection/ViewportEditorModeTracker.cpp
ViewportSelection/ViewportEditorModeTracker.h
ToolsFileUtils/ToolsFileUtils.h
+40 -40
View File
@@ -333,7 +333,7 @@ namespace UnitTest
};
template<class SocketProvider = SocketDriverProvider>
class Integ_CarrierAsyncHandshakeTestTemplate
class CarrierAsyncHandshakeTestTemplate
: public GridMateMPTestFixture
, protected SocketProvider
{
@@ -761,7 +761,7 @@ namespace UnitTest
};
template<class SocketProvider = SocketDriverProvider>
class Integ_CarrierDisconnectDetectionTestTemplate
class CarrierDisconnectDetectionTestTemplate
: public GridMateMPTestFixture
, protected SocketProvider
{
@@ -846,7 +846,7 @@ namespace UnitTest
* Sends reliable messages across different channels to each other
*/
template<class SocketProvider = SocketDriverProvider>
class Integ_CarrierMultiChannelTestTemplate
class CarrierMultiChannelTestTemplate
: public GridMateMPTestFixture
, protected SocketProvider
{
@@ -950,7 +950,7 @@ namespace UnitTest
* Stress tests multiple simultaneous Carriers
*/
template<class SocketProvider = SocketDriverProvider>
class Integ_CarrierMultiStressTestTemplate
class CarrierMultiStressTestTemplate
: public GridMateMPTestFixture
, protected SocketProvider
{
@@ -977,7 +977,7 @@ namespace UnitTest
public:
void run()
{
AZ_TracePrintf("GridMate", "Integ_CarrierMultiStressTest\n\n");
AZ_TracePrintf("GridMate", "CarrierMultiStressTest\n\n");
// initialize transport
const int k_numChannels = 1;
@@ -1108,7 +1108,7 @@ namespace UnitTest
/*** Congestion control back pressure test */
template<class SocketProvider = SocketDriverProvider>
class Integ_CarrierBackpressureTestTemplate
class CarrierBackpressureTestTemplate
: public GridMateMPTestFixture
, protected SocketProvider
, public CarrierEventBus::Handler
@@ -1380,7 +1380,7 @@ namespace UnitTest
};
template<class SocketProvider = SocketDriverProvider>
class Integ_CarrierACKTestTemplate
class CarrierACKTestTemplate
: public GridMateMPTestFixture
, protected SocketProvider
{
@@ -1544,13 +1544,13 @@ namespace UnitTest
//Create specific tests
using CarrierBasicTest = CarrierBasicTestTemplate<>;
using CarrierTest = CarrierTestTemplate<>;
using Integ_CarrierDisconnectDetectionTest = Integ_CarrierDisconnectDetectionTestTemplate<>;
using Integ_CarrierAsyncHandshakeTest = Integ_CarrierAsyncHandshakeTestTemplate<>;
using Integ_CarrierStressTest = CarrierStressTestTemplate<>;
using Integ_CarrierMultiChannelTest = Integ_CarrierMultiChannelTestTemplate<>;
using Integ_CarrierMultiStressTest = Integ_CarrierMultiStressTestTemplate<>;
using Integ_CarrierBackpressureTest = Integ_CarrierBackpressureTestTemplate<>;
using Integ_CarrierACKTest = Integ_CarrierACKTestTemplate<>;
using DISABLED_CarrierDisconnectDetectionTest = CarrierDisconnectDetectionTestTemplate<>;
using DISABLED_CarrierAsyncHandshakeTest = CarrierAsyncHandshakeTestTemplate<>;
using DISABLED_CarrierStressTest = CarrierStressTestTemplate<>;
using DISABLED_CarrierMultiChannelTest = CarrierMultiChannelTestTemplate<>;
using DISABLED_CarrierMultiStressTest = CarrierMultiStressTestTemplate<>;
using DISABLED_CarrierBackpressureTest = CarrierBackpressureTestTemplate<>;
using DISABLED_CarrierACKTest = CarrierACKTestTemplate<>;
#if AZ_TRAIT_GRIDMATE_TEST_WITH_SECURE_SOCKET_DRIVER
@@ -1658,20 +1658,20 @@ namespace UnitTest
using SecureProviderBadHost = SecureDriverProvider<SecureSocketDriver, SecureSocketHandshakeDrop<false>>;
using SecureProviderBadBoth = SecureDriverProvider<SecureSocketHandshakeDrop<true>, SecureSocketHandshakeDrop<false>>;
using Integ_CarrierSecureSocketHandshakeTestClient = CarrierBasicTestTemplate<SecureProviderBadClient, 200>;
using Integ_CarrierSecureSocketHandshakeTestHost = CarrierBasicTestTemplate<SecureProviderBadHost, 200>;
using Integ_CarrierSecureSocketHandshakeTestBoth = CarrierBasicTestTemplate<SecureProviderBadBoth, 200>;
using DISABLED_CarrierSecureSocketHandshakeTestClient = CarrierBasicTestTemplate<SecureProviderBadClient, 200>;
using DISABLED_CarrierSecureSocketHandshakeTestHost = CarrierBasicTestTemplate<SecureProviderBadHost, 200>;
using DISABLED_CarrierSecureSocketHandshakeTestBoth = CarrierBasicTestTemplate<SecureProviderBadBoth, 200>;
//Create secure socket variants of tests
using CarrierBasicTestSecure = CarrierBasicTestTemplate<SecureDriverProvider<>>;
using CarrierTestSecure = CarrierTestTemplate<SecureDriverProvider<>>;
using Integ_CarrierDisconnectDetectionTestSecure = Integ_CarrierDisconnectDetectionTestTemplate<SecureDriverProvider<>>;
using Integ_CarrierAsyncHandshakeTestSecure = Integ_CarrierAsyncHandshakeTestTemplate<SecureDriverProvider<>>;
using Integ_CarrierStressTestSecure = CarrierStressTestTemplate<SecureDriverProvider<>>;
using Integ_CarrierMultiChannelTestSecure = Integ_CarrierMultiChannelTestTemplate<SecureDriverProvider<>>;
using Integ_CarrierMultiStressTestSecure = Integ_CarrierMultiStressTestTemplate<SecureDriverProvider<>>;
using Integ_CarrierBackpressureTestSecure = Integ_CarrierBackpressureTestTemplate<SecureDriverProvider<>>;
using Integ_CarrierACKTestSecure = Integ_CarrierACKTestTemplate<SecureDriverProvider<>>;
using DISABLED_CarrierDisconnectDetectionTestSecure = CarrierDisconnectDetectionTestTemplate<SecureDriverProvider<>>;
using DISABLED_CarrierAsyncHandshakeTestSecure = CarrierAsyncHandshakeTestTemplate<SecureDriverProvider<>>;
using DISABLED_CarrierStressTestSecure = CarrierStressTestTemplate<SecureDriverProvider<>>;
using DISABLED_CarrierMultiChannelTestSecure = CarrierMultiChannelTestTemplate<SecureDriverProvider<>>;
using DISABLED_CarrierMultiStressTestSecure = CarrierMultiStressTestTemplate<SecureDriverProvider<>>;
using DISABLED_CarrierBackpressureTestSecure = CarrierBackpressureTestTemplate<SecureDriverProvider<>>;
using DISABLED_CarrierACKTestSecure = CarrierACKTestTemplate<SecureDriverProvider<>>;
#endif
}
@@ -1720,30 +1720,30 @@ GM_TEST_SUITE(CarrierSuite)
GM_TEST(CarrierBasicTest)
GM_TEST(CarrierTest)
#endif //AZ_TRAIT_GRIDMATE_UNIT_TEST_DISABLE_CARRIER_SESSION_TESTS
GM_TEST(Integ_CarrierAsyncHandshakeTest)
GM_TEST(DISABLED_CarrierAsyncHandshakeTest)
#if !defined(AZ_DEBUG_BUILD) // this test is a little slow for debug
GM_TEST(Integ_CarrierStressTest)
GM_TEST(Integ_CarrierMultiStressTest)
GM_TEST(DISABLED_CarrierStressTest)
GM_TEST(DISABLED_CarrierMultiStressTest)
#endif
GM_TEST(Integ_CarrierMultiChannelTest)
GM_TEST(Integ_CarrierBackpressureTest)
GM_TEST(Integ_CarrierACKTest)
GM_TEST(DISABLED_CarrierMultiChannelTest)
GM_TEST(DISABLED_CarrierBackpressureTest)
GM_TEST(DISABLED_CarrierACKTest)
#if AZ_TRAIT_GRIDMATE_TEST_WITH_SECURE_SOCKET_DRIVER
GM_TEST(CarrierBasicTestSecure)
GM_TEST(Integ_CarrierSecureSocketHandshakeTestClient)
GM_TEST(Integ_CarrierSecureSocketHandshakeTestHost)
GM_TEST(Integ_CarrierSecureSocketHandshakeTestBoth)
GM_TEST(DISABLED_CarrierBasicTestSecure)
GM_TEST(DISABLED_CarrierSecureSocketHandshakeTestClient)
GM_TEST(DISABLED_CarrierSecureSocketHandshakeTestHost)
GM_TEST(DISABLED_CarrierSecureSocketHandshakeTestBoth)
GM_TEST(CarrierTestSecure)
GM_TEST(Integ_CarrierAsyncHandshakeTestSecure)
GM_TEST(DISABLED_CarrierAsyncHandshakeTestSecure)
#if !defined(AZ_DEBUG_BUILD) // this test is a little slow for debug
GM_TEST(Integ_CarrierStressTestSecure)
GM_TEST(Integ_CarrierMultiStressTestSecure)
GM_TEST(DISABLED_CarrierStressTestSecure)
GM_TEST(DISABLED_CarrierMultiStressTestSecure)
#endif
GM_TEST(Integ_CarrierMultiChannelTestSecure)
GM_TEST(Integ_CarrierBackpressureTestSecure)
GM_TEST(Integ_CarrierACKTestSecure)
GM_TEST(DISABLED_CarrierMultiChannelTestSecure)
GM_TEST(DISABLED_CarrierBackpressureTestSecure)
GM_TEST(DISABLED_CarrierACKTestSecure)
#endif
@@ -172,7 +172,7 @@ public:
namespace UnitTest
{
class Integ_CarrierStreamBasicTest
class DISABLED_CarrierStreamBasicTest
: public GridMateMPTestFixture
, protected SocketDriverSupplier
{
@@ -330,7 +330,7 @@ namespace UnitTest
}
};
class Integ_CarrierStreamAsyncHandshakeTest
class DISABLED_CarrierStreamAsyncHandshakeTest
: public GridMateMPTestFixture
, protected SocketDriverSupplier
{
@@ -462,7 +462,7 @@ namespace UnitTest
}
};
class Integ_CarrierStreamStressTest
class CarrierStreamStressTest
: public GridMateMPTestFixture
, protected SocketDriverSupplier
, public ::testing::Test
@@ -470,7 +470,7 @@ namespace UnitTest
public:
};
TEST_F(Integ_CarrierStreamStressTest, Stress_Test)
TEST_F(CarrierStreamStressTest, DISABLED_Stress_Test)
{
CarrierStreamCallbacksHandler clientCB, serverCB;
UnitTest::TestCarrierDesc serverCarrierDesc, clientCarrierDesc;
@@ -581,7 +581,7 @@ namespace UnitTest
//////////////////////////////////////////////////////////////////////////
}
class Integ_CarrierStreamTest
class DISABLED_CarrierStreamTest
: public GridMateMPTestFixture
, protected SocketDriverSupplier
{
@@ -783,7 +783,7 @@ namespace UnitTest
}
};
class Integ_CarrierStreamDisconnectDetectionTest
class DISABLED_CarrierStreamDisconnectDetectionTest
: public GridMateMPTestFixture
, protected SocketDriverSupplier
{
@@ -873,7 +873,7 @@ namespace UnitTest
}
};
class Integ_CarrierStreamMultiChannelTest
class DISABLED_CarrierStreamMultiChannelTest
: public GridMateMPTestFixture
, protected SocketDriverSupplier
{
@@ -999,8 +999,8 @@ namespace UnitTest
}
GM_TEST_SUITE(CarrierStreamSuite)
GM_TEST(Integ_CarrierStreamBasicTest)
GM_TEST(Integ_CarrierStreamTest)
GM_TEST(Integ_CarrierStreamAsyncHandshakeTest)
GM_TEST(Integ_CarrierStreamMultiChannelTest)
GM_TEST(DISABLED_CarrierStreamBasicTest)
GM_TEST(DISABLED_CarrierStreamTest)
GM_TEST(DISABLED_CarrierStreamAsyncHandshakeTest)
GM_TEST(DISABLED_CarrierStreamMultiChannelTest)
GM_TEST_SUITE_END()
+47 -48
View File
@@ -6,7 +6,6 @@
*
*/
#include "Tests.h"
#include "TestProfiler.h"
#include <GridMate/Replica/ReplicaFunctions.h>
@@ -1888,12 +1887,12 @@ protected:
};
//-----------------------------------------------------------------------------
class Integ_ReplicaGMTest
class ReplicaGMTest
: public UnitTest::GridMateMPTestFixture
, public ::testing::Test
{};
TEST_F(Integ_ReplicaGMTest, ReplicaTest)
TEST_F(ReplicaGMTest, DISABLED_ReplicaTest)
{
ReplicaChunkDescriptorTable::Get().RegisterChunkType<MigratableReplica, MigratableReplica::Descriptor>();
ReplicaChunkDescriptorTable::Get().RegisterChunkType<NonMigratableReplica>();
@@ -2157,7 +2156,7 @@ TEST_F(Integ_ReplicaGMTest, ReplicaTest)
}
}
class Integ_ForcedReplicaMigrationTest
class ForcedReplicaMigrationTest
: public UnitTest::GridMateMPTestFixture
, public ReplicaMgrCallbackBus::Handler
, public MigratableReplica::MigratableReplicaDebugMsgs::EBus::Handler
@@ -2186,8 +2185,8 @@ class Integ_ForcedReplicaMigrationTest
}
public:
Integ_ForcedReplicaMigrationTest() { ReplicaMgrCallbackBus::Handler::BusConnect(m_gridMate); }
~Integ_ForcedReplicaMigrationTest() { ReplicaMgrCallbackBus::Handler::BusDisconnect(); }
ForcedReplicaMigrationTest() { ReplicaMgrCallbackBus::Handler::BusConnect(m_gridMate); }
~ForcedReplicaMigrationTest() { ReplicaMgrCallbackBus::Handler::BusDisconnect(); }
enum
@@ -2205,11 +2204,11 @@ public:
AZStd::unordered_map<ReplicaId, ReplicaManager*> m_replicaOwnership;
};
const int Integ_ForcedReplicaMigrationTest::k_frameTimePerNodeMs;
const int Integ_ForcedReplicaMigrationTest::k_numFramesToRun;
const int Integ_ForcedReplicaMigrationTest::k_hostSendRateMs;
const int ForcedReplicaMigrationTest::k_frameTimePerNodeMs;
const int ForcedReplicaMigrationTest::k_numFramesToRun;
const int ForcedReplicaMigrationTest::k_hostSendRateMs;
TEST_F(Integ_ForcedReplicaMigrationTest, ForcedReplicaMigrationTest)
TEST_F(ForcedReplicaMigrationTest, DISABLED_ForcedReplicaMigrationTest)
{
ReplicaChunkDescriptorTable::Get().RegisterChunkType<MigratableReplica, MigratableReplica::Descriptor>();
ReplicaChunkDescriptorTable::Get().RegisterChunkType<NonMigratableReplica>();
@@ -2360,7 +2359,7 @@ TEST_F(Integ_ForcedReplicaMigrationTest, ForcedReplicaMigrationTest)
MigratableReplica::MigratableReplicaDebugMsgs::EBus::Handler::BusDisconnect();
}
class Integ_ReplicaMigrationRequestTest
class ReplicaMigrationRequestTest
: public UnitTest::GridMateMPTestFixture
, public ::testing::Test
{
@@ -2516,7 +2515,7 @@ public:
static const int k_hostSendTimeMs = k_frameTimePerNodeMs * TotalNodes * 4; // limiting host send rate to be x4 times slower than tick
};
TEST_F(Integ_ReplicaMigrationRequestTest, ReplicaMigrationRequestTest)
TEST_F(ReplicaMigrationRequestTest, DISABLED_ReplicaMigrationRequestTest)
{
/*
Topology:
@@ -2837,11 +2836,11 @@ TEST_F(Integ_ReplicaMigrationRequestTest, ReplicaMigrationRequestTest)
}
}
const int Integ_ReplicaMigrationRequestTest::k_frameTimePerNodeMs;
const int Integ_ReplicaMigrationRequestTest::k_hostSendTimeMs;
const int ReplicaMigrationRequestTest::k_frameTimePerNodeMs;
const int ReplicaMigrationRequestTest::k_hostSendTimeMs;
class Integ_PeerRejoinTest
class PeerRejoinTest
: public UnitTest::GridMateMPTestFixture
, public ReplicaMgrCallbackBus::Handler
, public ::testing::Test
@@ -2860,11 +2859,11 @@ class Integ_PeerRejoinTest
}
public:
Integ_PeerRejoinTest() { ReplicaMgrCallbackBus::Handler::BusConnect(m_gridMate); }
~Integ_PeerRejoinTest() { ReplicaMgrCallbackBus::Handler::BusDisconnect(); }
PeerRejoinTest() { ReplicaMgrCallbackBus::Handler::BusConnect(m_gridMate); }
~PeerRejoinTest() { ReplicaMgrCallbackBus::Handler::BusDisconnect(); }
};
TEST_F(Integ_PeerRejoinTest, PeerRejoinTest)
TEST_F(PeerRejoinTest, DISABLED_PeerRejoinTest)
{
ReplicaChunkDescriptorTable::Get().RegisterChunkType<MigratableReplica, MigratableReplica::Descriptor>();
ReplicaChunkDescriptorTable::Get().RegisterChunkType<NonMigratableReplica>();
@@ -3011,7 +3010,7 @@ TEST_F(Integ_PeerRejoinTest, PeerRejoinTest)
}
}
class Integ_ReplicationSecurityOptionsTest
class ReplicationSecurityOptionsTest
: public UnitTest::GridMateMPTestFixture
, public ::testing::Test
{
@@ -3156,7 +3155,7 @@ public:
using TestChunkPtr = AZStd::intrusive_ptr<TestChunk> ;
};
TEST_F(Integ_ReplicationSecurityOptionsTest, ReplicationSecurityOptionsTest)
TEST_F(ReplicationSecurityOptionsTest, DISABLED_ReplicationSecurityOptionsTest)
{
AZ_TracePrintf("GridMate", "\n");
@@ -3356,7 +3355,7 @@ TEST_F(Integ_ReplicationSecurityOptionsTest, ReplicationSecurityOptionsTest)
Replica update time (msec): avg=4.94, min=1, max=9 (peers=40, replicas=16000, freq=10%, samples=4000)
Replica update time (msec): avg=8.05, min=6, max=15 (peers=40, replicas=16000, freq=100%, samples=4000)
*/
class Integ_ReplicaStressTest
class DISABLED_ReplicaStressTest
: public UnitTest::GridMateMPTestFixture
{
public:
@@ -3388,7 +3387,7 @@ public:
static const int BASE_PORT = 44270;
// TODO: Reduce the size or disable the test for platforms which can't allocate 2 GiB
Integ_ReplicaStressTest()
DISABLED_ReplicaStressTest()
: UnitTest::GridMateMPTestFixture(2000u * 1024u * 1024u)
{}
@@ -3516,33 +3515,33 @@ public:
virtual void RunStressTests(MPSession* sessions, vector<AZStd::pair<ReplicaPtr, StressTestReplica::Ptr> >& replicas)
{
// testing 3 cases & waiting for system to settle in between
TestProfiler::StartProfiling();
//TestProfiler::StartProfiling();
Wait(sessions, replicas, 50, FRAME_TIME);
TestProfiler::PrintProfilingTotal("GridMate");
//TestProfiler::PrintProfilingTotal("GridMate");
Wait(sessions, replicas, 20, FRAME_TIME);
TestProfiler::StartProfiling();
//TestProfiler::StartProfiling();
TestReplicas(sessions, replicas, 100, FRAME_TIME, 0.0); // no replicas are dirty
TestProfiler::PrintProfilingTotal("GridMate");
//TestProfiler::PrintProfilingTotal("GridMate");
Wait(sessions, replicas, 20, FRAME_TIME);
TestProfiler::StartProfiling();
//TestProfiler::StartProfiling();
TestReplicas(sessions, replicas, 1, FRAME_TIME, 1.0); // single burst dirty replicas
Wait(sessions, replicas, 2, FRAME_TIME);
TestProfiler::PrintProfilingTotal("GridMate");
//TestProfiler::PrintProfilingTotal("GridMate");
Wait(sessions, replicas, 20, FRAME_TIME);
TestProfiler::StartProfiling();
//TestProfiler::StartProfiling();
TestReplicas(sessions, replicas, 100, FRAME_TIME, 0.1); // 10% of replicas are marked dirty every frame
TestProfiler::PrintProfilingTotal("GridMate");
//TestProfiler::PrintProfilingTotal("GridMate");
Wait(sessions, replicas, 20, FRAME_TIME);
TestProfiler::StartProfiling();
//TestProfiler::StartProfiling();
TestReplicas(sessions, replicas, 100, FRAME_TIME, 1.0); // every replica is marked dirty every frame
TestProfiler::PrintProfilingTotal("GridMate");
TestProfiler::PrintProfilingSelf("GridMate");
//TestProfiler::PrintProfilingTotal("GridMate");
//TestProfiler::PrintProfilingSelf("GridMate");
TestProfiler::StopProfiling();
//TestProfiler::StopProfiling();
}
virtual void MarkChanging(vector<AZStd::pair<ReplicaPtr, StressTestReplica::Ptr> >& replicas, double freq)
@@ -3623,8 +3622,8 @@ public:
Replica update time (msec): avg=2.01, min=1, max=5 (peers=40, replicas=16000, freq=10%, samples=4000)
Replica update time (msec): avg=4.61, min=3, max=10 (peers=40, replicas=16000, freq=50%, samples=4000)
*/
class Integ_ReplicaStableStressTest
: public Integ_ReplicaStressTest
class DISABLED_ReplicaStableStressTest
: public DISABLED_ReplicaStressTest
{
public:
@@ -3636,21 +3635,21 @@ public:
void RunStressTests(MPSession* sessions, vector<AZStd::pair<ReplicaPtr, StressTestReplica::Ptr> >& replicas) override
{
Integ_ReplicaStressTest::MarkChanging(replicas, 0.1); // picks 10% of replicas
DISABLED_ReplicaStressTest::MarkChanging(replicas, 0.1); // picks 10% of replicas
Wait(sessions, replicas, 20, FRAME_TIME);
TestProfiler::StartProfiling();
//TestProfiler::StartProfiling();
TestReplicas(sessions, replicas, 100, FRAME_TIME, 0.1);
TestProfiler::PrintProfilingTotal("GridMate");
TestProfiler::PrintProfilingSelf("GridMate");
/*TestProfiler::PrintProfilingTotal("GridMate");
TestProfiler::PrintProfilingSelf("GridMate");*/
Integ_ReplicaStressTest::MarkChanging(replicas, 0.5); // picks 50% of replicas
DISABLED_ReplicaStressTest::MarkChanging(replicas, 0.5); // picks 50% of replicas
Wait(sessions, replicas, 20, FRAME_TIME);
TestProfiler::StartProfiling();
//TestProfiler::StartProfiling();
TestReplicas(sessions, replicas, 100, FRAME_TIME, 0.5);
TestProfiler::PrintProfilingTotal("GridMate");
/*TestProfiler::PrintProfilingTotal("GridMate");
TestProfiler::PrintProfilingSelf("GridMate");
TestProfiler::StopProfiling();
TestProfiler::StopProfiling();*/
}
};
@@ -3666,7 +3665,7 @@ public:
* expected |none |brst | capped |under cap |brst | capped |
*
*/
class Integ_ReplicaBandiwdthTest
class DISABLED_ReplicaBandiwdthTest
: public UnitTest::GridMateMPTestFixture
{
public:
@@ -3944,9 +3943,9 @@ GM_TEST_SUITE(ReplicaSuite)
GM_TEST(InterpolatorTest)
#if !defined(AZ_DEBUG_BUILD) // these tests are a little slow for debug
GM_TEST(Integ_ReplicaBandiwdthTest)
GM_TEST(Integ_ReplicaStressTest)
GM_TEST(Integ_ReplicaStableStressTest)
GM_TEST(DISABLED_ReplicaBandiwdthTest)
GM_TEST(DISABLED_ReplicaStressTest)
GM_TEST(DISABLED_ReplicaStableStressTest)
#endif
GM_TEST_SUITE_END()
@@ -457,13 +457,13 @@ namespace ReplicaBehavior {
Completed,
};
class Integ_SimpleBehaviorTest
class SimpleBehaviorTest
: public UnitTest::GridMateMPTestFixture
{
public:
//GM_CLASS_ALLOCATOR(SimpleBehaviorTest);
Integ_SimpleBehaviorTest()
SimpleBehaviorTest()
: m_sessionCount(0) { }
virtual int GetNumSessions() { return 0; }
@@ -654,11 +654,11 @@ namespace ReplicaBehavior {
*
* This is a simple sanity check to ensure the logic sends the update when it's necessary.
*/
class Integ_Replica_DontSendDataSets_WithNoDiffFromCtorData
: public Integ_SimpleBehaviorTest
class Replica_DontSendDataSets_WithNoDiffFromCtorData
: public SimpleBehaviorTest
{
public:
Integ_Replica_DontSendDataSets_WithNoDiffFromCtorData()
Replica_DontSendDataSets_WithNoDiffFromCtorData()
: m_replicaIdDefault(InvalidReplicaId), m_replicaIdModified(InvalidReplicaId)
{
}
@@ -774,9 +774,9 @@ namespace ReplicaBehavior {
FilteredHook<LargeChunkWithDefaults> m_driller;
};
TEST(Integ_Replica_DontSendDataSets_WithNoDiffFromCtorData, Integ_Replica_DontSendDataSets_WithNoDiffFromCtorData)
TEST(Replica_DontSendDataSets_WithNoDiffFromCtorData, DISABLED_Replica_DontSendDataSets_WithNoDiffFromCtorData)
{
Integ_Replica_DontSendDataSets_WithNoDiffFromCtorData tester;
Replica_DontSendDataSets_WithNoDiffFromCtorData tester;
tester.run();
}
@@ -784,11 +784,11 @@ namespace ReplicaBehavior {
* This test checks the actual size of the replica as marshalled in the binary payload.
* The assessment of the payload size is done using driller EBus.
*/
class Integ_ReplicaDefaultDataSetDriller
: public Integ_SimpleBehaviorTest
class ReplicaDefaultDataSetDriller
: public SimpleBehaviorTest
{
public:
Integ_ReplicaDefaultDataSetDriller()
ReplicaDefaultDataSetDriller()
: m_replicaId(InvalidReplicaId)
{
}
@@ -815,7 +815,7 @@ namespace ReplicaBehavior {
m_replicaId = m_sessions[sHost].GetReplicaMgr().AddPrimary(replica);
}
~Integ_ReplicaDefaultDataSetDriller() override
~ReplicaDefaultDataSetDriller() override
{
m_driller.BusDisconnect();
}
@@ -880,11 +880,11 @@ namespace ReplicaBehavior {
ReplicaId m_replicaId;
};
const int Integ_ReplicaDefaultDataSetDriller::NonDefaultValue;
const int ReplicaDefaultDataSetDriller::NonDefaultValue;
TEST(Integ_ReplicaDefaultDataSetDriller, Integ_ReplicaDefaultDataSetDriller)
TEST(ReplicaDefaultDataSetDriller, DISABLED_ReplicaDefaultDataSetDriller)
{
Integ_ReplicaDefaultDataSetDriller tester;
ReplicaDefaultDataSetDriller tester;
tester.run();
}
@@ -892,11 +892,11 @@ namespace ReplicaBehavior {
* This test checks the actual size of the replica as marshalled in the binary payload.
* The assessment of the payload size is done using driller EBus.
*/
class Integ_Replica_ComparePackingBoolsVsU8
: public Integ_SimpleBehaviorTest
class Replica_ComparePackingBoolsVsU8
: public SimpleBehaviorTest
{
public:
Integ_Replica_ComparePackingBoolsVsU8()
Replica_ComparePackingBoolsVsU8()
: m_replicaBoolsId(InvalidReplicaId)
, m_replicaU8Id(InvalidReplicaId)
{
@@ -928,7 +928,7 @@ namespace ReplicaBehavior {
m_replicaU8Id = m_sessions[sHost].GetReplicaMgr().AddPrimary(replica2);
}
~Integ_Replica_ComparePackingBoolsVsU8() override
~Replica_ComparePackingBoolsVsU8() override
{
m_driller.BusDisconnect();
}
@@ -1020,17 +1020,17 @@ namespace ReplicaBehavior {
ReplicaId m_replicaU8Id;
};
TEST(Integ_Replica_ComparePackingBoolsVsU8, Integ_Replica_ComparePackingBoolsVsU8)
TEST(Replica_ComparePackingBoolsVsU8, DISABLED_Replica_ComparePackingBoolsVsU8)
{
Integ_Replica_ComparePackingBoolsVsU8 tester;
Replica_ComparePackingBoolsVsU8 tester;
tester.run();
}
class Integ_CheckDataSetStreamIsntWrittenMoreThanNecessary
: public Integ_SimpleBehaviorTest
class CheckDataSetStreamIsntWrittenMoreThanNecessary
: public SimpleBehaviorTest
{
public:
Integ_CheckDataSetStreamIsntWrittenMoreThanNecessary()
CheckDataSetStreamIsntWrittenMoreThanNecessary()
: m_replicaId(InvalidReplicaId)
{
}
@@ -1057,7 +1057,7 @@ namespace ReplicaBehavior {
m_replicaId = m_sessions[sHost].GetReplicaMgr().AddPrimary(replica);
}
~Integ_CheckDataSetStreamIsntWrittenMoreThanNecessary() override
~CheckDataSetStreamIsntWrittenMoreThanNecessary() override
{
m_driller.BusDisconnect();
}
@@ -1117,17 +1117,17 @@ namespace ReplicaBehavior {
ReplicaId m_replicaId;
};
TEST(Integ_CheckDataSetStreamIsntWrittenMoreThanNecessary, Integ_CheckDataSetStreamIsntWrittenMoreThanNecessary)
TEST(CheckDataSetStreamIsntWrittenMoreThanNecessary, DISABLED_CheckDataSetStreamIsntWrittenMoreThanNecessary)
{
Integ_CheckDataSetStreamIsntWrittenMoreThanNecessary tester;
CheckDataSetStreamIsntWrittenMoreThanNecessary tester;
tester.run();
}
class Integ_CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty
: public Integ_SimpleBehaviorTest
class CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty
: public SimpleBehaviorTest
{
public:
Integ_CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty()
CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty()
: m_replicaId(InvalidReplicaId)
{
}
@@ -1154,7 +1154,7 @@ namespace ReplicaBehavior {
m_replicaId = m_sessions[sHost].GetReplicaMgr().AddPrimary(replica);
}
~Integ_CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty() override
~CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty() override
{
m_driller.BusDisconnect();
}
@@ -1213,17 +1213,17 @@ namespace ReplicaBehavior {
ReplicaId m_replicaId;
};
TEST(Integ_CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty, Integ_CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty)
TEST(CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty, DISABLED_CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty)
{
Integ_CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty tester;
CheckDataSetStreamIsntWrittenMoreThanNecessaryOnceDirty tester;
tester.run();
}
class Integ_CheckReplicaIsntSentWithNoChanges
: public Integ_SimpleBehaviorTest
class CheckReplicaIsntSentWithNoChanges
: public SimpleBehaviorTest
{
public:
Integ_CheckReplicaIsntSentWithNoChanges()
CheckReplicaIsntSentWithNoChanges()
: m_replicaId(InvalidReplicaId)
{
}
@@ -1248,7 +1248,7 @@ namespace ReplicaBehavior {
m_replicaId = m_sessions[sHost].GetReplicaMgr().AddPrimary(replica);
}
~Integ_CheckReplicaIsntSentWithNoChanges() override
~CheckReplicaIsntSentWithNoChanges() override
{
m_driller.BusDisconnect();
}
@@ -1323,17 +1323,17 @@ namespace ReplicaBehavior {
ReplicaId m_replicaId;
};
TEST(Integ_CheckReplicaIsntSentWithNoChanges, Integ_CheckReplicaIsntSentWithNoChanges)
TEST(CheckReplicaIsntSentWithNoChanges, DISABLED_CheckReplicaIsntSentWithNoChanges)
{
Integ_CheckReplicaIsntSentWithNoChanges tester;
CheckReplicaIsntSentWithNoChanges tester;
tester.run();
}
class Integ_CheckEntityScriptReplicaIsntSentWithNoChanges
: public Integ_SimpleBehaviorTest
class CheckEntityScriptReplicaIsntSentWithNoChanges
: public SimpleBehaviorTest
{
public:
Integ_CheckEntityScriptReplicaIsntSentWithNoChanges()
CheckEntityScriptReplicaIsntSentWithNoChanges()
: m_replicaId(InvalidReplicaId)
{
}
@@ -1359,7 +1359,7 @@ namespace ReplicaBehavior {
m_replicaId = m_sessions[sHost].GetReplicaMgr().AddPrimary(replica);
}
~Integ_CheckEntityScriptReplicaIsntSentWithNoChanges() override
~CheckEntityScriptReplicaIsntSentWithNoChanges() override
{
m_driller.BusDisconnect();
}
@@ -1410,9 +1410,9 @@ namespace ReplicaBehavior {
ReplicaId m_replicaId;
};
TEST(Integ_CheckEntityScriptReplicaIsntSentWithNoChanges, Integ_CheckEntityScriptReplicaIsntSentWithNoChanges)
TEST(CheckEntityScriptReplicaIsntSentWithNoChanges, DISABLED_CheckEntityScriptReplicaIsntSentWithNoChanges)
{
Integ_CheckEntityScriptReplicaIsntSentWithNoChanges tester;
CheckEntityScriptReplicaIsntSentWithNoChanges tester;
tester.run();
}
+80 -80
View File
@@ -596,12 +596,12 @@ public:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class MPSession
class MPSessionMedium
: public CarrierEventBus::Handler
{
public:
~MPSession() override
~MPSessionMedium() override
{
CarrierEventBus::Handler::BusDisconnect();
}
@@ -708,14 +708,14 @@ enum class TestStatus
Completed,
};
class Integ_SimpleTest
class SimpleTest
: public UnitTest::GridMateMPTestFixture
, public ::testing::Test
{
public:
//GM_CLASS_ALLOCATOR(Integ_SimpleTest);
//GM_CLASS_ALLOCATOR(SimpleTest);
Integ_SimpleTest()
SimpleTest()
: m_sessionCount(0) { }
virtual int GetNumSessions() { return 0; }
@@ -858,15 +858,15 @@ public:
}
int m_sessionCount;
AZStd::array<MPSession, 10> m_sessions;
AZStd::array<MPSessionMedium, 10> m_sessions;
AZStd::unique_ptr<DefaultSimulator> m_defaultSimulator;
};
class Integ_ReplicaChunkRPCExec
: public Integ_SimpleTest
class ReplicaChunkRPCExec
: public SimpleTest
{
public:
Integ_ReplicaChunkRPCExec()
ReplicaChunkRPCExec()
: m_chunk(nullptr)
, m_replicaId(0)
{ }
@@ -893,7 +893,7 @@ public:
ReplicaId m_replicaId;
};
TEST_F(Integ_ReplicaChunkRPCExec, ReplicaChunkRPCExec)
TEST_F(ReplicaChunkRPCExec, DISABLED_ReplicaChunkRPCExec)
{
RunTickLoop([this](int tick) -> TestStatus
{
@@ -1050,8 +1050,8 @@ int DestroyRPCChunk::s_afterDestroyFromPrimaryCalls = 0;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
class Integ_ReplicaDestroyedInRPC
: public Integ_SimpleTest
class ReplicaDestroyedInRPC
: public SimpleTest
{
public:
enum
@@ -1080,7 +1080,7 @@ public:
ReplicaId m_repId[2];
};
TEST_F(Integ_ReplicaDestroyedInRPC, ReplicaDestroyedInRPC)
TEST_F(ReplicaDestroyedInRPC, DISABLED_ReplicaDestroyedInRPC)
{
RunTickLoop([this](int tick)->TestStatus
{
@@ -1129,11 +1129,11 @@ TEST_F(Integ_ReplicaDestroyedInRPC, ReplicaDestroyedInRPC)
});
}
class Integ_ReplicaChunkAddWhileReplicated
: public Integ_SimpleTest
class ReplicaChunkAddWhileReplicated
: public SimpleTest
{
public:
Integ_ReplicaChunkAddWhileReplicated()
ReplicaChunkAddWhileReplicated()
: m_replica(nullptr)
, m_chunk(nullptr)
, m_replicaId(0)
@@ -1161,7 +1161,7 @@ public:
ReplicaId m_replicaId;
};
TEST_F(Integ_ReplicaChunkAddWhileReplicated, ReplicaChunkAddWhileReplicated)
TEST_F(ReplicaChunkAddWhileReplicated, DISABLED_ReplicaChunkAddWhileReplicated)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -1203,11 +1203,11 @@ TEST_F(Integ_ReplicaChunkAddWhileReplicated, ReplicaChunkAddWhileReplicated)
}
class Integ_ReplicaRPCValues
: public Integ_SimpleTest
class ReplicaRPCValues
: public SimpleTest
{
public:
Integ_ReplicaRPCValues()
ReplicaRPCValues()
: m_replica(nullptr)
, m_chunk(nullptr)
, m_replicaId(0)
@@ -1236,7 +1236,7 @@ public:
ReplicaId m_replicaId;
};
TEST_F(Integ_ReplicaRPCValues, ReplicaRPCValues)
TEST_F(ReplicaRPCValues, DISABLED_ReplicaRPCValues)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -1257,11 +1257,11 @@ TEST_F(Integ_ReplicaRPCValues, ReplicaRPCValues)
});
}
class Integ_FullRPCValues
: public Integ_SimpleTest
class FullRPCValues
: public SimpleTest
{
public:
Integ_FullRPCValues()
FullRPCValues()
: m_replica(nullptr)
, m_chunk(nullptr)
, m_replicaId(0)
@@ -1290,7 +1290,7 @@ public:
ReplicaId m_replicaId;
};
TEST_F(Integ_FullRPCValues, FullRPCValues)
TEST_F(FullRPCValues, DISABLED_FullRPCValues)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -1364,11 +1364,11 @@ TEST_F(Integ_FullRPCValues, FullRPCValues)
}
class Integ_ReplicaRemoveProxy
: public Integ_SimpleTest
class ReplicaRemoveProxy
: public SimpleTest
{
public:
Integ_ReplicaRemoveProxy()
ReplicaRemoveProxy()
: m_replica(nullptr)
, m_replicaId(0)
{
@@ -1395,7 +1395,7 @@ public:
ReplicaId m_replicaId;
};
TEST_F(Integ_ReplicaRemoveProxy, ReplicaRemoveProxy)
TEST_F(ReplicaRemoveProxy, DISABLED_ReplicaRemoveProxy)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -1424,11 +1424,11 @@ TEST_F(Integ_ReplicaRemoveProxy, ReplicaRemoveProxy)
}
class Integ_ReplicaChunkEvents
: public Integ_SimpleTest
class ReplicaChunkEvents
: public SimpleTest
{
public:
Integ_ReplicaChunkEvents()
ReplicaChunkEvents()
: m_replicaId(InvalidReplicaId)
, m_chunk(nullptr)
, m_proxyChunk(nullptr)
@@ -1463,7 +1463,7 @@ public:
AllEventChunk::Ptr m_proxyChunk;
};
TEST_F(Integ_ReplicaChunkEvents, ReplicaChunkEvents)
TEST_F(ReplicaChunkEvents, DISABLED_ReplicaChunkEvents)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -1501,11 +1501,11 @@ TEST_F(Integ_ReplicaChunkEvents, ReplicaChunkEvents)
}
class Integ_ReplicaChunksBeyond32
: public Integ_SimpleTest
class ReplicaChunksBeyond32
: public SimpleTest
{
public:
Integ_ReplicaChunksBeyond32()
ReplicaChunksBeyond32()
: m_replicaId(InvalidReplicaId)
{
}
@@ -1537,7 +1537,7 @@ public:
ReplicaId m_replicaId;
};
TEST_F(Integ_ReplicaChunksBeyond32, ReplicaChunksBeyond32)
TEST_F(ReplicaChunksBeyond32, DISABLED_ReplicaChunksBeyond32)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -1565,11 +1565,11 @@ TEST_F(Integ_ReplicaChunksBeyond32, ReplicaChunksBeyond32)
}
class Integ_ReplicaChunkEventsDeactivate
: public Integ_SimpleTest
class ReplicaChunkEventsDeactivate
: public SimpleTest
{
public:
Integ_ReplicaChunkEventsDeactivate()
ReplicaChunkEventsDeactivate()
: m_replica(nullptr)
, m_replicaId(0)
, m_chunk(nullptr)
@@ -1604,7 +1604,7 @@ public:
AllEventChunk::Ptr m_proxyChunk;
};
TEST_F(Integ_ReplicaChunkEventsDeactivate, ReplicaChunkEventsDeactivate)
TEST_F(ReplicaChunkEventsDeactivate, DISABLED_ReplicaChunkEventsDeactivate)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -1649,11 +1649,11 @@ TEST_F(Integ_ReplicaChunkEventsDeactivate, ReplicaChunkEventsDeactivate)
}
class Integ_ReplicaDriller
: public Integ_SimpleTest
class ReplicaDriller
: public SimpleTest
{
public:
Integ_ReplicaDriller()
ReplicaDriller()
: m_replicaId(InvalidReplicaId)
{
}
@@ -2007,7 +2007,7 @@ public:
m_replicaId = m_sessions[sHost].GetReplicaMgr().AddPrimary(replica);
}
~Integ_ReplicaDriller() override
~ReplicaDriller() override
{
m_driller.BusDisconnect();
}
@@ -2016,7 +2016,7 @@ public:
ReplicaId m_replicaId;
};
TEST_F(Integ_ReplicaDriller, ReplicaDriller)
TEST_F(ReplicaDriller, DISABLED_ReplicaDriller)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2082,11 +2082,11 @@ TEST_F(Integ_ReplicaDriller, ReplicaDriller)
}
class Integ_DataSetChangedTest
: public Integ_SimpleTest
class DataSetChangedTest
: public SimpleTest
{
public:
Integ_DataSetChangedTest()
DataSetChangedTest()
: m_replica(nullptr)
, m_replicaId(0)
, m_chunk(nullptr)
@@ -2115,7 +2115,7 @@ public:
DataSetChunk::Ptr m_chunk;
};
TEST_F(Integ_DataSetChangedTest, DataSetChangedTest)
TEST_F(DataSetChangedTest, DISABLED_DataSetChangedTest)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2144,11 +2144,11 @@ TEST_F(Integ_DataSetChangedTest, DataSetChangedTest)
}
class Integ_CustomHandlerTest
: public Integ_SimpleTest
class CustomHandlerTest
: public SimpleTest
{
public:
Integ_CustomHandlerTest()
CustomHandlerTest()
: m_replica(nullptr)
, m_replicaId(0)
, m_chunk(nullptr)
@@ -2181,7 +2181,7 @@ public:
AZStd::scoped_ptr<CustomHandler> m_proxyHandler;
};
TEST_F(Integ_CustomHandlerTest, CustomHandlerTest)
TEST_F(CustomHandlerTest, DISABLED_CustomHandlerTest)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2234,11 +2234,11 @@ TEST_F(Integ_CustomHandlerTest, CustomHandlerTest)
}
class Integ_NonConstMarshalerTest
: public Integ_SimpleTest
class NonConstMarshalerTest
: public SimpleTest
{
public:
Integ_NonConstMarshalerTest()
NonConstMarshalerTest()
: m_replica(nullptr)
, m_replicaId(0)
, m_chunk(nullptr)
@@ -2266,7 +2266,7 @@ public:
NonConstMarshalerChunk::Ptr m_chunk;
};
TEST_F(Integ_NonConstMarshalerTest, NonConstMarshalerTest)
TEST_F(NonConstMarshalerTest, DISABLED_NonConstMarshalerTest)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2309,11 +2309,11 @@ TEST_F(Integ_NonConstMarshalerTest, NonConstMarshalerTest)
}
class Integ_SourcePeerTest
: public Integ_SimpleTest
class SourcePeerTest
: public SimpleTest
{
public:
Integ_SourcePeerTest()
SourcePeerTest()
: m_replica(nullptr)
, m_replicaId(0)
, m_chunk(nullptr)
@@ -2343,7 +2343,7 @@ public:
SourcePeerChunk::Ptr m_chunk2;
};
TEST_F(Integ_SourcePeerTest, SourcePeerTest)
TEST_F(SourcePeerTest, DISABLED_SourcePeerTest)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2404,8 +2404,8 @@ TEST_F(Integ_SourcePeerTest, SourcePeerTest)
}
class Integ_SendWithPriority
: public Integ_SimpleTest
class SendWithPriority
: public SimpleTest
{
public:
enum
@@ -2438,8 +2438,8 @@ public:
{
public:
ReplicaDrillerHook()
: m_expectedSendValue(Integ_SendWithPriority::kNumReplicas)
, m_expectedRecvValue(Integ_SendWithPriority::kNumReplicas)
: m_expectedSendValue(SendWithPriority::kNumReplicas)
, m_expectedRecvValue(SendWithPriority::kNumReplicas)
{
}
@@ -2495,7 +2495,7 @@ public:
PriorityChunk::Ptr m_chunks[kNumReplicas];
};
TEST_F(Integ_SendWithPriority, SendWithPriority)
TEST_F(SendWithPriority, DISABLED_SendWithPriority)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2511,8 +2511,8 @@ TEST_F(Integ_SendWithPriority, SendWithPriority)
}
class Integ_SuspendUpdatesTest
: public Integ_SimpleTest
class SuspendUpdatesTest
: public SimpleTest
{
public:
enum
@@ -2597,7 +2597,7 @@ public:
unsigned int m_numRpcCalled = 0;
};
TEST_F(Integ_SuspendUpdatesTest, SuspendUpdatesTest)
TEST_F(SuspendUpdatesTest, DISABLED_SuspendUpdatesTest)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2657,7 +2657,7 @@ TEST_F(Integ_SuspendUpdatesTest, SuspendUpdatesTest)
}
class Integ_BasicHostChunkDescriptorTest
class BasicHostChunkDescriptorTest
: public UnitTest::GridMateMPTestFixture
, public ::testing::Test
{
@@ -2694,17 +2694,17 @@ public:
static int nProxyActivations;
};
};
int Integ_BasicHostChunkDescriptorTest::HostChunk::nPrimaryActivations = 0;
int Integ_BasicHostChunkDescriptorTest::HostChunk::nProxyActivations = 0;
int BasicHostChunkDescriptorTest::HostChunk::nPrimaryActivations = 0;
int BasicHostChunkDescriptorTest::HostChunk::nProxyActivations = 0;
TEST_F(Integ_BasicHostChunkDescriptorTest, BasicHostChunkDescriptorTest)
TEST_F(BasicHostChunkDescriptorTest, DISABLED_BasicHostChunkDescriptorTest)
{
AZ_TracePrintf("GridMate", "\n");
// Register test chunks
ReplicaChunkDescriptorTable::Get().RegisterChunkType<HostChunk, GridMate::BasicHostChunkDescriptor<HostChunk>>();
MPSession nodes[nNodes];
MPSessionMedium nodes[nNodes];
// initialize transport
int basePort = 4427;
@@ -2791,8 +2791,8 @@ TEST_F(Integ_BasicHostChunkDescriptorTest, BasicHostChunkDescriptorTest)
* Create and immedietly destroy primary replica
* Test that it does not result in any network sync
*/
class Integ_CreateDestroyPrimary
: public Integ_SimpleTest
class CreateDestroyPrimary
: public SimpleTest
, public Debug::ReplicaDrillerBus::Handler
{
public:
@@ -2827,7 +2827,7 @@ public:
}
};
TEST_F(Integ_CreateDestroyPrimary, CreateDestroyPrimary)
TEST_F(CreateDestroyPrimary, DISABLED_CreateDestroyPrimary)
{
RunTickLoop([this](int tick)-> TestStatus
{
@@ -2861,7 +2861,7 @@ TEST_F(Integ_CreateDestroyPrimary, CreateDestroyPrimary)
* The ReplicaTarget will prevent sending more updates.
*/
class ReplicaACKfeedbackTestFixture
: public Integ_SimpleTest
: public SimpleTest
{
public:
ReplicaACKfeedbackTestFixture()
@@ -2900,7 +2900,7 @@ public:
size_t m_replicaBytesSentPrev = 0;
ReplicaId m_replicaId;
Integ_ReplicaDriller::ReplicaDrillerHook m_driller;
ReplicaDriller::ReplicaDrillerHook m_driller;
};
TEST_F(ReplicaACKfeedbackTestFixture, ReplicaACKfeedbackTest)
+30 -30
View File
@@ -40,7 +40,7 @@ namespace UnitTest
}
}
class Integ_LANSessionMatchmakingParamsTest
class DISABLED_LANSessionMatchmakingParamsTest
: public GridMateMPTestFixture
, public SessionEventBus::MultiHandler
{
@@ -52,7 +52,7 @@ namespace UnitTest
}
public:
Integ_LANSessionMatchmakingParamsTest(bool useIPv6 = false)
DISABLED_LANSessionMatchmakingParamsTest(bool useIPv6 = false)
: m_hostSession(nullptr)
, m_clientGridMate(nullptr)
{
@@ -71,7 +71,7 @@ namespace UnitTest
AZ_TEST_ASSERT(GridMate::LANSessionServiceBus::FindFirstHandler(m_clientGridMate) != nullptr);
//////////////////////////////////////////////////////////////////////////
}
~Integ_LANSessionMatchmakingParamsTest() override
~DISABLED_LANSessionMatchmakingParamsTest() override
{
SessionEventBus::MultiHandler::BusDisconnect(m_gridMate);
SessionEventBus::MultiHandler::BusDisconnect(m_clientGridMate);
@@ -192,7 +192,7 @@ namespace UnitTest
IGridMate* m_clientGridMate;
};
class Integ_LANSessionTest
class DISABLED_LANSessionTest
: public GridMateMPTestFixture
{
class TestPeerInfo
@@ -264,7 +264,7 @@ namespace UnitTest
};
public:
Integ_LANSessionTest(bool useIPv6 = false)
DISABLED_LANSessionTest(bool useIPv6 = false)
{
m_driverType = useIPv6 ? Driver::BSD_AF_INET6 : Driver::BSD_AF_INET;
m_doSessionParamsTest = k_numMachines > 1;
@@ -290,7 +290,7 @@ namespace UnitTest
AZ_TEST_ASSERT(LANSessionServiceBus::FindFirstHandler(m_peers[i].m_gridMate) != nullptr);
}
}
~Integ_LANSessionTest() override
~DISABLED_LANSessionTest() override
{
StopGridMateService<LANSessionService>(m_peers[0].m_gridMate);
@@ -555,15 +555,15 @@ namespace UnitTest
bool m_doSessionParamsTest;
};
class Integ_LANSessionTestIPv6
: public Integ_LANSessionTest
class DISABLED_LANSessionTestIPv6
: public DISABLED_LANSessionTest
{
public:
Integ_LANSessionTestIPv6()
: Integ_LANSessionTest(true) {}
DISABLED_LANSessionTestIPv6()
: DISABLED_LANSessionTest(true) {}
};
class Integ_LANMultipleSessionTest
class DISABLED_LANMultipleSessionTest
: public GridMateMPTestFixture
, public SessionEventBus::Handler
{
@@ -620,7 +620,7 @@ namespace UnitTest
m_sessions[i] = nullptr;
}
Integ_LANMultipleSessionTest()
DISABLED_LANMultipleSessionTest()
: GridMateMPTestFixture(200 * 1024 * 1024)
{
//////////////////////////////////////////////////////////////////////////
@@ -645,7 +645,7 @@ namespace UnitTest
}
}
~Integ_LANMultipleSessionTest() override
~DISABLED_LANMultipleSessionTest() override
{
GridMate::StopGridMateService<GridMate::LANSessionService>(m_gridMates[0]);
@@ -799,7 +799,7 @@ namespace UnitTest
* Testing session with low latency. This is special mode usually used by tools and communication channels
* where we try to response instantly on messages.
*/
class Integ_LANLatencySessionTest
class DISABLED_LANLatencySessionTest
: public GridMateMPTestFixture
, public SessionEventBus::Handler
{
@@ -857,7 +857,7 @@ namespace UnitTest
m_sessions[i] = nullptr;
}
Integ_LANLatencySessionTest()
DISABLED_LANLatencySessionTest()
#ifdef AZ_TEST_LANLATENCY_ENABLE_MONSTER_BUFFER
: GridMateMPTestFixture(50 * 1024 * 1024)
#endif
@@ -884,7 +884,7 @@ namespace UnitTest
}
}
~Integ_LANLatencySessionTest() override
~DISABLED_LANLatencySessionTest() override
{
StopGridMateService<LANSessionService>(m_gridMates[0]);
@@ -1162,7 +1162,7 @@ namespace UnitTest
* 5. After host migration we drop the new host again. (after migration we have 3 members).
* Session should be fully operational at the end with 3 members left.
*/
class Integ_LANSessionMigarationTestTest
class LANSessionMigarationTestTest
: public SessionEventBus::Handler
, public GridMateMPTestFixture
{
@@ -1257,7 +1257,7 @@ namespace UnitTest
}
}
Integ_LANSessionMigarationTestTest()
LANSessionMigarationTestTest()
{
//////////////////////////////////////////////////////////////////////////
// Create all grid mates
@@ -1283,7 +1283,7 @@ namespace UnitTest
//StartDrilling("lanmigration");
}
~Integ_LANSessionMigarationTestTest() override
~LANSessionMigarationTestTest() override
{
StopGridMateService<LANSessionService>(m_gridMates[0]);
@@ -1476,7 +1476,7 @@ namespace UnitTest
* 5. We join a 2 new members to the session.
* Session should be fully operational at the end with 4 members in it.
*/
class Integ_LANSessionMigarationTestTest2
class LANSessionMigarationTestTest2
: public SessionEventBus::Handler
, public GridMateMPTestFixture
{
@@ -1571,7 +1571,7 @@ namespace UnitTest
}
}
}
Integ_LANSessionMigarationTestTest2()
LANSessionMigarationTestTest2()
{
//////////////////////////////////////////////////////////////////////////
// Create all grid mates
@@ -1597,7 +1597,7 @@ namespace UnitTest
//StartDrilling("lanmigration2");
}
~Integ_LANSessionMigarationTestTest2() override
~LANSessionMigarationTestTest2() override
{
StopGridMateService<LANSessionService>(m_gridMates[0]);
@@ -1816,7 +1816,7 @@ namespace UnitTest
* 3. Add 2 new joins to the original session.
* Original session should remain fully operational with 4 members in it.
*/
class Integ_LANSessionMigarationTestTest3
class LANSessionMigarationTestTest3
: public SessionEventBus::Handler
, public GridMateMPTestFixture
{
@@ -1910,7 +1910,7 @@ namespace UnitTest
}
}
}
Integ_LANSessionMigarationTestTest3()
LANSessionMigarationTestTest3()
{
//////////////////////////////////////////////////////////////////////////
// Create all grid mates
@@ -1936,7 +1936,7 @@ namespace UnitTest
//StartDrilling("lanmigration2");
}
~Integ_LANSessionMigarationTestTest3() override
~LANSessionMigarationTestTest3() override
{
StopGridMateService<LANSessionService>(m_gridMates[0]);
@@ -2122,13 +2122,13 @@ namespace UnitTest
}
GM_TEST_SUITE(SessionSuite)
GM_TEST(Integ_LANSessionMatchmakingParamsTest)
GM_TEST(Integ_LANSessionTest)
GM_TEST(DISABLED_LANSessionMatchmakingParamsTest)
GM_TEST(DISABLED_LANSessionTest)
#if (AZ_TRAIT_GRIDMATE_TEST_SOCKET_IPV6_SUPPORT_ENABLED)
GM_TEST(Integ_LANSessionTestIPv6)
GM_TEST(DISABLED_LANSessionTestIPv6)
#endif
GM_TEST(Integ_LANMultipleSessionTest)
GM_TEST(Integ_LANLatencySessionTest)
GM_TEST(DISABLED_LANMultipleSessionTest)
GM_TEST(DISABLED_LANLatencySessionTest)
// Manually enabled tests (require 2+ machines and online services)
//GM_TEST(LANSessionMigarationTestTest)
@@ -110,7 +110,7 @@ namespace UnitTest
std::array<char, SIZE> m_buffer;
};
class Integ_StreamSecureSocketDriverTestsBindSocketEmpty
class DISABLED_StreamSecureSocketDriverTestsBindSocketEmpty
: public GridMateMPTestFixture
{
public:
@@ -134,7 +134,7 @@ namespace UnitTest
}
};
class Integ_StreamSecureSocketDriverTestsConnection
class DISABLED_StreamSecureSocketDriverTestsConnection
: public GridMateMPTestFixture
{
public:
@@ -146,7 +146,7 @@ namespace UnitTest
}
};
class Integ_StreamSecureSocketDriverTestsConnectionAndHelloWorld
class DISABLED_StreamSecureSocketDriverTestsConnectionAndHelloWorld
: public GridMateMPTestFixture
{
public:
@@ -190,7 +190,7 @@ namespace UnitTest
}
};
class Integ_StreamSecureSocketDriverTestsPingPong
class DISABLED_StreamSecureSocketDriverTestsPingPong
: public GridMateMPTestFixture
{
public:
@@ -425,13 +425,13 @@ namespace UnitTest
void BuildStateMachine()
{
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_TOP), AZ::HSM::StateHandler(this, &Integ_StreamSecureSocketDriverTestsPingPong::OnStateTop), AZ::HSM::InvalidStateId, TS_START);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_START), AZ::HSM::StateHandler(this, &Integ_StreamSecureSocketDriverTestsPingPong::OnStateStart), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_SERVER_GET_PING), AZ::HSM::StateHandler(this, &Integ_StreamSecureSocketDriverTestsPingPong::OnStateServerGetPing), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_PING_GET_SERVER), AZ::HSM::StateHandler(this, &Integ_StreamSecureSocketDriverTestsPingPong::OnStatePingGetServer), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_SERVER_GET_PONG), AZ::HSM::StateHandler(this, &Integ_StreamSecureSocketDriverTestsPingPong::OnStateServerGetPong), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_PONG_GET_SERVER), AZ::HSM::StateHandler(this, &Integ_StreamSecureSocketDriverTestsPingPong::OnStatePongGetServer), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_IN_ERROR), AZ::HSM::StateHandler(this, &Integ_StreamSecureSocketDriverTestsPingPong::OnStateInError), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_TOP), AZ::HSM::StateHandler(this, &DISABLED_StreamSecureSocketDriverTestsPingPong::OnStateTop), AZ::HSM::InvalidStateId, TS_START);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_START), AZ::HSM::StateHandler(this, &DISABLED_StreamSecureSocketDriverTestsPingPong::OnStateStart), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_SERVER_GET_PING), AZ::HSM::StateHandler(this, &DISABLED_StreamSecureSocketDriverTestsPingPong::OnStateServerGetPing), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_PING_GET_SERVER), AZ::HSM::StateHandler(this, &DISABLED_StreamSecureSocketDriverTestsPingPong::OnStatePingGetServer), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_SERVER_GET_PONG), AZ::HSM::StateHandler(this, &DISABLED_StreamSecureSocketDriverTestsPingPong::OnStateServerGetPong), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_PONG_GET_SERVER), AZ::HSM::StateHandler(this, &DISABLED_StreamSecureSocketDriverTestsPingPong::OnStatePongGetServer), TS_TOP);
m_stateMachine.SetStateHandler(AZ_HSM_STATE_NAME(TS_IN_ERROR), AZ::HSM::StateHandler(this, &DISABLED_StreamSecureSocketDriverTestsPingPong::OnStateInError), TS_TOP);
m_stateMachine.Start();
}
@@ -486,10 +486,10 @@ namespace UnitTest
}
GM_TEST_SUITE(StreamSecureSocketDriverTests)
GM_TEST(Integ_StreamSecureSocketDriverTestsBindSocketEmpty);
GM_TEST(Integ_StreamSecureSocketDriverTestsConnection);
GM_TEST(Integ_StreamSecureSocketDriverTestsConnectionAndHelloWorld);
GM_TEST(Integ_StreamSecureSocketDriverTestsPingPong);
GM_TEST(DISABLED_StreamSecureSocketDriverTestsBindSocketEmpty);
GM_TEST(DISABLED_StreamSecureSocketDriverTestsConnection);
GM_TEST(DISABLED_StreamSecureSocketDriverTestsConnectionAndHelloWorld);
GM_TEST(DISABLED_StreamSecureSocketDriverTestsPingPong);
GM_TEST_SUITE_END()
#endif // AZ_TRAIT_GRIDMATE_ENABLE_OPENSSL
@@ -308,7 +308,7 @@ namespace UnitTest
}
};
class Integ_StreamSocketDriverTestsTooManyConnections
class DISABLED_StreamSocketDriverTestsTooManyConnections
: public GridMateMPTestFixture
{
public:
@@ -529,7 +529,7 @@ GM_TEST_SUITE(StreamSocketDriverTests)
GM_TEST(StreamSocketDriverTestsSimpleLockStepConnection);
GM_TEST(StreamSocketDriverTestsEstablishConnectAndSend);
GM_TEST(StreamSocketDriverTestsManyRandomPackets);
GM_TEST(Integ_StreamSocketDriverTestsTooManyConnections);
GM_TEST(DISABLED_StreamSocketDriverTestsTooManyConnections);
GM_TEST(StreamSocketDriverTestsClientToInvalidServer);
GM_TEST(StreamSocketDriverTestsManySends);
@@ -1,244 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "Tests.h"
#include "TestProfiler.h"
#include <AzCore/Debug/Profiler.h>
#include <AzCore/Math/Crc.h>
#include <GridMate/Containers/set.h>
#include <GridMate/Containers/unordered_set.h>
using namespace GridMate;
typedef set<const AZ::Debug::ProfilerRegister*> ProfilerSet;
static bool CollectPerformanceCounters(const AZ::Debug::ProfilerRegister& reg, const AZStd::thread_id&, ProfilerSet& profilers, const char* systemId)
{
if (reg.m_type != AZ::Debug::ProfilerRegister::PRT_TIME)
{
return true;
}
if (reg.m_systemId != AZ::Crc32(systemId))
{
return true;
}
const AZ::Debug::ProfilerRegister* profReg = &reg;
profilers.insert(profReg);
return true;
}
static AZStd::string FormatString(const AZStd::string& pre, const AZStd::string& name, const AZStd::string& post, AZ::u64 time, AZ::u64 calls)
{
AZStd::string units = "us";
if (AZ::u64 divtime = time / 1000)
{
time = divtime;
units = "ms";
}
return AZStd::string::format("%s%s %s %10llu%s (%llu calls)\n", pre.c_str(), name.c_str(), post.c_str(), time, units.c_str(), calls);
}
struct TotalSortContainer
{
TotalSortContainer(const AZ::Debug::ProfilerRegister* self = nullptr)
{
m_self = self;
}
void Print(AZ::s32 level, const char* systemId)
{
if (m_self && level >= 0)
{
AZStd::string levelIndent;
for (AZ::s32 i = 0; i < level; i++)
{
levelIndent += (i == level - 1) ? "+---" : "| ";
}
AZStd::string name = m_self->m_name ? m_self->m_name : m_self->m_function;
AZStd::string outputTotal = FormatString(levelIndent, name, " Total:", m_self->m_timeData.m_time, m_self->m_timeData.m_calls);
AZ_Printf(systemId, outputTotal.c_str());
if (m_self->m_timeData.m_childrenTime || m_self->m_timeData.m_childrenCalls)
{
AZStd::string childIndent = levelIndent;
for (auto i = name.begin(); i != name.end(); ++i)
{
childIndent += " ";
}
childIndent[level * 4] = '|';
AZStd::string outputChild = FormatString(childIndent, "", "Child:", m_self->m_timeData.m_childrenTime, m_self->m_timeData.m_childrenCalls);
AZ_Printf(systemId, outputChild.c_str());
AZStd::string outputSelf = FormatString(childIndent, "", "Self :", m_self->m_timeData.m_time - m_self->m_timeData.m_childrenTime, m_self->m_timeData.m_calls);
AZ_Printf(systemId, outputSelf.c_str());
}
}
for (auto i = m_children.begin(); i != m_children.end(); ++i)
{
i->Print(level + 1, systemId);
}
}
TotalSortContainer* Find(const AZ::Debug::ProfilerRegister* obj)
{
if (m_self == obj)
{
return this;
}
for (TotalSortContainer& child : m_children)
{
TotalSortContainer* found = child.Find(obj);
if (found)
{
return found;
}
}
return nullptr;
}
struct TotalSorter
{
bool operator()(const TotalSortContainer& a, const TotalSortContainer& b) const
{
if (a.m_self->m_timeData.m_time == b.m_self->m_timeData.m_time)
{
return a.m_self > b.m_self;
}
return a.m_self->m_timeData.m_time > b.m_self->m_timeData.m_time;
}
};
set<TotalSortContainer, TotalSorter> m_children;
const AZ::Debug::ProfilerRegister* m_self;
};
void TestProfiler::StartProfiling()
{
StopProfiling();
AZ::Debug::Profiler::Create();
}
void TestProfiler::StopProfiling()
{
if (AZ::Debug::Profiler::IsReady())
{
AZ::Debug::Profiler::Destroy();
}
}
void TestProfiler::PrintProfilingTotal(const char* systemId)
{
if (!AZ::Debug::Profiler::IsReady())
{
return;
}
ProfilerSet profilers;
AZ::Debug::Profiler::Instance().ReadRegisterValues(AZStd::bind(&CollectPerformanceCounters, AZStd::placeholders::_1, AZStd::placeholders::_2, AZStd::ref(profilers), systemId));
// Validate we wont get stuck in an infinite loop
TotalSortContainer root;
for (auto i = profilers.begin(); i != profilers.end(); )
{
const AZ::Debug::ProfilerRegister* profile = *i;
if (profile->m_timeData.m_lastParent)
{
auto parent = profilers.find(profile->m_timeData.m_lastParent);
if (parent == profilers.end())
{
// Error, just ignore this entry
i = profilers.erase(i);
continue;
}
}
++i;
}
// Put all root nodes into the final list
for (auto i = profilers.begin(); i != profilers.end(); )
{
const AZ::Debug::ProfilerRegister* profile = *i;
if (!profile->m_timeData.m_lastParent)
{
root.m_children.insert(profile);
i = profilers.erase(i);
}
else
{
++i;
}
}
// Put all non-root nodes into the final list
while (!profilers.empty())
{
for (auto i = profilers.begin(); i != profilers.end(); )
{
const AZ::Debug::ProfilerRegister* profile = *i;
TotalSortContainer* found = root.Find(profile->m_timeData.m_lastParent);
if (found)
{
found->m_children.insert(profile);
i = profilers.erase(i);
}
else
{
++i;
}
}
}
AZ_Printf(systemId, "Profiling timers by total execution time:\n");
root.Print(-1, systemId);
}
void TestProfiler::PrintProfilingSelf(const char* systemId)
{
if (!AZ::Debug::Profiler::IsReady())
{
return;
}
ProfilerSet profilers;
AZ::Debug::Profiler::Instance().ReadRegisterValues(AZStd::bind(&CollectPerformanceCounters, AZStd::placeholders::_1, AZStd::placeholders::_2, AZStd::ref(profilers), systemId));
struct SelfSorter
{
bool operator()(const AZ::Debug::ProfilerRegister* a, const AZ::Debug::ProfilerRegister* b) const
{
auto aTime = a->m_timeData.m_time - a->m_timeData.m_childrenTime;
auto bTime = b->m_timeData.m_time - b->m_timeData.m_childrenTime;
if (aTime == bTime)
{
return a > b;
}
return aTime > bTime;
}
};
set<const AZ::Debug::ProfilerRegister*, SelfSorter> selfSorted;
for (auto& profiler : profilers)
{
selfSorted.insert(profiler);
}
AZ_Printf(systemId, "Profiling timers by exclusive execution time:\n");
for (auto profiler : selfSorted)
{
AZStd::string str = FormatString("", profiler->m_name ? profiler->m_name : profiler->m_function, "Self Time:",
profiler->m_timeData.m_time - profiler->m_timeData.m_childrenTime, profiler->m_timeData.m_calls);
AZ_Printf(systemId, str.c_str());
}
}
@@ -1,24 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef GM_TEST_PROFILER_H
#define GM_TEST_PROFILER_H
namespace GridMate
{
class TestProfiler
{
public:
static void StartProfiling();
static void StopProfiling();
static void PrintProfilingTotal(const char* systemId);
static void PrintProfilingSelf(const char* systemId);
};
}
#endif
@@ -12,6 +12,7 @@ set(FILES
Session.cpp
Serialize.cpp
Certificates.cpp
Replica.cpp
ReplicaSmall.cpp
ReplicaMedium.cpp
ReplicaBehavior.cpp
@@ -291,6 +291,9 @@ namespace AssetBundler
int main(int argc, char* argv[])
{
AZ::Debug::Trace::HandleExceptions(true);
AZ::Test::ApplyGlobalParameters(&argc, argv);
INVOKE_AZ_UNIT_TEST_MAIN();
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
@@ -262,7 +262,7 @@ namespace UnitTests
auto result = m_data->m_reporter->ComputeDestination(entryContainer, m_data->m_platformConfig.GetScanFolderByPath(scanFolderEntry.m_scanFolder.c_str()), source, destination, destInfo);
ASSERT_EQ(result.IsSuccess(), expectSuccess) << result.GetError().c_str();
ASSERT_EQ(result.IsSuccess(), expectSuccess) << (!result.IsSuccess() ? result.GetError().c_str() : "");
if (expectSuccess)
{
@@ -29,6 +29,9 @@ int main(int argc, char* argv[])
{
qputenv("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM", "1");
AZ::Debug::Trace::HandleExceptions(true);
AZ::Test::ApplyGlobalParameters(&argc, argv);
// If "--unittest" is present on the command line, run unit testing
// and return immediately. Otherwise, continue as normal.
AZ::Test::addTestEnvironment(new BaseAssetProcessorTestEnvironment());
+7 -74
View File
@@ -18,45 +18,35 @@ namespace AzTestRunner
const int LIB_NOT_FOUND = 102;
const int SYMBOL_NOT_FOUND = 103;
// note that MODULE_SKIPPED is not an error condition, but not 0 to indicate its not the
// same as successfully running tests and finding them.
const int MODULE_SKIPPED = 104;
const char* INTEG_BOOTSTRAP = "AzTestIntegBootstrap";
//! display proper usage of the application
void usage([[maybe_unused]] AZ::Test::Platform& platform)
{
std::stringstream ss;
ss <<
"AzTestRunner\n"
"Runs AZ unit and integration tests. Exit code is the result from GoogleTest.\n"
"Runs AZ tests. Exit code is the result from GoogleTest.\n"
"\n"
"Usage:\n"
" AzTestRunner.exe <lib> (AzRunUnitTests|AzRunIntegTests) [--integ] [--wait-for-debugger] [--pause-on-completion] [google-test-args]\n"
" AzTestRunner.exe <lib> (AzRunUnitTests|AzRunBenchmarks) [--wait-for-debugger] [--pause-on-completion] [google-test-args]\n"
"\n"
"Options:\n"
" <lib>: the module to test\n"
" <hook>: the name of the aztest hook function to run in the <lib>\n"
" 'AzRunUnitTests' will hook into unit tests\n"
" 'AzRunIntegTests' will hook into integration tests\n"
" --integ: tells runner to bootstrap the engine, needed for integration tests\n"
" Note: you can run unit tests with a bootstrapped engine (AzRunUnitTests --integ),\n"
" but running integration tests without a bootstrapped engine (AzRunIntegTests w/ no --integ) might not work.\n"
" 'AzRunBenchmarks' will hook into benchmark tests\n"
" --wait-for-debugger: tells runner to wait for debugger to attach to process (on supported platforms)\n"
" --pause-on-completion: tells the runner to pause after running the tests\n"
" --quiet: disables stdout for minimal output while running tests\n"
"\n"
"Example:\n"
" AzTestRunner.exe CrySystem.dll AzRunUnitTests --pause-on-completion\n"
" AzTestRunner.exe CrySystem.dll AzRunIntegTests --integ\n"
" AzTestRunner.exe AzCore.Tests.dll AzRunUnitTests --pause-on-completion\n"
"\n"
"Exit Codes:\n"
" 0 - all tests pass\n"
" 1 - test failure\n"
<< " " << INCORRECT_USAGE << " - incorrect usage (see above)\n"
<< " " << LIB_NOT_FOUND << " - library/dll could not be loaded\n"
<< " " << SYMBOL_NOT_FOUND << " - export symbol not found\n"
<< " " << MODULE_SKIPPED << " - non-integ module was skipped (not an error)\n";
<< " " << SYMBOL_NOT_FOUND << " - export symbol not found\n";
std::cerr << ss.str() << std::endl;
}
@@ -82,7 +72,6 @@ namespace AzTestRunner
// capture optional arguments
bool waitForDebugger = false;
bool isInteg = false;
bool pauseOnCompletion = false;
bool quiet = false;
for (int i = 0; i < argc; i++)
@@ -93,12 +82,6 @@ namespace AzTestRunner
AZ::Test::RemoveParameters(argc, argv, i, i);
i--;
}
else if (strcmp(argv[i], "--integ") == 0)
{
isInteg = true;
AZ::Test::RemoveParameters(argc, argv, i, i);
i--;
}
else if (strcmp(argv[i], "--pause-on-completion") == 0)
{
pauseOnCompletion = true;
@@ -172,47 +155,11 @@ namespace AzTestRunner
if (result != 0)
{
module.reset();
if ((isInteg) && (result == SYMBOL_NOT_FOUND))
{
// special case: It is not required to put an INTEG test inside every DLL - so if
// we failed to find the INTEG entry point in this DLL, its not an error.
// its only an error if we find it and there are no tests, or we find it and tests actually
// fail.
std::cerr << "INTEG module has no entry point and will be skipped: " << lib << std::endl;
return MODULE_SKIPPED;
}
return result;
}
platform.SuppressPopupWindows();
// Grab a bootstrapper library if requested
std::shared_ptr<AZ::Test::IModuleHandle> bootstrap;
if (isInteg)
{
bootstrap = platform.GetModule(INTEG_BOOTSTRAP);
if (!bootstrap->IsValid())
{
std::cerr << "FAILED to load bootstrapper" << std::endl;
return LIB_NOT_FOUND;
}
// Initialize the bootstrapper
auto init = bootstrap->GetFunction("Initialize");
if (init->IsValid())
{
int initResult = (*init)();
if (initResult != 0)
{
std::cerr << "Bootstrapper Initialize failed with code " << initResult << ", exiting" << std::endl;
return initResult;
}
}
}
// run the test main function.
if (testMainFunction->IsValid())
{
@@ -231,22 +178,6 @@ namespace AzTestRunner
// system allocator / etc.
module.reset();
// Shutdown the bootstrapper
if (bootstrap)
{
auto shutdown = bootstrap->GetFunction("Shutdown");
if (shutdown->IsValid())
{
int shutdownResult = (*shutdown)();
if (shutdownResult != 0)
{
std::cerr << "Bootstrapper shutdown failed with code " << shutdownResult << ", exiting" << std::endl;
return shutdownResult;
}
}
bootstrap.reset();
}
if (pauseOnCompletion)
{
AzTestRunner::pause_on_completion();
@@ -258,6 +189,8 @@ namespace AzTestRunner
int wrapped_main(int argc/*=0*/, char** argv/*=nullptr*/)
{
AZ::Debug::Trace::HandleExceptions(true);
if (argc>0 && argv!=nullptr)
{
return wrapped_command_arg_main(argc, argv);
+3
View File
@@ -18,6 +18,9 @@ int runDefaultRunner(int argc, char* argv[])
int main(int argc, char* argv[])
{
AZ::Debug::Trace::HandleExceptions(true);
AZ::Test::ApplyGlobalParameters(&argc, argv);
if (argc == 1)
{
// if no parameters are provided, add the --unittests parameter
@@ -23,6 +23,9 @@ int runDefaultRunner(int argc, char* argv[])
int main(int argc, char* argv[])
{
AZ::Debug::Trace::HandleExceptions(true);
AZ::Test::ApplyGlobalParameters(&argc, argv);
// ran with no parameters?
if (argc == 1)
{
@@ -10,7 +10,6 @@
#include <scenesrg.srgi>
#include <viewsrg.srgi>
#include "JitterTablePcf.azsli"
#include "Shadow.azsli"
#include "ShadowmapAtlasLib.azsli"
#include "BicubicPcfFilters.azsli"
@@ -82,12 +81,6 @@ class DirectionalLightShadow
// result.y == true if the given coordinate is in shadow.
bool2 IsShadowed(float3 shadowCoord, uint indexOfCascade);
// This checks if the point is shadowed or not for the given center coordinate and jitter.
bool IsShadowedWithJitter(
float3 jitterUnit,
float jitterDepthDiffBase,
uint jitterIndex);
// This outputs visibility ratio (from 0.0 to 1.0) of the given coordinate
// from the light origin without filtering.
float GetVisibilityFromLightNoFilter();
@@ -189,75 +182,6 @@ bool2 DirectionalLightShadow::IsShadowed(float3 shadowCoord, uint indexOfCascade
return bool2(false, false);
}
bool DirectionalLightShadow::IsShadowedWithJitter(
float3 jitterUnit,
float jitterDepthDiffBase,
uint jitterIndex)
{
const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount;
const float4x4 worldToLightViewMatrices[ViewSrg::MaxCascadeCount] =
ViewSrg::m_directionalLightShadows[m_lightIndex].m_worldToLightViewMatrices;
const float4x4 lightViewToShadowmapMatrices[ViewSrg::MaxCascadeCount] =
ViewSrg::m_directionalLightShadows[m_lightIndex].m_lightViewToShadowmapMatrices;
const float boundaryScale =
ViewSrg::m_directionalLightShadows[m_lightIndex].m_boundaryScale;
const float2 jitterXY = g_jitterTablePcf[jitterIndex];
// jitterLightView is the jittering diff vector from the lighted point on the surface
// in the light view space. It is remarked as "v_J" in the comment
// named "Calculate depth adjusting diff for jittered samples"
// just before the function GetJitterUnitVectorDepthDiffBase.
const float4 jitterLightView = float4(jitterXY, 0., 0.) * boundaryScale;
// It checks the jittered point is lit or shadowed from the detailed cascade
// to the less detailed one.
for (uint indexOfCascade = 0; indexOfCascade < cascadeCount; ++indexOfCascade)
{
// jitterShadowmap is the jittering diff vector in the shadowmap space.
const float4 jitterShadowmap = mul(lightViewToShadowmapMatrices[indexOfCascade], jitterLightView);
// Calculation of the jittering for Z-coordinate (light direction) is required
// to check lit/shadowed for the jittered point.
// jitterDepthDiff is the Z-coordinate of the jittering diff vector
// in the shadowmap space.
float jitterDepthDiff = 0.;
// jitterDepthDiffBase is "1/tan(theta)" in the comment.
if (jitterDepthDiffBase != 0.)
{
// jitterUnitLightView is the unit vector in the light view space
// noted as "v_M" in the comment.
const float3 jitterUnitLightView =
normalize(mul(worldToLightViewMatrices[indexOfCascade], float4(jitterUnit, 0.)).xyz);
const float lightViewToShadowmapZScale = -lightViewToShadowmapMatrices[indexOfCascade]._m22;
// jitterDepthDiff is the "d" in the note, and it is calculated by
// d = (v_J . v_M) / tan(theta)
// in the light view space. Furthermore it have to be converted
// to the light clip space, which can be done by lightViewToShadowmapZScale.
jitterDepthDiff =
dot(jitterLightView.xyz, jitterUnitLightView) * jitterDepthDiffBase *
lightViewToShadowmapZScale;
}
// jitteredCoord is the coordinate of the jittered point in the shadowmap space.
const float3 jitteredCoord =
m_shadowCoords[indexOfCascade] + float3(jitterShadowmap.xy, jitterDepthDiff);
// Check for the jittered point is lit or shadowed.
const bool2 checkedShadowed = IsShadowed(
jitteredCoord,
indexOfCascade);
// If check is done, return the lit/shadowed flag.
// Otherwise make it pend to the next cascade.
if (checkedShadowed.x)
{
m_debugInfo.m_cascadeIndex = indexOfCascade;
return checkedShadowed.y;
}
}
m_debugInfo.m_cascadeIndex = cascadeCount;
return false;
}
float DirectionalLightShadow::GetVisibilityFromLightNoFilter()
{
const uint cascadeCount = ViewSrg::m_directionalLightShadows[m_lightIndex].m_cascadeCount;
@@ -1,185 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
/*
The following is the output of
$ python3 pcf_jitter_table.py 6 g_jitterTablePcf 0
where pcf_jitter_table.py has the following contents.
@code
#!/usr/bin/env python3
import random
import sys
import math
""" Returns if a point in the range
[radius_min, radius_sup)*[angle_min, angle_sup)
is contained in the tuple polar coordinates.
"""
def is_point_include(radius_min, radius_sup, angle_min, angle_sup, polars):
for polar in polars:
if (radius_min <= polar[0] and polar[0] < radius_sup and
angle_min <= polar[1] and polar[1] < angle_sup):
return True
return False
""" Insert a randomly generated polar coordianted point in each
range [r0, r1)*[a0, a1) if there has not been such a point
in tuple coords yet, where [0, 1)*[0, 2pi) is divided
into the rad_count*agl_count ranges.
"""
def add_jitter_coords(radius_count, angle_count, polars):
radius_base = 1.0 / math.sqrt(radius_count)
for radius_index in range(radius_count):
# range of radius
radius_min = math.sqrt(radius_index) * radius_base
radius_sup = math.sqrt(radius_index + 1) * radius_base
# randomize angle order
random_state = random.getstate()
angle_indices = list(range(angle_count))
random.shuffle(angle_indices)
random.setstate(random_state)
for angle_index in angle_indices:
# range of angle
angle_min = 2 * math.pi * angle_index / angle_count
angle_sup = 2 * math.pi * (angle_index + 1) / angle_count
# if no point in the radius/angle range, add a new point
if not is_point_include(radius_min, radius_sup,
angle_min, angle_sup,
polars):
radius = radius_min + (radius_sup - radius_min) * random.random()
angle = angle_min + (angle_sup - angle_min) * random.random()
polars += [[radius, angle]]
""" Return a formatted string readable as an array of
orthogonal coordinated points which are in inside of the unit disk.
"""
def conv_array_string(polars):
result = "{\n"
for [radius, angle] in polars:
x = radius * math.cos(angle)
y = radius * math.sin(angle)
result += str.format(" float2({: 1.20e}, {: 1.20e}),\n", x, y)
result = result.rstrip(",\n") + "\n};\n"
return result
if __name__ == "__main__":
rad_size = 1
ang_size = 1
if len(sys.argv) > 3:
random_seed = int(sys.argv[3])
else:
random_seed = 0
if len(sys.argv) > 2:
array_name = sys.argv[2]
else:
array_name = False
if len(sys.argv) > 1:
len_log = int(sys.argv[1])
else:
print(" usage: {} array_len_log2 [array_file_name] [random_seed]".format(__file__))
print(" array_len_log2 = 2 -> array length = 4")
print(" array_len_log2 = 6 -> array length = 64")
sys.exit()
random.seed(random_seed)
coords = []
add_jitter_coords(rad_size, ang_size, coords)
for index in range(len_log):
if index % 2 == 0:
rad_size *= 2
else:
ang_size *= 2
add_jitter_coords(rad_size, ang_size, coords)
if array_name:
print(str.format("static const float2 {}[{}] =", array_name, len(coords)))
print(conv_array_string(coords))
@endcode
*/
#pragma once
static const float2 g_jitterTablePcf[64] =
{
float2( 4.21857815578105532772e-02, -8.43367430701083664601e-01),
float2(-1.66526814909220763350e-02, 2.96922406531470617352e-01),
float2(-1.06374665780382349212e-01, -3.45521852905696924552e-01),
float2( 5.42648241814168375008e-01, 7.63475573328278533936e-01),
float2(-1.55045122122251910479e-01, 5.78282315712970729216e-01),
float2( 1.01310018770242576264e-02, -6.88001749851880561870e-01),
float2(-5.41276603451248283783e-01, 5.21888233660957712168e-01),
float2(-6.69885071867917680777e-01, -6.72019666097878665134e-01),
float2( 1.22985029409499718039e-02, 4.54706838949524849713e-01),
float2( 4.00334354168925599105e-01, -6.20112671104014120949e-02),
float2( 2.32326155804074424571e-01, 5.14183027524470093184e-01),
float2(-3.26788693165450228051e-01, -6.03339478694129849323e-01),
float2( 7.72374386126136736053e-01, 1.23204314299169448432e-01),
float2(-4.45379212004159807936e-01, -6.35591042627205338178e-01),
float2( 9.86986293787213919693e-01, -5.18195017297516449806e-02),
float2(-9.09197225477999193544e-01, 1.95281945570711268356e-01),
float2( 8.78123785413316704229e-02, -2.77671865082058690055e-02),
float2( 1.93947312440399088906e-01, 4.27852204081567363825e-03),
float2(-2.06133675819526185347e-01, -1.49183652412411493771e-01),
float2(-4.11351098583102647854e-01, 2.36214692717993696158e-01),
float2( 3.50058750095615767162e-01, -3.57193658067260721989e-01),
float2(-5.54174780014121681759e-01, -2.23361040823672196698e-01),
float2(-6.29913348094886860196e-01, 1.29962593232600148729e-01),
float2( 3.96119563669521335125e-01, 4.90495219155295036906e-01),
float2( 7.26077464944819728210e-01, -3.70531027878536270426e-02),
float2(-5.50726266551596621568e-01, 6.48997654184258587762e-01),
float2(-6.98067624269093189859e-01, -3.83843898992943299842e-01),
float2( 8.72900706885875177221e-02, 8.24287559846993866941e-01),
float2( 6.65413234189638491678e-01, -5.66029707430476647367e-01),
float2(-5.97071574457786802270e-01, -6.93417220711863180327e-01),
float2( 6.09778569514949131403e-01, 6.92279483269558570946e-01),
float2(-8.10051800827623957879e-01, 5.82366304247235455627e-01),
float2(-8.77200948157437071506e-02, -1.88326609190753474499e-01),
float2( 9.79306884403889771340e-02, 1.86693151785678163046e-01),
float2( 4.60071424048798319206e-02, -1.98255149016034859510e-01),
float2(-5.37585860722621794450e-02, 3.99205315590760584366e-02),
float2( 2.18621803321778829243e-01, -3.85632280444686503795e-01),
float2(-2.98409571230789372187e-02, 4.22286693608096730390e-01),
float2( 3.58654757584850270025e-01, 2.95175871390239985548e-01),
float2(-3.85631921979480485341e-01, -3.00322047091407640096e-01),
float2( 4.49800763439369810648e-01, 3.98492182500493397068e-01),
float2(-4.97878650048238891035e-01, 2.57984038389083569776e-01),
float2(-3.12055242602567339816e-01, -4.88013525550807125697e-01),
float2( 5.87078632117718268724e-01, -6.97256834327608099322e-02),
float2( 6.23692403999373534695e-01, 3.11519734097943645779e-01),
float2( 6.64426445690903810792e-01, -2.27661844509491811950e-01),
float2(-3.24662942872471160793e-01, 5.68939932480760024447e-01),
float2(-5.31263995010459511015e-01, -4.66108719959298256619e-01),
float2( 5.10323549430644951563e-01, 5.81027848262460677731e-01),
float2( 2.82695533021593392586e-01, -7.03582425015577883620e-01),
float2(-5.98419541732174709026e-01, -4.68015982003612274198e-01),
float2(-3.95281650646674975746e-01, 6.10614720709622194050e-01),
float2( 7.87454411900813555647e-01, 1.37726315874787758053e-01),
float2(-7.36310249594224086600e-01, 4.25723821775386646049e-01),
float2( 6.48232481978769037312e-01, -5.53108138515975955585e-01),
float2(-1.88558544306507869237e-01, -7.79120748356531223067e-01),
float2(-3.78614630625567993860e-01, 7.82366459873827913007e-01),
float2(-8.48582606942172357201e-01, -3.78504015913022351381e-01),
float2( 1.91472859899175090748e-02, -9.13050020447597532325e-01),
float2( 8.08826910050883585157e-01, 4.17202663034078935489e-01),
float2(-9.27062588380768493046e-01, -2.94160352051227980130e-01),
float2( 6.67882607007592055126e-01, -6.88642020601400450808e-01),
float2(-1.59349274307943010454e-02, 9.37629353656756814317e-01),
float2( 9.86975590293644233775e-01, 1.44401793964158337014e-01)
};
@@ -13,7 +13,6 @@
#include <Atom/Features/Shadow/ShadowmapAtlasLib.azsli>
#include <Atom/RPI/Math.azsli>
#include "BicubicPcfFilters.azsli"
#include "JitterTablePcf.azsli"
#include "Shadow.azsli"
// ProjectedShadow calculates shadowed area projected from a light.
@@ -44,11 +43,6 @@ class ProjectedShadow
float GetThickness();
bool IsShadowed(float3 shadowPosition);
bool IsShadowedWithJitter(
float3 jitterUnitX,
float3 jitterUnitY,
float jitterDepthDiffBase,
uint jitterIndex);
void SetShadowPosition();
float3 GetAtlasPosition(float2 texturePosition);
static float UnprojectDepth(uint shadowIndex, float depthBufferValue);
@@ -321,35 +315,6 @@ bool ProjectedShadow::IsShadowed(float3 shadowPosition)
return false;
}
bool ProjectedShadow::IsShadowedWithJitter(
float3 jitterUnitX,
float3 jitterUnitY,
float jitterDepthDiffBase,
uint jitterIndex)
{
ViewSrg::ProjectedShadow shadow = ViewSrg::m_projectedShadows[m_shadowIndex];
const float4x4 depthBiasMatrix = shadow.m_depthBiasMatrix;
const float boundaryScale = shadow.m_boundaryScale;
const float2 jitterXY = g_jitterTablePcf[jitterIndex];
const float dist = distance(m_worldPosition, m_viewPosition);
const float boundaryRadius = dist * tan(boundaryScale);
// jitterWorldXY is the jittering diff vector from the lighted point on the surface
// in the world space. It is remarked as "v_J" in the comment
// named "Calculate depth adjusting diff for jittered samples"
// just before the function GetJitterUnitVectorDepthDiffBase.
const float3 jitterWorldXY = jitterUnitX * (jitterXY.x * boundaryRadius) + jitterUnitY * (jitterXY.y * boundaryRadius);
// The adjusting diff of depth ("d" in the comment) is calculated by
// jitterXY.y * boundaryRadius * jitterDepthDiffBase.
const float3 jitterWorldZ = m_lightDirection * (jitterXY.y * boundaryRadius * jitterDepthDiffBase);
const float3 jitteredWorldPosition = m_worldPosition + jitterWorldXY + jitterWorldZ;
const float4 jitteredShadowmapHomogeneous = mul(depthBiasMatrix, float4(jitteredWorldPosition, 1));
return IsShadowed(jitteredShadowmapHomogeneous.xyz / jitteredShadowmapHomogeneous.w);
}
void ProjectedShadow::SetShadowPosition()
{
const float4x4 depthBiasMatrix = ViewSrg::m_projectedShadows[m_shadowIndex].m_depthBiasMatrix;
@@ -23,14 +23,11 @@ struct FilterParameter
uint m_isEnabled;
uint2 m_shadowmapOriginInSlice;
uint m_shadowmapSize;
uint m_parameterOffset;
uint m_parameterCount;
float m_lightDistanceOfCameraViewFrustum;
float m_n_f_n; // n / (f - n)
float m_n_f; // n - f
float m_f; // f
// where n: nearDepth, f: farDepth.
float2 m_padding; // explicit padding
};
class Shadow
@@ -22,14 +22,11 @@ partial ShaderResourceGroup ViewSrg
uint m_isEnabled;
uint2 m_shadowmapOriginInSlice;
uint m_shadowmapSize;
uint m_parameterOffset;
uint m_parameterCount;
float m_lightDistanceOfCameraViewFrustum;
float m_n_f_n; // n / (f - n)
float m_n_f; // n - f
float m_f; // f
// where n: nearDepth, f: farDepth.
float2 m_padding; // explicit padding
};
// Simple Point Lights
@@ -286,7 +286,6 @@ set(FILES
ShaderLib/Atom/Features/ScreenSpace/ScreenSpaceUtil.azsli
ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli
ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli
ShaderLib/Atom/Features/Shadow/JitterTablePcf.azsli
ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli
ShaderLib/Atom/Features/Shadow/Shadow.azsli
ShaderLib/Atom/Features/Shadow/ShadowmapAtlasLib.azsli
@@ -154,12 +154,6 @@ namespace AZ
//! @param count Sample Count for filtering (up to 64)
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! This specifies the width of boundary between shadowed area and lit area.
//! @param handle the light handle.
//! @param width Boundary width. The shadow is gradually changed the degree of shadowed.
//! If width == 0, softening edge is disabled. Units are in meters.
virtual void SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth) = 0;
//! Sets whether the directional shadowmap should use receiver plane bias.
//! This attempts to reduce shadow acne when using large pcf filters.
virtual void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) = 0;
@@ -90,8 +90,6 @@ namespace AZ
virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0;
//! Specifies filter method of shadows.
virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0;
//! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on the boundary. 0 disables softening.
virtual void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) = 0;
//! Sets sample count for filtering of shadow boundary (up to 64)
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
@@ -70,9 +70,6 @@ namespace AZ
virtual void SetShadowBias(LightHandle handle, float bias) = 0;
//! Specifies filter method of shadows.
virtual void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) = 0;
//! Specifies the width of boundary between shadowed area and lit area in radians. The degree ofshadowed gradually changes on
//! the boundary. 0 disables softening.
virtual void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) = 0;
//! Sets sample count for filtering of shadow boundary (up to 64)
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
@@ -42,7 +42,6 @@ namespace AZ
// [GFX TODO][ATOM-2408] Make the max number of cascade modifiable at runtime.
static constexpr uint16_t MaxNumberOfCascades = 4;
static constexpr uint16_t MaxPcfSamplingCount = 64;
static constexpr float MaxSofteningBoundaryWidth = 0.1f;
} // namespace Shadow
} // namespace Render
@@ -54,8 +54,6 @@ namespace AZ::Render
virtual void SetShadowBias(ShadowId id, float bias) = 0;
//! Sets the shadow filter method
virtual void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) = 0;
//! Sets the width of boundary between shadowed area and lit area.
virtual void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) = 0;
//! Sets the sample count for filtering of the shadow boundary, max 64.
virtual void SetFilteringSampleCount(ShadowId id, uint16_t count) = 0;
//! Sets all of the shadow properites in one call
@@ -584,15 +584,6 @@ namespace AZ
m_shadowBufferNeedsUpdate = true;
}
void DirectionalLightFeatureProcessor::SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth)
{
for (auto& it : m_shadowData)
{
it.second.GetData(handle.GetIndex()).m_boundaryScale = boundaryWidth / 2.f;
}
m_shadowBufferNeedsUpdate = true;
}
void DirectionalLightFeatureProcessor::SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable)
{
m_shadowProperties.GetData(handle.GetIndex()).m_isReceiverPlaneBiasEnabled = enable;
@@ -1116,50 +1107,13 @@ namespace AZ
for (const auto& passIt : m_esmShadowmapsPasses)
{
const RPI::View* cameraView = passIt.second.front()->GetRenderPipeline()->GetDefaultView().get();
UpdateStandardDeviations(handle, cameraView);
UpdateFilterOffsetsCounts(handle, cameraView);
UpdateFilterEnabled(handle, cameraView);
UpdateShadowmapPositionInAtlas(handle, cameraView);
SetFilterParameterToPass(handle, cameraView);
}
}
void DirectionalLightFeatureProcessor::UpdateStandardDeviations(LightHandle handle, const RPI::View* cameraView)
{
if (handle != m_shadowingLightHandle)
{
return;
}
const DirectionalLightShadowData& data = m_shadowData.at(cameraView).GetData(handle.GetIndex());
const ShadowProperty& property = m_shadowProperties.GetData(handle.GetIndex());
AZStd::fixed_vector<float, Shadow::MaxNumberOfCascades> standardDeviations;
for (size_t cascadeIndex = 0; cascadeIndex < property.m_segments.at(cameraView).size(); ++cascadeIndex)
{
const Aabb& aabb = property.m_segments.at(cameraView)[cascadeIndex].m_aabb;
const float aabbDiameter = AZStd::GetMax(
aabb.GetMax().GetX() - aabb.GetMin().GetX(),
aabb.GetMax().GetZ() - aabb.GetMin().GetZ());
float standardDeviation = 0.f;
if (aabbDiameter > 0.f)
{
const float boundaryWidth = data.m_boundaryScale * 2.f;
const float ratioToAabbWidth = boundaryWidth / aabbDiameter;
const float widthInPixels = ratioToAabbWidth * data.m_shadowmapSize;
standardDeviation = widthInPixels / (2 * GaussianMathFilter::ReliableSectionFactor);
}
standardDeviations.push_back(standardDeviation);
}
for (const RPI::RenderPipelineId& pipelineId : m_renderPipelineIdsForPersistentView.at(cameraView))
{
for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses.at(pipelineId))
{
esmPass->SetFilterParameters(standardDeviations);
}
}
}
void DirectionalLightFeatureProcessor::UpdateFilterOffsetsCounts(LightHandle handle, const RPI::View* cameraView)
void DirectionalLightFeatureProcessor::UpdateFilterEnabled(LightHandle handle, const RPI::View* cameraView)
{
if (handle != m_shadowingLightHandle)
{
@@ -1170,29 +1124,11 @@ namespace AZ
if (shadowData.m_shadowFilterMethod == aznumeric_cast<uint32_t>(ShadowFilterMethod::Esm) ||
(shadowData.m_shadowFilterMethod == aznumeric_cast<uint32_t>(ShadowFilterMethod::EsmPcf)))
{
// Get array of filter counts for the camera view.
const RPI::RenderPipelineId& pipelineId = m_renderPipelineIdsForPersistentView.at(cameraView).front();
AZ_Assert(!m_esmShadowmapsPasses.at(pipelineId).empty(), "Cannot find a EsmShadowmapsPass.");
const AZStd::array_view<uint32_t> filterCounts = m_esmShadowmapsPasses.at(pipelineId).front()->GetFilterCounts();
AZ_Assert(filterCounts.size() == GetCascadeCount(handle), "FilterCounts differs with cascade count.");
// Create array of filter offsets
AZStd::vector<uint32_t> filterOffsets;
filterOffsets.reserve(filterCounts.size());
uint32_t filterOffset = 0;
for (const uint32_t count : filterCounts)
{
filterOffsets.push_back(filterOffset);
filterOffset += count;
}
// Write filter offsets and filter counts to ESM data
for (uint16_t index = 0; index < GetCascadeCount(handle); ++index)
{
EsmShadowmapsPass::FilterParameter& filterParameter = m_esmParameterData.at(cameraView).GetData(index);
filterParameter.m_isEnabled = true;
filterParameter.m_parameterOffset = filterOffsets[index];
filterParameter.m_parameterCount = filterCounts[index];
}
}
else
@@ -1202,8 +1138,6 @@ namespace AZ
{
EsmShadowmapsPass::FilterParameter& filterParameter = m_esmParameterData.at(cameraView).GetData(index);
filterParameter.m_isEnabled = false;
filterParameter.m_parameterOffset = 0;
filterParameter.m_parameterCount = 0;
}
}
}
@@ -217,7 +217,6 @@ namespace AZ
void SetDebugFlags(LightHandle handle, DebugDrawFlags flags) override;
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetShadowBoundaryWidth(LightHandle handle, float boundaryWidth) override;
void SetShadowReceiverPlaneBiasEnabled(LightHandle handle, bool enable) override;
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
@@ -278,10 +277,8 @@ namespace AZ
//! This updates the parameter of Gaussian filter used in ESM.
void UpdateFilterParameters(LightHandle handle);
//! This updates standard deviations for each cascade.
void UpdateStandardDeviations(LightHandle handle, const RPI::View* cameraView);
//! This updates filter offset and size for each cascade.
void UpdateFilterOffsetsCounts(LightHandle handle, const RPI::View* cameraView);
//! This updates if the filter is enabled.
void UpdateFilterEnabled(LightHandle handle, const RPI::View* cameraView);
//! This updates shadowmap position(origin and size) in the atlas for each cascade.
void UpdateShadowmapPositionInAtlas(LightHandle handle, const RPI::View* cameraView);
//! This set filter parameters to passes which execute filtering.
@@ -322,11 +322,6 @@ namespace AZ
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowFilterMethod, method);
}
void DiskLightFeatureProcessor::SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle, boundaryWidthRadians);
}
void DiskLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count)
{
@@ -53,7 +53,6 @@ namespace AZ
void SetShadowBias(LightHandle handle, float bias) override;
void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override;
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetEsmExponent(LightHandle handle, float esmExponent) override;
@@ -42,28 +42,6 @@ namespace AZ
return m_lightTypeName;
}
void EsmShadowmapsPass::SetFilterParameters(const AZStd::array_view<float>& standardDeviations)
{
// Set descriptor for Gaussian filters for given set of standard deviations.
MathFilterDescriptor descriptor;
descriptor.m_kind = MathFilterKind::Gaussian;
descriptor.m_gaussians.reserve(standardDeviations.size());
for (const float standardDeviation : standardDeviations)
{
descriptor.m_gaussians.emplace_back(GaussianFilterDescriptor{ standardDeviation });
}
// Set filter paramter buffer along with element counts for each filter.
MathFilter::BufferWithElementCounts bufferCounts = MathFilter::FindOrCreateFilterBuffer(descriptor);
m_filterTableBuffer = bufferCounts.first;
m_filterCounts = AZStd::move(bufferCounts.second);
}
AZStd::array_view<uint32_t> EsmShadowmapsPass::GetFilterCounts() const
{
return m_filterCounts;
}
void EsmShadowmapsPass::SetShadowmapIndexTableBuffer(const Data::Instance<RPI::Buffer>& tableBuffer)
{
m_shadowmapIndexTableBuffer = tableBuffer;
@@ -50,14 +50,11 @@ namespace AZ
uint32_t m_isEnabled = false;
AZStd::array<uint32_t, 2> m_shadowmapOriginInSlice = { {0, 0 } }; // shadowmap origin in the slice of the atlas.
uint32_t m_shadowmapSize = static_cast<uint32_t>(ShadowmapSize::None); // width and height of shadowmap.
uint32_t m_parameterOffset; // offset of the filter parameter.
uint32_t m_parameterCount; // element count of the filter parameter.
float m_lightDistanceOfCameraViewFrustum = 0.f;
float m_n_f_n = 0.f; // n / (f - n)
float m_n_f = 0.f; // n - f
float m_f = 0.f; // f
// where n: nearDepth, f: farDepth.
AZStd::array<float, 2> m_padding = {{0.f, 0.f}}; // explicit padding
};
virtual ~EsmShadowmapsPass() = default;
@@ -65,13 +62,6 @@ namespace AZ
const Name& GetLightTypeName() const;
//! This sets the standard deviations of the Gaussian filter
//! for each cascade.
void SetFilterParameters(const AZStd::array_view<float>& standardDeviations);
//! This returns element count of filters.
AZStd::array_view<uint32_t> GetFilterCounts() const;
//! This sets the buffer of the table which enable to get shadowmap index
//! from the coordinate in the atlas.
//! Note that shadowmpa index is shader light index for a spot light
@@ -292,11 +292,6 @@ namespace AZ
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowFilterMethod, method);
}
void PointLightFeatureProcessor::SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle, boundaryWidthRadians);
}
void PointLightFeatureProcessor::SetFilteringSampleCount(LightHandle handle, uint16_t count)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetFilteringSampleCount, count);
@@ -50,7 +50,6 @@ namespace AZ
void SetShadowBias(LightHandle handle, float bias) override;
void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override;
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
void SetSofteningBoundaryWidthAngle(LightHandle handle, float boundaryWidthRadians) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetEsmExponent(LightHandle handle, float esmExponent) override;
void SetPointData(LightHandle handle, const PointLightData& data) override;
@@ -54,10 +54,14 @@ namespace AZ
{
AZStd::shared_ptr<AZStd::vector<uint8_t>> buffer = readbackResult.m_dataBuffer;
RHI::Format format = readbackResult.m_imageDescriptor.m_format;
// convert bgra to rgba by swapping channels
const int numChannels = AZ::RHI::GetFormatComponentCount(readbackResult.m_imageDescriptor.m_format);
if (readbackResult.m_imageDescriptor.m_format == RHI::Format::B8G8R8A8_UNORM)
if (format == RHI::Format::B8G8R8A8_UNORM)
{
format = RHI::Format::R8G8B8A8_UNORM;
buffer = AZStd::make_shared<AZStd::vector<uint8_t>>(readbackResult.m_dataBuffer->size());
AZStd::copy(readbackResult.m_dataBuffer->begin(), readbackResult.m_dataBuffer->end(), buffer->begin());
@@ -89,7 +93,7 @@ namespace AZ
jobCompletion.StartAndWaitForCompletion();
}
Utils::PngFile image = Utils::PngFile::Create(readbackResult.m_imageDescriptor.m_size, readbackResult.m_imageDescriptor.m_format, *buffer);
Utils::PngFile image = Utils::PngFile::Create(readbackResult.m_imageDescriptor.m_size, format, *buffer);
Utils::PngFile::SaveSettings saveSettings;
saveSettings.m_compressionLevel = r_pngCompressionLevel;
@@ -507,7 +507,8 @@ namespace AZ
}
}
//Check if buffer view data changed from previous frame.
// Check if buffer view data changed from previous frame.
// Look into making 'm_meshBuffers != meshBuffers' faster by possibly building a crc and doing a crc check.
if (m_meshBuffers.size() != meshBuffers.size() || m_meshBuffers != meshBuffers)
{
m_meshBuffers = meshBuffers;
@@ -186,17 +186,6 @@ namespace AZ::Render
m_filterParameterNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowBoundaryWidthAngle().");
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
shadowData.m_boundaryScale = boundaryWidthRadians / 2.0f;
m_shadowmapPassNeedsUpdate = true;
m_filterParameterNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetFilteringSampleCount(ShadowId id, uint16_t count)
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetFilteringSampleCount().");
@@ -368,14 +357,13 @@ namespace AZ::Render
{
if (m_filterParameterNeedsUpdate)
{
UpdateStandardDeviations();
UpdateFilterOffsetsCounts();
UpdateEsmPassEnabled();
SetFilterParameterToPass();
m_filterParameterNeedsUpdate = false;
}
}
void ProjectedShadowFeatureProcessor::UpdateStandardDeviations()
void ProjectedShadowFeatureProcessor::UpdateEsmPassEnabled()
{
if (m_esmShadowmapsPasses.empty())
{
@@ -383,24 +371,7 @@ namespace AZ::Render
return;
}
AZStd::vector<float> standardDeviations(m_shadowProperties.GetDataCount());
for (uint32_t i = 0; i < m_shadowProperties.GetDataCount(); ++i)
{
ShadowProperty& shadowProperty = m_shadowProperties.GetDataVector().at(i);
const ShadowData& shadow = m_shadowData.GetElement<ShadowDataIndex>(shadowProperty.m_shadowId.GetIndex());
if (!FilterMethodIsEsm(shadow))
{
continue;
}
const FilterParameter& filter = m_shadowData.GetElement<FilterParamIndex>(shadowProperty.m_shadowId.GetIndex());
const float boundaryWidthAngle = shadow.m_boundaryScale * 2.0f;
const float fieldOfView = GetMax(shadowProperty.m_desc.m_fieldOfViewYRadians, MinimumFieldOfView);
const float ratioToEntireWidth = boundaryWidthAngle / fieldOfView;
const float widthInPixels = ratioToEntireWidth * filter.m_shadowmapSize;
standardDeviations.at(i) = widthInPixels / (2.0f * GaussianMathFilter::ReliableSectionFactor);
}
if (standardDeviations.empty())
if (m_shadowProperties.GetDataCount() == 0)
{
for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses)
{
@@ -411,50 +382,6 @@ namespace AZ::Render
for (EsmShadowmapsPass* esmPass : m_esmShadowmapsPasses)
{
esmPass->SetEnabledComputation(true);
esmPass->SetFilterParameters(standardDeviations);
}
}
void ProjectedShadowFeatureProcessor::UpdateFilterOffsetsCounts()
{
if (m_esmShadowmapsPasses.empty())
{
AZ_Error("ProjectedShadowFeatureProcessor", false, "Cannot find a required pass.");
return;
}
// Get array of filter counts for the camera view.
const AZStd::array_view<uint32_t> filterCounts = m_esmShadowmapsPasses.front()->GetFilterCounts();
// Create array of filter offsets.
AZStd::vector<uint32_t> filterOffsets;
filterOffsets.reserve(filterCounts.size());
uint32_t filterOffset = 0;
for (const uint32_t count : filterCounts)
{
filterOffsets.push_back(filterOffset);
filterOffset += count;
}
auto& shadowProperties = m_shadowProperties.GetDataVector();
for (uint32_t i = 0; i < shadowProperties.size(); ++i)
{
ShadowProperty& shadowProperty = shadowProperties.at(i);
const ShadowId shadowId = shadowProperty.m_shadowId;
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(shadowId.GetIndex());
FilterParameter& filterData = m_shadowData.GetElement<FilterParamIndex>(shadowId.GetIndex());
if (FilterMethodIsEsm(shadowData))
{
filterData.m_parameterOffset = filterOffsets[i];
filterData.m_parameterCount = filterCounts[i];
}
else
{
// If filter is not required, reset offsets and counts of filter in ESM data.
filterData.m_parameterOffset = 0;
filterData.m_parameterCount = 0;
}
}
}
@@ -49,7 +49,6 @@ namespace AZ::Render
void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override;
void SetShadowBias(ShadowId id, float bias) override;
void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override;
void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override;
void SetFilteringSampleCount(ShadowId id, uint16_t count) override;
void SetShadowProperties(ShadowId id, const ProjectedShadowDescriptor& descriptor) override;
const ProjectedShadowDescriptor& GetShadowProperties(ShadowId id) override;
@@ -101,8 +100,7 @@ namespace AZ::Render
//! Functions to update the parameter of Gaussian filter used in ESM.
void UpdateFilterParameters();
void UpdateStandardDeviations();
void UpdateFilterOffsetsCounts();
void UpdateEsmPassEnabled();
void SetFilterParameterToPass();
bool FilterMethodIsEsm(const ShadowData& shadowData) const;
+1 -3
View File
@@ -109,13 +109,11 @@ namespace AZ
{
if (attachment->GetFirstScopeAttachment() == nullptr)
{
//We allow the rendering to continue even if an attachment is not used.
AZ_Error(
"FrameGraph", false,
"Invalid State: attachment '%s' was added but never used!",
attachment->GetId().GetCStr());
Clear();
return ResultCode::InvalidOperation;
}
}
}
@@ -111,13 +111,19 @@ namespace AZ
{
AZStd::lock_guard<AZStd::shared_mutex> lock(m_groupsToCompileMutex);
AZ_Assert(!shaderResourceGroup.IsQueuedForCompile(), "Attempting to compile an SRG that's already been queued for compile. Only compile an SRG once per frame.");
bool isQueuedForCompile = shaderResourceGroup.IsQueuedForCompile();
AZ_Warning(
"ShaderResourceGroupPool", !isQueuedForCompile,
"Attempting to compile an SRG that's already been queued for compile. Only compile an SRG once per frame.");
CalculateGroupDataDiff(shaderResourceGroup, groupData);
if (!isQueuedForCompile)
{
CalculateGroupDataDiff(shaderResourceGroup, groupData);
shaderResourceGroup.SetData(groupData);
shaderResourceGroup.SetData(groupData);
QueueForCompileNoLock(shaderResourceGroup);
QueueForCompileNoLock(shaderResourceGroup);
}
}
void ShaderResourceGroupPool::QueueForCompile(ShaderResourceGroup& group)

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