Merge remote-tracking branch 'upstream/development' into Atom/santorac/WarnOnMaterialPsoChanges

This commit is contained in:
santorac
2021-09-15 11:35:39 -07:00
225 changed files with 3305 additions and 2203 deletions
@@ -46,4 +46,15 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT
AutomatedTesting.Assets
Editor
)
ly_add_pytest(
NAME AutomatedTesting::AtomRenderer_HydraTests_ShaderBuildPipeline
TEST_SUITE main
PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_ShaderBuildPipelineSuite.py
TEST_SERIAL
TIMEOUT 600
RUNTIME_DEPENDENCIES
AssetProcessor
AutomatedTesting.Assets
Editor
)
endif()
@@ -0,0 +1,55 @@
/*
* 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
*
*/
/*
This is a dummy shader used to validate detection of "#included files"
*/
#include <Atom/Features/SrgSemantics.azsli>
#include "Test1Color.azsli"
#include <Test3Color.azsli>
ShaderResourceGroup DummySrg : SRG_PerDraw
{
float4 m_color;
}
struct VSInput
{
float3 m_position : POSITION;
float4 m_color : COLOR0;
};
struct VSOutput
{
float4 m_position : SV_Position;
float4 m_color : COLOR0;
};
VSOutput MainVS(VSInput vsInput)
{
VSOutput OUT;
OUT.m_position = float4(vsInput.m_position, 1.0);
OUT.m_color = vsInput.m_color;
return OUT;
}
struct PSOutput
{
float4 m_color : SV_Target0;
};
PSOutput MainPS(VSOutput vsOutput)
{
PSOutput OUT;
OUT.m_color = GetTest1Color(DummySrg::m_color) + GetTest3Color(DummySrg::m_color);
return OUT;
}
@@ -0,0 +1,26 @@
// This is a dummy shader used to validate detection of "#included files"
{
"Source" : "DependencyValidation.azsl",
"DepthStencilState" : {
"Depth" : { "Enable" : false, "CompareFunc" : "GreaterEqual" }
},
"DrawList" : "forward",
"ProgramSettings":
{
"EntryPoints":
[
{
"name": "MainVS",
"type": "Vertex"
},
{
"name": "MainPS",
"type": "Fragment"
}
]
}
}
@@ -0,0 +1,18 @@
/*
* 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
*
*/
/*
This is a dummy shader used to validate detection of "#included files"
*/
#include "Test2Color.azsli"
float4 GetTest1Color(float4 color)
{
return color + GetTest2Color(color);
}
@@ -0,0 +1,16 @@
/*
* 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
*
*/
/*
This is a dummy shader used to validate detection of "#included files"
*/
float4 GetTest2Color(float4 color)
{
return color * 0.5;
}
@@ -0,0 +1,16 @@
/*
* 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
*
*/
/*
This is a dummy shader used to validate detection of "#included files"
*/
float4 GetTest3Color(float4 color)
{
return color * 0.13;
}
@@ -3,8 +3,6 @@ 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
Hydra script that creates an entity and attaches Atom components to it for test verification.
"""
import os
@@ -17,6 +15,7 @@ import azlmbr.asset as asset
import azlmbr.entity as entity
import azlmbr.legacy.general as general
import azlmbr.editor as editor
import azlmbr.render as render
sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests"))
@@ -125,6 +124,19 @@ def run():
def verify_set_property(entity_obj, path, value):
entity_obj.get_set_test(0, path, value)
# Verify cubemap generation
def verify_cubemap_generation(component_name, entity_obj):
# Initially Check if the component has Reflection Probe component
if not hydra.has_components(entity_obj.id, ["Reflection Probe"]):
raise ValueError(f"Given entity {entity_obj.name} has no Reflection Probe component")
render.EditorReflectionProbeBus(azlmbr.bus.Event, "BakeReflectionProbe", entity_obj.id)
def get_value():
hydra.get_component_property_value(entity_obj.components[0], "Cubemap|Baked Cubemap Path")
TestHelper.wait_for_condition(lambda: get_value() != "", 20.0)
general.log(f"{component_name}_test: Cubemap is generated: {get_value() != ''}")
# Wait for Editor idle loop before executing Python hydra scripts.
TestHelper.init_idle()
@@ -215,6 +227,12 @@ def run():
# Display Mapper Component
ComponentTests("Display Mapper")
# Reflection Probe Component
reflection_probe = "Reflection Probe"
ComponentTests(
reflection_probe,
lambda entity_obj: verify_required_component_addition(entity_obj, ["Box Shape"], reflection_probe),
lambda entity_obj: verify_cubemap_generation(reflection_probe, entity_obj),)
if __name__ == "__main__":
run()
@@ -31,8 +31,6 @@ SPHERE_AND_SPOT_DISK_LIGHT_PROPERTIES = [
("Controller|Configuration|Shadows|Shadow filter method", 1), # PCF
("Controller|Configuration|Shadows|Filtering sample count", 4.0),
("Controller|Configuration|Shadows|Filtering sample count", 64.0),
("Controller|Configuration|Shadows|PCF method", 0), # Bicubic
("Controller|Configuration|Shadows|PCF method", 1), # Boundary search
("Controller|Configuration|Shadows|Shadow filter method", 2), # ECM
("Controller|Configuration|Shadows|ESM exponent", 50),
("Controller|Configuration|Shadows|ESM exponent", 5000),
@@ -0,0 +1,188 @@
"""
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
"""
import os
import shutil
def _copy_file(src_file, src_path, target_file, target_path):
# type: (str, str, str, str) -> None
"""
Copies the [src_file] located in [src_path] to the [target_file] located at [target_path].
Leaves the [target_file] unlocked for reading and writing privileges
:param src_file: The source file to copy (file name)
:param src_path: The source file's path
:param target_file: The target file to copy into (file name)
:param target_path: The target file's path
:return: None
"""
target_file_path = os.path.join(target_path, target_file)
src_file_path = os.path.join(src_path, src_file)
if os.path.exists(target_file_path):
fs.unlock_file(target_file_path)
shutil.copyfile(src_file_path, target_file_path)
def _copy_tmp_files_in_order(src_directory, file_list, dst_directory, wait_time_in_between = 0.0):
# type: (str, list, str, float) -> None
"""
This function assumes that for each file name listed in @file_list
there's file named "@filename.txt" which the original source file
but they will be copied with just the @filename (.txt removed).
"""
for filename in file_list:
src_name = f"{filename}.txt"
_copy_file(src_name, src_directory, filename, dst_directory)
if wait_time_in_between > 0.0:
print(f"Created {filename} in {dst_directory}")
general.idle_wait(wait_time_in_between)
def _remove_file(src_file, src_path):
# type: (str, str) -> None
"""
Removes the [src_file] located in [src_path].
:param src_file: The source file to copy (file name)
:param src_path: The source file's path
:return: None
"""
src_file_path = os.path.join(src_path, src_file)
if os.path.exists(src_file_path):
fs.unlock_file(src_file_path)
os.remove(src_file_path)
def _remove_files(directory, file_list):
for filename in file_list:
_remove_file(filename, directory)
def _asset_exists(cache_relative_path):
asset_id = azasset.AssetCatalogRequestBus(azbus.Broadcast, "GetAssetIdByPath", cache_relative_path, azmath.Uuid(), False)
return asset_id.is_valid()
# List of results that we want to check, this is not 100% necessary but it's a good
# practice to make it easier to debug tests.
# Here we define a tuple of tests
class Results():
azshader_was_removed = ("azshader was removed", "Failed to remove azshader")
azshader_was_compiled = ("azshader was compiled", "Failed to compile azshader")
def ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges():
"""
This test validates [ATOM-5441] Shader Builders May Fail When Multiple New Files Are Added
It creates source assets to compile a particular shader.
1- The first phase generates the source assets out of order and slowly. The AP should
wakeup each time one of the source dependencies appears but will fail each time. Only when the
last dependency appears then the shader should build successfully.
2- The second phase is similar as above, except that all source assets will be created
at once and We also expect that in the end the shader is built successfully.
"""
# Required for automated tests
helper.init_idle()
game_root_path = os.path.normpath(general.get_game_folder())
game_asset_path = os.path.join(game_root_path, "Assets")
base_dir = os.path.dirname(__file__)
src_assets_subdir = os.path.join(base_dir, "TestAssets", "ShaderAssetBuilder")
with Tracer() as error_tracer:
# The script drives the execution of the test, to return the flow back to the editor,
# we will tick it one time
general.idle_wait_frames(1)
# This is the order in which the source assets should be deployed
# to avoid source dependency issues with the old MCPP-based CreateJobs.
file_list = [
"Test2Color.azsli",
"Test3Color.azsli",
"Test1Color.azsli",
"DependencyValidation.azsl",
"DependencyValidation.shader"
]
reverse_file_list = file_list[::-1]
# Remove files in reverse order
_remove_files(game_asset_path, reverse_file_list)
# Wait here until the azshader doesn't exist anymore.
azshader_name = "assets/dependencyvalidation.azshader"
helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0)
Report.critical_result(Results.azshader_was_removed, not _asset_exists(azshader_name))
_copy_tmp_files_in_order(src_assets_subdir, file_list, game_asset_path, 1.0)
# Give enough time to AP to compile the shader
helper.wait_for_condition(lambda: _asset_exists(azshader_name), 60.0)
Report.critical_result(Results.azshader_was_compiled, _asset_exists(azshader_name))
# The first part was about compiling the shader under normal conditions.
# Let's remove the files from the previous phase and will proceed
# to make the source files visible to the AP in reverse order. The
# ShaderAssetBuilder will only succeed when the last file becomes visible.
_remove_files(game_asset_path, reverse_file_list)
helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0)
Report.critical_result(Results.azshader_was_removed, not _asset_exists(azshader_name))
# Remark, if you are running this test manually from the Editor with "pyRunFile",
# You'll notice how the AP issues notifications that it fails to compile the shader
# as the source files are being copied to the "Assets" subfolder.
# Those errors are OK and also expected because We need the AP to wake up as each
# reported source dependency exists. Once the last file is copied then all source
# dependencies are fully satisfied and the shader should compile successfully.
# And this summarizes the importance of this Test: The previous version
# of ShaderAssetBuilder::CreateJobs was incapable of compiling the shader under the conditions
# presented in this test, but with the new version of ShaderAssetBuilder::CreateJobs, which
# doesn't use MCPP for #include files discovery, it should eventually compile the shader
# once all the source files are in place.
_copy_tmp_files_in_order(src_assets_subdir, reverse_file_list, game_asset_path, 3.0)
# Give enough time to AP to compile the shader
helper.wait_for_condition(lambda: _asset_exists(azshader_name), 60.0)
Report.critical_result(Results.azshader_was_compiled, _asset_exists(azshader_name))
# The last phase of the test puts stress on potential race conditions
# when all required files appear as soon as possible.
# First Clean up.
# Remove left over files.
_remove_files(game_asset_path, reverse_file_list)
helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0)
Report.critical_result(Results.azshader_was_removed, not _asset_exists(azshader_name))
# Now let's copy all the source files to the "Assets" folder as fast as possible.
_copy_tmp_files_in_order(src_assets_subdir, reverse_file_list, game_asset_path)
# Give enough time to AP to compile the shader
helper.wait_for_condition(lambda: _asset_exists(azshader_name), 60.0)
Report.critical_result(Results.azshader_was_compiled, _asset_exists(azshader_name))
# All good, let's cleanup leftover files before closing the test.
_remove_files(game_asset_path, reverse_file_list)
helper.wait_for_condition(lambda: not _asset_exists(azshader_name), 5.0)
if __name__ == "__main__":
# All exposed python bindings are in azlmbr
import azlmbr.legacy.general as general
import azlmbr.bus as azbus
import azlmbr.asset as azasset
import azlmbr.math as azmath
# Import report and test helper utilities
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.utils import Tracer
import ly_test_tools.environment.file_system as fs
Report.start_test(ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges)
@@ -161,6 +161,21 @@ class TestAtomEditorComponentsMain(object):
"Display Mapper_test: Entity deleted: True",
"Display Mapper_test: UNDO entity deletion works: True",
"Display Mapper_test: REDO entity deletion works: True",
# Reflection Probe Component
"Reflection Probe Entity successfully created",
"Reflection Probe_test: Component added to the entity: True",
"Reflection Probe_test: Component removed after UNDO: True",
"Reflection Probe_test: Component added after REDO: True",
"Reflection Probe_test: Entered game mode: True",
"Reflection Probe_test: Exit game mode: True",
"Reflection Probe_test: Entity disabled initially: True",
"Reflection Probe_test: Entity enabled after adding required components: True",
"Reflection Probe_test: Cubemap is generated: True",
"Reflection Probe_test: Entity is hidden: True",
"Reflection Probe_test: Entity is shown: True",
"Reflection Probe_test: Entity deleted: True",
"Reflection Probe_test: UNDO entity deletion works: True",
"Reflection Probe_test: REDO entity deletion works: True",
]
unexpected_lines = [
@@ -200,8 +215,6 @@ class TestAtomEditorComponentsMain(object):
"Controller|Configuration|Shadows|Shadow filter method set to 1", # PCF
"Controller|Configuration|Shadows|Filtering sample count set to 4",
"Controller|Configuration|Shadows|Filtering sample count set to 64",
"Controller|Configuration|Shadows|PCF method set to 0",
"Controller|Configuration|Shadows|PCF method set to 1",
"Controller|Configuration|Shadows|Shadow filter method set to 2", # ESM
"Controller|Configuration|Shadows|ESM exponent set to 50.0",
"Controller|Configuration|Shadows|ESM exponent set to 5000.0",
@@ -0,0 +1,19 @@
"""
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
Main suite tests for the Shader Build Pipeline.
"""
import pytest
from ly_test_tools import LAUNCHERS
from ly_test_tools.o3de.editor_test import EditorTestSuite, EditorSingleTest
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
class TestShaderBuildPipelineMain(EditorTestSuite):
"""Holds tests for Shader Build Pipeline validation"""
class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSingleTest):
from .atom_hydra_scripts import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module
+8 -2
View File
@@ -20,6 +20,7 @@
// AzCore
#include <AzCore/Casting/numeric_cast.h> // for aznumeric_cast
#include <AzQtComponents/Utilities/PixmapScaleUtilities.h>
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <ui_AboutDialog.h>
@@ -46,8 +47,13 @@ CAboutDialog::CAboutDialog(QString versionText, QString richTextCopyrightNotice,
CAboutDialog > QLabel#link { text-decoration: underline; color: #94D2FF; }");
// Prepare background image
QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg"));
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")),
screen(),
QSize(m_enforcedWidth, m_enforcedHeight),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation
);
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
+1 -1
View File
@@ -44,7 +44,7 @@ enum
{
// in milliseconds
GameModeIdleFrequency = 0,
EditorModeIdleFrequency = 1,
EditorModeIdleFrequency = 0,
InactiveModeFrequency = 10,
UninitializedFrequency = 9999,
};
-4
View File
@@ -77,10 +77,6 @@ namespace
// This closes the current document (level)
currentLevel->OnNewDocument();
// Then we freeze the viewport's input
AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Broadcast(
&AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Events::FreezeViewportInput, true);
// Then we need to tell the game engine there is no level to render anymore
if (GetIEditor()->GetGameEngine())
{
+2 -22
View File
@@ -669,16 +669,6 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
case eNotify_OnEndSceneSave:
PopDisableRendering();
break;
case eNotify_OnBeginLoad: // disables viewport input when starting to load an existing level
case eNotify_OnBeginCreate: // disables viewport input when starting to create a new level
m_freezeViewportInput = true;
break;
case eNotify_OnEndLoad: // enables viewport input when finished loading an existing level
case eNotify_OnEndCreate: // enables viewport input when finished creating a new level
m_freezeViewportInput = false;
break;
}
}
@@ -962,16 +952,6 @@ AzFramework::ScreenPoint EditorViewportWidget::ViewportWorldToScreen(const AZ::V
return m_renderViewport->ViewportWorldToScreen(worldPosition);
}
bool EditorViewportWidget::IsViewportInputFrozen()
{
return m_freezeViewportInput;
}
void EditorViewportWidget::FreezeViewportInput(bool freeze)
{
m_freezeViewportInput = freeze;
}
QWidget* EditorViewportWidget::GetWidgetForViewportContextMenu()
{
return this;
@@ -1057,9 +1037,9 @@ void EditorViewportWidget::SetViewportId(int id)
void EditorViewportWidget::ConnectViewportInteractionRequestBus()
{
AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusConnect(GetViewportId());
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId());
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(GetViewportId());
AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusConnect();
m_viewportUi.ConnectViewportUiBus(GetViewportId());
AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusConnect();
@@ -1070,9 +1050,9 @@ void EditorViewportWidget::DisconnectViewportInteractionRequestBus()
AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusDisconnect();
m_viewportUi.DisconnectViewportUiBus();
AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusDisconnect();
}
namespace AZ::ViewportHelpers
-8
View File
@@ -89,7 +89,6 @@ class SANDBOX_API EditorViewportWidget final
, private Camera::EditorCameraRequestBus::Handler
, private Camera::CameraNotificationBus::Handler
, private AzFramework::InputSystemCursorConstraintRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::EditorModifierKeyRequestBus::Handler
@@ -202,10 +201,6 @@ private:
// AzFramework::InputSystemCursorConstraintRequestBus overrides ...
void* GetSystemCursorConstraintWindow() const override;
// AzToolsFramework::ViewportFreezeRequestBus overrides ...
bool IsViewportInputFrozen() override;
void FreezeViewportInput(bool freeze) override;
// AzToolsFramework::MainEditorViewportInteractionRequestBus overrides ...
AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) override;
AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) override;
@@ -387,9 +382,6 @@ private:
// Unclear if it's still necessary.
QSet<int> m_keyDown;
// State for ViewportFreezeRequestBus, currently does nothing
bool m_freezeViewportInput = false;
// This widget holds a reference to the manipulator manage because its responsible for drawing manipulators
AZStd::shared_ptr<AzToolsFramework::ManipulatorManager> m_manipulatorManager;
+1 -1
View File
@@ -318,7 +318,7 @@ void CGameExporter::ExportLevelInfo(const QString& path)
root->setAttr("Name", levelName.toUtf8().data());
auto terrain = AzFramework::Terrain::TerrainDataRequestBus::FindFirstHandler();
const AZ::Aabb terrainAabb = terrain ? terrain->GetTerrainAabb() : AZ::Aabb::CreateFromPoint(AZ::Vector3::CreateZero());
const AZ::Vector2 terrainGridResolution = terrain ? terrain->GetTerrainGridResolution() : AZ::Vector2::CreateOne();
const AZ::Vector2 terrainGridResolution = terrain ? terrain->GetTerrainHeightQueryResolution() : AZ::Vector2::CreateOne();
const int compiledHeightmapSize = static_cast<int>(terrainAabb.GetXExtent() / terrainGridResolution.GetX());
root->setAttr("HeightmapSize", compiledHeightmapSize);
+9 -8
View File
@@ -9,11 +9,11 @@
// Description : implementation file
#include "EditorDefs.h"
#include "StartupLogoDialog.h"
#include <AzQtComponents/Utilities/PixmapScaleUtilities.h>
// Qt
#include <QPainter>
#include <QThread>
@@ -22,8 +22,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <ui_StartupLogoDialog.h>
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
/////////////////////////////////////////////////////////////////////////////
// CStartupLogoDialog dialog
@@ -36,13 +34,16 @@ CStartupLogoDialog::CStartupLogoDialog(QString versionText, QString richTextCopy
m_ui->setupUi(this);
s_pLogoWindow = this;
m_backgroundImage = QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg"));
setFixedSize(QSize(600, 300));
// Prepare background image
QImage backgroundImage(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg"));
m_backgroundImage = QPixmap::fromImage(backgroundImage.scaled(m_enforcedWidth, m_enforcedHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
m_backgroundImage = AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(QStringLiteral(":/StartupLogoDialog/splashscreen_background_developer_preview.jpg")),
screen(),
QSize(m_enforcedWidth, m_enforcedHeight),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation
);
// Draw the Open 3D Engine logo from svg
m_ui->m_logo->load(QStringLiteral(":/StartupLogoDialog/o3de_logo.svg"));
-90
View File
@@ -191,94 +191,4 @@ ConsoleTextEdit:focus,
border-width: 0px;
border-color: #e9e9e9;
border-style: solid;
}
/* Welcome Screen styling */
WelcomeScreenDialog QLabel
{
font-size: 12px;
color: #FFFFFF;
line-height: 20px;
background-color: transparent;
margin: 0;
}
WelcomeScreenDialog QLabel#currentProjectLabel
{
margin-top: 10px;
}
WelcomeScreenDialog QPushButton
{
font-size: 14px;
line-height: 16px;
}
WelcomeScreenDialog QWidget#articleViewContainerRoot
{
background: #444444;
}
WelcomeScreenDialog QWidget#levelViewFTUEContainer
{
background: #282828;
}
QTableWidget#recentLevelTable::item {
background-color: rgb(64,64,64);
margin-bottom: 4px;
margin-top: 4px;
}
/* Particle Editor */
#NumParticlesLabel
{
margin-top: 6px;
}
#LibrarySearchIcon
{
max-width: 16px;
max-height: 16px;
qproperty-iconSize: 16px 16px;
}
#ClosePrefabDialog, #SavePrefabDialog
{
min-width : 640px;
}
#SaveDependentPrefabsCard
{
margin: 0px 15px 10px 15px;
}
#PrefabSavedMessageFrame{
border: 1px solid green;
margin: 10px 15px 10px 15px;
border-radius: 2px;
padding: 5px 2px 5px 2px;
}
#ClosePrefabDialog #PrefabSaveWarningFrame
{
border: 1px solid orange;
margin: 10px 15px 10px 15px;
border-radius: 2px;
padding: 5px 2px 5px 2px;
color : white;
}
#SavePrefabDialog #FooterSeparatorLine
{
color: gray;
}
#SavePrefabDialog #PrefabSavePreferenceHint
{
font: italic;
color: #999999;
}
@@ -36,6 +36,9 @@
#include "CryEdit.h"
#include "Viewport.h"
// Atom Renderer
#include <Atom/RPI.Public/RPISystemInterface.h>
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
#include <TrackView/ui_SequenceBatchRenderDialog.h>
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
@@ -1234,6 +1237,13 @@ void CSequenceBatchRenderDialog::OnKickIdleTimout()
{
componentApplication->TickSystem();
}
// Directly tick the renderer, as it's no longer part of the system tick
if (auto rpiSystem = AZ::RPI::RPISystemInterface::Get())
{
rpiSystem->SimulationTick();
rpiSystem->RenderTick();
}
}
}
@@ -34,6 +34,7 @@
// AzQtComponents
#include <AzQtComponents/Components/Widgets/CheckBox.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzQtComponents/Utilities/PixmapScaleUtilities.h>
// Editor
#include "Settings.h"
@@ -79,8 +80,11 @@ WelcomeScreenDialog::WelcomeScreenDialog(QWidget* pParent)
{
projectPreviewPath = ":/WelcomeScreenDialog/DefaultProjectImage.png";
}
ui->activeProjectIcon->setPixmap(
QPixmap(projectPreviewPath).scaled(
AzQtComponents::ScalePixmapForScreenDpi(
QPixmap(projectPreviewPath),
screen(),
ui->activeProjectIcon->size(),
Qt::KeepAspectRatioByExpanding,
Qt::SmoothTransformation
@@ -74,6 +74,8 @@
#include <AzCore/Module/Environment.h>
#include <AzCore/std/string/conversions.h>
AZ_CVAR(float, g_simulation_tick_rate, 0, nullptr, AZ::ConsoleFunctorFlags::Null, "The rate at which the game simulation tick loop runs, or 0 for as fast as possible");
static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments)
{
if (arguments.empty())
@@ -1392,6 +1394,23 @@ namespace AZ
AZ_PROFILE_SCOPE(AzCore, "ComponentApplication::Tick:OnTick");
EBUS_EVENT(TickBus, OnTick, m_deltaTime, ScriptTimePoint(now));
}
// If tick rate limiting is on, ensure (1 / g_simulation_tick_rate) ms has elapsed since the last frame,
// sleeping if there's still time remaining.
if (g_simulation_tick_rate > 0.f)
{
now = AZStd::chrono::system_clock::now();
// Work in microsecond durations here as that's the native measurement time for time_point
constexpr float microsecondsPerSecond = 1000.f * 1000.f;
const AZStd::chrono::microseconds timeBudgetPerTick(static_cast<int>(microsecondsPerSecond / g_simulation_tick_rate));
AZStd::chrono::microseconds timeUntilNextTick = m_currentTime + timeBudgetPerTick - now;
if (timeUntilNextTick.count() > 0)
{
AZStd::this_thread::sleep_for(timeUntilNextTick);
}
}
}
}
@@ -46,6 +46,8 @@ namespace AZ
TICK_PRE_RENDER = 750, ///< Suggested tick handler position to update render-related data.
TICK_RENDER = 800, ///< Suggested tick handler position for rendering.
TICK_DEFAULT = 1000, ///< Default tick handler position when the handler is constructed.
TICK_UI = 2000, ///< Suggested tick handler position for UI components.
@@ -96,7 +96,7 @@ namespace AZ
const char* get_name() const { return m_name; }
void set_name(const char* name) { m_name = name; }
size_type get_max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
constexpr size_type max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
size_type get_allocated_size() const { return 0; }
bool is_lock_free() { return false; }
+3 -1
View File
@@ -273,7 +273,7 @@ namespace AZ::IO
// If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept;
constexpr int compare_string_view(AZStd::string_view other) const;
constexpr int ComparePathView(const PathView& other) const;
constexpr AZStd::string_view root_name_view() const;
constexpr AZStd::string_view root_directory_view() const;
constexpr AZStd::string_view root_path_raw_view() const;
@@ -480,6 +480,8 @@ namespace AZ::IO
// compare
//! Performs a compare of each of the path parts for equivalence
//! Each part of the path is compare using string comparison
//! If both *this path and the input path uses the WindowsPathSeparator
//! then a non-case sensitive compare is performed
//! Ex: Comparing "test/foo" against "test/fop" returns -1;
//! Path separators of the contained path string aren't compared
//! Ex. Comparing "C:/test\foo" against C:\test/foo" returns 0;
+19 -36
View File
@@ -224,15 +224,15 @@ namespace AZ::IO
// compare
constexpr int PathView::Compare(const PathView& other) const noexcept
{
return compare_string_view(other.m_path);
return ComparePathView(other);
}
constexpr int PathView::Compare(AZStd::string_view pathView) const noexcept
{
return compare_string_view(pathView);
return ComparePathView(PathView(pathView, m_preferred_separator));
}
constexpr int PathView::Compare(const value_type* path) const noexcept
{
return compare_string_view(path);
return ComparePathView(PathView(path, m_preferred_separator));
}
constexpr AZStd::fixed_string<MaxPathLength> PathView::FixedMaxPathString() const noexcept
@@ -398,10 +398,10 @@ namespace AZ::IO
return true;
}
constexpr int PathView::compare_string_view(AZStd::string_view pathView) const
constexpr int PathView::ComparePathView(const PathView& other) const
{
auto lhsPathParser = parser::PathParser::CreateBegin(m_path, m_preferred_separator);
auto rhsPathParser = parser::PathParser::CreateBegin(pathView, m_preferred_separator);
auto rhsPathParser = parser::PathParser::CreateBegin(other.m_path, other.m_preferred_separator);
if (int res = CompareRootName(&lhsPathParser, &rhsPathParser); res != 0)
{
@@ -476,6 +476,8 @@ namespace AZ::IO
template <typename PathResultType>
constexpr void PathView::MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base)
{
const bool exactCaseCompare = path.m_preferred_separator == PosixPathSeparator
|| base.m_preferred_separator == PosixPathSeparator;
{
// perform root-name/root-directory mismatch checks
auto pathParser = parser::PathParser::CreateBegin(path.m_path, path.m_preferred_separator);
@@ -487,7 +489,7 @@ namespace AZ::IO
};
if (pathParser.InRootName() && pathParserBase.InRootName())
{
if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, pathParser.m_preferred_separator);
if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare);
res != 0)
{
pathResult.m_path = AZStd::string_view{};
@@ -519,7 +521,7 @@ namespace AZ::IO
auto pathParser = parser::PathParser::CreateBegin(path.m_path, path.m_preferred_separator);
auto pathParserBase = parser::PathParser::CreateBegin(base.m_path, base.m_preferred_separator);
while (pathParser && pathParserBase && pathParser.m_parser_state == pathParserBase.m_parser_state &&
Internal::ComparePathSegment(*pathParser, *pathParserBase, pathParser.m_preferred_separator) == 0)
Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare) == 0)
{
++pathParser;
++pathParserBase;
@@ -1080,25 +1082,25 @@ namespace AZ::IO
template <typename StringType>
constexpr int BasicPath<StringType>::Compare(const PathView& other) const noexcept
{
return static_cast<PathView>(*this).compare_string_view(other.m_path);
return static_cast<PathView>(*this).ComparePathView(other);
}
template <typename StringType>
constexpr int BasicPath<StringType>::Compare(const string_type& pathString) const
{
return static_cast<PathView>(*this).compare_string_view(pathString);
return static_cast<PathView>(*this).ComparePathView(PathView(pathString, m_preferred_separator));
}
template <typename StringType>
constexpr int BasicPath<StringType>::Compare(AZStd::string_view pathView) const noexcept
{
return static_cast<PathView>(*this).compare_string_view(pathView);
return static_cast<PathView>(*this).ComparePathView(pathView);
}
template <typename StringType>
constexpr int BasicPath<StringType>::Compare(const value_type* pathString) const noexcept
{
return static_cast<PathView>(*this).compare_string_view(pathString);
return static_cast<PathView>(*this).ComparePathView(pathString);
}
// decomposition
@@ -1330,10 +1332,12 @@ namespace AZ::IO
// PathView::LexicallyRelative is not being used as it returns a FixedMaxPath
// which has a limitation that it requires the relative path to fit within
// an AZ::IO::MaxPathLength buffer
auto ComparePathPart = [pathSeparator = m_preferred_separator](
const bool exactCaseCompare = m_preferred_separator == PosixPathSeparator
|| base.m_preferred_separator == PosixPathSeparator;
auto ComparePathPart = [exactCaseCompare](
const PathIterable::PartKindPair& left, const PathIterable::PartKindPair& right) -> bool
{
return Internal::ComparePathSegment(left.first, right.first, pathSeparator) == 0;
return Internal::ComparePathSegment(left.first, right.first, exactCaseCompare) == 0;
};
const PathIterable thisPathParts = GetNormalPathParts(*this);
@@ -1471,37 +1475,16 @@ namespace AZStd
template <>
struct hash<AZ::IO::PathView>
{
/// Path is using FNV-1a algorithm 64 bit version.
static size_t hash_path(AZStd::string_view pathSegment, const char pathSeparator)
{
size_t hash = 14695981039346656037ULL;
constexpr size_t fnvPrime = 1099511628211ULL;
for (const char first : pathSegment)
{
hash ^= static_cast<size_t>((pathSeparator == AZ::IO::PosixPathSeparator)
? first : tolower(first));
hash *= fnvPrime;
}
return hash;
}
size_t operator()(const AZ::IO::PathView& pathToHash) noexcept
{
auto pathParser = AZ::IO::parser::PathParser::CreateBegin(pathToHash.Native(), pathToHash.m_preferred_separator);
size_t hash_value = 0;
while (pathParser)
{
AZStd::hash_combine(hash_value, hash_path(*pathParser, pathToHash.m_preferred_separator));
++pathParser;
}
return hash_value;
return AZ::IO::parser::HashPath(pathParser);
}
};
template <typename StringType>
struct hash<AZ::IO::BasicPath<StringType>>
{
const size_t operator()(const AZ::IO::BasicPath<StringType>& pathToHash) noexcept
size_t operator()(const AZ::IO::BasicPath<StringType>& pathToHash) noexcept
{
return AZStd::hash<AZ::IO::PathView>{}(pathToHash);
}
@@ -183,13 +183,12 @@ namespace AZ::IO::Internal
return IsAbsolute(pathView.begin(), pathView.end(), preferredSeparator);
}
// Compares path segments using either Posix or Windows path rules based on the path separator in use
// Posix paths perform a case-sensitive comparison, while Windows paths perform a case-insensitive comparison
static int ComparePathSegment(AZStd::string_view left, AZStd::string_view right, char pathSeparator)
// Compares path segments using either Posix or Windows path rules based on the exactCaseCompare option
static int ComparePathSegment(AZStd::string_view left, AZStd::string_view right, bool exactCaseCompare)
{
const size_t maxCharsToCompare = (AZStd::min)(left.size(), right.size());
int charCompareResult = pathSeparator == PosixPathSeparator
int charCompareResult = exactCaseCompare
? maxCharsToCompare ? strncmp(left.data(), right.data(), maxCharsToCompare) : 0
: maxCharsToCompare ? azstrnicmp(left.data(), right.data(), maxCharsToCompare) : 0;
return charCompareResult == 0
@@ -594,7 +593,10 @@ namespace AZ::IO::parser
{
return pathParser->InRootName() ? **pathParser : "";
};
int res = Internal::ComparePathSegment(GetRootName(lhsPathParser), GetRootName(rhsPathParser), lhsPathParser->m_preferred_separator);
const bool exactCaseCompare = lhsPathParser->m_preferred_separator == PosixPathSeparator
|| rhsPathParser->m_preferred_separator == PosixPathSeparator;
int res = Internal::ComparePathSegment(GetRootName(lhsPathParser), GetRootName(rhsPathParser), exactCaseCompare);
ConsumeRootName(lhsPathParser);
ConsumeRootName(rhsPathParser);
return res;
@@ -621,9 +623,11 @@ namespace AZ::IO::parser
auto& lhsPathParser = *lhsPathParserPtr;
auto& rhsPathParser = *rhsPathParserPtr;
const bool exactCaseCompare = lhsPathParser.m_preferred_separator == PosixPathSeparator
|| rhsPathParser.m_preferred_separator == PosixPathSeparator;
while (lhsPathParser && rhsPathParser)
{
if (int res = Internal::ComparePathSegment(*lhsPathParser, *rhsPathParser, lhsPathParser.m_preferred_separator);
if (int res = Internal::ComparePathSegment(*lhsPathParser, *rhsPathParser, exactCaseCompare);
res != 0)
{
return res;
@@ -646,6 +650,46 @@ namespace AZ::IO::parser
return 0;
}
//path.hash
/// Path is using FNV-1a algorithm 64 bit version.
inline size_t HashSegment(AZStd::string_view pathSegment, bool hashExactPath)
{
size_t hash = 14695981039346656037ULL;
constexpr size_t fnvPrime = 1099511628211ULL;
for (const char first : pathSegment)
{
hash ^= static_cast<size_t>(hashExactPath ? first : tolower(first));
hash *= fnvPrime;
}
return hash;
}
constexpr size_t HashPath(PathParser& pathParser)
{
size_t hash_value = 0;
const bool hashExactPath = pathParser.m_preferred_separator == AZ::IO::PosixPathSeparator;
while (pathParser)
{
switch (pathParser.m_parser_state)
{
case PS_InRootName:
case PS_InFilenames:
AZStd::hash_combine(hash_value, HashSegment(*pathParser, hashExactPath));
break;
case PS_InRootDir:
// Only hash the PosixPathSeparator when a root directory is seen
// This makes the hash consistent for root directories path of C:\ and C:/
AZStd::hash_combine(hash_value, HashSegment("/", hashExactPath));
break;
default:
// The BeforeBegin and AtEnd states contain no segments to hash
break;
}
++pathParser;
}
return hash_value;
}
constexpr int DetermineLexicalElementCount(PathParser pathParser)
{
int count = 0;
@@ -216,6 +216,11 @@ namespace AZ
return m_source->GetMaxAllocationSize();
}
auto AllocatorOverrideShim::GetMaxContiguousAllocationSize() const -> size_type
{
return m_source->GetMaxContiguousAllocationSize();
}
IAllocatorAllocate* AllocatorOverrideShim::GetSubAllocator()
{
return m_source->GetSubAllocator();
@@ -52,6 +52,7 @@ namespace AZ
size_type NumAllocatedBytes() const override;
size_type Capacity() const override;
size_type GetMaxAllocationSize() const override;
size_type GetMaxContiguousAllocationSize() const override;
IAllocatorAllocate* GetSubAllocator() override;
private:
@@ -188,6 +188,11 @@ BestFitExternalMapAllocator::GetMaxAllocationSize() const
return m_schema->GetMaxAllocationSize();
}
auto BestFitExternalMapAllocator::GetMaxContiguousAllocationSize() const -> size_type
{
return m_schema->GetMaxContiguousAllocationSize();
}
//=========================================================================
// GetSubAllocator
// [1/28/2011]
@@ -63,6 +63,7 @@ namespace AZ
size_type NumAllocatedBytes() const override;
size_type Capacity() const override;
size_type GetMaxAllocationSize() const override;
size_type GetMaxContiguousAllocationSize() const override;
IAllocatorAllocate* GetSubAllocator() override;
//////////////////////////////////////////////////////////////////////////
@@ -136,6 +136,12 @@ BestFitExternalMapSchema::GetMaxAllocationSize() const
return 0;
}
auto BestFitExternalMapSchema::GetMaxContiguousAllocationSize() const -> size_type
{
// Return the maximum size of any single allocation
return AZ_CORE_MAX_ALLOCATOR_SIZE;
}
//=========================================================================
// GarbageCollect
// [1/28/2011]
@@ -57,6 +57,7 @@ namespace AZ
AZ_FORCE_INLINE size_type NumAllocatedBytes() const { return m_used; }
AZ_FORCE_INLINE size_type Capacity() const { return m_desc.m_memoryBlockByteSize; }
size_type GetMaxAllocationSize() const;
size_type GetMaxContiguousAllocationSize() const;
AZ_FORCE_INLINE IAllocatorAllocate* GetSubAllocator() const { return m_desc.m_mapAllocator; }
/**
@@ -244,6 +244,11 @@ namespace AZ
return maxChunk;
}
auto HeapSchema::GetMaxContiguousAllocationSize() const -> size_type
{
return MAX_REQUEST;
}
AZ_FORCE_INLINE HeapSchema::size_type
HeapSchema::ChunckSize(pointer_type ptr)
{
@@ -57,6 +57,7 @@ namespace AZ
virtual size_type NumAllocatedBytes() const { return m_used; }
virtual size_type Capacity() const { return m_capacity; }
virtual size_type GetMaxAllocationSize() const;
size_type GetMaxContiguousAllocationSize() const override;
virtual IAllocatorAllocate* GetSubAllocator() { return m_subAllocator; }
virtual void GarbageCollect() {}
@@ -1069,6 +1069,7 @@ namespace AZ {
/// returns allocation size for the pointer if it belongs to the allocator. result is undefined if the pointer doesn't belong to the allocator.
size_t AllocationSize(void* ptr);
size_t GetMaxAllocationSize() const;
size_t GetMaxContiguousAllocationSize() const;
size_t GetUnAllocatedMemory(bool isPrint) const;
void* SystemAlloc(size_t size, size_t align);
@@ -2301,6 +2302,11 @@ namespace AZ {
return maxSize;
}
size_t HpAllocator::GetMaxContiguousAllocationSize() const
{
return AZ_CORE_MAX_ALLOCATOR_SIZE;
}
//=========================================================================
// GetUnAllocatedMemory
// [9/30/2013]
@@ -2677,6 +2683,11 @@ namespace AZ {
return m_allocator->GetMaxAllocationSize();
}
auto HphaSchema::GetMaxContiguousAllocationSize() const -> size_type
{
return m_allocator->GetMaxContiguousAllocationSize();
}
//=========================================================================
// GetUnAllocatedMemory
// [9/30/2013]
@@ -66,6 +66,7 @@ namespace AZ
virtual size_type NumAllocatedBytes() const;
virtual size_type Capacity() const;
virtual size_type GetMaxAllocationSize() const;
size_type GetMaxContiguousAllocationSize() const override;
virtual size_type GetUnAllocatedMemory(bool isPrint = false) const;
virtual IAllocatorAllocate* GetSubAllocator() { return m_desc.m_subAllocator; }
@@ -62,6 +62,8 @@ namespace AZ
virtual size_type Capacity() const = 0;
/// Returns max allocation size if possible. If not returned value is 0
virtual size_type GetMaxAllocationSize() const { return 0; }
/// Returns the maximum contiguous allocation size of a single allocation
virtual size_type GetMaxContiguousAllocationSize() const { return 0; }
/**
* Returns memory allocated by the allocator and available to the user for allocations.
* IMPORTANT: this is not the overhead memory this is just the memory that is allocated, but not used. Example: the pool allocators
@@ -144,6 +144,11 @@ AZ::MallocSchema::size_type AZ::MallocSchema::GetMaxAllocationSize() const
return 0xFFFFFFFFull;
}
AZ::MallocSchema::size_type AZ::MallocSchema::GetMaxContiguousAllocationSize() const
{
return AZ_CORE_MAX_ALLOCATOR_SIZE;
}
AZ::IAllocatorAllocate* AZ::MallocSchema::GetSubAllocator()
{
return nullptr;
@@ -50,6 +50,7 @@ namespace AZ
virtual size_type NumAllocatedBytes() const override;
virtual size_type Capacity() const override;
virtual size_type GetMaxAllocationSize() const override;
virtual size_type GetMaxContiguousAllocationSize() const override;
virtual IAllocatorAllocate* GetSubAllocator() override;
virtual void GarbageCollect() override;
+8 -3
View File
@@ -839,6 +839,11 @@ namespace AZ
return AZ::AllocatorInstance<Parent>::Get().GetMaxAllocationSize();
}
size_type GetMaxContiguousAllocationSize() const override
{
return AZ::AllocatorInstance<Parent>::Get().GetMaxContiguousAllocationSize();
}
size_type GetUnAllocatedMemory(bool isPrint = false) const override
{
return AZ::AllocatorInstance<Parent>::Get().GetUnAllocatedMemory(isPrint);
@@ -896,7 +901,7 @@ namespace AZ
}
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
size_type get_max_size() const { return AllocatorInstance<Allocator>::Get().GetMaxAllocationSize(); }
size_type max_size() const { return AllocatorInstance<Allocator>::Get().GetMaxContiguousAllocationSize(); }
size_type get_allocated_size() const { return AllocatorInstance<Allocator>::Get().NumAllocatedBytes(); }
AZ_FORCE_INLINE bool is_lock_free() { return AllocatorInstance<Allocator>::Get().is_lock_free(); }
@@ -954,7 +959,7 @@ namespace AZ
}
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
size_type get_max_size() const { return m_allocator->GetMaxAllocationSize(); }
size_type max_size() const { return m_allocator->GetMaxContiguousAllocationSize(); }
size_type get_allocated_size() const { return m_allocator->NumAllocatedBytes(); }
AZ_FORCE_INLINE bool operator==(const AZStdIAllocator& rhs) const { return m_allocator == rhs.m_allocator; }
@@ -1006,7 +1011,7 @@ namespace AZ
}
constexpr const char* get_name() const { return m_name; }
void set_name(const char* name) { m_name = name; }
size_type get_max_size() const { return m_allocatorFunctor().GetMaxAllocationSize(); }
size_type max_size() const { return m_allocatorFunctor().GetMaxContiguousAllocationSize(); }
size_type get_allocated_size() const { return m_allocatorFunctor().NumAllocatedBytes(); }
constexpr bool operator==(const AZStdFunctorAllocator& rhs) const { return m_allocatorFunctor == rhs.m_allocatorFunctor; }
@@ -61,6 +61,7 @@ namespace AZ
size_type NumAllocatedBytes() const override { return m_custom ? m_custom->NumAllocatedBytes() : m_numAllocatedBytes; }
size_type Capacity() const override { return m_custom ? m_custom->Capacity() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited
size_type GetMaxAllocationSize() const override { return m_custom ? m_custom->GetMaxAllocationSize() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited
size_type GetMaxContiguousAllocationSize() const override { return m_custom ? m_custom->GetMaxContiguousAllocationSize() : AZ_CORE_MAX_ALLOCATOR_SIZE; } // custom size or unlimited
IAllocatorAllocate* GetSubAllocator() override { return m_custom ? m_custom : NULL; }
protected:
@@ -232,6 +232,7 @@ namespace AZ
size_type NumAllocatedBytes() const;
size_type Capacity() const;
size_type GetMaxAllocationSize() const;
size_type GetMaxContiguousAllocationSize() const;
IAllocatorAllocate* GetSubAllocator();
void GarbageCollect();
@@ -674,6 +675,11 @@ AZ::OverrunDetectionSchema::size_type AZ::OverrunDetectionSchemaImpl::GetMaxAllo
return 0;
}
auto AZ::OverrunDetectionSchemaImpl::GetMaxContiguousAllocationSize() const -> size_type
{
return 0;
}
AZ::IAllocatorAllocate* AZ::OverrunDetectionSchemaImpl::GetSubAllocator()
{
return nullptr;
@@ -799,6 +805,11 @@ AZ::OverrunDetectionSchema::size_type AZ::OverrunDetectionSchema::GetMaxAllocati
return m_impl->GetMaxAllocationSize();
}
auto AZ::OverrunDetectionSchema::GetMaxContiguousAllocationSize() const -> size_type
{
return m_impl->GetMaxContiguousAllocationSize();
}
AZ::IAllocatorAllocate* AZ::OverrunDetectionSchema::GetSubAllocator()
{
return m_impl->GetSubAllocator();
@@ -86,6 +86,7 @@ namespace AZ
virtual size_type NumAllocatedBytes() const override;
virtual size_type Capacity() const override;
virtual size_type GetMaxAllocationSize() const override;
size_type GetMaxContiguousAllocationSize() const override;
virtual IAllocatorAllocate* GetSubAllocator() override;
virtual void GarbageCollect() override;
@@ -707,6 +707,11 @@ PoolSchema::GarbageCollect()
//m_impl->GarbageCollect();
}
auto PoolSchema::GetMaxContiguousAllocationSize() const -> size_type
{
return m_impl->m_allocator.m_maxAllocationSize;
}
//=========================================================================
// NumAllocatedBytes
// [11/1/2010]
@@ -1052,6 +1057,11 @@ ThreadPoolSchema::GarbageCollect()
m_impl->GarbageCollect();
}
auto ThreadPoolSchema::GetMaxContiguousAllocationSize() const -> size_type
{
return m_impl->m_maxAllocationSize;
}
//=========================================================================
// NumAllocatedBytes
// [11/1/2010]
@@ -70,6 +70,7 @@ namespace AZ
/// Return unused memory to the OS. Don't call this too often because you will force unnecessary allocations.
void GarbageCollect() override;
size_type GetMaxContiguousAllocationSize() const override;
size_type NumAllocatedBytes() const override;
size_type Capacity() const override;
IAllocatorAllocate* GetSubAllocator() override;
@@ -115,6 +116,7 @@ namespace AZ
/// Return unused memory to the OS. Don't call this too often because you will force unnecessary allocations.
void GarbageCollect() override;
size_type GetMaxContiguousAllocationSize() const override;
size_type NumAllocatedBytes() const override;
size_type Capacity() const override;
IAllocatorAllocate* GetSubAllocator() override;
@@ -179,6 +179,11 @@ namespace AZ
return m_schema->GetMaxAllocationSize();
}
size_type GetMaxContiguousAllocationSize() const override
{
return m_schema->GetMaxContiguousAllocationSize();
}
size_type GetUnAllocatedMemory(bool isPrint = false) const override
{
return m_schema->GetUnAllocatedMemory(isPrint);
@@ -103,6 +103,7 @@ namespace AZ
size_type Capacity() const override { return m_allocator->Capacity(); }
/// Keep in mind this operation will execute GarbageCollect to make sure it returns, max allocation. This function WILL be slow.
size_type GetMaxAllocationSize() const override { return m_allocator->GetMaxAllocationSize(); }
size_type GetMaxContiguousAllocationSize() const override { return m_allocator->GetMaxContiguousAllocationSize(); }
size_type GetUnAllocatedMemory(bool isPrint = false) const override { return m_allocator->GetUnAllocatedMemory(isPrint); }
IAllocatorAllocate* GetSubAllocator() override { return m_isCustom ? m_allocator : m_allocator->GetSubAllocator(); }
@@ -61,7 +61,7 @@ namespace AZ
const char* get_name() const { return m_name; }
void set_name(const char* name) { m_name = name; }
size_type get_max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
constexpr size_type max_size() const { return AZ_CORE_MAX_ALLOCATOR_SIZE; }
size_type get_allocated_size() const { return 0; }
bool is_lock_free() { return false; }
@@ -2306,7 +2306,7 @@ LUA_API const Node* lua_getDummyNode()
else // even references are stored by value as we need to convert from lua native type, i.e. there is not real reference for NativeTypes (numbers, strings, etc.)
{
bool usedBackupAlloc = false;
if (backupAllocator != nullptr && sizeof(T) > tempAllocator.get_max_size())
if (backupAllocator != nullptr && sizeof(T) > AZStd::allocator_traits<decltype(tempAllocator)>::max_size(tempAllocator))
{
value.m_value = backupAllocator->allocate(sizeof(T), AZStd::alignment_of<T>::value, 0);
usedBackupAlloc = true;
@@ -2340,7 +2340,7 @@ LUA_API const Node* lua_getDummyNode()
else // it's a value type
{
bool usedBackupAlloc = false;
if (backupAllocator != nullptr && valueClass->m_size > tempAllocator.get_max_size())
if (backupAllocator != nullptr && valueClass->m_size > AZStd::allocator_traits<decltype(tempAllocator)>::max_size(tempAllocator))
{
value.m_value = backupAllocator->allocate(valueClass->m_size, valueClass->m_alignment, 0);
usedBackupAlloc = true;
@@ -45,7 +45,7 @@ namespace UnitTest
virtual ~AllocatorsBase() = default;
void SetupAllocator()
void SetupAllocator(const AZ::SystemAllocator::Descriptor& allocatorDesc = {})
{
m_drillerManager = AZ::Debug::DrillerManager::Create();
m_drillerManager->Register(aznew AZ::Debug::MemoryDriller);
@@ -54,7 +54,7 @@ namespace UnitTest
// Only create the SystemAllocator if it s not ready
if (!AZ::AllocatorInstance<AZ::SystemAllocator>::IsReady())
{
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
AZ::AllocatorInstance<AZ::SystemAllocator>::Create(allocatorDesc);
m_ownsAllocator = true;
}
}
@@ -85,6 +85,7 @@ namespace UnitTest
{
public:
ScopedAllocatorSetupFixture() { SetupAllocator(); }
explicit ScopedAllocatorSetupFixture(const AZ::SystemAllocator::Descriptor& allocatorDesc) { SetupAllocator(allocatorDesc); }
~ScopedAllocatorSetupFixture() { TeardownAllocator(); }
};
@@ -40,15 +40,11 @@ namespace AZStd
return AZ::AllocatorInstance<AZ::SystemAllocator>::Get().Resize(ptr, newSize);
}
//=========================================================================
// get_max_size
// [1/1/2008]
//=========================================================================
allocator::size_type
allocator::get_max_size() const
auto allocator::max_size() const -> size_type
{
return AZ::AllocatorInstance<AZ::SystemAllocator>::Get().GetMaxAllocationSize();
return AZ::AllocatorInstance<AZ::SystemAllocator>::Get().GetMaxContiguousAllocationSize();
}
//=========================================================================
// get_allocated_size
// [1/1/2008]
+5 -4
View File
@@ -49,8 +49,8 @@ namespace AZStd
* const char* get_name() const;
* void set_name(const char* name);
*
* // Returns maximum size we can allocate from this allocator.
* size_type get_max_size() const;
* // Returns theoretical maximum size of a single contiguous allocation from this allocator.
* size_type max_size() const;
* <optional> size_type get_allocated_size() const;
* };
*
@@ -100,7 +100,8 @@ namespace AZStd
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0);
void deallocate(pointer_type ptr, size_type byteSize, size_type alignment);
size_type resize(pointer_type ptr, size_type newSize);
size_type get_max_size() const;
// max_size actually returns the true maximum size of a single allocation
size_type max_size() const;
size_type get_allocated_size() const;
AZ_FORCE_INLINE bool is_lock_free() { return false; }
@@ -157,7 +158,7 @@ namespace AZStd
AZ_FORCE_INLINE const char* get_name() const;
AZ_FORCE_INLINE void set_name(const char* name);
AZ_FORCE_INLINE size_type get_max_size() const;
AZ_FORCE_INLINE size_type max_size() const;
AZ_FORCE_INLINE bool is_lock_free();
AZ_FORCE_INLINE bool is_stale_read_allowed();
@@ -41,7 +41,7 @@ namespace AZStd
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
AZ_FORCE_INLINE size_type get_max_size() const { return m_allocator->get_max_size(); }
constexpr size_type max_size() const { return m_allocator->max_size(); }
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_allocator->get_allocated_size(); }
@@ -59,7 +59,7 @@ namespace AZStd
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
AZ_FORCE_INLINE size_type get_max_size() const { return m_size - (m_freeData - m_data); }
constexpr size_type max_size() const { return m_size; }
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_freeData - m_data; }
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0)
@@ -63,7 +63,7 @@ namespace AZStd
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
AZ_FORCE_INLINE size_type get_max_size() const { return Size - (m_freeData - reinterpret_cast<const char*>(&m_data)); }
constexpr size_type max_size() const { return Size; }
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_freeData - reinterpret_cast<const char*>(&m_data); }
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0)
@@ -190,7 +190,7 @@ namespace AZStd
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
AZ_FORCE_INLINE size_type get_max_size() const { return (NumNodes - m_numOfAllocatedNodes) * sizeof(Node); }
constexpr size_type max_size() const { return NumNodes * sizeof(Node); }
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_numOfAllocatedNodes * sizeof(Node); }
inline Node* allocate()
@@ -6,11 +6,10 @@
*
*/
#pragma once
#ifndef AZSTD_DEQUE_H
#define AZSTD_DEQUE_H 1
#include <AzCore/std/allocator.h>
#include <AzCore/std/allocator_traits.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/createdestroy.h>
#include <AzCore/std/typetraits/aligned_storage.h>
@@ -350,7 +349,7 @@ namespace AZStd
}
AZ_FORCE_INLINE size_type size() const { return m_size; }
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.get_max_size() / sizeof(block_node_type); }
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(block_node_type); }
AZ_FORCE_INLINE bool empty() const { return m_size == 0; }
AZ_FORCE_INLINE const_reference at(size_type offset) const { return *const_iterator(AZSTD_CHECKED_ITERATOR_2(const_iterator_impl, m_firstOffset + offset, this)); }
@@ -1243,5 +1242,3 @@ namespace AZStd
return removedCount;
}
}
#endif // AZSTD_DEQUE_H
@@ -286,7 +286,7 @@ namespace AZStd
}
AZ_FORCE_INLINE size_type size() const { return m_numElements; }
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
AZ_FORCE_INLINE bool empty() const { return (m_numElements == 0); }
AZ_FORCE_INLINE iterator begin() { return iterator(AZSTD_CHECKED_ITERATOR(iterator_impl, m_head.m_next)); }
@@ -5,11 +5,11 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef AZSTD_LIST_H
#define AZSTD_LIST_H 1
#pragma once
#include <AzCore/std/allocator.h>
#include <AzCore/std/allocator_traits.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/createdestroy.h>
#include <AzCore/std/typetraits/alignment_of.h>
@@ -316,7 +316,7 @@ namespace AZStd
}
AZ_FORCE_INLINE size_type size() const { return m_numElements; }
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
AZ_FORCE_INLINE bool empty() const { return (m_numElements == 0); }
AZ_FORCE_INLINE iterator begin() { return iterator(AZSTD_CHECKED_ITERATOR(iterator_impl, m_head.m_next)); }
@@ -1346,5 +1346,3 @@ namespace AZStd
return container.remove_if(predicate);
}
}
#endif // AZSTD_LIST_H
@@ -484,7 +484,7 @@ namespace AZStd
AZ_FORCE_INLINE bool empty() const { return m_numElements == 0; }
AZ_FORCE_INLINE size_type size() const { return m_numElements; }
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
rbtree(this_type&& rhs)
: m_numElements(0) // it will be set during swap
@@ -5,10 +5,11 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#ifndef AZSTD_RINGBUFFER_H
#define AZSTD_RINGBUFFER_H 1
#pragma once
#include <AzCore/std/allocator.h>
#include <AzCore/std/allocator_traits.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/createdestroy.h>
#include <AzCore/std/utils.h>
@@ -416,7 +417,7 @@ namespace AZStd
}
AZ_FORCE_INLINE size_type size() const { return m_size; }
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.max_size() / sizeof(node_type); }
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
AZ_FORCE_INLINE bool empty() const { return m_size == 0; }
AZ_FORCE_INLINE bool full() const { return size_type(m_end - m_buff) == m_size; }
AZ_FORCE_INLINE size_type free() const { return size_type(m_end - m_buff) - m_size; }
@@ -1240,6 +1241,3 @@ namespace AZStd
lhs.swap(rhs);
}
}
#endif // AZSTD_RINGBUFFER_H
#pragma once
@@ -9,6 +9,7 @@
#include <AzCore/std/allocator.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/allocator_traits.h>
#include <AzCore/std/createdestroy.h>
#include <AzCore/std/typetraits/alignment_of.h>
#include <AzCore/std/typetraits/is_integral.h>
@@ -431,7 +432,7 @@ namespace AZStd
}
AZ_FORCE_INLINE size_type size() const { return m_last - m_start; }
AZ_FORCE_INLINE size_type max_size() const { return m_allocator.get_max_size() / sizeof(node_type); }
AZ_FORCE_INLINE size_type max_size() const { return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(node_type); }
AZ_FORCE_INLINE bool empty() const { return m_start == m_last; }
void reserve(size_type numElements)
@@ -22,7 +22,7 @@ namespace AZStd
* Internally the buffer is allocated using aligned_storage.
* \note only allocate/deallocate are thread safe.
* reset, leak_before_destroy and comparison operators are not thread safe.
* get_max_size and get_allocated_size are thread safe but the returned value is not perfectly in
* get_allocated_size is thread safe but the returned value is not perfectly in
* sync on the actual number of allocations (the number of allocations is incremented before the
* allocation happens and decremented after the allocation happens, trying to give a conservative
* number)
@@ -71,7 +71,7 @@ namespace AZStd
AZ_FORCE_INLINE const char* get_name() const { return m_name; }
AZ_FORCE_INLINE void set_name(const char* name) { m_name = name; }
AZ_FORCE_INLINE size_type get_max_size() const { return (NumNodes - m_numOfAllocatedNodes.load(AZStd::memory_order_relaxed)) * sizeof(Node); }
constexpr size_type max_size() const { return NumNodes * sizeof(Node); }
AZ_FORCE_INLINE size_type get_allocated_size() const { return m_numOfAllocatedNodes.load(AZStd::memory_order_relaxed) * sizeof(Node); }
inline Node* allocate()
@@ -16,6 +16,7 @@
#include <AzCore/std/base.h>
#include <AzCore/std/iterator.h>
#include <AzCore/std/allocator.h>
#include <AzCore/std/allocator_traits.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/typetraits/alignment_of.h>
#include <AzCore/std/typetraits/is_integral.h>
@@ -862,8 +863,7 @@ namespace AZStd
inline size_type max_size() const
{
// return maximum possible length of sequence
size_type num = m_allocator.get_max_size();
return (num <= 1 ? 1 : num - 1);
return AZStd::allocator_traits<allocator_type>::max_size(m_allocator) / sizeof(value_type);
}
inline void resize(size_type newSize)
@@ -122,8 +122,15 @@ namespace UnitTest
TEST_F(AllocatorDefaultTest, AllocatorTraitsMaxSizeCompilesWithoutErrors)
{
using AZStdAllocatorTraits = AZStd::allocator_traits<AZStd::allocator>;
AZStd::allocator testAllocator("trait allocator");
struct AllocatorWithGetMaxSize
: AZStd::allocator
{
using AZStd::allocator::allocator;
size_t get_max_size() { return max_size(); }
};
using AZStdAllocatorTraits = AZStd::allocator_traits<AllocatorWithGetMaxSize>;
AllocatorWithGetMaxSize testAllocator("trait allocator");
typename AZStdAllocatorTraits::size_type maxSize = AZStdAllocatorTraits::max_size(testAllocator);
EXPECT_EQ(testAllocator.get_max_size(), maxSize);
}
@@ -149,32 +156,32 @@ namespace UnitTest
myalloc.set_name(newName);
AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
buffer_alloc_type::pointer_type data = myalloc.allocate(100, 1);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100);
EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100);
myalloc.deallocate(data, 100, 1); // we can free the last allocation only
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize);
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
data = myalloc.allocate(100, 1);
myalloc.allocate(3, 1);
myalloc.deallocate(data); // can't free allocation which is not the last.
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 103);
EXPECT_EQ(bufferSize - 103, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 103);
myalloc.reset();
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
data = myalloc.allocate(50, 64);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(((AZStd::size_t)data & 63) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() <= bufferSize - 50);
EXPECT_LE(myalloc.max_size() - myalloc.get_allocated_size(), bufferSize - 50);
AZ_TEST_ASSERT(myalloc.get_allocated_size() >= 50);
buffer_alloc_type myalloc2;
@@ -194,28 +201,28 @@ namespace UnitTest
myalloc.set_name(newName);
AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() == sizeof(int) * numNodes);
EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
int* data = reinterpret_cast<int*>(myalloc.allocate(sizeof(int), 1));
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == (numNodes - 1) * sizeof(int));
EXPECT_EQ((numNodes - 1) * sizeof(int), myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == sizeof(int));
myalloc.deallocate(data, sizeof(int), 1);
AZ_TEST_ASSERT(myalloc.get_max_size() == sizeof(int) * numNodes);
EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
for (int i = 0; i < numNodes; ++i)
{
data = reinterpret_cast<int*>(myalloc.allocate(sizeof(int), 1));
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == (numNodes - (i + 1)) * sizeof(int));
EXPECT_EQ((numNodes - (i + 1)) * sizeof(int), myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == (i + 1) * sizeof(int));
}
myalloc.reset();
AZ_TEST_ASSERT(myalloc.get_max_size() == numNodes * sizeof(int));
EXPECT_EQ(numNodes * sizeof(int), myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
AZ_TEST_ASSERT(myalloc == myalloc);
@@ -233,7 +240,7 @@ namespace UnitTest
AZ_TEST_ASSERT(aligned_data != nullptr);
AZ_TEST_ASSERT(((AZStd::size_t)aligned_data & (dataAlignment - 1)) == 0);
AZ_TEST_ASSERT(myaligned_pool.get_max_size() == (numNodes - 1) * sizeof(aligned_int_type));
EXPECT_EQ((numNodes - 1) * sizeof(aligned_int_type), myaligned_pool.max_size() - myaligned_pool.get_allocated_size());
AZ_TEST_ASSERT(myaligned_pool.get_allocated_size() == sizeof(aligned_int_type));
myaligned_pool.deallocate(aligned_data, sizeof(aligned_int_type), dataAlignment); // Make sure we free what we have allocated.
@@ -268,32 +275,32 @@ namespace UnitTest
ref_allocator_type::pointer_type data1 = ref_allocator1.allocate(10, 1);
AZ_TEST_ASSERT(data1 != nullptr);
AZ_TEST_ASSERT(ref_allocator1.get_max_size() == bufferSize - 10);
EXPECT_EQ(bufferSize - 10, ref_allocator1.max_size() - ref_allocator1.get_allocated_size());
AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() == 10);
AZ_TEST_ASSERT(shared_allocator.get_max_size() == bufferSize - 10);
EXPECT_EQ(bufferSize - 10, shared_allocator.max_size() - shared_allocator.get_allocated_size());
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() == 10);
ref_allocator_type::pointer_type data2 = ref_allocator2.allocate(10, 1);
AZ_TEST_ASSERT(data2 != nullptr);
AZ_TEST_ASSERT(ref_allocator2.get_max_size() <= bufferSize - 20);
EXPECT_LE(ref_allocator2.max_size() - ref_allocator2.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(ref_allocator2.get_allocated_size() >= 20);
AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 20);
EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 20);
shared_allocator.reset();
data1 = ref_allocator1.allocate(10, 32);
AZ_TEST_ASSERT(data1 != nullptr);
AZ_TEST_ASSERT(ref_allocator1.get_max_size() <= bufferSize - 10);
EXPECT_LE(ref_allocator1.max_size() - ref_allocator1.get_allocated_size(), bufferSize - 10);
AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() >= 10);
AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 10);
EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 10);
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 10);
data2 = ref_allocator2.allocate(10, 32);
AZ_TEST_ASSERT(data2 != nullptr);
AZ_TEST_ASSERT(ref_allocator1.get_max_size() <= bufferSize - 20);
EXPECT_LE(ref_allocator1.max_size() - ref_allocator1.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(ref_allocator1.get_allocated_size() >= 20);
AZ_TEST_ASSERT(shared_allocator.get_max_size() <= bufferSize - 20);
EXPECT_LE(shared_allocator.max_size() - shared_allocator.get_allocated_size(), bufferSize - 20);
AZ_TEST_ASSERT(shared_allocator.get_allocated_size() >= 20);
AZ_TEST_ASSERT(ref_allocator1 == ref_allocator2);
@@ -312,31 +319,31 @@ namespace UnitTest
myalloc.set_name(newName);
AZ_TEST_ASSERT(strcmp(myalloc.get_name(), newName) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
stack_allocator::pointer_type data = myalloc.allocate(100, 1);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100);
EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100);
myalloc.deallocate(data, 100, 1); // this allocator doesn't free data
AZ_TEST_ASSERT(myalloc.get_max_size() == bufferSize - 100);
EXPECT_EQ(bufferSize - 100, myalloc.max_size() - myalloc.get_allocated_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 100);
myalloc.reset();
AZ_TEST_ASSERT(myalloc.get_max_size() == AZStd::size_t(bufferSize));
EXPECT_EQ(bufferSize, myalloc.max_size());
AZ_TEST_ASSERT(myalloc.get_allocated_size() == 0);
data = myalloc.allocate(50, 64);
AZ_TEST_ASSERT(data != nullptr);
AZ_TEST_ASSERT(((AZStd::size_t)data & 63) == 0);
AZ_TEST_ASSERT(myalloc.get_max_size() <= bufferSize - 50);
EXPECT_LE(myalloc.max_size() - myalloc.get_allocated_size(), bufferSize - 50);
AZ_TEST_ASSERT(myalloc.get_allocated_size() >= 50);
AZ_STACK_ALLOCATOR(myalloc2, 200); // test the macro declaration
AZ_TEST_ASSERT(myalloc2.get_max_size() == 200);
EXPECT_EQ(200, myalloc2.max_size() );
AZ_TEST_ASSERT(myalloc == myalloc);
AZ_TEST_ASSERT((myalloc2 != myalloc));
@@ -49,7 +49,7 @@ namespace UnitTest
const char newName[] = "My new test allocator";
myalloc.set_name(newName);
EXPECT_EQ(0, strcmp(myalloc.get_name(), newName));
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.get_max_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.max_size());
}
}
@@ -61,10 +61,10 @@ namespace UnitTest
typename TestFixture::allocator_type::pointer_type data = myalloc.allocate();
EXPECT_NE(nullptr, data);
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_allocated_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (s_allocatorCapacity - 1), myalloc.get_max_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (s_allocatorCapacity - 1), myalloc.max_size() - myalloc.get_allocated_size());
myalloc.deallocate(data);
EXPECT_EQ(0, myalloc.get_allocated_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.get_max_size());
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * s_allocatorCapacity, myalloc.max_size());
}
TYPED_TEST(ConcurrentAllocatorTestFixture, MultipleAllocateDeallocate)
@@ -84,19 +84,19 @@ namespace UnitTest
EXPECT_EQ(dataSize, dataSet.size());
dataSet.clear();
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * dataSize, myalloc.get_allocated_size());
EXPECT_EQ((s_allocatorCapacity - dataSize) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size());
EXPECT_EQ((s_allocatorCapacity - dataSize) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size() - myalloc.get_allocated_size());
for (size_t i = 0; i < dataSize; i += 2)
{
myalloc.deallocate(data[i]);
}
EXPECT_EQ(sizeof(typename TestFixture::allocator_type::value_type) * (dataSize / 2), myalloc.get_allocated_size());
EXPECT_EQ((s_allocatorCapacity - dataSize / 2) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size());
EXPECT_EQ((s_allocatorCapacity - dataSize / 2) * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size() - myalloc.get_allocated_size());
for (size_t i = 1; i < dataSize; i += 2)
{
myalloc.deallocate(data[i]);
}
EXPECT_EQ(0, myalloc.get_allocated_size());
EXPECT_EQ(s_allocatorCapacity * sizeof(typename TestFixture::allocator_type::value_type), myalloc.get_max_size());
EXPECT_EQ(s_allocatorCapacity * sizeof(typename TestFixture::allocator_type::value_type), myalloc.max_size());
}
TYPED_TEST(ConcurrentAllocatorTestFixture, ConcurrentAllocateoDeallocate)
@@ -159,7 +159,7 @@ namespace UnitTest
EXPECT_NE(nullptr, aligned_data);
EXPECT_EQ(0, ((AZStd::size_t)aligned_data & (dataAlignment - 1)));
EXPECT_EQ((s_allocatorCapacity - 1) * sizeof(aligned_int_type), myaligned_pool.get_max_size());
EXPECT_EQ((s_allocatorCapacity - 1) * sizeof(aligned_int_type), myaligned_pool.max_size() - myaligned_pool.get_allocated_size());
EXPECT_EQ(sizeof(aligned_int_type), myaligned_pool.get_allocated_size());
myaligned_pool.deallocate(aligned_data, sizeof(aligned_int_type), dataAlignment); // Make sure we free what we have allocated.
@@ -213,6 +213,82 @@ namespace UnitTest
AZStd::tuple<AZStd::string_view, AZStd::string_view>(R"(foO/Bar)", "foo/bar")
));
struct PathHashCompareParams
{
AZ::IO::PathView m_testPath{};
::testing::Matcher<AZ::IO::PathView> m_compareMatcher;
::testing::Matcher<size_t> m_hashMatcher;
};
class PathHashCompareFixture
: public ScopedAllocatorSetupFixture
, public ::testing::WithParamInterface<PathHashCompareParams>
{};
// Verifies that two paths that compare equal has their hash value compare equal
TEST_P(PathHashCompareFixture, PathsWhichCompareEqual_HashesToSameValue_Succeeds)
{
auto&& [testPath1, compareMatcher, hashMatcher] = GetParam();
// Compare path using parameterized Matcher
EXPECT_THAT(testPath1, compareMatcher);
// Compare hash using parameterized Matcher
const size_t testPath1Hash = AZStd::hash<AZ::IO::PathView>{}(testPath1);
AZ_PUSH_DISABLE_WARNING(4296, "-Wunknown-warning-option")
EXPECT_THAT(testPath1Hash, hashMatcher);
AZ_POP_DISABLE_WARNING
}
INSTANTIATE_TEST_CASE_P(
HashPathCompareValidation,
PathHashCompareFixture,
::testing::Values(
PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::WindowsPathSeparator),
testing::Eq(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)),
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/foo", AZ::IO::WindowsPathSeparator),
testing::Eq(AZ::IO::PathView(R"(/test/FOO)", AZ::IO::WindowsPathSeparator)),
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/FOO)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::WindowsPathSeparator),
testing::Eq(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)),
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("C:/test/foo", AZ::IO::PosixPathSeparator),
testing::Ne(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:\test/foo)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView(R"(C:\test\foo)", AZ::IO::WindowsPathSeparator),
testing::Ne(AZ::IO::PathView(R"(c:/test/foo)", AZ::IO::PosixPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(c:/test/foo)", AZ::IO::PosixPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator),
testing::Eq(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator)),
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::PosixPathSeparator),
testing::Gt(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator)),
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator),
testing::Gt(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::PosixPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/AOO)", AZ::IO::PosixPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/AOO", AZ::IO::PosixPathSeparator),
testing::Lt(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/AOO", AZ::IO::WindowsPathSeparator),
testing::Lt(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::PosixPathSeparator)),
testing::Eq(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::PosixPathSeparator))) },
// Paths with different character values, comparison based on path separator
PathHashCompareParams{ AZ::IO::PathView("/test/BOO", AZ::IO::PosixPathSeparator),
testing::Le(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/BOO", AZ::IO::WindowsPathSeparator),
testing::Ge(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/aoo)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::WindowsPathSeparator),
testing::Le(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator))) },
PathHashCompareParams{ AZ::IO::PathView("/test/aoo", AZ::IO::PosixPathSeparator),
testing::Ge(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator)),
testing::Ne(AZStd::hash<AZ::IO::PathView>{}(AZ::IO::PathView(R"(/test/Boo)", AZ::IO::WindowsPathSeparator))) }
));
class PathSingleParamFixture
: public ScopedAllocatorSetupFixture
, public ::testing::WithParamInterface<AZStd::tuple<AZStd::string_view>>
+2
View File
@@ -1179,6 +1179,8 @@ namespace UnitTest
size_type Capacity() const override { return 1 * 1024 * 1024 * 1024; }
/// Returns max allocation size if possible. If not returned value is 0
size_type GetMaxAllocationSize() const override { return 1 * 1024 * 1024 * 1024; }
/// Returns max allocation size of a single contiguous allocation
size_type GetMaxContiguousAllocationSize() const override { return 1 * 1024 * 1024 * 1024; }
/// Returns a pointer to a sub-allocator or NULL.
IAllocatorAllocate* GetSubAllocator() override { return NULL; }
};
@@ -2185,7 +2185,7 @@ namespace AZ::IO
AZStd::unique_lock lock(m_archiveMutex);
if (pArchive)
{
AZ_TracePrintf("Archive", "Closing Archive file: %s", pArchive->GetFullPath());
AZ_TracePrintf("Archive", "Closing Archive file: %s\n", pArchive->GetFullPath());
}
ArchiveArray::iterator it;
if (m_arrArchives.size() < 16)
@@ -51,7 +51,8 @@ namespace AzFramework
->Event("GetNormal", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormal)
->Event("GetNormalFromFloats", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetNormalFromFloats)
->Event("GetTerrainAabb", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainAabb)
->Event("GetTerrainGridResolution", &AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainGridResolution)
->Event("GetTerrainHeightQueryResolution",
&AzFramework::Terrain::TerrainDataRequestBus::Events::GetTerrainHeightQueryResolution)
;
}
@@ -59,8 +59,11 @@ namespace AzFramework
static AZ::Vector3 GetDefaultTerrainNormal() { return AZ::Vector3::CreateAxisZ(); }
// System-level queries to understand world size and resolution
virtual AZ::Vector2 GetTerrainGridResolution() const = 0;
virtual AZ::Vector2 GetTerrainHeightQueryResolution() const = 0;
virtual void SetTerrainHeightQueryResolution(AZ::Vector2 queryResolution) = 0;
virtual AZ::Aabb GetTerrainAabb() const = 0;
virtual void SetTerrainAabb(const AZ::Aabb& worldBounds) = 0;
//! Returns terrains height in meters at location x,y.
//! @terrainExistsPtr: Can be nullptr. If != nullptr then, if there's no terrain at location x,y or location x,y is inside a terrain HOLE then *terrainExistsPtr will become false,
@@ -263,21 +263,29 @@ namespace AzFramework
}
commandAndArgs[commandTokens.size()] = nullptr;
AZStd::vector<AZStd::unique_ptr<char[]>> environmentVariablesManaged;
AZStd::vector<char*> environmentVariablesVector;
char** environmentVariables = nullptr;
int numEnvironmentVars = 0;
if (processLaunchInfo.m_environmentVariables)
{
numEnvironmentVars = processLaunchInfo.m_environmentVariables->size();
// Adding one more as exec expects the array to have a nullptr as the last element
environmentVariables = new char*[numEnvironmentVars + 1];
for (int i = 0; i < numEnvironmentVars; i++)
for (const auto& envVarString : *processLaunchInfo.m_environmentVariables)
{
const AZStd::string& envVarString = processLaunchInfo.m_environmentVariables->at(i);
environmentVariables[i] = new char[envVarString.size() + 1];
environmentVariables[i][0] = '\0';
azstrcat(environmentVariables[i], envVarString.size(), envVarString.c_str());
auto& environmentVariable = environmentVariablesManaged.emplace_back(AZStd::make_unique<char[]>(envVarString.size() + 1));
environmentVariable[0] = '\0';
azstrcat(environmentVariable.get(), envVarString.size() + 1, envVarString.c_str());
environmentVariablesVector.emplace_back(environmentVariable.get());
}
environmentVariables[numEnvironmentVars] = nullptr;
// Adding one more as exec expects the array to have a nullptr as the last element
environmentVariablesVector.emplace_back(nullptr);
environmentVariables = environmentVariablesVector.data();
}
else
{
// If no environment variables were specified, then use the current process's environment variables
// and pass it along for the execute .
extern char **environ; // Defined in unistd.h
environmentVariables = ::environ;
AZ_Assert(environmentVariables, "Environment variables for current process not available\n");
}
pid_t child_pid = fork();
@@ -290,15 +298,6 @@ namespace AzFramework
// Close these handles as they are only to be used by the child process
processData.m_startupInfo.CloseAllHandles();
if (processLaunchInfo.m_environmentVariables)
{
for (int i = 0; i < numEnvironmentVars; i++)
{
delete [] environmentVariables[i];
}
delete [] environmentVariables;
}
for (int i = 0; i < commandTokens.size(); i++)
{
delete [] commandAndArgs[i];
@@ -39,6 +39,8 @@ namespace AzManipulatorTestFramework
DerivedDispatcherT* MouseLButtonDown();
//! Set the left mouse button up.
DerivedDispatcherT* MouseLButtonUp();
//! Send a double click event.
DerivedDispatcherT* MouseLButtonDoubleClick();
//! Set the keyboard modifier button down.
DerivedDispatcherT* KeyboardModifierDown(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier);
//! Set the keyboard modifier button up.
@@ -71,6 +73,7 @@ namespace AzManipulatorTestFramework
virtual void CameraStateImpl(const AzFramework::CameraState& cameraState) = 0;
virtual void MouseLButtonDownImpl() = 0;
virtual void MouseLButtonUpImpl() = 0;
virtual void MouseLButtonDoubleClickImpl() = 0;
virtual void MousePositionImpl(const AzFramework::ScreenPoint& position) = 0;
virtual void KeyboardModifierDownImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) = 0;
virtual void KeyboardModifierUpImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) = 0;
@@ -167,7 +170,7 @@ namespace AzManipulatorTestFramework
template<typename DerivedDispatcherT>
DerivedDispatcherT* ActionDispatcher<DerivedDispatcherT>::MouseLButtonDown()
{
Log("%s", "Mouse left button down");
Log("Mouse left button down");
MouseLButtonDownImpl();
return static_cast<DerivedDispatcherT*>(this);
}
@@ -175,11 +178,19 @@ namespace AzManipulatorTestFramework
template<typename DerivedDispatcherT>
DerivedDispatcherT* ActionDispatcher<DerivedDispatcherT>::MouseLButtonUp()
{
Log("%s", "Mouse left button up");
Log("Mouse left button up");
MouseLButtonUpImpl();
return static_cast<DerivedDispatcherT*>(this);
}
template<typename DerivedDispatcherT>
DerivedDispatcherT* ActionDispatcher<DerivedDispatcherT>::MouseLButtonDoubleClick()
{
Log("Mouse left button double click");
MouseLButtonDoubleClickImpl();
return static_cast<DerivedDispatcherT*>(this);
}
template<typename DerivedDispatcherT>
const char* ActionDispatcher<DerivedDispatcherT>::KeyboardModifierString(
const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier)
@@ -58,6 +58,7 @@ namespace AzManipulatorTestFramework
void CameraStateImpl(const AzFramework::CameraState& cameraState) override;
void MouseLButtonDownImpl() override;
void MouseLButtonUpImpl() override;
void MouseLButtonDoubleClickImpl() override;
void MousePositionImpl(const AzFramework::ScreenPoint& position) override;
void KeyboardModifierDownImpl(const KeyboardModifier& keyModifier) override;
void KeyboardModifierUpImpl(const KeyboardModifier& keyModifier) override;
@@ -1,55 +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
*
*/
#pragma once
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzManipulatorTestFramework/ActionDispatcher.h>
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzCore/std/containers/list.h>
#include <AzCore/std/functional.h>
namespace AzManipulatorTestFramework
{
//! Buffers actions to be dispatched upon a call to Execute().
class RetainedModeActionDispatcher
: public ActionDispatcher<RetainedModeActionDispatcher>
{
public:
explicit RetainedModeActionDispatcher(ManipulatorViewportInteraction& viewportManipulatorInteraction);
//! Execute the sequence of actions and lock the dispatcher from adding further actions.
RetainedModeActionDispatcher* Execute();
//! Reset the sequence of actions and unlock the dispatcher from adding further actions.
RetainedModeActionDispatcher* ResetSequence();
protected:
// ActionDispatcher ...
void EnableSnapToGridImpl() override;
void DisableSnapToGridImpl() override;
void GridSizeImpl(float size) override;
void CameraStateImpl(const AzFramework::CameraState& cameraState) override;
void MouseLButtonDownImpl() override;
void MouseLButtonUpImpl() override;
void MousePositionImpl(const AzFramework::ScreenPoint& position) override;
void KeyboardModifierDownImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) override;
void KeyboardModifierUpImpl(const AzToolsFramework::ViewportInteraction::KeyboardModifier& keyModifier) override;
void ExpectManipulatorBeingInteractedImpl() override;
void ExpectManipulatorNotBeingInteractedImpl() override;
void SetEntityWorldTransformImpl(AZ::EntityId entityId, const AZ::Transform& transform) override;
void SetSelectedEntityImpl(AZ::EntityId entity) override;
void SetSelectedEntitiesImpl(const AzToolsFramework::EntityIdList& entities) override;
void EnterComponentModeImpl(const AZ::Uuid& uuid) override;
private:
using Action = AZStd::function<void()>;
void AddActionToSequence(Action&& action);
ImmediateModeActionDispatcher m_dispatcher;
AZStd::list<Action> m_actions;
bool m_locked = false;
};
} // namespace AzManipulatorTestFramework
@@ -83,7 +83,17 @@ namespace AzManipulatorTestFramework
void ImmediateModeActionDispatcher::MouseLButtonUpImpl()
{
GetMouseInteractionEvent()->m_mouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent::Up;
m_viewportManipulatorInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*GetMouseInteractionEvent());
m_viewportManipulatorInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*m_event);
ToggleOff(GetMouseInteractionEvent()->m_mouseInteraction.m_mouseButtons.m_mouseButtons, MouseButton::Left);
// the mouse position will be the same as the previous event, thus the delta will be 0
MouseMoveAfterButton();
}
void ImmediateModeActionDispatcher::MouseLButtonDoubleClickImpl()
{
GetMouseInteractionEvent()->m_mouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent::DoubleClick;
ToggleOn(GetMouseInteractionEvent()->m_mouseInteraction.m_mouseButtons.m_mouseButtons, MouseButton::Left);
m_viewportManipulatorInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*m_event);
ToggleOff(GetMouseInteractionEvent()->m_mouseInteraction.m_mouseButtons.m_mouseButtons, MouseButton::Left);
// the mouse position will be the same as the previous event, thus the delta will be 0
MouseMoveAfterButton();
@@ -1,129 +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 <AzManipulatorTestFramework/RetainedModeActionDispatcher.h>
namespace AzManipulatorTestFramework
{
using KeyboardModifier = AzToolsFramework::ViewportInteraction::KeyboardModifier;
RetainedModeActionDispatcher::RetainedModeActionDispatcher(
ManipulatorViewportInteraction& viewportManipulatorInteraction)
: m_dispatcher(viewportManipulatorInteraction)
{
}
void RetainedModeActionDispatcher::AddActionToSequence(Action&& action)
{
if (m_locked)
{
const char* error = "Couldn't add action to sequence, dispatcher is locked (you must call ResetSequence() \
before adding actions to this dispatcher)";
Log("%s", error);
AZ_Assert(false, "Error: %s", error);
}
m_actions.emplace_back(action);
}
void RetainedModeActionDispatcher::EnableSnapToGridImpl()
{
AddActionToSequence([=]() { m_dispatcher.EnableSnapToGrid(); });
}
void RetainedModeActionDispatcher::DisableSnapToGridImpl()
{
AddActionToSequence([=]() { m_dispatcher.DisableSnapToGrid(); });
}
void RetainedModeActionDispatcher::GridSizeImpl(float size)
{
AddActionToSequence([=]() { m_dispatcher.GridSize(size); });
}
void RetainedModeActionDispatcher::CameraStateImpl(const AzFramework::CameraState& cameraState)
{
AddActionToSequence([=]() { m_dispatcher.CameraState(cameraState); });
}
void RetainedModeActionDispatcher::MouseLButtonDownImpl()
{
AddActionToSequence([=]() { m_dispatcher.MouseLButtonDown(); });
}
void RetainedModeActionDispatcher::MouseLButtonUpImpl()
{
AddActionToSequence([=]() { m_dispatcher.MouseLButtonUp(); });
}
void RetainedModeActionDispatcher::MousePositionImpl(const AzFramework::ScreenPoint& position)
{
AddActionToSequence([=]() { m_dispatcher.MousePosition(position); });
}
void RetainedModeActionDispatcher::KeyboardModifierDownImpl(const KeyboardModifier& keyModifier)
{
AddActionToSequence([=]() { m_dispatcher.KeyboardModifierDown(keyModifier); });
}
void RetainedModeActionDispatcher::KeyboardModifierUpImpl(const KeyboardModifier& keyModifier)
{
AddActionToSequence([=]() { m_dispatcher.KeyboardModifierUp(keyModifier); });
}
void RetainedModeActionDispatcher::ExpectManipulatorBeingInteractedImpl()
{
AddActionToSequence([=]() { m_dispatcher.ExpectManipulatorBeingInteracted(); });
}
void RetainedModeActionDispatcher::ExpectManipulatorNotBeingInteractedImpl()
{
AddActionToSequence([=]() { m_dispatcher.ExpectManipulatorNotBeingInteracted(); });
}
void RetainedModeActionDispatcher::SetEntityWorldTransformImpl(AZ::EntityId entityId, const AZ::Transform& transform)
{
AddActionToSequence([=]() { m_dispatcher.SetEntityWorldTransform(entityId, transform); });
}
void RetainedModeActionDispatcher::SetSelectedEntityImpl(AZ::EntityId entity)
{
AddActionToSequence([=]() { m_dispatcher.SetSelectedEntity(entity); });
}
void RetainedModeActionDispatcher::SetSelectedEntitiesImpl(const AzToolsFramework::EntityIdList& entities)
{
AddActionToSequence([=]() { m_dispatcher.SetSelectedEntities(entities); });
}
void RetainedModeActionDispatcher::EnterComponentModeImpl(const AZ::Uuid& uuid)
{
AddActionToSequence([=]() { m_dispatcher.EnterComponentMode(uuid); });
}
RetainedModeActionDispatcher* RetainedModeActionDispatcher::ResetSequence()
{
Log("%s", "Resetting the action sequence");
m_actions.clear();
m_dispatcher.ResetEvent();
m_locked = false;
return this;
}
RetainedModeActionDispatcher* RetainedModeActionDispatcher::Execute()
{
Log("Executing %u actions", m_actions.size());
for (auto& action : m_actions)
{
action();
}
m_dispatcher.ResetEvent();
m_locked = true;
return this;
}
} // namespace AzManipulatorTestFramework
@@ -14,12 +14,10 @@ set(FILES
Include/AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h
Include/AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h
Include/AzManipulatorTestFramework/ImmediateModeActionDispatcher.h
Include/AzManipulatorTestFramework/RetainedModeActionDispatcher.h
Include/AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h
Source/ViewportInteraction.cpp
Source/DirectManipulatorViewportInteraction.cpp
Source/IndirectManipulatorViewportInteraction.cpp
Source/ImmediateModeActionDispatcher.cpp
Source/RetainedModeActionDispatcher.cpp
Source/AzManipulatorTestFrameworkUtils.cpp
)
@@ -2461,6 +2461,18 @@ namespace AzQtComponents
placeholderRect.translate(0, -margins.bottom());
}
// Also adjust the placeholderRect by the relative dpi change from the original screen, since setGeometry uses the screen's
// virtualGeometry!
QScreen* fromScreen = dock->screen();
QScreen* toScreen = Utilities::ScreenAtPoint(placeholderRect.topLeft());
if (fromScreen != toScreen)
{
qreal factorRatio = QHighDpiScaling::factor(fromScreen) / QHighDpiScaling::factor(toScreen);
placeholderRect.setWidth(aznumeric_cast<int>(aznumeric_cast<qreal>(placeholderRect.width()) * factorRatio));
placeholderRect.setHeight(aznumeric_cast<int>(aznumeric_cast<qreal>(placeholderRect.height()) * factorRatio));
}
// Place the floating dock widget
makeDockWidgetFloating(dock, placeholderRect);
clearDraggingState();
@@ -169,6 +169,10 @@ namespace AzQtComponents
initializeSearchPaths(application, engineRootPath);
initializeFonts();
QFont defaultFont("Open Sans");
defaultFont.setPixelSize(12);
QApplication::setFont(defaultFont);
m_titleBarOverdrawHandler = TitleBarOverdrawHandler::createHandler(application, this);
// The window decoration wrappers require the titlebar overdraw handler
@@ -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/Casting/numeric_cast.h>
#include <AzQtComponents/Utilities/PixmapScaleUtilities.h>
#include <QtGui/private/qhighdpiscaling_p.h>
namespace AzQtComponents
{
QPixmap ScalePixmapForScreenDpi(
QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode)
{
qreal screenDpiFactor = QHighDpiScaling::factor(screen);
pixmap.setDevicePixelRatio(screenDpiFactor);
QPixmap scaledPixmap;
size.setWidth(aznumeric_cast<int>(aznumeric_cast<qreal>(size.width()) * screenDpiFactor));
size.setHeight(aznumeric_cast<int>(aznumeric_cast<qreal>(size.height()) * screenDpiFactor));
scaledPixmap = pixmap.scaled(size, aspectRatioMode, transformationMode);
return scaledPixmap;
}
}
@@ -0,0 +1,19 @@
/*
* 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 <AzQtComponents/AzQtComponentsAPI.h>
#include <QPixmap>
#include <QScreen>
namespace AzQtComponents
{
AZ_QT_COMPONENTS_API QPixmap ScalePixmapForScreenDpi(QPixmap pixmap, QScreen* screen, QSize size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformationMode);
}; // namespace AzQtComponents
@@ -276,6 +276,8 @@ set(FILES
Utilities/HandleDpiAwareness.cpp
Utilities/HandleDpiAwareness.h
Utilities/MouseHider.h
Utilities/PixmapScaleUtilities.cpp
Utilities/PixmapScaleUtilities.h
Utilities/QtPluginPaths.cpp
Utilities/QtPluginPaths.h
Utilities/QtWindowUtilities.cpp
@@ -47,9 +47,9 @@ namespace AzToolsFramework
return QString();
}
QPixmap EditorEntityUiHandlerBase::GenerateItemIcon(AZ::EntityId /*entityId*/) const
QIcon EditorEntityUiHandlerBase::GenerateItemIcon(AZ::EntityId /*entityId*/) const
{
return QPixmap();
return QIcon();
}
bool EditorEntityUiHandlerBase::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const
@@ -40,7 +40,7 @@ namespace AzToolsFramework
//! Returns the item tooltip text to display in the Outliner.
virtual QString GenerateItemTooltip(AZ::EntityId entityId) const;
//! Returns the item icon pixmap to display in the Outliner.
virtual QPixmap GenerateItemIcon(AZ::EntityId entityId) const;
virtual QIcon GenerateItemIcon(AZ::EntityId entityId) const;
//! Returns whether the element's lock and visibility state should be accessible in the Outliner
virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const;
//! Returns whether the element's name should be editable
@@ -66,9 +66,9 @@ namespace AzToolsFramework
return result;
}
QPixmap LayerUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const
QIcon LayerUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const
{
return QPixmap(m_layerIconPath);
return QIcon(m_layerIconPath);
}
void LayerUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
@@ -24,7 +24,7 @@ namespace AzToolsFramework
// EditorEntityUiHandler...
QString GenerateItemInfoString(AZ::EntityId entityId) const override;
QPixmap GenerateItemIcon(AZ::EntityId entityId) const override;
QIcon GenerateItemIcon(AZ::EntityId entityId) const override;
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
const QModelIndex& descendantIndex) const override;
@@ -280,17 +280,17 @@ namespace AzToolsFramework
QVariant EntityOutlinerListModel::GetEntityIcon(const AZ::EntityId& id) const
{
auto entityUiHandler = m_editorEntityFrameworkInterface->GetHandler(id);
QPixmap pixmap;
QIcon icon;
// Retrieve the icon from the handler
if (entityUiHandler != nullptr)
{
pixmap = entityUiHandler->GenerateItemIcon(id);
icon = entityUiHandler->GenerateItemIcon(id);
}
if (!pixmap.isNull())
if (!icon.isNull())
{
return QIcon(pixmap);
return icon;
}
// If no icon was returned by the handler, use the default one.
@@ -299,7 +299,7 @@ namespace AzToolsFramework
if (isEditorOnly)
{
return QIcon(QPixmap(QString(":/Icons/Entity_Editor_Only.svg")));
return QIcon(QString(":/Icons/Entity_Editor_Only.svg"));
}
AZ::Entity* entity = nullptr;
@@ -308,10 +308,10 @@ namespace AzToolsFramework
if (!isInitiallyActive)
{
return QIcon(QPixmap(QString(":/Icons/Entity_Not_Active.svg")));
return QIcon(QString(":/Icons/Entity_Not_Active.svg"));
}
return QIcon(QPixmap(QString(":/Icons/Entity.svg")));
return QIcon(QString(":/Icons/Entity.svg"));
}
QVariant EntityOutlinerListModel::GetEntityTooltip(const AZ::EntityId& id) const
@@ -41,9 +41,9 @@ namespace AzToolsFramework
}
}
QPixmap LevelRootUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const
QIcon LevelRootUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const
{
return QPixmap(m_levelRootIconPath);
return QIcon(m_levelRootIconPath);
}
QString LevelRootUiHandler::GenerateItemInfoString(AZ::EntityId entityId) const
@@ -29,7 +29,7 @@ namespace AzToolsFramework
~LevelRootUiHandler() override = default;
// EditorEntityUiHandler...
QPixmap GenerateItemIcon(AZ::EntityId entityId) const override;
QIcon GenerateItemIcon(AZ::EntityId entityId) const override;
QString GenerateItemInfoString(AZ::EntityId entityId) const override;
bool CanToggleLockVisibility(AZ::EntityId entityId) const override;
bool CanRename(AZ::EntityId entityId) const override;
@@ -81,14 +81,14 @@ namespace AzToolsFramework
return tooltip;
}
QPixmap PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const
QIcon PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const
{
if (m_prefabEditInterface->IsOwningPrefabBeingEdited(entityId))
{
return QPixmap(m_prefabEditIconPath);
return QIcon(m_prefabEditIconPath);
}
return QPixmap(m_prefabIconPath);
return QIcon(m_prefabIconPath);
}
void PrefabUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
@@ -31,7 +31,7 @@ namespace AzToolsFramework
// EditorEntityUiHandler...
QString GenerateItemInfoString(AZ::EntityId entityId) const override;
QString GenerateItemTooltip(AZ::EntityId entityId) const override;
QPixmap GenerateItemIcon(AZ::EntityId entityId) const override;
QIcon GenerateItemIcon(AZ::EntityId entityId) const override;
void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
void PaintDescendantBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index,
const QModelIndex& descendantIndex) const override;
@@ -221,24 +221,6 @@ namespace AzToolsFramework
using ViewportSettingsNotificationBus = AZ::EBus<ViewportSettingNotifications, ViewportEBusTraits>;
//! Requests to freeze the Viewport Input
//! Added to prevent a bug with the legacy CryEngine Viewport code that would
//! keep doing raycast tests even when no level is loaded, causing a crash.
class ViewportFreezeRequests
{
public:
//! Return if Viewport Input is frozen
virtual bool IsViewportInputFrozen() = 0;
//! Sets the Viewport Input freeze state
virtual void FreezeViewportInput(bool freeze) = 0;
protected:
~ViewportFreezeRequests() = default;
};
//! Type to inherit to implement ViewportFreezeRequests.
using ViewportFreezeRequestBus = AZ::EBus<ViewportFreezeRequests, ViewportEBusTraits>;
//! Viewport requests that are only guaranteed to be serviced by the Main Editor viewport.
class MainEditorViewportInteractionRequests
{
@@ -207,6 +207,7 @@ namespace AzToolsFramework
void SetSelectedEntities(const EntityIdList& entityIds);
void DeselectEntities();
bool SelectDeselect(AZ::EntityId entityId);
void ChangeSelectedEntity(AZ::EntityId entityId);
void RefreshSelectedEntityIds();
void RefreshSelectedEntityIds(const EntityIdList& selectedEntityIds);
@@ -298,6 +299,11 @@ namespace AzToolsFramework
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation);
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Quaternion& localRotation);
bool PerformGroupDitto(AZ::EntityId entityId);
bool PerformIndividualDitto(AZ::EntityId entityId);
void PerformManipulatorDitto(AZ::EntityId entityId);
void PerformSnapToTerrain(const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
//! Responsible for keeping the space cluster in sync with the current reference frame.
void UpdateSpaceCluster(ReferenceFrame referenceFrame);
@@ -614,7 +614,7 @@ namespace UnitTest
using EditorTransformComponentSelectionViewportPickingManipulatorTestFixture =
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionViewportPickingFixture>;
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickWithNoSelectionWillSelectEntity)
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickySingleClickWithNoSelectionWillSelectEntity)
{
AzToolsFramework::ed_viewportStickySelect = true;
@@ -637,19 +637,44 @@ namespace UnitTest
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickOffEntityWithSelectionWillNotDeselectEntity)
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickySingleClickWithNoSelectionWillSelectEntity)
{
AzToolsFramework::ed_viewportStickySelect = false;
PositionEntities();
PositionCamera(m_cameraState);
using ::testing::Eq;
auto selectedEntitiesBefore = SelectedEntities();
EXPECT_TRUE(selectedEntitiesBefore.empty());
// calculate the position in screen space of the initial entity position
const auto entity1ScreenPosition = AzFramework::WorldToScreen(m_entity1WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity1ScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
// entity is selected
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
StickySingleClickOffEntityWithSelectionWillNotDeselectEntity)
{
AzToolsFramework::ed_viewportStickySelect = true;
PositionEntities();
PositionCamera(m_cameraState);
// position in space above the entity
// position in space above the entities
const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the initial position of the entity
// calculate the screen space position of the click
const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState);
// click the empty space in the viewport
@@ -662,9 +687,32 @@ namespace UnitTest
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickySingleClickOffEntityWithSelectionWillDeselectEntity)
{
AzToolsFramework::ed_viewportStickySelect = false;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// position in space above the entities
const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f);
// calculate the screen space position of the click
const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState);
// click the empty space in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDown()->MouseLButtonUp();
// entity was deselected
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_TRUE(selectedEntitiesAfter.empty());
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
SingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity)
StickySingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity)
{
AzToolsFramework::ed_viewportStickySelect = true;
@@ -688,7 +736,31 @@ namespace UnitTest
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
CtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection)
UnstickySingleClickOnNewEntityWithSelectionWillChangeSelectedEntity)
{
AzToolsFramework::ed_viewportStickySelect = false;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
// entity selection was changed
using ::testing::Eq;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId2));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
StickyCtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection)
{
AzToolsFramework::ed_viewportStickySelect = true;
@@ -715,7 +787,34 @@ namespace UnitTest
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
CtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection)
UnstickyCtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection)
{
AzToolsFramework::ed_viewportStickySelect = false;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(entity2ScreenPosition)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
->MouseLButtonUp();
// entity selection was changed (one entity selected to two)
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
StickyCtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection)
{
AzToolsFramework::ed_viewportStickySelect = true;
@@ -740,6 +839,33 @@ namespace UnitTest
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
UnstickyCtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection)
{
AzToolsFramework::ed_viewportStickySelect = false;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2 });
// calculate the position in screen space of the second entity
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(entity2ScreenPosition)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
->MouseLButtonUp();
// entity selection was changed (entity2 was deselected)
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithNoInitialSelectionAddsEntitiesToSelection)
{
AzToolsFramework::ed_viewportStickySelect = true;
@@ -835,6 +961,56 @@ namespace UnitTest
EXPECT_TRUE(selectedEntitiesAfter.empty());
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, StickyDoubleClickWithSelectionWillDeselectEntities)
{
AzToolsFramework::ed_viewportStickySelect = true;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2, m_entityId3 });
using ::testing::UnorderedElementsAre;
auto selectedEntitiesBefore = SelectedEntities();
EXPECT_THAT(selectedEntitiesBefore, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3));
// position in space above the entities
const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f);
// calculate the screen space position of the click
const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState);
// double click to deselect entities
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDoubleClick();
// no entities are selected
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_TRUE(selectedEntitiesAfter.empty());
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, UnstickyUndoOperationForChangeInSelectionIsAtomic)
{
AzToolsFramework::ed_viewportStickySelect = false;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// single click select entity2
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
// undo action
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequestBus::Events::UndoPressed);
// entity1 is selected after undo
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
}
using EditorTransformComponentSelectionManipulatorTestFixture =
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionFixture>;
+6 -5
View File
@@ -232,13 +232,17 @@ namespace
// our frame time to be managed by AzGameFramework::GameApplication
// instead, which probably isn't going to happen anytime soon given
// how many things depend on the ITimer interface).
bool continueRunning = true;
ISystem* system = gEnv ? gEnv->pSystem : nullptr;
while (continueRunning)
while (!gameApplication.WasExitMainLoopRequested())
{
// Pump the system event loop
gameApplication.PumpSystemEventLoopUntilEmpty();
if (gameApplication.WasExitMainLoopRequested())
{
break;
}
// Update the AzFramework system tick bus
gameApplication.TickSystem();
@@ -256,9 +260,6 @@ namespace
{
system->UpdatePostTickBus();
}
// Check for quit requests
continueRunning = !gameApplication.WasExitMainLoopRequested() && continueRunning;
}
}
}
+5
View File
@@ -31,6 +31,11 @@ class AZCoreLogSink
: public AZ::Debug::TraceMessageBus::Handler
{
public:
~AZCoreLogSink()
{
Disconnect();
}
inline static void Connect()
{
GetInstance().m_ignoredAsserts = new IgnoredAssertMap();
@@ -233,6 +233,7 @@ CLevelSystem::CLevelSystem(ISystem* pSystem, const char* levelsFolder)
//------------------------------------------------------------------------
CLevelSystem::~CLevelSystem()
{
UnloadLevel();
}
//------------------------------------------------------------------------
-23
View File
@@ -548,29 +548,6 @@ void CSystem::Quit()
logger->Flush();
}
/*
* TODO: This call to _exit, _Exit, TerminateProcess etc. needs to
* eventually be removed. This causes an extremely early exit before we
* actually perform cleanup. When this gets called most managers are
* simply never deleted and we leave it to the OS to clean up our mess
* which is just really bad practice. However there are LOTS of issues
* with shutdown at the moment. Removing this will simply cause
* a crash when either the Editor or Launcher initiate shutdown. Both
* applications crash differently too. Bugs will be logged about those
* issues.
*/
#if defined(AZ_RESTRICTED_PLATFORM)
#define AZ_RESTRICTED_SECTION SYSTEM_CPP_SECTION_4
#include AZ_RESTRICTED_FILE(System_cpp)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
#elif defined(WIN32) || defined(WIN64)
TerminateProcess(GetCurrentProcess(), m_env.retCode);
#else
exit(m_env.retCode);
#endif
#ifdef WIN32
//Post a WM_QUIT message to the Win32 api which causes the message loop to END
//This is not the same as handling a WM_DESTROY event which destroys a window

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