Merge branch 'development' into cmake/warn_virtual
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -7,8 +7,10 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
Tests that require a GPU in order to run.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -40,6 +42,33 @@ def golden_images_directory():
|
||||
return golden_images_dir
|
||||
|
||||
|
||||
def create_screenshots_archive(screenshot_path):
|
||||
"""
|
||||
Creates a new zip file archive at archive_path containing all files listed within archive_path.
|
||||
:param screenshot_path: location containing the files to archive, the zip archive file will also be saved here.
|
||||
:return: None, but creates a new zip file archive inside path containing all of the files inside archive_path.
|
||||
"""
|
||||
files_to_archive = []
|
||||
|
||||
# Search for .png and .ppm files to add to the zip archive file.
|
||||
for (folder_name, sub_folders, file_names) in os.walk(screenshot_path):
|
||||
for file_name in file_names:
|
||||
if file_name.endswith(".png") or file_name.endswith(".ppm"):
|
||||
file_path = os.path.join(folder_name, file_name)
|
||||
files_to_archive.append(file_path)
|
||||
|
||||
# Setup variables for naming the zip archive file.
|
||||
timestamp = datetime.datetime.now().timestamp()
|
||||
formatted_timestamp = datetime.datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d_%H-%M-%S")
|
||||
screenshots_file = os.path.join(screenshot_path, f'zip_archive_{formatted_timestamp}.zip')
|
||||
|
||||
# Write all of the valid .png and .ppm files to the archive file.
|
||||
with zipfile.ZipFile(screenshots_file, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zip_archive:
|
||||
for file_path in files_to_archive:
|
||||
file_name = os.path.basename(file_path)
|
||||
zip_archive.write(file_path, file_name)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
@pytest.mark.parametrize("launcher_platform", ["windows_editor"])
|
||||
@pytest.mark.parametrize("level", ["auto_test"])
|
||||
@@ -53,8 +82,8 @@ class TestAllComponentsIndepthTests(object):
|
||||
Tests that a basic rendering level setup can be created (lighting, meshes, materials, etc.).
|
||||
"""
|
||||
# Clear existing test screenshots before starting test.
|
||||
test_screenshots = [os.path.join(
|
||||
workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot_name)]
|
||||
screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH)
|
||||
test_screenshots = [os.path.join(screenshot_directory, screenshot_name)]
|
||||
file_system.delete(test_screenshots, True, True)
|
||||
|
||||
golden_images = [os.path.join(golden_images_directory(), screenshot_name)]
|
||||
@@ -86,6 +115,8 @@ class TestAllComponentsIndepthTests(object):
|
||||
for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
|
||||
compare_screenshots(test_screenshot, golden_screenshot)
|
||||
|
||||
create_screenshots_archive(screenshot_directory)
|
||||
|
||||
def test_LightComponent_ScreenshotMatchesGoldenImage(
|
||||
self, request, editor, workspace, project, launcher_platform, level):
|
||||
"""
|
||||
@@ -105,9 +136,10 @@ class TestAllComponentsIndepthTests(object):
|
||||
"SpotLight_5.ppm",
|
||||
"SpotLight_6.ppm",
|
||||
]
|
||||
screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH)
|
||||
test_screenshots = []
|
||||
for screenshot in screenshot_names:
|
||||
screenshot_path = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot)
|
||||
screenshot_path = os.path.join(screenshot_directory, screenshot)
|
||||
test_screenshots.append(screenshot_path)
|
||||
file_system.delete(test_screenshots, True, True)
|
||||
|
||||
@@ -139,6 +171,8 @@ class TestAllComponentsIndepthTests(object):
|
||||
for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
|
||||
compare_screenshots(test_screenshot, golden_screenshot)
|
||||
|
||||
create_screenshots_archive(screenshot_directory)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('rhi', ['dx12', 'vulkan'])
|
||||
@pytest.mark.parametrize("project", ["AutomatedTesting"])
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c1b6f5e409a8358ad95b310473046ce1a2f2aa5f7e05d0c3396044aa52aa7f6d
|
||||
size 9103
|
||||
oid sha256:d674eac2070ed0028ceff1e84692c9cf1f69db2192c2295b6d714670ccd50308
|
||||
size 8936
|
||||
|
||||
+1670
-1426
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a1e648464adab2e7d3218aa61888676f6f016d65bed18c303273986614fe9a7e
|
||||
size 6703
|
||||
oid sha256:982f085cfb17ce957cd1534e89a6fb5c76bcbe6936caec214ecd422b0a5dbe7b
|
||||
size 5214
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+75
-18
@@ -33,6 +33,7 @@ AZ_POP_DISABLE_WARNING
|
||||
#include <QScopedValueRollback>
|
||||
#include <QClipboard>
|
||||
#include <QMenuBar>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
// Aws Native SDK
|
||||
#include <aws/sts/STSClient.h>
|
||||
@@ -716,8 +717,24 @@ void CCryEditApp::OnFileSave()
|
||||
}
|
||||
|
||||
const QScopedValueRollback<bool> rollback(m_savingLevel, true);
|
||||
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
|
||||
GetIEditor()->GetDocument()->DoFileSave();
|
||||
if (!usePrefabSystemForLevels)
|
||||
{
|
||||
GetIEditor()->GetDocument()->DoFileSave();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
auto* prefabIntegrationInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabIntegrationInterface>::Get();
|
||||
AZ_Assert(prefabEditorEntityOwnershipInterface != nullptr, "PrefabEditorEntityOwnershipInterface is not found.");
|
||||
AZ_Assert(prefabIntegrationInterface != nullptr, "PrefabIntegrationInterface is not found.");
|
||||
AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId();
|
||||
prefabIntegrationInterface->ExecuteSavePrefabDialog(rootPrefabTemplateId, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3128,29 +3145,69 @@ bool CCryEditApp::CreateLevel(bool& wasCreateLevelOperationCancelled)
|
||||
bool bIsDocModified = GetIEditor()->GetDocument()->IsModified();
|
||||
if (GetIEditor()->GetDocument()->IsDocumentReady() && bIsDocModified)
|
||||
{
|
||||
QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName());
|
||||
int result = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QObject::tr("Save Level"), str, QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
if (QMessageBox::Yes == result)
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
if (!usePrefabSystemForLevels)
|
||||
{
|
||||
if (!GetIEditor()->GetDocument()->DoFileSave())
|
||||
QString str = QObject::tr("Level %1 has been changed. Save Level?").arg(GetIEditor()->GetGameEngine()->GetLevelName());
|
||||
int result = QMessageBox::question(
|
||||
AzToolsFramework::GetActiveWindow(), QObject::tr("Save Level"), str,
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
if (QMessageBox::Yes == result)
|
||||
{
|
||||
if (!GetIEditor()->GetDocument()->DoFileSave())
|
||||
{
|
||||
// if the file save operation failed, assume that the user was informed of why
|
||||
// already and treat it as a cancel
|
||||
wasCreateLevelOperationCancelled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bIsDocModified = false;
|
||||
}
|
||||
else if (QMessageBox::No == result)
|
||||
{
|
||||
// Set Modified flag to false to prevent show Save unchanged dialog again
|
||||
GetIEditor()->GetDocument()->SetModifiedFlag(false);
|
||||
}
|
||||
else if (QMessageBox::Cancel == result)
|
||||
{
|
||||
// if the file save operation failed, assume that the user was informed of why
|
||||
// already and treat it as a cancel
|
||||
wasCreateLevelOperationCancelled = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
auto* prefabIntegrationInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabIntegrationInterface>::Get();
|
||||
AZ_Assert(prefabEditorEntityOwnershipInterface != nullptr, "PrefabEditorEntityOwnershipInterface is not found.");
|
||||
AZ_Assert(prefabIntegrationInterface != nullptr, "PrefabIntegrationInterface is not found.");
|
||||
|
||||
bIsDocModified = false;
|
||||
}
|
||||
else if (QMessageBox::No == result)
|
||||
{
|
||||
// Set Modified flag to false to prevent show Save unchanged dialog again
|
||||
GetIEditor()->GetDocument()->SetModifiedFlag(false);
|
||||
}
|
||||
else if (QMessageBox::Cancel == result)
|
||||
{
|
||||
wasCreateLevelOperationCancelled = true;
|
||||
return false;
|
||||
if (prefabEditorEntityOwnershipInterface == nullptr || prefabIntegrationInterface == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId();
|
||||
int prefabSaveSelection = prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId);
|
||||
|
||||
// In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here.
|
||||
// For example, QDialog::Rejected(0) is emitted when dialog is closed. But the int value corresponds to
|
||||
// QDialogButtonBox::AcceptRole(0).
|
||||
switch (1 - prefabSaveSelection)
|
||||
{
|
||||
case QDialogButtonBox::AcceptRole:
|
||||
bIsDocModified = false;
|
||||
break;
|
||||
case QDialogButtonBox::RejectRole:
|
||||
wasCreateLevelOperationCancelled = true;
|
||||
return false;
|
||||
case QDialogButtonBox::InvalidRole:
|
||||
// Set Modified flag to false to prevent show Save unchanged dialog again
|
||||
GetIEditor()->GetDocument()->SetModifiedFlag(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+73
-15
@@ -13,6 +13,7 @@
|
||||
|
||||
// Qt
|
||||
#include <QDateTime>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
// AzCore
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
@@ -30,7 +31,6 @@
|
||||
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
|
||||
#include <AzToolsFramework/UI/Layer/NameConflictWarning.hxx>
|
||||
#include <AzToolsFramework/API/EditorLevelNotificationBus.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
|
||||
// Editor
|
||||
#include "Settings.h"
|
||||
@@ -132,6 +132,19 @@ CCryEditDoc::CCryEditDoc()
|
||||
RegisterConsoleVariables();
|
||||
|
||||
MainWindow::instance()->GetActionManager()->RegisterActionHandler(ID_FILE_SAVE_AS, this, &CCryEditDoc::OnFileSaveAs);
|
||||
bool isPrefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(isPrefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (isPrefabSystemEnabled)
|
||||
{
|
||||
m_prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
AZ_Assert(m_prefabSystemComponentInterface, "PrefabSystemComponentInterface is not found.");
|
||||
m_prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
AZ_Assert(m_prefabEditorEntityOwnershipInterface, "PrefabEditorEntityOwnershipInterface is not found.");
|
||||
m_prefabLoaderInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
|
||||
AZ_Assert(m_prefabLoaderInterface, "PrefabLoaderInterface is not found.");
|
||||
m_prefabIntegrationInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabIntegrationInterface>::Get();
|
||||
AZ_Assert(m_prefabIntegrationInterface, "PrefabIntegrationInterface is not found.");
|
||||
}
|
||||
}
|
||||
|
||||
CCryEditDoc::~CCryEditDoc()
|
||||
@@ -664,19 +677,56 @@ bool CCryEditDoc::SaveModified()
|
||||
return true;
|
||||
}
|
||||
|
||||
auto button = QMessageBox::question(AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
switch (button)
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
if (!usePrefabSystemForLevels)
|
||||
{
|
||||
case QMessageBox::Cancel:
|
||||
return false;
|
||||
case QMessageBox::Yes:
|
||||
return DoFileSave();
|
||||
case QMessageBox::No:
|
||||
SetModifiedFlag(false);
|
||||
return true;
|
||||
QMessageBox saveModifiedMessageBox(AzToolsFramework::GetActiveWindow());
|
||||
saveModifiedMessageBox.setText(QString("Save changes to %1?").arg(GetTitle()));
|
||||
saveModifiedMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
saveModifiedMessageBox.setIcon(QMessageBox::Icon::Question);
|
||||
|
||||
auto button = QMessageBox::question(
|
||||
AzToolsFramework::GetActiveWindow(), QString(), tr("Save changes to %1?").arg(GetTitle()),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
switch (button)
|
||||
{
|
||||
case QMessageBox::Cancel:
|
||||
return false;
|
||||
case QMessageBox::Yes:
|
||||
return DoFileSave();
|
||||
case QMessageBox::No:
|
||||
SetModifiedFlag(false);
|
||||
return true;
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
else
|
||||
{
|
||||
AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId = m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId();
|
||||
if (!m_prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int prefabSaveSelection = m_prefabIntegrationInterface->ExecuteClosePrefabDialog(rootPrefabTemplateId);
|
||||
|
||||
// In order to get the accept and reject codes of QDialog and QDialogButtonBox aligned, we do (1-prefabSaveSelection) here.
|
||||
// For example, QDialog::Rejected(0) is emitted when dialog is closed. But the int value corresponds to
|
||||
// QDialogButtonBox::AcceptRole(0).
|
||||
switch (1 - prefabSaveSelection)
|
||||
{
|
||||
case QDialogButtonBox::AcceptRole:
|
||||
return true;
|
||||
case QDialogButtonBox::RejectRole:
|
||||
return false;
|
||||
case QDialogButtonBox::InvalidRole:
|
||||
SetModifiedFlag(false);
|
||||
return true;
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
void CCryEditDoc::OnFileSaveAs()
|
||||
@@ -690,6 +740,15 @@ void CCryEditDoc::OnFileSaveAs()
|
||||
if (OnSaveDocument(levelFileDialog.GetFileName()))
|
||||
{
|
||||
CCryEditApp::instance()->AddToRecentFileList(levelFileDialog.GetFileName());
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
if (usePrefabSystemForLevels)
|
||||
{
|
||||
AzToolsFramework::Prefab::TemplateId rootPrefabTemplateId =
|
||||
m_prefabEditorEntityOwnershipInterface->GetRootPrefabTemplateId();
|
||||
SetModifiedFlag(m_prefabSystemComponentInterface->AreDirtyTemplatesPresent(rootPrefabTemplateId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1238,8 +1297,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
if (prefabEditorEntityOwnershipInterface)
|
||||
if (m_prefabEditorEntityOwnershipInterface)
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(fileIO, "No File IO implementation available");
|
||||
@@ -1250,7 +1308,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
|
||||
if (openResult)
|
||||
{
|
||||
AZ::IO::FileIOStream stream(tempSaveFileHandle, AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary, false);
|
||||
contentsAllSaved = prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size()));
|
||||
contentsAllSaved = m_prefabEditorEntityOwnershipInterface->SaveToStream(stream, AZStd::string_view(filenameStrData.data(), filenameStrData.size()));
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,13 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "DocMultiArchive.h"
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <AzToolsFramework/Entity/SliceEditorEntityOwnershipServiceBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzQtComponents/Components/Widgets/Card.h>
|
||||
#include <TimeValue.h>
|
||||
#include <IEditor.h>
|
||||
#endif
|
||||
@@ -207,6 +212,10 @@ protected:
|
||||
const char* m_envProbeSliceRelativePath = "EngineAssets/Slices/DefaultLevelSetup.slice";
|
||||
const float m_envProbeHeight = 200.0f;
|
||||
bool m_hasErrors = false; ///< This is used to warn the user that they may lose work when they go to save.
|
||||
AzToolsFramework::Prefab::PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr;
|
||||
AzToolsFramework::PrefabEditorEntityOwnershipInterface* m_prefabEditorEntityOwnershipInterface = nullptr;
|
||||
AzToolsFramework::Prefab::PrefabLoaderInterface* m_prefabLoaderInterface = nullptr;
|
||||
AzToolsFramework::Prefab::PrefabIntegrationInterface* m_prefabIntegrationInterface = nullptr;
|
||||
};
|
||||
|
||||
class CAutoDocNotReady
|
||||
|
||||
@@ -42,6 +42,10 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
|
||||
->Field("EnableSceneInspector", &GeneralSettings::m_enableSceneInspector)
|
||||
->Field("RestoreViewportCamera", &GeneralSettings::m_restoreViewportCamera);
|
||||
|
||||
serialize.Class<LevelSaveSettings>()
|
||||
->Version(1)
|
||||
->Field("SaveAllPrefabsPreference", &LevelSaveSettings::m_saveAllPrefabsPreference);
|
||||
|
||||
serialize.Class<Messaging>()
|
||||
->Version(2)
|
||||
->Field("ShowDashboard", &Messaging::m_showDashboard)
|
||||
@@ -64,6 +68,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
|
||||
serialize.Class<CEditorPreferencesPage_General>()
|
||||
->Version(1)
|
||||
->Field("General Settings", &CEditorPreferencesPage_General::m_generalSettings)
|
||||
->Field("Level Save Settings", &CEditorPreferencesPage_General::m_levelSaveSettings)
|
||||
->Field("Messaging", &CEditorPreferencesPage_General::m_messaging)
|
||||
->Field("Undo", &CEditorPreferencesPage_General::m_undo)
|
||||
->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection)
|
||||
@@ -92,6 +97,14 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
|
||||
->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_restoreViewportCamera, EditorPreferencesGeneralRestoreViewportCameraSettingName, "Keep the original editor viewport transform when exiting game mode.")
|
||||
->DataElement(AZ::Edit::UIHandlers::CheckBox, &GeneralSettings::m_enableSceneInspector, "Enable Scene Inspector (EXPERIMENTAL)", "Enable the option to inspect the internal data loaded from scene files like .fbx. This is an experimental feature. Restart the Scene Settings if the option is not visible under the Help menu.");
|
||||
|
||||
editContext->Class<LevelSaveSettings>("Level Save Settings", "")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &LevelSaveSettings::m_saveAllPrefabsPreference, "Save All Prefabs Preference",
|
||||
"This option controls whether prefabs should be saved along with the level")
|
||||
->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime, "Ask every time")
|
||||
->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::SaveAll, "Save all")
|
||||
->EnumAttribute(AzToolsFramework::Prefab::SaveAllPrefabsPreference::SaveNone, "Save none");
|
||||
|
||||
editContext->Class<Messaging>("Messaging", "")
|
||||
->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showDashboard, "Show Welcome to Open 3D Engine at startup", "Show Welcome to Open 3D Engine at startup")
|
||||
->DataElement(AZ::Edit::UIHandlers::CheckBox, &Messaging::m_showCircularDependencyError, "Show Error: Circular dependency", "Show an error message when adding a slice instance to the target slice would create a cyclic asset dependency. All other valid overrides will be saved even if this is turned off.");
|
||||
@@ -115,6 +128,7 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize)
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_generalSettings, "General Settings", "General Editor Preferences")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_levelSaveSettings, "Level Save Settings", "File>Save")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection")
|
||||
@@ -161,6 +175,9 @@ void CEditorPreferencesPage_General::OnApply()
|
||||
MainWindow::instance()->AdjustToolBarIconSize(m_generalSettings.m_toolbarIconSize);
|
||||
}
|
||||
|
||||
//prefabs
|
||||
gSettings.levelSaveSettings.saveAllPrefabsPreference = m_levelSaveSettings.m_saveAllPrefabsPreference;
|
||||
|
||||
//undo
|
||||
gSettings.undoLevels = m_undo.m_undoLevels;
|
||||
|
||||
@@ -190,6 +207,9 @@ void CEditorPreferencesPage_General::InitializeSettings()
|
||||
|
||||
m_generalSettings.m_toolbarIconSize = static_cast<AzQtComponents::ToolBar::ToolBarIconSize>(gSettings.gui.nToolbarIconSize);
|
||||
|
||||
//prefabs
|
||||
m_levelSaveSettings.m_saveAllPrefabsPreference = gSettings.levelSaveSettings.saveAllPrefabsPreference;
|
||||
|
||||
//Messaging
|
||||
m_messaging.m_showDashboard = gSettings.bShowDashboardAtStartup;
|
||||
m_messaging.m_showCircularDependencyError = gSettings.m_showCircularDependencyError;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzQtComponents/Components/Widgets/ToolBar.h>
|
||||
#include <AzToolsFramework/Editor/EditorSettingsAPIBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
||||
#include <QIcon>
|
||||
|
||||
#include "Settings.h"
|
||||
@@ -57,6 +58,12 @@ private:
|
||||
bool m_enableSceneInspector;
|
||||
};
|
||||
|
||||
struct LevelSaveSettings
|
||||
{
|
||||
AZ_TYPE_INFO(LevelSaveSettings, "{E297DAE3-3985-4BC2-8B43-45F3B1522F6B}");
|
||||
AzToolsFramework::Prefab::SaveAllPrefabsPreference m_saveAllPrefabsPreference;
|
||||
};
|
||||
|
||||
struct Messaging
|
||||
{
|
||||
AZ_TYPE_INFO(Messaging, "{A6AD87CB-E905-409B-A2BF-C43CDCE63B0C}")
|
||||
@@ -89,6 +96,7 @@ private:
|
||||
};
|
||||
|
||||
GeneralSettings m_generalSettings;
|
||||
LevelSaveSettings m_levelSaveSettings;
|
||||
Messaging m_messaging;
|
||||
Undo m_undo;
|
||||
DeepSelection m_deepSelection;
|
||||
|
||||
@@ -1087,6 +1087,7 @@ void EditorViewportWidget::ConnectViewportInteractionRequestBus()
|
||||
{
|
||||
AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusConnect(GetViewportId());
|
||||
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId());
|
||||
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(GetViewportId());
|
||||
m_viewportUi.ConnectViewportUiBus(GetViewportId());
|
||||
|
||||
AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusConnect();
|
||||
@@ -1097,6 +1098,7 @@ void EditorViewportWidget::DisconnectViewportInteractionRequestBus()
|
||||
AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusDisconnect();
|
||||
|
||||
m_viewportUi.DisconnectViewportUiBus();
|
||||
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ class SANDBOX_API EditorViewportWidget final
|
||||
, private AzFramework::InputSystemCursorConstraintRequestBus::Handler
|
||||
, private AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler
|
||||
, private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler
|
||||
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
, private AZ::RPI::SceneNotificationBus::Handler
|
||||
{
|
||||
@@ -128,10 +129,12 @@ private:
|
||||
CameraComponent,
|
||||
ViewSourceTypesCount,
|
||||
};
|
||||
|
||||
enum class PlayInEditorState
|
||||
{
|
||||
Editor, Starting, Started
|
||||
};
|
||||
|
||||
enum class KeyPressedState
|
||||
{
|
||||
AllUp,
|
||||
@@ -142,7 +145,7 @@ private:
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Method overrides ...
|
||||
|
||||
// QWidget
|
||||
// QWidget overrides ...
|
||||
void focusOutEvent(QFocusEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
bool event(QEvent* event) override;
|
||||
@@ -150,7 +153,7 @@ private:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
|
||||
// QtViewport/IDisplayViewport/CViewport
|
||||
// QtViewport/IDisplayViewport/CViewport overrides ...
|
||||
EViewportType GetType() const override { return ET_ViewportCamera; }
|
||||
void SetType([[maybe_unused]] EViewportType type) override { assert(type == ET_ViewportCamera); };
|
||||
AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction(
|
||||
@@ -176,16 +179,17 @@ private:
|
||||
void Update() override;
|
||||
void UpdateContent(int flags) override;
|
||||
|
||||
// SceneNotificationBus
|
||||
// SceneNotificationBus overrides ...
|
||||
void OnBeginPrepareRender() override;
|
||||
|
||||
// Camera::CameraNotificationBus
|
||||
// Camera::CameraNotificationBus overrides ...
|
||||
void OnActiveViewChanged(const AZ::EntityId&) override;
|
||||
|
||||
// IEditorEventListener
|
||||
// IEditorEventListener overrides ...
|
||||
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
|
||||
|
||||
// AzToolsFramework::EditorEntityContextNotificationBus (handler moved to cpp to resolve link issues in unity builds)
|
||||
// AzToolsFramework::EditorEntityContextNotificationBus overrides ...
|
||||
// note: handler moved to cpp to resolve link issues in unity builds
|
||||
void OnStartPlayInEditor();
|
||||
void OnStopPlayInEditor();
|
||||
void OnStartPlayInEditorBegin();
|
||||
@@ -194,10 +198,10 @@ private:
|
||||
void BeginUndoTransaction() override;
|
||||
void EndUndoTransaction() override;
|
||||
|
||||
// AzFramework::InputSystemCursorConstraintRequestBus
|
||||
// AzFramework::InputSystemCursorConstraintRequestBus overrides ...
|
||||
void* GetSystemCursorConstraintWindow() const override;
|
||||
|
||||
// AzToolsFramework::ViewportFreezeRequestBus
|
||||
// AzToolsFramework::ViewportFreezeRequestBus overrides ...
|
||||
bool IsViewportInputFrozen() override;
|
||||
void FreezeViewportInput(bool freeze) override;
|
||||
|
||||
@@ -205,13 +209,15 @@ private:
|
||||
AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) override;
|
||||
AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) override;
|
||||
float TerrainHeight(const AZ::Vector2& position) override;
|
||||
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntitiesOut) override;
|
||||
bool ShowingWorldSpace() override;
|
||||
QWidget* GetWidgetForViewportContextMenu() override;
|
||||
void BeginWidgetContext() override;
|
||||
void EndWidgetContext() override;
|
||||
|
||||
// Camera::EditorCameraRequestBus
|
||||
// EditorEntityViewportInteractionRequestBus overrides ...
|
||||
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override;
|
||||
|
||||
// Camera::EditorCameraRequestBus overrides ...
|
||||
void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override;
|
||||
void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override;
|
||||
AZ::EntityId GetCurrentViewEntityId() override;
|
||||
@@ -327,7 +333,7 @@ private:
|
||||
// Determines also if the current camera for this viewport is default editor camera
|
||||
ViewSourceType m_viewSourceType = ViewSourceType::None;
|
||||
|
||||
// During play game in editor, holds the editor entity ID of the last
|
||||
// During play game in editor, holds the editor entity ID of the last
|
||||
AZ::EntityId m_viewEntityIdCachedForEditMode;
|
||||
|
||||
// The editor camera TM before switching to game mode
|
||||
|
||||
@@ -27,7 +27,6 @@ enum ObjectEvent
|
||||
EVENT_OUTOFGAME, //!< Signals that editor is switching out of the game mode.
|
||||
EVENT_REFRESH, //!< Signals that editor is refreshing level.
|
||||
EVENT_DBLCLICK, //!< Signals that object have been double clicked.
|
||||
EVENT_KEEP_HEIGHT, //!< Signals that object must preserve its height over changed terrain.
|
||||
EVENT_RELOAD_ENTITY,//!< Signals that entities scripts must be reloaded.
|
||||
EVENT_RELOAD_GEOM, //!< Signals that all possible geometries should be reloaded.
|
||||
EVENT_UNLOAD_GEOM, //!< Signals that all possible geometries should be unloaded.
|
||||
|
||||
@@ -618,12 +618,6 @@ bool CBaseObject::SetPos(const Vec3& pos, int flags)
|
||||
StoreUndo("Position", true, flags);
|
||||
}
|
||||
|
||||
float terrainElevation = AzFramework::Terrain::TerrainDataRequests::GetDefaultTerrainHeight();
|
||||
AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult(terrainElevation
|
||||
, &AzFramework::Terrain::TerrainDataRequests::GetHeightFromFloats
|
||||
, pos.x, pos.y, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR, nullptr);
|
||||
m_height = pos.z - terrainElevation;
|
||||
|
||||
if (!bPositionDelegated)
|
||||
{
|
||||
m_pos = pos;
|
||||
@@ -1275,14 +1269,6 @@ void CBaseObject::OnEvent(ObjectEvent event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case EVENT_KEEP_HEIGHT:
|
||||
{
|
||||
float h = m_height;
|
||||
float newz = GetIEditor()->GetTerrainElevation(m_pos.x, m_pos.y) + m_height;
|
||||
SetPos(Vec3(m_pos.x, m_pos.y, newz));
|
||||
m_height = h;
|
||||
}
|
||||
break;
|
||||
case EVENT_CONFIG_SPEC_CHANGE:
|
||||
UpdateVisibility(!IsHidden());
|
||||
break;
|
||||
|
||||
@@ -795,8 +795,6 @@ private:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Area radius around object, where terrain is flatten and static objects removed.
|
||||
float m_flattenArea;
|
||||
//! Every object keeps for itself height above terrain.
|
||||
float m_height;
|
||||
//! Object's name.
|
||||
QString m_name;
|
||||
//! Class description for this object.
|
||||
|
||||
@@ -241,6 +241,7 @@ SEditorSettings::SEditorSettings()
|
||||
g_TemporaryLevelName = nullptr;
|
||||
|
||||
sliceSettings.dynamicByDefault = false;
|
||||
levelSaveSettings.saveAllPrefabsPreference = AzToolsFramework::Prefab::SaveAllPrefabsPreference::AskEveryTime;
|
||||
}
|
||||
|
||||
void SEditorSettings::Connect()
|
||||
@@ -643,12 +644,20 @@ void SEditorSettings::Save()
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(
|
||||
&AzFramework::ApplicationRequests::SetPrefabSystemEnabled, prefabSystem);
|
||||
|
||||
AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface =
|
||||
AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
|
||||
prefabLoaderInterface->SetSaveAllPrefabsPreference(levelSaveSettings.saveAllPrefabsPreference);
|
||||
|
||||
SaveSettingsRegistryFile();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void SEditorSettings::Load()
|
||||
{
|
||||
AzToolsFramework::Prefab::PrefabLoaderInterface* prefabLoaderInterface =
|
||||
AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
|
||||
levelSaveSettings.saveAllPrefabsPreference = prefabLoaderInterface->GetSaveAllPrefabsPreference();
|
||||
|
||||
// Load from Settings Registry
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
prefabSystem, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
@@ -1110,11 +1119,17 @@ void SEditorSettings::SaveSettingsRegistryFile()
|
||||
|
||||
AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings;
|
||||
dumperSettings.m_prettifyOutput = true;
|
||||
dumperSettings.m_jsonPointerPrefix = "/Amazon/Preferences";
|
||||
dumperSettings.m_includeFilter = [](AZStd::string_view path)
|
||||
{
|
||||
AZStd::string_view amazonPrefixPath("/Amazon/Preferences");
|
||||
AZStd::string_view o3dePrefixPath("/O3DE/Preferences");
|
||||
return amazonPrefixPath.starts_with(path.substr(0, amazonPrefixPath.size())) ||
|
||||
o3dePrefixPath.starts_with(path.substr(0, o3dePrefixPath.size()));
|
||||
};
|
||||
|
||||
AZStd::string stringBuffer;
|
||||
AZ::IO::ByteContainerStream stringStream(&stringBuffer);
|
||||
if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "/Amazon/Preferences", stringStream, dumperSettings))
|
||||
if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(*registry, "", stringStream, dumperSettings))
|
||||
{
|
||||
AZ_Warning("SEditorSettings", false, R"(Unable to save changes to the Editor Preferences registry file at "%s"\n)",
|
||||
editorPreferencesFilePath.c_str());
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <QSettings>
|
||||
|
||||
#include <AzToolsFramework/Editor/EditorSettingsAPIBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
||||
#include <AzCore/JSON/document.h>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/ToolBar.h>
|
||||
@@ -214,6 +215,11 @@ struct SSliceSettings
|
||||
bool dynamicByDefault;
|
||||
};
|
||||
|
||||
struct SLevelSaveSettings
|
||||
{
|
||||
AzToolsFramework::Prefab::SaveAllPrefabsPreference saveAllPrefabsPreference;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SAssetBrowserSettings
|
||||
{
|
||||
@@ -448,6 +454,8 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING
|
||||
|
||||
SSliceSettings sliceSettings;
|
||||
|
||||
SLevelSaveSettings levelSaveSettings;
|
||||
|
||||
bool prefabSystem = true; ///< Toggle to enable/disable the Prefab system for level entities.
|
||||
|
||||
private:
|
||||
|
||||
@@ -244,3 +244,41 @@ QTableWidget#recentLevelTable::item {
|
||||
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;
|
||||
}
|
||||
@@ -1092,9 +1092,8 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
|
||||
const int viewportId = GetViewportId();
|
||||
|
||||
AzToolsFramework::EntityIdList visibleEntityIds;
|
||||
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Event(
|
||||
viewportId,
|
||||
&AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequests::FindVisibleEntities,
|
||||
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
|
||||
viewportId, &AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
|
||||
visibleEntityIds);
|
||||
|
||||
// Look through all visible entities to find the closest one to the specified mouse point
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace AZ
|
||||
|
||||
void AssetData::Acquire()
|
||||
{
|
||||
AZ_Assert(m_useCount >= 0, "AssetData has been deleted")
|
||||
AZ_Assert(m_useCount >= 0, "AssetData has been deleted");
|
||||
|
||||
AcquireWeak();
|
||||
++m_useCount;
|
||||
|
||||
@@ -990,7 +990,7 @@ namespace AZ
|
||||
template<class T>
|
||||
u8 Asset<T>::GetFlags() const
|
||||
{
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by GetAutoLoadBehavior")
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by GetAutoLoadBehavior");
|
||||
return static_cast<u8>(m_loadBehavior);
|
||||
}
|
||||
|
||||
@@ -1012,7 +1012,7 @@ namespace AZ
|
||||
template<class T>
|
||||
bool Asset<T>::SetFlags(u8 flags)
|
||||
{
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by SetAutoLoadBehavior")
|
||||
AZ_Warning("Asset", false, "Deprecated - replaced by SetAutoLoadBehavior");
|
||||
if (!m_assetData)
|
||||
{
|
||||
AZ_Assert(flags < static_cast<u8>(AssetLoadBehavior::Count), "Flags value is out of range");
|
||||
|
||||
@@ -2132,7 +2132,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("AssetManager", false, "Couldn't find handler for asset %s (%s)", asset.GetId().ToString<AZStd::string>().c_str(), asset.GetHint().c_str())
|
||||
AZ_Warning("AssetManager", false, "Couldn't find handler for asset %s (%s)", asset.GetId().ToString<AZStd::string>().c_str(), asset.GetHint().c_str());
|
||||
}
|
||||
|
||||
// Notify any dependent jobs.
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#define AZ_VA_HAS_ARGS(...) ""#__VA_ARGS__[0] != 0
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -262,17 +261,18 @@ namespace AZ
|
||||
#define AZ_VerifyWarning(window, expression, ...) AZ_Warning(window, 0 != (expression), __VA_ARGS__)
|
||||
|
||||
#else // !AZ_ENABLE_TRACING
|
||||
#define AZ_Assert(expression, ...)
|
||||
#define AZ_Error(window, expression, ...)
|
||||
#define AZ_ErrorOnce(window, expression, ...)
|
||||
#define AZ_Warning(window, expression, ...)
|
||||
#define AZ_WarningOnce(window, expression, ...)
|
||||
#define AZ_TracePrintf(window, ...)
|
||||
#define AZ_TracePrintfOnce(window, ...)
|
||||
|
||||
#define AZ_Verify(expression, ...) (void)(expression)
|
||||
#define AZ_VerifyError(window, expression, ...) (void)(expression)
|
||||
#define AZ_VerifyWarning(window, expression, ...) (void)(expression)
|
||||
#define AZ_Assert(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_Error(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_ErrorOnce(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_Warning(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_WarningOnce(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_TracePrintf(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_TracePrintfOnce(...) AZ_UNUSED(__VA_ARGS__);
|
||||
|
||||
#define AZ_Verify(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_VerifyError(...) AZ_UNUSED(__VA_ARGS__);
|
||||
#define AZ_VerifyWarning(...) AZ_UNUSED(__VA_ARGS__);
|
||||
|
||||
#endif // AZ_ENABLE_TRACING
|
||||
|
||||
|
||||
@@ -693,7 +693,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(m_isPooledString == false && m_isPooledStringCrc32 == false, "This stream requires using of a string pool as the string is send only once and afterwards only the Crc32 is used!")
|
||||
AZ_Assert(m_isPooledString == false && m_isPooledStringCrc32 == false, "This stream requires using of a string pool as the string is send only once and afterwards only the Crc32 is used!");
|
||||
}
|
||||
return srcData;
|
||||
}
|
||||
|
||||
@@ -150,9 +150,7 @@ namespace AZ::IO::IStreamerTypes
|
||||
|
||||
private:
|
||||
AZStd::atomic_int m_lockCounter{ 0 };
|
||||
#ifdef AZ_ENABLE_TRACING
|
||||
AZStd::atomic_int m_allocationCounter{ 0 };
|
||||
#endif
|
||||
AZ::IAllocatorAllocate& m_allocator;
|
||||
};
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace AZ
|
||||
|
||||
int AddRefCount(int value)
|
||||
{
|
||||
AZ_Assert(value == 1 || value == -1, "ModRefCount is only for incrementing or decrementing on copy or destruction of ExposedLambda")
|
||||
AZ_Assert(value == 1 || value == -1, "ModRefCount is only for incrementing or decrementing on copy or destruction of ExposedLambda");
|
||||
lua_rawgeti(m_lua, LUA_REGISTRYINDEX, m_refCountRegistryIndex);
|
||||
// Lua: refCount-old
|
||||
const int refCount = Internal::azlua_tointeger(m_lua, -1) + value;
|
||||
|
||||
@@ -240,11 +240,6 @@ namespace AZ
|
||||
{
|
||||
IO::SizeType length = stream.GetLength();
|
||||
|
||||
if (length > AZ::Utils::DefaultMaxFileSize)
|
||||
{
|
||||
return AZ::Failure(AZStd::string{ "Data is too large." });
|
||||
}
|
||||
|
||||
AZStd::vector<char> memoryBuffer;
|
||||
memoryBuffer.resize_no_construct(static_cast<AZStd::vector<char>::size_type>(static_cast<AZStd::vector<char>::size_type>(length) + 1));
|
||||
|
||||
@@ -259,12 +254,12 @@ namespace AZ
|
||||
return ReadJsonString(AZStd::string_view{memoryBuffer.data(), memoryBuffer.size()});
|
||||
}
|
||||
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(AZStd::string_view filePath)
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(AZStd::string_view filePath, size_t maxFileSize)
|
||||
{
|
||||
// Read into memory first and then parse the json, rather than passing a file stream to rapidjson.
|
||||
// This should avoid creating a large number of micro-reads from the file.
|
||||
|
||||
auto readResult = AZ::Utils::ReadFile<AZStd::string>(filePath);
|
||||
auto readResult = AZ::Utils::ReadFile<AZStd::string>(filePath, maxFileSize);
|
||||
if(!readResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(readResult.GetError());
|
||||
@@ -308,6 +303,55 @@ namespace AZ
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStringByType(void* objectToLoad, const Uuid& classId, AZStd::string_view stream,
|
||||
const JsonDeserializerSettings* settings)
|
||||
{
|
||||
JsonDeserializerSettings loadSettings;
|
||||
AZStd::string deserializeErrors;
|
||||
auto prepare = PrepareDeserializerSettings(settings, loadSettings, deserializeErrors);
|
||||
if (!prepare.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(prepare.GetError());
|
||||
}
|
||||
|
||||
auto parseResult = ReadJsonString(stream);
|
||||
if (!parseResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(parseResult.GetError());
|
||||
}
|
||||
|
||||
const rapidjson::Document& jsonDocument = parseResult.GetValue();
|
||||
|
||||
auto validateResult = ValidateJsonClassHeader(jsonDocument);
|
||||
if (!validateResult.IsSuccess())
|
||||
{
|
||||
return AZ::Failure(validateResult.GetError());
|
||||
}
|
||||
|
||||
const char* className = jsonDocument.FindMember(ClassNameTag)->value.GetString();
|
||||
|
||||
// validate class name
|
||||
auto classData = loadSettings.m_serializeContext->FindClassData(classId);
|
||||
if (!classData)
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Try to load class from Id %s", classId.ToString<AZStd::string>().c_str()));
|
||||
}
|
||||
|
||||
if (azstricmp(classData->m_name, className) != 0)
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Try to load class %s from class %s data", classData->m_name, className));
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode result = JsonSerialization::Load(objectToLoad, classId, jsonDocument.FindMember(ClassDataTag)->value, loadSettings);
|
||||
|
||||
if (!WasLoadSuccess(result.GetOutcome()) || !deserializeErrors.empty())
|
||||
{
|
||||
return AZ::Failure(deserializeErrors);
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStreamByType(void* objectToLoad, const Uuid& classId, IO::GenericStream& stream,
|
||||
const JsonDeserializerSettings* settings)
|
||||
{
|
||||
|
||||
@@ -70,13 +70,18 @@ namespace AZ
|
||||
//! Parse json text. Returns a failure with error message if the content is not valid JSON.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonString(AZStd::string_view jsonText);
|
||||
|
||||
//! Parse a json file. Returns a failure with error message if the content is not valid JSON.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(AZStd::string_view filePath);
|
||||
//! Parse a json file. Returns a failure with error message if the content is not valid JSON or if
|
||||
//! the file size is larger than the max file size provided.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonFile(
|
||||
AZStd::string_view filePath, size_t maxFileSize = AZStd::numeric_limits<size_t>::max());
|
||||
|
||||
//! Parse a json stream. Returns a failure with error message if the content is not valid JSON.
|
||||
AZ::Outcome<rapidjson::Document, AZStd::string> ReadJsonStream(IO::GenericStream& stream);
|
||||
|
||||
//! Load object with known class type
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStringByType(void* objectToLoad, const Uuid& objectType, AZStd::string_view source,
|
||||
const JsonDeserializerSettings* settings = nullptr);
|
||||
|
||||
AZ::Outcome<void, AZStd::string> LoadObjectFromStreamByType(void* objectToLoad, const Uuid& objectType, IO::GenericStream& stream,
|
||||
const JsonDeserializerSettings* settings = nullptr);
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
AZ_Assert(!keyValues.Empty(), "Intermediate array for associative container can't be empty "
|
||||
"because an empty array would be stored as an empty default object.")
|
||||
"because an empty array would be stored as an empty default object.");
|
||||
|
||||
if (CanBeConvertedToObject(keyValues))
|
||||
{
|
||||
|
||||
@@ -2300,7 +2300,7 @@ namespace AZ
|
||||
{
|
||||
if (classData->m_converter)
|
||||
{
|
||||
AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported.")
|
||||
AZ_Assert(false, "A deprecated element with a data converter was passed to CloneObject, this is not supported.");
|
||||
}
|
||||
// push a dummy node in the stack
|
||||
cloneData->m_parentStack.push_back();
|
||||
|
||||
@@ -110,12 +110,12 @@ namespace AZ::Internal
|
||||
{
|
||||
FixedValueString engineName;
|
||||
settingsRegistry.Get(engineName, engineMonikerKey);
|
||||
AZ_Warning("SettingsRegistryMergeUtils",engineInfo.m_moniker == engineName,
|
||||
AZ_Warning("SettingsRegistryMergeUtils", engineInfo.m_moniker == engineName,
|
||||
R"(The engine name key "%s" mapped to engine path "%s" within the global manifest of "%s")"
|
||||
R"( does not match the "engine_name" field "%s" in the engine.json)" "\n"
|
||||
"This engine should be re-registered.",
|
||||
engineInfo.m_moniker.c_str(), engineInfo.m_path.c_str(), engineManifestPath.c_str(),
|
||||
engineName.c_str())
|
||||
engineName.c_str());
|
||||
engineInfo.m_moniker = engineName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3464,7 +3464,7 @@ namespace AZ
|
||||
const SliceComponent::DataFlagsPerEntity* SliceComponent::GetCorrectBundleOfDataFlags(EntityId entityId) const
|
||||
{
|
||||
// It would be possible to search non-instantiated slices by crawling over lists, but we haven't needed the capability yet.
|
||||
AZ_Assert(IsInstantiated(), "Data flag access is only permitted after slice is instantiated.")
|
||||
AZ_Assert(IsInstantiated(), "Data flag access is only permitted after slice is instantiated.");
|
||||
|
||||
if (IsInstantiated())
|
||||
{
|
||||
|
||||
@@ -22,10 +22,6 @@ namespace AZ
|
||||
{
|
||||
namespace Utils
|
||||
{
|
||||
//! Protects from allocating too much memory. The choice of a 1MB threshold is arbitrary.
|
||||
//! If you need to work with larger files, please use AZ::IO directly instead of these utility functions.
|
||||
inline constexpr size_t DefaultMaxFileSize = 1024 * 1024;
|
||||
|
||||
//! Terminates the application without going through the shutdown procedure.
|
||||
//! This is used when due to abnormal circumstances the application can no
|
||||
//! longer continue. On most platforms and in most configurations this will
|
||||
@@ -115,6 +111,7 @@ namespace AZ
|
||||
//! Read a file into a string. Returns a failure with error message if the content could not be loaded or if
|
||||
//! the file size is larger than the max file size provided.
|
||||
template<typename Container = AZStd::string>
|
||||
AZ::Outcome<Container, AZStd::string> ReadFile(AZStd::string_view filePath, size_t maxFileSize = DefaultMaxFileSize);
|
||||
AZ::Outcome<Container, AZStd::string> ReadFile(
|
||||
AZStd::string_view filePath, size_t maxFileSize = AZStd::numeric_limits<size_t>::max());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,9 @@
|
||||
* example. AZ_VA_NUM_ARGS(x,y,z) -> expands to 3
|
||||
*/
|
||||
#ifndef AZ_VA_NUM_ARGS
|
||||
|
||||
# define AZ_VA_HAS_ARGS(...) ""#__VA_ARGS__[0] != 0
|
||||
|
||||
// we add the zero to avoid the case when we require at least 1 param at the end...
|
||||
# define AZ_VA_NUM_ARGS(...) AZ_VA_NUM_ARGS_IMPL_((__VA_ARGS__, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
|
||||
# define AZ_VA_NUM_ARGS_IMPL_(tuple) AZ_VA_NUM_ARGS_IMPL tuple
|
||||
@@ -170,15 +173,15 @@
|
||||
// This is a pain they we use macros to call functions (with no params).
|
||||
|
||||
// we implement functions for up to 10 params
|
||||
#define AZ_FUNCTION_CALL_1(_1) _1()
|
||||
#define AZ_FUNCTION_CALL_2(_1, _2) _1(_2)
|
||||
#define AZ_FUNCTION_CALL_3(_1, _2, _3) _1(_2, _3)
|
||||
#define AZ_FUNCTION_CALL_4(_1, _2, _3, _4) _1(_2, _3, _4)
|
||||
#define AZ_FUNCTION_CALL_5(_1, _2, _3, _4, _5) _1(_2, _3, _4, _5)
|
||||
#define AZ_FUNCTION_CALL_6(_1, _2, _3, _4, _5, _6) _1(_2, _3, _4, _5, _6)
|
||||
#define AZ_FUNCTION_CALL_7(_1, _2, _3, _4, _5, _6, _7) _1(_2, _3, _4, _5, _6, _7)
|
||||
#define AZ_FUNCTION_CALL_8(_1, _2, _3, _4, _5, _6, _7, _8) _1(_2, _3, _4, _5, _6, _7, _8)
|
||||
#define AZ_FUNCTION_CALL_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) _1(_2, _3, _4, _5, _6, _7, _8, _9)
|
||||
#define AZ_FUNCTION_CALL_1(_1) _1()
|
||||
#define AZ_FUNCTION_CALL_2(_1, _2) _1(_2)
|
||||
#define AZ_FUNCTION_CALL_3(_1, _2, _3) _1(_2, _3)
|
||||
#define AZ_FUNCTION_CALL_4(_1, _2, _3, _4) _1(_2, _3, _4)
|
||||
#define AZ_FUNCTION_CALL_5(_1, _2, _3, _4, _5) _1(_2, _3, _4, _5)
|
||||
#define AZ_FUNCTION_CALL_6(_1, _2, _3, _4, _5, _6) _1(_2, _3, _4, _5, _6)
|
||||
#define AZ_FUNCTION_CALL_7(_1, _2, _3, _4, _5, _6, _7) _1(_2, _3, _4, _5, _6, _7)
|
||||
#define AZ_FUNCTION_CALL_8(_1, _2, _3, _4, _5, _6, _7, _8) _1(_2, _3, _4, _5, _6, _7, _8)
|
||||
#define AZ_FUNCTION_CALL_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) _1(_2, _3, _4, _5, _6, _7, _8, _9)
|
||||
#define AZ_FUNCTION_CALL_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) _1(_2, _3, _4, _5, _6, _7, _8, _9, _10)
|
||||
|
||||
// We require at least 1 param FunctionName
|
||||
@@ -293,7 +296,20 @@ namespace AZ
|
||||
#define AZ_DEFAULT_COPY_MOVE(_Class) AZ_DEFAULT_COPY(_Class) AZ_DEFAULT_MOVE(_Class)
|
||||
|
||||
// Macro that can be used to avoid unreferenced variable warnings
|
||||
#define AZ_UNUSED(x) (void)x
|
||||
#define AZ_UNUSED_1(x) (void)(x);
|
||||
#define AZ_UNUSED_2(x1, x2) AZ_UNUSED_1(x1) AZ_UNUSED_1(x2)
|
||||
#define AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_1(x1) AZ_UNUSED_2(x2, x3)
|
||||
#define AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_2(x1, x2) AZ_UNUSED_2(x3, x4)
|
||||
#define AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_2(x1, x2) AZ_UNUSED_3(x3, x4, x5)
|
||||
#define AZ_UNUSED_6(x1, x2, x3, x4, x5, x6) AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_3(x4, x5, x6)
|
||||
#define AZ_UNUSED_7(x1, x2, x3, x4, x5, x6, x7) AZ_UNUSED_3(x1, x2, x3) AZ_UNUSED_4(x4, x5, x6, x7)
|
||||
#define AZ_UNUSED_8(x1, x2, x3, x4, x5, x6, x7, x8) AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_4(x5, x6, x7, x8)
|
||||
#define AZ_UNUSED_9(x1, x2, x3, x4, x5, x6, x7, x8, x9) AZ_UNUSED_4(x1, x2, x3, x4) AZ_UNUSED_5(x5, x6, x7, x8, x9)
|
||||
#define AZ_UNUSED_10(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_5(x6, x7, x8, x9, x10)
|
||||
#define AZ_UNUSED_11(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) AZ_UNUSED_5(x1, x2, x3, x4, x5) AZ_UNUSED_6(x6, x7, x8, x9, x10, x11)
|
||||
#define AZ_UNUSED_12(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) AZ_UNUSED_6(x1, x2, x3, x4, x5, x6) AZ_UNUSED_6(x7, x8, x9, x10, x11, x12)
|
||||
|
||||
#define AZ_UNUSED(...) AZ_MACRO_SPECIALIZE(AZ_UNUSED_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
|
||||
|
||||
#define AZ_DEFINE_ENUM_BITWISE_OPERATORS(EnumType) \
|
||||
inline constexpr EnumType operator | (EnumType a, EnumType b) \
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("System", false, "Failed to open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid!")
|
||||
AZ_Error("System", false, "Failed to open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid!");
|
||||
}
|
||||
|
||||
wchar_t* hostname = machineInfo + wcslen(machineInfo);
|
||||
|
||||
@@ -2651,7 +2651,7 @@ namespace UnitTest
|
||||
if (!rootElement.GetChildData(AZ_CRC("InnerBaseStringField"), stringField))
|
||||
{
|
||||
AZ_Error("PatchingTest", false, "Unable to retrieve 'InnerBaseStringField' data for %u version of the InnerObjectFieldConverterClass",
|
||||
rootElement.GetVersion())
|
||||
rootElement.GetVersion());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
|
||||
#include <AzFramework/CommandLine/CommandLine.h>
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Math/Vector4.h>
|
||||
#include <AzCore/Math/Matrix3x4.h>
|
||||
#include <AzCore/Math/Color.h>
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
@@ -100,6 +101,8 @@ namespace AzFramework
|
||||
virtual AZ::u32 SetState(AZ::u32 state) { (void)state; return 0; }
|
||||
virtual void PushMatrix(const AZ::Transform& tm) { (void)tm; }
|
||||
virtual void PopMatrix() {}
|
||||
virtual void PushPremultipliedMatrix(const AZ::Matrix3x4& matrix) { (void)matrix; }
|
||||
virtual AZ::Matrix3x4 PopPremultipliedMatrix() { return AZ::Matrix3x4::CreateIdentity(); }
|
||||
|
||||
protected:
|
||||
virtual ~DebugDisplayRequests() = default;
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace AzFramework
|
||||
AZ_PROFILE_FUNCTION(AzCore);
|
||||
|
||||
auto data = AZStd::get_if<FileRequest::ReadData>(&request->GetCommand());
|
||||
AZ_Assert(data, "Request doing reading in the RemoteStorageDrive didn't contain read data.")
|
||||
AZ_Assert(data, "Request doing reading in the RemoteStorageDrive didn't contain read data.");
|
||||
|
||||
HandleType file = InvalidHandle;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace AzFramework::ProjectManager
|
||||
return ProjectPathCheckResult::ProjectManagerLaunchFailed;
|
||||
}
|
||||
|
||||
bool LaunchProjectManager(const AZStd::string& commandLineArgs)
|
||||
bool LaunchProjectManager([[maybe_unused]]const AZStd::string& commandLineArgs)
|
||||
{
|
||||
bool launchSuccess = false;
|
||||
#if (AZ_TRAIT_AZFRAMEWORK_USE_PROJECT_MANAGER)
|
||||
|
||||
@@ -588,6 +588,12 @@ namespace AzFramework
|
||||
// pass through the camera's position and look vector for use in the lookAt function
|
||||
if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()))
|
||||
{
|
||||
// default to internal look at behavior if the look at point matches the camera translation
|
||||
if (targetCamera.m_lookAt.IsClose(*lookAt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt);
|
||||
nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt);
|
||||
UpdateCameraFromTransform(nextCamera, transform);
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace AzFramework
|
||||
protected:
|
||||
~BoundsRequests() = default;
|
||||
};
|
||||
|
||||
using BoundsRequestBus = AZ::EBus<BoundsRequests>;
|
||||
|
||||
//! Returns a union of all local Aabbs provided by components implementing the BoundsRequestBus.
|
||||
|
||||
+1
@@ -57,6 +57,7 @@ namespace AzFramework
|
||||
|
||||
uint32_t NativeWindowImpl_Android::GetDisplayRefreshRate() const
|
||||
{
|
||||
// [GFX TODO][GHI - 2678]
|
||||
// Using 60 for now until proper support is added
|
||||
return 60;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,29 @@ namespace AzFramework
|
||||
|
||||
using LinuxXcbConnectionManagerBus = AZ::EBus<LinuxXcbConnectionManager, LinuxXcbConnectionManagerBusTraits>;
|
||||
using LinuxXcbConnectionManagerInterface = AZ::Interface<LinuxXcbConnectionManager>;
|
||||
|
||||
class LinuxXcbEventHandler
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(LinuxXcbEventHandler, "{3F756E14-8D74-42FD-843C-4863307710DB}");
|
||||
|
||||
virtual ~LinuxXcbEventHandler() = default;
|
||||
|
||||
virtual void HandleXcbEvent(xcb_generic_event_t* event) = 0;
|
||||
};
|
||||
|
||||
class LinuxXcbEventHandlerBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
using LinuxXcbEventHandlerBus = AZ::EBus<LinuxXcbEventHandler, LinuxXcbEventHandlerBusTraits>;
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
} // namespace AzFramework
|
||||
|
||||
+12
-85
@@ -6,101 +6,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
#include "Application_Linux_xcb.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
class LinuxXcbConnectionManagerImpl
|
||||
: public LinuxXcbConnectionManagerBus::Handler
|
||||
{
|
||||
public:
|
||||
LinuxXcbConnectionManagerImpl()
|
||||
{
|
||||
m_xcbConnection = xcb_connect(nullptr, nullptr);
|
||||
AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
|
||||
LinuxXcbConnectionManagerBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~LinuxXcbConnectionManagerImpl() override
|
||||
{
|
||||
LinuxXcbConnectionManagerBus::Handler::BusDisconnect();
|
||||
xcb_disconnect(m_xcbConnection);
|
||||
}
|
||||
xcb_connection_t* GetXcbConnection() const override
|
||||
{
|
||||
return m_xcbConnection;
|
||||
}
|
||||
private:
|
||||
xcb_connection_t* m_xcbConnection = nullptr;
|
||||
};
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class ApplicationLinux
|
||||
: public Application::Implementation
|
||||
, public LinuxLifecycleEvents::Bus::Handler
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
AZ_CLASS_ALLOCATOR(ApplicationLinux, AZ::SystemAllocator, 0);
|
||||
ApplicationLinux();
|
||||
~ApplicationLinux() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Application::Implementation
|
||||
void PumpSystemEventLoopOnce() override;
|
||||
void PumpSystemEventLoopUntilEmpty() override;
|
||||
private:
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
AZStd::unique_ptr<LinuxXcbConnectionManager> m_xcbConnectionManager;
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Application::Implementation* Application::Implementation::Create()
|
||||
{
|
||||
return aznew ApplicationLinux();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux::ApplicationLinux()
|
||||
{
|
||||
LinuxLifecycleEvents::Bus::Handler::BusConnect();
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
m_xcbConnectionManager = AZStd::make_unique<LinuxXcbConnectionManagerImpl>();
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == nullptr)
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
|
||||
}
|
||||
return aznew ApplicationLinux_xcb();
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB
|
||||
#error "Linux Window Manager XLIB not supported."
|
||||
return nullptr;
|
||||
#else
|
||||
#error "Linux Window Manager not recognized."
|
||||
return nullptr;
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux::~ApplicationLinux()
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
|
||||
}
|
||||
m_xcbConnectionManager.reset();
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
LinuxLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux::PumpSystemEventLoopOnce()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux::PumpSystemEventLoopUntilEmpty()
|
||||
{
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include "Application_Linux_xcb.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class LinuxXcbConnectionManagerImpl
|
||||
: public LinuxXcbConnectionManagerBus::Handler
|
||||
{
|
||||
public:
|
||||
LinuxXcbConnectionManagerImpl()
|
||||
{
|
||||
m_xcbConnection = xcb_connect(nullptr, nullptr);
|
||||
AZ_Error("ApplicationLinux", m_xcbConnection != nullptr, "Unable to connect to X11 Server.");
|
||||
LinuxXcbConnectionManagerBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~LinuxXcbConnectionManagerImpl()
|
||||
{
|
||||
LinuxXcbConnectionManagerBus::Handler::BusDisconnect();
|
||||
xcb_disconnect(m_xcbConnection);
|
||||
}
|
||||
|
||||
xcb_connection_t* GetXcbConnection() const override
|
||||
{
|
||||
return m_xcbConnection;
|
||||
}
|
||||
|
||||
private:
|
||||
xcb_connection_t* m_xcbConnection = nullptr;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux_xcb::ApplicationLinux_xcb()
|
||||
{
|
||||
LinuxLifecycleEvents::Bus::Handler::BusConnect();
|
||||
m_xcbConnectionManager = AZStd::make_unique<LinuxXcbConnectionManagerImpl>();
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == nullptr)
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Register(m_xcbConnectionManager.get());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
ApplicationLinux_xcb::~ApplicationLinux_xcb()
|
||||
{
|
||||
if (LinuxXcbConnectionManagerInterface::Get() == m_xcbConnectionManager.get())
|
||||
{
|
||||
LinuxXcbConnectionManagerInterface::Unregister(m_xcbConnectionManager.get());
|
||||
}
|
||||
m_xcbConnectionManager.reset();
|
||||
LinuxLifecycleEvents::Bus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux_xcb::PumpSystemEventLoopOnce()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
if (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void ApplicationLinux_xcb::PumpSystemEventLoopUntilEmpty()
|
||||
{
|
||||
if (xcb_connection_t* xcbConnection = m_xcbConnectionManager->GetXcbConnection())
|
||||
{
|
||||
while (xcb_generic_event_t* event = xcb_poll_for_event(xcbConnection))
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Broadcast(&LinuxXcbEventHandlerBus::Events::HandleXcbEvent, event);
|
||||
free(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class ApplicationLinux_xcb
|
||||
: public Application::Implementation
|
||||
, public LinuxLifecycleEvents::Bus::Handler
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
AZ_CLASS_ALLOCATOR(ApplicationLinux_xcb, AZ::SystemAllocator, 0);
|
||||
ApplicationLinux_xcb();
|
||||
~ApplicationLinux_xcb() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Application::Implementation
|
||||
void PumpSystemEventLoopOnce() override;
|
||||
void PumpSystemEventLoopUntilEmpty() override;
|
||||
|
||||
private:
|
||||
AZStd::unique_ptr<LinuxXcbConnectionManager> m_xcbConnectionManager;
|
||||
};
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
+12
-36
@@ -6,48 +6,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include "NativeWindow_Linux_xcb.h"
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class NativeWindowImpl_Linux final
|
||||
: public NativeWindow::Implementation
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux, AZ::SystemAllocator, 0);
|
||||
NativeWindowImpl_Linux() = default;
|
||||
~NativeWindowImpl_Linux() override = default;
|
||||
|
||||
// NativeWindow::Implementation overrides...
|
||||
void InitWindow(const AZStd::string& title,
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks) override;
|
||||
NativeWindowHandle GetWindowHandle() const override;
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
};
|
||||
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
{
|
||||
return aznew NativeWindowImpl_Linux();
|
||||
}
|
||||
|
||||
void NativeWindowImpl_Linux::InitWindow([[maybe_unused]]const AZStd::string& title,
|
||||
const WindowGeometry& geometry,
|
||||
[[maybe_unused]]const WindowStyleMasks& styleMasks)
|
||||
{
|
||||
m_width = geometry.m_width;
|
||||
m_height = geometry.m_height;
|
||||
}
|
||||
|
||||
NativeWindowHandle NativeWindowImpl_Linux::GetWindowHandle() const
|
||||
{
|
||||
AZ_Assert(false, "NativeWindow not implemented for Linux");
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
return aznew NativeWindowImpl_Linux_xcb();
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_WAYLAND
|
||||
#error "Linux Window Manager Wayland not supported."
|
||||
return nullptr;
|
||||
#elif PAL_TRAIT_LINUX_WINDOW_MANAGER_XLIB
|
||||
#error "Linux Window Manager XLIB not supported."
|
||||
return nullptr;
|
||||
#else
|
||||
#error "Linux Window Manager not recognized."
|
||||
return nullptr;
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
}
|
||||
|
||||
uint32_t NativeWindowImpl_Linux::GetDisplayRefreshRate() const
|
||||
{
|
||||
//Using 60 for now until proper support is added
|
||||
return 60;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include "NativeWindow_Linux_xcb.h"
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
[[maybe_unused]] const char LinuxXcbErrorWindow[] = "NativeWindow_Linux_xcb";
|
||||
static constexpr uint8_t s_XcbFormatDataSize = 32; // Format indicator for xcb for client messages
|
||||
static constexpr uint16_t s_DefaultXcbWindowBorderWidth = 4; // The default border with in pixels if a border was specified
|
||||
static constexpr uint8_t s_XcbResponseTypeMask = 0x7f; // Mask to extract the specific event type from an xcb event
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowImpl_Linux_xcb::NativeWindowImpl_Linux_xcb()
|
||||
: NativeWindow::Implementation()
|
||||
{
|
||||
if (auto xcbConnectionManager = AzFramework::LinuxXcbConnectionManagerInterface::Get();
|
||||
xcbConnectionManager != nullptr)
|
||||
{
|
||||
m_xcbConnection = xcbConnectionManager->GetXcbConnection();
|
||||
}
|
||||
AZ_Error(LinuxXcbErrorWindow, m_xcbConnection != nullptr, "Unable to get XCB Connection");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowImpl_Linux_xcb::~NativeWindowImpl_Linux_xcb()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::InitWindow(const AZStd::string& title,
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks)
|
||||
{
|
||||
// Get the parent window
|
||||
const xcb_setup_t* xcbSetup = xcb_get_setup(m_xcbConnection);
|
||||
xcb_screen_t* xcbRootScreen = xcb_setup_roots_iterator(xcbSetup).data;
|
||||
xcb_window_t xcbParentWindow = xcbRootScreen->root;
|
||||
|
||||
// Create an XCB window from the connection
|
||||
m_xcbWindow = xcb_generate_id(m_xcbConnection);
|
||||
|
||||
uint16_t borderWidth = 0;
|
||||
const uint32_t mask = styleMasks.m_platformAgnosticStyleMask;
|
||||
if ((mask & WindowStyleMasks::WINDOW_STYLE_BORDERED) ||
|
||||
(mask & WindowStyleMasks::WINDOW_STYLE_RESIZEABLE))
|
||||
{
|
||||
borderWidth = s_DefaultXcbWindowBorderWidth;
|
||||
}
|
||||
|
||||
uint32_t eventMask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
||||
|
||||
uint32_t valueList[] = { xcbRootScreen->black_pixel,
|
||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY };
|
||||
|
||||
xcb_void_cookie_t xcbCheckResult;
|
||||
|
||||
xcbCheckResult = xcb_create_window_checked(m_xcbConnection,
|
||||
XCB_COPY_FROM_PARENT,
|
||||
m_xcbWindow,
|
||||
xcbParentWindow,
|
||||
aznumeric_cast<int16_t>(geometry.m_posX),
|
||||
aznumeric_cast<int16_t>(geometry.m_posY),
|
||||
aznumeric_cast<int16_t>(geometry.m_width),
|
||||
aznumeric_cast<int16_t>(geometry.m_height),
|
||||
borderWidth,
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||
xcbRootScreen->root_visual,
|
||||
eventMask,
|
||||
valueList);
|
||||
|
||||
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to create xcb window.");
|
||||
|
||||
SetWindowTitle(title);
|
||||
|
||||
// Setup the window close event
|
||||
const static char* wmProtocolString = "WM_PROTOCOLS";
|
||||
|
||||
xcb_intern_atom_cookie_t cookieProtocol = xcb_intern_atom(m_xcbConnection, 1, strlen(wmProtocolString), wmProtocolString);
|
||||
xcb_intern_atom_reply_t* replyProtocol = xcb_intern_atom_reply(m_xcbConnection, cookieProtocol, nullptr);
|
||||
AZ_Error(LinuxXcbErrorWindow, replyProtocol != nullptr, "Unable to query xcb '%s' atom", wmProtocolString);
|
||||
m_xcbAtomProtocols = replyProtocol->atom;
|
||||
|
||||
const static char* wmDeleteWindowString = "WM_DELETE_WINDOW";
|
||||
xcb_intern_atom_cookie_t cookieDeleteWindow = xcb_intern_atom(m_xcbConnection, 0, strlen(wmDeleteWindowString), wmDeleteWindowString);
|
||||
xcb_intern_atom_reply_t* replyDeleteWindow = xcb_intern_atom_reply(m_xcbConnection, cookieDeleteWindow, nullptr);
|
||||
AZ_Error(LinuxXcbErrorWindow, replyDeleteWindow != nullptr, "Unable to query xcb '%s' atom", wmDeleteWindowString);
|
||||
m_xcbAtomDeleteWindow = replyDeleteWindow->atom;
|
||||
|
||||
xcbCheckResult = xcb_change_property_checked(m_xcbConnection,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
m_xcbWindow,
|
||||
m_xcbAtomProtocols,
|
||||
XCB_ATOM_ATOM,
|
||||
s_XcbFormatDataSize,
|
||||
1,
|
||||
&m_xcbAtomDeleteWindow);
|
||||
|
||||
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to change the xcb atom property for WM_CLOSE event");
|
||||
|
||||
m_width = geometry.m_width;
|
||||
m_height = geometry.m_height;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::Activate()
|
||||
{
|
||||
LinuxXcbEventHandlerBus::Handler::BusConnect();
|
||||
|
||||
if (!m_activated) // nothing to do if window was already activated
|
||||
{
|
||||
m_activated = true;
|
||||
|
||||
xcb_map_window(m_xcbConnection, m_xcbWindow);
|
||||
xcb_flush(m_xcbConnection);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::Deactivate()
|
||||
{
|
||||
if (m_activated) // nothing to do if window was already deactivated
|
||||
{
|
||||
m_activated = false;
|
||||
|
||||
WindowNotificationBus::Event(reinterpret_cast<NativeWindowHandle>(m_xcbWindow), &WindowNotificationBus::Events::OnWindowClosed);
|
||||
|
||||
xcb_unmap_window(m_xcbConnection, m_xcbWindow);
|
||||
xcb_flush(m_xcbConnection);
|
||||
}
|
||||
LinuxXcbEventHandlerBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
NativeWindowHandle NativeWindowImpl_Linux_xcb::GetWindowHandle() const
|
||||
{
|
||||
return reinterpret_cast<NativeWindowHandle>(m_xcbWindow);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::SetWindowTitle(const AZStd::string& title)
|
||||
{
|
||||
xcb_void_cookie_t xcbCheckResult;
|
||||
xcbCheckResult = xcb_change_property(m_xcbConnection,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
m_xcbWindow,
|
||||
XCB_ATOM_WM_NAME,
|
||||
XCB_ATOM_STRING,
|
||||
8,
|
||||
static_cast<uint32_t>(title.size()),
|
||||
title.c_str());
|
||||
AZ_Assert(ValidateXcbResult(xcbCheckResult), "Failed to set window title.");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::ResizeClientArea(WindowSize clientAreaSize)
|
||||
{
|
||||
const uint32_t values[] = { clientAreaSize.m_width, clientAreaSize.m_height };
|
||||
|
||||
xcb_configure_window(m_xcbConnection, m_xcbWindow, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
|
||||
|
||||
m_width = clientAreaSize.m_width;
|
||||
m_height = clientAreaSize.m_height;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
uint32_t NativeWindowImpl_Linux_xcb::GetDisplayRefreshRate() const
|
||||
{
|
||||
// [GFX TODO][GHI - 2678]
|
||||
// Using 60 for now until proper support is added
|
||||
return 60;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool NativeWindowImpl_Linux_xcb::ValidateXcbResult(xcb_void_cookie_t cookie)
|
||||
{
|
||||
bool result = true;
|
||||
if (xcb_generic_error_t* error = xcb_request_check(m_xcbConnection, cookie))
|
||||
{
|
||||
AZ_TracePrintf("Error","Error code %d", error->error_code);
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::HandleXcbEvent(xcb_generic_event_t* event)
|
||||
{
|
||||
switch (event->response_type & s_XcbResponseTypeMask)
|
||||
{
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
{
|
||||
xcb_configure_notify_event_t* cne = reinterpret_cast<xcb_configure_notify_event_t*>(event);
|
||||
WindowSizeChanged(aznumeric_cast<uint32_t>(cne->width),
|
||||
aznumeric_cast<uint32_t>(cne->height));
|
||||
|
||||
break;
|
||||
}
|
||||
case XCB_CLIENT_MESSAGE:
|
||||
{
|
||||
xcb_client_message_event_t* cme = reinterpret_cast<xcb_client_message_event_t*>(event);
|
||||
if ((cme->type == m_xcbAtomProtocols) &&
|
||||
(cme->format == s_XcbFormatDataSize) &&
|
||||
(cme->data.data32[0] == m_xcbAtomDeleteWindow))
|
||||
{
|
||||
Deactivate();
|
||||
|
||||
ApplicationRequests::Bus::Broadcast(&ApplicationRequests::ExitMainLoop);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void NativeWindowImpl_Linux_xcb::WindowSizeChanged(const uint32_t width, const uint32_t height)
|
||||
{
|
||||
if (m_width != width || m_height != height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
if (m_activated)
|
||||
{
|
||||
WindowNotificationBus::Event(reinterpret_cast<NativeWindowHandle>(m_xcbWindow), &WindowNotificationBus::Events::OnWindowResized, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI_Platform.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
#include <AzFramework/Windowing/NativeWindow.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
#if PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
class NativeWindowImpl_Linux_xcb final
|
||||
: public NativeWindow::Implementation
|
||||
, public LinuxXcbEventHandlerBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(NativeWindowImpl_Linux_xcb, AZ::SystemAllocator, 0);
|
||||
NativeWindowImpl_Linux_xcb();
|
||||
~NativeWindowImpl_Linux_xcb() override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// NativeWindow::Implementation
|
||||
void InitWindow(const AZStd::string& title,
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks) override;
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
NativeWindowHandle GetWindowHandle() const override;
|
||||
void SetWindowTitle(const AZStd::string& title) override;
|
||||
void ResizeClientArea(WindowSize clientAreaSize) override;
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LinuxXcbEventHandlerBus::Handler
|
||||
void HandleXcbEvent(xcb_generic_event_t* event) override;
|
||||
|
||||
private:
|
||||
bool ValidateXcbResult(xcb_void_cookie_t cookie);
|
||||
void WindowSizeChanged(const uint32_t width, const uint32_t height);
|
||||
|
||||
xcb_connection_t* m_xcbConnection = nullptr;
|
||||
xcb_window_t m_xcbWindow = 0;
|
||||
xcb_atom_t m_xcbAtomProtocols;
|
||||
xcb_atom_t m_xcbAtomDeleteWindow;
|
||||
};
|
||||
#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB
|
||||
|
||||
} // namespace AzFramework
|
||||
@@ -12,6 +12,8 @@ set(FILES
|
||||
AzFramework/API/ApplicationAPI_Platform.h
|
||||
AzFramework/API/ApplicationAPI_Linux.h
|
||||
AzFramework/Application/Application_Linux.cpp
|
||||
AzFramework/Application/Application_Linux_xcb.h
|
||||
AzFramework/Application/Application_Linux_xcb.cpp
|
||||
AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp
|
||||
AzFramework/Process/ProcessWatcher_Linux.cpp
|
||||
AzFramework/Process/ProcessCommon.h
|
||||
@@ -20,6 +22,8 @@ set(FILES
|
||||
../Common/Unimplemented/AzFramework/StreamingInstall/StreamingInstall_Unimplemented.cpp
|
||||
../Common/Default/AzFramework/TargetManagement/TargetManagementComponent_Default.cpp
|
||||
AzFramework/Windowing/NativeWindow_Linux.cpp
|
||||
AzFramework/Windowing/NativeWindow_Linux_xcb.h
|
||||
AzFramework/Windowing/NativeWindow_Linux_xcb.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Gamepad/InputDeviceGamepad_Unimplemented.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard_Unimplemented.cpp
|
||||
../Common/Unimplemented/AzFramework/Input/Devices/Motion/InputDeviceMotion_Unimplemented.cpp
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
@@ -47,18 +48,17 @@ namespace UnitTest
|
||||
m_firstPersonTranslateCamera =
|
||||
AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::LookTranslation, m_translateCameraInputChannelIds);
|
||||
|
||||
auto orbitCamera =
|
||||
AZStd::make_shared<AzFramework::OrbitCameraInput>(AzFramework::InputChannelId("keyboard_key_modifier_alt_l"));
|
||||
m_orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>(m_orbitChannelId);
|
||||
auto orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Left);
|
||||
auto orbitTranslateCamera =
|
||||
AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::OrbitTranslation, m_translateCameraInputChannelIds);
|
||||
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
|
||||
|
||||
m_cameraSystem->m_cameras.AddCamera(m_firstPersonRotateCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(m_firstPersonTranslateCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(orbitCamera);
|
||||
m_cameraSystem->m_cameras.AddCamera(m_orbitCamera);
|
||||
|
||||
// these tests rely on using motion delta, not cursor positions (default is true)
|
||||
AzFramework::ed_cameraSystemUseCursor = false;
|
||||
@@ -68,6 +68,7 @@ namespace UnitTest
|
||||
{
|
||||
AzFramework::ed_cameraSystemUseCursor = true;
|
||||
|
||||
m_orbitCamera.reset();
|
||||
m_firstPersonRotateCamera.reset();
|
||||
m_firstPersonTranslateCamera.reset();
|
||||
|
||||
@@ -77,12 +78,14 @@ namespace UnitTest
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId m_orbitChannelId = AzFramework::InputChannelId("keyboard_key_modifier_alt_l");
|
||||
AzFramework::TranslateCameraInputChannelIds m_translateCameraInputChannelIds;
|
||||
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_firstPersonRotateCamera;
|
||||
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_firstPersonTranslateCamera;
|
||||
AZStd::shared_ptr<AzFramework::OrbitCameraInput> m_orbitCamera;
|
||||
};
|
||||
|
||||
TEST_F(CameraInputFixture, Begin_and_end_OrbitCameraInput_consumes_correct_events)
|
||||
TEST_F(CameraInputFixture, BeginAndEndOrbitCameraInputConsumesCorrectEvents)
|
||||
{
|
||||
// begin orbit camera
|
||||
const bool consumed1 = HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceKeyboard::Key::ModifierAltL,
|
||||
@@ -102,7 +105,7 @@ namespace UnitTest
|
||||
EXPECT_THAT(allConsumed, ElementsAre(true, false, true, false));
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, Begin_CameraInput_notifies_ActivationBeganFn_for_TranslateCameraInput)
|
||||
TEST_F(CameraInputFixture, BeginCameraInputNotifiesActivationBeganFnForTranslateCameraInput)
|
||||
{
|
||||
bool activationBegan = false;
|
||||
m_firstPersonTranslateCamera->SetActivationBeganFn(
|
||||
@@ -111,13 +114,13 @@ namespace UnitTest
|
||||
activationBegan = true;
|
||||
});
|
||||
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
|
||||
EXPECT_TRUE(activationBegan);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, Begin_CameraInput_notifies_ActivationBeganFn_after_delta_for_RotateCameraInput)
|
||||
TEST_F(CameraInputFixture, BeginCameraInputNotifiesActivationBeganFnAfterDeltaForRotateCameraInput)
|
||||
{
|
||||
bool activationBegan = false;
|
||||
m_firstPersonRotateCamera->SetActivationBeganFn(
|
||||
@@ -133,7 +136,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(activationBegan);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, Begin_CameraInput_does_not_notify_ActivationBeganFn_with_no_delta_for_RotateCameraInput)
|
||||
TEST_F(CameraInputFixture, BeginCameraInputDoesNotNotifyActivationBeganFnWithNoDeltaForRotateCameraInput)
|
||||
{
|
||||
bool activationBegan = false;
|
||||
m_firstPersonRotateCamera->SetActivationBeganFn(
|
||||
@@ -148,7 +151,7 @@ namespace UnitTest
|
||||
EXPECT_FALSE(activationBegan);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, End_CameraInput_notifies_ActivationEndFn_after_delta_for_RotateCameraInput)
|
||||
TEST_F(CameraInputFixture, EndCameraInputNotifiesActivationEndFnAfterDeltaForRotateCameraInput)
|
||||
{
|
||||
bool activationEnded = false;
|
||||
m_firstPersonRotateCamera->SetActivationEndedFn(
|
||||
@@ -166,7 +169,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(activationEnded);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, End_CameraInput_does_not_notify_ActivationBeganFn_or_ActivationBeganFn_with_no_delta_for_RotateCameraInput)
|
||||
TEST_F(CameraInputFixture, EndCameraInputDoesNotNotifyActivationBeganFnOrActivationBeganFnWithNoDeltaForRotateCameraInput)
|
||||
{
|
||||
bool activationBegan = false;
|
||||
m_firstPersonRotateCamera->SetActivationBeganFn(
|
||||
@@ -191,7 +194,7 @@ namespace UnitTest
|
||||
EXPECT_FALSE(activationEnded);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, End_CameraInput_notifies_ActivationBeganFn_or_ActivationEndFn_with_TranslateCamera)
|
||||
TEST_F(CameraInputFixture, End_CameraInputNotifiesActivationBeganFnOrActivationEndFnWithTranslateCamera)
|
||||
{
|
||||
bool activationBegan = false;
|
||||
m_firstPersonTranslateCamera->SetActivationBeganFn(
|
||||
@@ -207,16 +210,16 @@ namespace UnitTest
|
||||
activationEnded = true;
|
||||
});
|
||||
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Ended });
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Ended });
|
||||
|
||||
EXPECT_TRUE(activationBegan);
|
||||
EXPECT_TRUE(activationEnded);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, End_activation_called_for_CameraInput_if_active_when_cameras_are_cleared)
|
||||
TEST_F(CameraInputFixture, EndActivationCalledForCameraInputIfActiveWhenCamerasAreCleared)
|
||||
{
|
||||
bool activationEnded = false;
|
||||
m_firstPersonTranslateCamera->SetActivationEndedFn(
|
||||
@@ -225,11 +228,37 @@ namespace UnitTest
|
||||
activationEnded = true;
|
||||
});
|
||||
|
||||
HandleEventAndUpdate(
|
||||
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began });
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
|
||||
AzFramework::InputChannel::State::Began });
|
||||
|
||||
m_cameraSystem->m_cameras.Clear();
|
||||
|
||||
EXPECT_TRUE(activationEnded);
|
||||
}
|
||||
|
||||
TEST_F(CameraInputFixture, OrbitCameraInputHandlesLookAtPointAndSelfAtSamePositionWhenOrbiting)
|
||||
{
|
||||
// create pathological lookAtFn that just returns the same position as the camera
|
||||
m_orbitCamera->SetLookAtFn(
|
||||
[](const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
|
||||
{
|
||||
return position;
|
||||
});
|
||||
|
||||
AzFramework::UpdateCameraFromTransform(
|
||||
m_targetCamera,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 10.0f, 10.0f)));
|
||||
|
||||
m_camera = m_targetCamera;
|
||||
|
||||
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
|
||||
|
||||
// verify the camera yaw has not changed and the look at point
|
||||
// does not match that of the camera translation
|
||||
using ::testing::Eq;
|
||||
using ::testing::Not;
|
||||
EXPECT_THAT(m_camera.m_yaw, Eq(AZ::DegToRad(90.0f)));
|
||||
EXPECT_THAT(m_camera.m_lookAt, Not(IsClose(m_camera.Translation())));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
+3
@@ -45,6 +45,9 @@ namespace AzManipulatorTestFramework
|
||||
virtual void SetAngularStep(float step) = 0;
|
||||
//! Get the viewport id.
|
||||
virtual int GetViewportId() const = 0;
|
||||
//! Updates the visibility state.
|
||||
//! Updates which entities are currently visible given the current camera state.
|
||||
virtual void UpdateVisibility() = 0;
|
||||
};
|
||||
|
||||
//! This interface is used to simulate the manipulator manager while the manipulators are under test.
|
||||
|
||||
+6
-8
@@ -12,8 +12,8 @@
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
|
||||
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
|
||||
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace UnitTest
|
||||
@@ -21,20 +21,18 @@ namespace UnitTest
|
||||
//! Fixture to provide the indirect call viewport interaction that is dependent on AzToolsFramework::ToolsApplication.
|
||||
//! \tparam ToolsApplicationFixtureT The fixture that provides the AzToolsFramework::ToolsApplication functionality.
|
||||
template<typename ToolsApplicationFixtureT>
|
||||
class IndirectCallManipulatorViewportInteractionFixtureMixin
|
||||
: public ToolsApplicationFixtureT
|
||||
class IndirectCallManipulatorViewportInteractionFixtureMixin : public ToolsApplicationFixtureT
|
||||
{
|
||||
using IndirectCallManipulatorViewportInteraction =
|
||||
AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction;
|
||||
using IndirectCallManipulatorViewportInteraction = AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction;
|
||||
using ImmediateModeActionDispatcher = AzManipulatorTestFramework::ImmediateModeActionDispatcher;
|
||||
|
||||
|
||||
void SetUpEditorFixtureImpl() override
|
||||
{
|
||||
ToolsApplicationFixtureT::SetUpEditorFixtureImpl();
|
||||
m_viewportManipulatorInteraction = AZStd::make_unique<IndirectCallManipulatorViewportInteraction>();
|
||||
m_actionDispatcher = AZStd::make_unique<ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction);
|
||||
m_cameraState = AzFramework::CreateIdentityDefaultCamera(
|
||||
AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
|
||||
m_cameraState =
|
||||
AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
|
||||
}
|
||||
|
||||
void TearDownEditorFixtureImpl() override
|
||||
|
||||
+3
-4
@@ -9,8 +9,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
|
||||
|
||||
namespace AzManipulatorTestFramework
|
||||
{
|
||||
@@ -18,13 +18,12 @@ namespace AzManipulatorTestFramework
|
||||
class IndirectCallManipulatorManager;
|
||||
|
||||
//! Implementation of manipulator viewport interaction that manipulates the manager indirectly via bus calls.
|
||||
class IndirectCallManipulatorViewportInteraction
|
||||
: public ManipulatorViewportInteraction
|
||||
class IndirectCallManipulatorViewportInteraction : public ManipulatorViewportInteraction
|
||||
{
|
||||
public:
|
||||
IndirectCallManipulatorViewportInteraction();
|
||||
~IndirectCallManipulatorViewportInteraction();
|
||||
|
||||
|
||||
// ManipulatorViewportInteractionInterface ...
|
||||
const ViewportInteractionInterface& GetViewportInteraction() const override;
|
||||
const ManipulatorManagerInterface& GetManipulatorManager() const override;
|
||||
|
||||
+7
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Visibility/EntityVisibilityQuery.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
|
||||
namespace AzManipulatorTestFramework
|
||||
@@ -19,6 +20,7 @@ namespace AzManipulatorTestFramework
|
||||
: public ViewportInteractionInterface
|
||||
, public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
|
||||
, public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
|
||||
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
ViewportInteraction();
|
||||
@@ -34,6 +36,7 @@ namespace AzManipulatorTestFramework
|
||||
void SetGridSize(float size) override;
|
||||
void SetAngularStep(float step) override;
|
||||
int GetViewportId() const override;
|
||||
void UpdateVisibility() override;
|
||||
|
||||
// ViewportInteractionRequestBus overrides ...
|
||||
AzFramework::CameraState GetCameraState() override;
|
||||
@@ -52,7 +55,11 @@ namespace AzManipulatorTestFramework
|
||||
float ManipulatorLineBoundWidth() const override;
|
||||
float ManipulatorCircleBoundWidth() const override;
|
||||
|
||||
// EditorEntityViewportInteractionRequestBus overrides ...
|
||||
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override;
|
||||
|
||||
private:
|
||||
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
|
||||
AZStd::unique_ptr<NullDebugDisplayRequests> m_nullDebugDisplayRequests;
|
||||
const int m_viewportId = 1234; // Arbitrary viewport id for manipulator tests
|
||||
AzFramework::CameraState m_cameraState;
|
||||
|
||||
+3
-3
@@ -91,12 +91,12 @@ namespace AzManipulatorTestFramework
|
||||
AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(
|
||||
const AzFramework::ScreenPoint& screenPoint, const AzFramework::CameraState& cameraState)
|
||||
{
|
||||
const auto screenToWorld = AzFramework::ScreenToWorld(screenPoint, cameraState);
|
||||
const auto nearPlaneWorldPosition = AzFramework::ScreenToWorld(screenPoint, cameraState);
|
||||
|
||||
AzToolsFramework::ViewportInteraction::MousePick mousePick;
|
||||
mousePick.m_screenCoordinates = screenPoint;
|
||||
mousePick.m_rayOrigin = screenToWorld;
|
||||
mousePick.m_rayDirection = (screenToWorld - cameraState.m_position).GetNormalized();
|
||||
mousePick.m_rayOrigin = cameraState.m_position;
|
||||
mousePick.m_rayDirection = (nearPlaneWorldPosition - cameraState.m_position).GetNormalized();
|
||||
|
||||
return mousePick;
|
||||
}
|
||||
|
||||
+10
-4
@@ -16,8 +16,7 @@ namespace AzManipulatorTestFramework
|
||||
using MouseInteractionEvent = AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
|
||||
|
||||
//! Implementation of the manipulator interface using bus calls to access to the manipulator manager.
|
||||
class IndirectCallManipulatorManager
|
||||
: public ManipulatorManagerInterface
|
||||
class IndirectCallManipulatorManager : public ManipulatorManagerInterface
|
||||
{
|
||||
public:
|
||||
IndirectCallManipulatorManager(ViewportInteractionInterface& viewportInteraction);
|
||||
@@ -39,11 +38,18 @@ namespace AzManipulatorTestFramework
|
||||
|
||||
void IndirectCallManipulatorManager::ConsumeMouseInteractionEvent(const MouseInteractionEvent& event)
|
||||
{
|
||||
m_viewportInteraction.UpdateVisibility();
|
||||
|
||||
// ensure we call display viewport 2d to simulate this update step (some state may be
|
||||
// updated here, e.g. box select)
|
||||
AzFramework::ViewportDebugDisplayEventBus::Event(
|
||||
AzToolsFramework::GetEntityContextId(), &AzFramework::ViewportDebugDisplayEvents::DisplayViewport2d,
|
||||
AzFramework::ViewportInfo{ m_viewportInteraction.GetViewportId() }, m_viewportInteraction.GetDebugDisplay());
|
||||
|
||||
DrawManipulators();
|
||||
AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event(
|
||||
AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions,
|
||||
event);
|
||||
&AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions, event);
|
||||
DrawManipulators();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,12 @@ namespace AzManipulatorTestFramework
|
||||
{
|
||||
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(m_viewportId);
|
||||
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(m_viewportId);
|
||||
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(m_viewportId);
|
||||
}
|
||||
|
||||
ViewportInteraction::~ViewportInteraction()
|
||||
{
|
||||
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
@@ -74,6 +76,16 @@ namespace AzManipulatorTestFramework
|
||||
return 0.1f;
|
||||
}
|
||||
|
||||
void ViewportInteraction::FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntitiesOut)
|
||||
{
|
||||
visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End());
|
||||
}
|
||||
|
||||
void ViewportInteraction::UpdateVisibility()
|
||||
{
|
||||
m_entityVisibilityQuery.UpdateVisibility(m_cameraState);
|
||||
}
|
||||
|
||||
AzFramework::ScreenPoint ViewportInteraction::ViewportWorldToScreen(const AZ::Vector3& worldPosition)
|
||||
{
|
||||
return AzFramework::WorldToScreen(worldPosition, m_cameraState);
|
||||
|
||||
@@ -342,7 +342,7 @@ namespace AzQtComponents
|
||||
config.toolTipPaddingInPixels = 5;
|
||||
config.headerIconSizeInPixels = CardHeader::defaultIconSize();
|
||||
config.rootLayoutSpacing = 0;
|
||||
config.warningIcon = QStringLiteral(":/Cards/img/UI20/Cards/warning.svg");
|
||||
config.warningIcon = QStringLiteral(":/Notifications/warning.svg");
|
||||
config.warningIconSize = {24, 24};
|
||||
config.disabledIconAlpha = 0.25;
|
||||
|
||||
|
||||
@@ -303,7 +303,7 @@ VectorInput::~VectorInput()
|
||||
void VectorInput::setLabel(int index, const QString& label)
|
||||
{
|
||||
AZ_Warning("PropertyGrid", index < m_elementCount,
|
||||
"This control handles only %i controls", m_elementCount)
|
||||
"This control handles only %i controls", m_elementCount);
|
||||
if (index < m_elementCount)
|
||||
{
|
||||
m_elements[index]->setLabel(label);
|
||||
@@ -313,7 +313,7 @@ void VectorInput::setLabel(int index, const QString& label)
|
||||
void VectorInput::setLabelStyle(int index, const QString& qss)
|
||||
{
|
||||
AZ_Warning("PropertyGrid", index < m_elementCount,
|
||||
"This control handles only %i controls", m_elementCount)
|
||||
"This control handles only %i controls", m_elementCount);
|
||||
if (index < m_elementCount)
|
||||
{
|
||||
m_elements[index]->getLabelWidget()->setStyleSheet(qss);
|
||||
@@ -323,7 +323,7 @@ void VectorInput::setLabelStyle(int index, const QString& qss)
|
||||
void VectorInput::setValuebyIndex(double value, int elementIndex)
|
||||
{
|
||||
AZ_Warning("PropertyGrid", elementIndex < m_elementCount,
|
||||
"This control handles only %i controls", m_elementCount)
|
||||
"This control handles only %i controls", m_elementCount);
|
||||
if (elementIndex < m_elementCount)
|
||||
{
|
||||
m_elements[elementIndex]->setValue(value);
|
||||
|
||||
@@ -424,7 +424,6 @@
|
||||
<file>img/UI20/Cards/menu_ico.png</file>
|
||||
<file>img/UI20/Cards/error_icon.png</file>
|
||||
<file>img/UI20/Cards/warning.png</file>
|
||||
<file>img/UI20/Cards/warning.svg</file>
|
||||
<file>img/UI20/Cards/search.png</file>
|
||||
<file>img/UI20/Cards/close.png</file>
|
||||
<file>img/UI20/Cards/error-conclict-state.svg</file>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -30,6 +30,7 @@
|
||||
<file alias="checkmark.svg">Notifications/checkmark.svg</file>
|
||||
<file alias="download.svg">Notifications/download.svg</file>
|
||||
<file alias="link.svg">Notifications/link.svg</file>
|
||||
<file alias="warning.svg">Notifications/warning.svg</file>
|
||||
</qresource>
|
||||
<qresource prefix="/Outliner">
|
||||
<file alias="sort_a_to_z.svg">Outliner/sort_a_to_z.svg</file>
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ::EBusReduceResult<AZ::Aabb, AzFramework::AabbUnionAggregator> aabbResult(AZ::Aabb::CreateNull());
|
||||
EditorComponentSelectionRequestsBus::EventResult(
|
||||
aabbResult, entityId, &EditorComponentSelectionRequests::GetEditorSelectionBoundsViewport, viewportInfo);
|
||||
aabbResult, entityId, &EditorComponentSelectionRequestsBus::Events::GetEditorSelectionBoundsViewport, viewportInfo);
|
||||
|
||||
return aabbResult.value;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace AzToolsFramework
|
||||
const char AssetBundleSettingsFileExtension[] = "bundlesettings";
|
||||
const char BundleFileExtension[] = "pak";
|
||||
const char ComparisonRulesFileExtension[] = "rules";
|
||||
const char ErrorWindowName[] = "AssetBundler";
|
||||
[[maybe_unused]] const char ErrorWindowName[] = "AssetBundler";
|
||||
const char* AssetFileInfoListComparison::ComparisonTypeNames[] = { "delta", "union", "intersection", "complement", "filepattern", "intersectioncount" };
|
||||
const char* AssetFileInfoListComparison::FilePatternTypeNames[] = { "wildcard", "regex" };
|
||||
const char DefaultTypeName[] = "default";
|
||||
|
||||
+2
@@ -43,6 +43,8 @@ namespace AzToolsFramework
|
||||
|
||||
virtual Prefab::InstanceOptionalReference GetRootPrefabInstance() = 0;
|
||||
|
||||
virtual Prefab::TemplateId GetRootPrefabTemplateId() = 0;
|
||||
|
||||
//! Get all Assets generated by Prefab processing when entering Play-In Editor mode (Ctrl+G)
|
||||
//! /return The vector of Assets generated by Prefab processing
|
||||
virtual const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& GetPlayInEditorAssetData() = 0;
|
||||
|
||||
+6
@@ -359,6 +359,12 @@ namespace AzToolsFramework
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
Prefab::TemplateId PrefabEditorEntityOwnershipService::GetRootPrefabTemplateId()
|
||||
{
|
||||
AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService.");
|
||||
return m_rootInstance ? m_rootInstance->GetTemplateId() : Prefab::InvalidTemplateId;
|
||||
}
|
||||
|
||||
const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData()
|
||||
{
|
||||
return m_playInEditorData.m_assets;
|
||||
|
||||
+1
@@ -193,6 +193,7 @@ namespace AzToolsFramework
|
||||
AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) override;
|
||||
|
||||
Prefab::InstanceOptionalReference GetRootPrefabInstance() override;
|
||||
Prefab::TemplateId GetRootPrefabTemplateId() override;
|
||||
|
||||
const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& GetPlayInEditorAssetData() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -26,6 +26,19 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
static constexpr const char s_saveAllPrefabsKey[] = "/O3DE/Preferences/Prefabs/SaveAllPrefabs";
|
||||
|
||||
void PrefabLoader::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Enum<SaveAllPrefabsPreference>()
|
||||
->Value("Ask every time", SaveAllPrefabsPreference::AskEveryTime)
|
||||
->Value("Save all", SaveAllPrefabsPreference::SaveAll)
|
||||
->Value("Save none", SaveAllPrefabsPreference::SaveNone);
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabLoader::RegisterPrefabLoaderInterface()
|
||||
{
|
||||
m_prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
|
||||
@@ -657,6 +670,24 @@ namespace AzToolsFramework
|
||||
return finalPath;
|
||||
}
|
||||
|
||||
SaveAllPrefabsPreference PrefabLoader::GetSaveAllPrefabsPreference() const
|
||||
{
|
||||
SaveAllPrefabsPreference saveAllPrefabsPreference = SaveAllPrefabsPreference::AskEveryTime;
|
||||
if (auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
registry->GetObject(saveAllPrefabsPreference, s_saveAllPrefabsKey);
|
||||
}
|
||||
return saveAllPrefabsPreference;
|
||||
}
|
||||
|
||||
void PrefabLoader::SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference)
|
||||
{
|
||||
if (auto* registry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
registry->SetObject(s_saveAllPrefabsKey, saveAllPrefabsPreference);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::Path PrefabLoaderInterface::GeneratePath()
|
||||
{
|
||||
return AZStd::string::format("Prefab_%s", AZ::Entity::MakeId().ToString().c_str());
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace AzToolsFramework
|
||||
AZ_CLASS_ALLOCATOR(PrefabLoader, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(PrefabLoader, "{A302B072-4DC4-4B7E-9188-226F56A3429C8}", PrefabLoaderInterface);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PrefabLoaderInterface interface implementation
|
||||
|
||||
@@ -108,6 +110,9 @@ namespace AzToolsFramework
|
||||
//! Returns if the path is a valid path for a prefab
|
||||
static bool IsValidPrefabPath(AZ::IO::PathView path);
|
||||
|
||||
SaveAllPrefabsPreference GetSaveAllPrefabsPreference() const override;
|
||||
void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Copies the template dom provided and manipulates it into the proper format to be saved to disk.
|
||||
|
||||
@@ -17,6 +17,13 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
enum class SaveAllPrefabsPreference
|
||||
{
|
||||
AskEveryTime,
|
||||
SaveAll,
|
||||
SaveNone
|
||||
};
|
||||
|
||||
/*!
|
||||
* PrefabLoaderInterface
|
||||
* Interface for saving/loading Prefab files.
|
||||
@@ -84,6 +91,9 @@ namespace AzToolsFramework
|
||||
//! The path will always use the '/' separator.
|
||||
virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0;
|
||||
|
||||
virtual SaveAllPrefabsPreference GetSaveAllPrefabsPreference() const = 0;
|
||||
virtual void SetSaveAllPrefabsPreference(SaveAllPrefabsPreference saveAllPrefabsPreference) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
// Generates a new path
|
||||
@@ -93,3 +103,8 @@ namespace AzToolsFramework
|
||||
} // namespace Prefab
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_TYPE_INFO_SPECIALIZE(AzToolsFramework::Prefab::SaveAllPrefabsPreference, "{7E61EA82-4DE4-4A3F-945F-C8FEDC1114B5}");
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace AzToolsFramework
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor::Reflect(context);
|
||||
AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover::Reflect(context);
|
||||
PrefabPublicRequestHandler::Reflect(context);
|
||||
PrefabLoader::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
@@ -369,9 +370,11 @@ namespace AzToolsFramework
|
||||
PrefabDom& PrefabSystemComponent::FindTemplateDom(TemplateId templateId)
|
||||
{
|
||||
AZStd::optional<AZStd::reference_wrapper<Template>> findTemplateResult = FindTemplate(templateId);
|
||||
AZ_Assert(findTemplateResult.has_value(),
|
||||
AZ_Assert(
|
||||
findTemplateResult.has_value(),
|
||||
"PrefabSystemComponent::FindTemplateDom - Unable to retrieve Prefab template with id: '%llu'. "
|
||||
"Template could not be found", templateId);
|
||||
"Template could not be found",
|
||||
templateId);
|
||||
|
||||
AZ_Assert(findTemplateResult->get().IsValid(),
|
||||
"PrefabSystemComponent::FindTemplateDom - Unable to retrieve Prefab template with id: '%llu'. "
|
||||
@@ -526,12 +529,10 @@ namespace AzToolsFramework
|
||||
|
||||
Template& targetTemplate = targetTemplateReference->get();
|
||||
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
Template& sourceTemplate = sourceTemplateReference->get();
|
||||
AZStd::string_view instanceName(instanceIterator->name.GetString(), instanceIterator->name.GetStringLength());
|
||||
const AZStd::string& targetTemplateFilePath = targetTemplate.GetFilePath().Native();
|
||||
const AZStd::string& sourceTemplateFilePath = sourceTemplate.GetFilePath().Native();
|
||||
#endif
|
||||
|
||||
LinkId newLinkId = CreateUniqueLinkId();
|
||||
Link newLink(newLinkId);
|
||||
@@ -753,6 +754,89 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
bool PrefabSystemComponent::AreDirtyTemplatesPresent(TemplateId rootTemplateId)
|
||||
{
|
||||
TemplateReference prefabTemplate = FindTemplate(rootTemplateId);
|
||||
|
||||
if (!prefabTemplate.has_value())
|
||||
{
|
||||
AZ_Assert(false, "Template with id %llu is not found", rootTemplateId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsTemplateDirty(rootTemplateId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const Template::Links& linkIds = prefabTemplate->get().GetLinks();
|
||||
|
||||
for (LinkId linkId : linkIds)
|
||||
{
|
||||
auto linkIterator = m_linkIdMap.find(linkId);
|
||||
if (linkIterator != m_linkIdMap.end())
|
||||
{
|
||||
return AreDirtyTemplatesPresent(linkIterator->second.GetSourceTemplateId());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrefabSystemComponent::SaveAllDirtyTemplates(TemplateId rootTemplateId)
|
||||
{
|
||||
AZStd::set<AZ::IO::PathView> dirtyTemplatePaths = GetDirtyTemplatePaths(rootTemplateId);
|
||||
|
||||
for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths)
|
||||
{
|
||||
auto dirtyTemplateIterator = m_templateFilePathToIdMap.find(dirtyTemplatePath);
|
||||
if (dirtyTemplateIterator == m_templateFilePathToIdMap.end())
|
||||
{
|
||||
AZ_Assert(false, "Template id for template with path '%s' is not found.", dirtyTemplatePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prefabLoader.SaveTemplate(dirtyTemplateIterator->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::set<AZ::IO::PathView> PrefabSystemComponent::GetDirtyTemplatePaths(TemplateId rootTemplateId)
|
||||
{
|
||||
AZStd::vector<AZ::IO::PathView> dirtyTemplatePathVector;
|
||||
GetDirtyTemplatePathsHelper(rootTemplateId, dirtyTemplatePathVector);
|
||||
AZStd::set<AZ::IO::PathView> dirtyTemplatePaths;
|
||||
dirtyTemplatePaths.insert(dirtyTemplatePathVector.begin(), dirtyTemplatePathVector.end());
|
||||
return AZStd::move(dirtyTemplatePaths);
|
||||
}
|
||||
|
||||
void PrefabSystemComponent::GetDirtyTemplatePathsHelper(
|
||||
TemplateId rootTemplateId, AZStd::vector<AZ::IO::PathView>& dirtyTemplatePaths)
|
||||
{
|
||||
TemplateReference prefabTemplate = FindTemplate(rootTemplateId);
|
||||
|
||||
if (!prefabTemplate.has_value())
|
||||
{
|
||||
AZ_Assert(false, "Template with id %llu is not found", rootTemplateId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsTemplateDirty(rootTemplateId))
|
||||
{
|
||||
dirtyTemplatePaths.emplace_back(prefabTemplate->get().GetFilePath());
|
||||
}
|
||||
|
||||
const Template::Links& linkIds = prefabTemplate->get().GetLinks();
|
||||
|
||||
for (LinkId linkId : linkIds)
|
||||
{
|
||||
auto linkIterator = m_linkIdMap.find(linkId);
|
||||
if (linkIterator != m_linkIdMap.end())
|
||||
{
|
||||
GetDirtyTemplatePathsHelper(linkIterator->second.GetSourceTemplateId(), dirtyTemplatePaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PrefabSystemComponent::ConnectTemplates(
|
||||
Link& link,
|
||||
TemplateId sourceTemplateId,
|
||||
@@ -770,10 +854,8 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
Template& sourceTemplate = sourceTemplateReference->get();
|
||||
Template& targetTemplate = targetTemplateReference->get();
|
||||
#endif
|
||||
|
||||
AZStd::string_view instanceName(instanceIterator->name.GetString(), instanceIterator->name.GetStringLength());
|
||||
|
||||
@@ -783,10 +865,9 @@ namespace AzToolsFramework
|
||||
|
||||
PrefabDomValue& instance = instanceIterator->value;
|
||||
AZ_Assert(instance.IsObject(), "Nested instance DOM provided is not a valid JSON object.");
|
||||
[[maybe_unused]] PrefabDomValueReference sourceTemplateName = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::SourceName);
|
||||
PrefabDomValueReference sourceTemplateName = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::SourceName);
|
||||
AZ_Assert(sourceTemplateName, "Couldn't find source template name in the DOM of the nested instance while creating a link.");
|
||||
AZ_Assert(
|
||||
sourceTemplateName->get() == sourceTemplate.GetFilePath().c_str(),
|
||||
AZ_Assert(sourceTemplateName->get() == sourceTemplate.GetFilePath().c_str(),
|
||||
"The name of the source template in the nested instance DOM does not match the name of the source template already loaded");
|
||||
|
||||
PrefabDomValueReference patchesReference = PrefabDomUtils::FindPrefabDomValue(instance, PrefabDomUtils::PatchesName);
|
||||
|
||||
@@ -183,6 +183,12 @@ namespace AzToolsFramework
|
||||
*/
|
||||
void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) override;
|
||||
|
||||
bool AreDirtyTemplatesPresent(TemplateId rootTemplateId) override;
|
||||
|
||||
void SaveAllDirtyTemplates(TemplateId rootTemplateId) override;
|
||||
|
||||
AZStd::set<AZ::IO::PathView> GetDirtyTemplatePaths(TemplateId rootTemplateId) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
@@ -335,6 +341,9 @@ namespace AzToolsFramework
|
||||
*/
|
||||
bool RemoveLinkFromTargetTemplate(const LinkId& linkId, const Link& link);
|
||||
|
||||
// Helper function for GetDirtyTemplatePaths(). It uses vector to speed up iteration times.
|
||||
void GetDirtyTemplatePathsHelper(TemplateId rootTemplateId, AZStd::vector<AZ::IO::PathView>& dirtyTemplatePaths);
|
||||
|
||||
// A container for mapping Templates to the Links they may propagate changes to.
|
||||
AZStd::unordered_map<TemplateId, AZStd::unordered_set<LinkId>> m_templateToLinkIdsMap;
|
||||
|
||||
|
||||
+15
-1
@@ -9,11 +9,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/Link/Link.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabIdTypes.h>
|
||||
#include <AzToolsFramework/Prefab/Template/Template.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -50,6 +51,19 @@ namespace AzToolsFramework
|
||||
virtual bool IsTemplateDirty(const TemplateId& templateId) = 0;
|
||||
virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0;
|
||||
|
||||
//! Recursive function to check if the template is dirty or if any dirty templates are presents in the links of the template.
|
||||
//! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links.
|
||||
virtual bool AreDirtyTemplatesPresent(TemplateId rootTemplateId) = 0;
|
||||
|
||||
//! Recursive function to save if the template is dirty and save all the dirty templates in the links of the template.
|
||||
//! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links.
|
||||
virtual void SaveAllDirtyTemplates(TemplateId rootTemplateId) = 0;
|
||||
|
||||
//! Recursive function that fetches the set of dirty templates given a starting template to check for outgoing links.
|
||||
//! @param rootTemplateId The id of the template provided as the beginning template to check the outgoing links.
|
||||
//! @return The set of dirty template paths populated.
|
||||
virtual AZStd::set<AZ::IO::PathView> GetDirtyTemplatePaths(TemplateId rootTemplateId) = 0;
|
||||
|
||||
virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0;
|
||||
virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0;
|
||||
virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
|
||||
|
||||
+10
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabIdTypes.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -28,6 +29,15 @@ namespace AzToolsFramework
|
||||
* @return The id of the newly created entity.
|
||||
*/
|
||||
virtual AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) = 0;
|
||||
|
||||
//! Constructs and executes the close dialog on a prefab template corresponding to templateId.
|
||||
//! @param templateId The id of the template the user chose to close.
|
||||
virtual int ExecuteClosePrefabDialog(TemplateId templateId) = 0;
|
||||
|
||||
//! Constructs and executes the save dialog on a prefab template corresponding to templateId.
|
||||
//! @param templateId The id of the template the user chose to save.
|
||||
//! @param useSaveAllPrefabsPreference A flag indicating whether SaveAllPrefabsPreference should be used for saving templates.
|
||||
virtual void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference = false) = 0;
|
||||
};
|
||||
|
||||
} // namespace Prefab
|
||||
|
||||
+269
@@ -12,6 +12,7 @@
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
@@ -27,12 +28,28 @@
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
|
||||
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/CheckBox.h>
|
||||
#include <AzQtComponents/Components/FlowLayout.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/Widgets/CardHeader.h>
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QFrame>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMainWindow>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -43,8 +60,19 @@ namespace AzToolsFramework
|
||||
PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr;
|
||||
PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr;
|
||||
PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr;
|
||||
PrefabSystemComponentInterface* PrefabIntegrationManager::s_prefabSystemComponentInterface = nullptr;
|
||||
|
||||
const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab";
|
||||
|
||||
static const char* const ClosePrefabDialog = "ClosePrefabDialog";
|
||||
static const char* const FooterSeparatorLine = "FooterSeparatorLine";
|
||||
static const char* const PrefabSavedMessageFrame = "PrefabSavedMessageFrame";
|
||||
static const char* const PrefabSavePreferenceHint = "PrefabSavePreferenceHint";
|
||||
static const char* const PrefabSaveWarningFrame = "PrefabSaveWarningFrame";
|
||||
static const char* const SaveDependentPrefabsCard = "SaveDependentPrefabsCard";
|
||||
static const char* const SavePrefabDialog = "SavePrefabDialog";
|
||||
static const char* const UnsavedPrefabFileName = "UnsavedPrefabFileName";
|
||||
|
||||
|
||||
void PrefabUserSettings::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
@@ -88,6 +116,13 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
s_prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get();
|
||||
if (s_prefabSystemComponentInterface == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "Prefab - could not get PrefabSystemComponentInterface on PrefabIntegrationManager construction.");
|
||||
return;
|
||||
}
|
||||
|
||||
EditorContextMenuBus::Handler::BusConnect();
|
||||
PrefabInstanceContainerNotificationBus::Handler::BusConnect();
|
||||
AZ::Interface<PrefabIntegrationInterface>::Register(this);
|
||||
@@ -1050,5 +1085,239 @@ namespace AzToolsFramework
|
||||
return AZ::EntityId();
|
||||
}
|
||||
}
|
||||
|
||||
int PrefabIntegrationManager::ExecuteClosePrefabDialog(TemplateId templateId)
|
||||
{
|
||||
if (s_prefabSystemComponentInterface->AreDirtyTemplatesPresent(templateId))
|
||||
{
|
||||
auto prefabSaveSelectionDialog = ConstructClosePrefabDialog(templateId);
|
||||
|
||||
int prefabSaveSelection = prefabSaveSelectionDialog->exec();
|
||||
|
||||
if (prefabSaveSelection == QDialog::Accepted)
|
||||
{
|
||||
SavePrefabsInDialog(prefabSaveSelectionDialog.get());
|
||||
}
|
||||
|
||||
return prefabSaveSelection;
|
||||
}
|
||||
|
||||
return QDialogButtonBox::DestructiveRole;
|
||||
}
|
||||
|
||||
void PrefabIntegrationManager::ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference)
|
||||
{
|
||||
auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId);
|
||||
AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath();
|
||||
|
||||
if (s_prefabSystemComponentInterface->IsTemplateDirty(templateId))
|
||||
{
|
||||
if (s_prefabLoaderInterface->SaveTemplate(templateId) == false)
|
||||
{
|
||||
AZ_Error("Prefab", false, "Template '%s' could not be saved successfully.", prefabTemplatePath.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_prefabSystemComponentInterface->AreDirtyTemplatesPresent(templateId))
|
||||
{
|
||||
if (useSaveAllPrefabsPreference)
|
||||
{
|
||||
SaveAllPrefabsPreference saveAllPrefabsPreference = s_prefabLoaderInterface->GetSaveAllPrefabsPreference();
|
||||
|
||||
if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveAll)
|
||||
{
|
||||
s_prefabSystemComponentInterface->SaveAllDirtyTemplates(templateId);
|
||||
return;
|
||||
}
|
||||
else if (saveAllPrefabsPreference == SaveAllPrefabsPreference::SaveNone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<QDialog> savePrefabDialog = ConstructSavePrefabDialog(templateId, useSaveAllPrefabsPreference);
|
||||
if (savePrefabDialog)
|
||||
{
|
||||
int prefabSaveSelection = savePrefabDialog->exec();
|
||||
|
||||
if (prefabSaveSelection == QDialog::Accepted)
|
||||
{
|
||||
SavePrefabsInDialog(savePrefabDialog.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabIntegrationManager::SavePrefabsInDialog(QDialog* unsavedPrefabsDialog)
|
||||
{
|
||||
QList<QLabel*> unsavedPrefabFileLabels = unsavedPrefabsDialog->findChildren<QLabel*>(UnsavedPrefabFileName);
|
||||
if (unsavedPrefabFileLabels.size() > 0)
|
||||
{
|
||||
for (const QLabel* unsavedPrefabFileLabel : unsavedPrefabFileLabels)
|
||||
{
|
||||
AZStd::string unsavedPrefabFileName = unsavedPrefabFileLabel->property("FilePath").toString().toUtf8().data();
|
||||
AzToolsFramework::Prefab::TemplateId unsavedPrefabTemplateId =
|
||||
s_prefabSystemComponentInterface->GetTemplateIdFromFilePath(unsavedPrefabFileName.data());
|
||||
bool isTemplateSavedSuccessfully = s_prefabLoaderInterface->SaveTemplate(unsavedPrefabTemplateId);
|
||||
AZ_Error("Prefab", isTemplateSavedSuccessfully, "Prefab '%s' could not be saved successfully.", unsavedPrefabFileName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<QDialog> PrefabIntegrationManager::ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference)
|
||||
{
|
||||
AZStd::unique_ptr<QDialog> savePrefabDialog = AZStd::make_unique<QDialog>(AzToolsFramework::GetActiveWindow());
|
||||
|
||||
savePrefabDialog->setWindowTitle("Unsaved files detected");
|
||||
|
||||
// Main Content section begins.
|
||||
savePrefabDialog->setObjectName(SavePrefabDialog);
|
||||
QBoxLayout* contentLayout = new QVBoxLayout(savePrefabDialog.get());
|
||||
|
||||
QFrame* prefabSavedMessageFrame = new QFrame(savePrefabDialog.get());
|
||||
QHBoxLayout* prefabSavedMessageLayout = new QHBoxLayout(savePrefabDialog.get());
|
||||
prefabSavedMessageFrame->setObjectName(PrefabSavedMessageFrame);
|
||||
prefabSavedMessageFrame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
|
||||
|
||||
// Add a checkMark icon next to the level entities saved message.
|
||||
QPixmap checkMarkIcon(QString(":/Notifications/checkmark.svg"));
|
||||
QLabel* prefabSavedSuccessfullyIconContainer = new QLabel(savePrefabDialog.get());
|
||||
prefabSavedSuccessfullyIconContainer->setPixmap(checkMarkIcon);
|
||||
prefabSavedSuccessfullyIconContainer->setFixedWidth(checkMarkIcon.width());
|
||||
|
||||
// Add a message that level entities are saved successfully.
|
||||
|
||||
auto prefabTemplate = s_prefabSystemComponentInterface->FindTemplate(templateId);
|
||||
AZ::IO::Path prefabTemplatePath = prefabTemplate->get().GetFilePath();
|
||||
QLabel* prefabSavedSuccessfullyLabel = new QLabel(
|
||||
QString("Prefab '<b>%1</b>' has been saved. Do you want to save the below dependent prefabs too?").arg(prefabTemplatePath.c_str()),
|
||||
savePrefabDialog.get());
|
||||
prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyIconContainer);
|
||||
prefabSavedMessageLayout->addWidget(prefabSavedSuccessfullyLabel);
|
||||
prefabSavedMessageFrame->setLayout(prefabSavedMessageLayout);
|
||||
contentLayout->addWidget(prefabSavedMessageFrame);
|
||||
|
||||
AZStd::unique_ptr<AzQtComponents::Card> unsavedPrefabsContainer = ConstructUnsavedPrefabsCard(templateId);
|
||||
contentLayout->addWidget(unsavedPrefabsContainer.release());
|
||||
|
||||
contentLayout->addStretch();
|
||||
|
||||
// Footer section begins.
|
||||
QHBoxLayout* footerLayout = new QHBoxLayout(savePrefabDialog.get());
|
||||
|
||||
if (useSaveAllPrefabsPreference)
|
||||
{
|
||||
QFrame* footerSeparatorLine = new QFrame(savePrefabDialog.get());
|
||||
footerSeparatorLine->setObjectName(FooterSeparatorLine);
|
||||
footerSeparatorLine->setFrameShape(QFrame::HLine);
|
||||
contentLayout->addWidget(footerSeparatorLine);
|
||||
|
||||
QLabel* prefabSavePreferenceHint = new QLabel(
|
||||
"<u>You can prevent this window from showing in the future by updating your global save preferences.</u>",
|
||||
savePrefabDialog.get());
|
||||
prefabSavePreferenceHint->setToolTip(
|
||||
"Go to 'Edit > Editor Settings > Global Preferences... > Global save preferences' to update your preference");
|
||||
prefabSavePreferenceHint->setObjectName(PrefabSavePreferenceHint);
|
||||
footerLayout->addWidget(prefabSavePreferenceHint);
|
||||
}
|
||||
|
||||
QDialogButtonBox* prefabSaveConfirmationButtons =
|
||||
new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::No, savePrefabDialog.get());
|
||||
footerLayout->addWidget(prefabSaveConfirmationButtons);
|
||||
contentLayout->addLayout(footerLayout);
|
||||
connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, savePrefabDialog.get(), &QDialog::accept);
|
||||
connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, savePrefabDialog.get(), &QDialog::reject);
|
||||
AzQtComponents::StyleManager::setStyleSheet(savePrefabDialog->parentWidget(), QStringLiteral("style:Editor.qss"));
|
||||
|
||||
savePrefabDialog->setLayout(contentLayout);
|
||||
return AZStd::move(savePrefabDialog);
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<QDialog> PrefabIntegrationManager::ConstructClosePrefabDialog(TemplateId templateId)
|
||||
{
|
||||
AZStd::shared_ptr<QDialog> closePrefabDialog = AZStd::make_shared<QDialog>(AzToolsFramework::GetActiveWindow());
|
||||
closePrefabDialog->setWindowTitle("Unsaved files detected");
|
||||
AZStd::weak_ptr<QDialog> closePrefabDialogWeakPtr(closePrefabDialog);
|
||||
closePrefabDialog->setObjectName(ClosePrefabDialog);
|
||||
|
||||
// Main Content section begins.
|
||||
QVBoxLayout* contentLayout = new QVBoxLayout(closePrefabDialog.get());
|
||||
QFrame* prefabSaveWarningFrame = new QFrame(closePrefabDialog.get());
|
||||
QHBoxLayout* levelEntitiesSaveQuestionLayout = new QHBoxLayout(closePrefabDialog.get());
|
||||
prefabSaveWarningFrame->setObjectName(PrefabSaveWarningFrame);
|
||||
|
||||
// Add a warning icon next to save prefab warning.
|
||||
prefabSaveWarningFrame->setLayout(levelEntitiesSaveQuestionLayout);
|
||||
QPixmap warningIcon(QString(":/Notifications/warning.svg"));
|
||||
QLabel* warningIconContainer = new QLabel(closePrefabDialog.get());
|
||||
warningIconContainer->setPixmap(warningIcon);
|
||||
warningIconContainer->setFixedWidth(warningIcon.width());
|
||||
levelEntitiesSaveQuestionLayout->addWidget(warningIconContainer);
|
||||
|
||||
// Ask user if they want to save entities in level.
|
||||
QLabel* prefabSaveQuestionLabel = new QLabel("Do you want to save the below unsaved prefabs?", closePrefabDialog.get());
|
||||
levelEntitiesSaveQuestionLayout->addWidget(prefabSaveQuestionLabel);
|
||||
contentLayout->addWidget(prefabSaveWarningFrame);
|
||||
|
||||
auto templateToSave = s_prefabSystemComponentInterface->FindTemplate(templateId);
|
||||
AZ::IO::Path templateToSaveFilePath = templateToSave->get().GetFilePath();
|
||||
AZStd::unique_ptr<AzQtComponents::Card> unsavedPrefabsCard = ConstructUnsavedPrefabsCard(templateId);
|
||||
contentLayout->addWidget(unsavedPrefabsCard.release());
|
||||
|
||||
contentLayout->addStretch();
|
||||
|
||||
QHBoxLayout* footerLayout = new QHBoxLayout(closePrefabDialog.get());
|
||||
|
||||
QDialogButtonBox* prefabSaveConfirmationButtons = new QDialogButtonBox(
|
||||
QDialogButtonBox::Save | QDialogButtonBox::Discard | QDialogButtonBox::Cancel, closePrefabDialog.get());
|
||||
footerLayout->addWidget(prefabSaveConfirmationButtons);
|
||||
contentLayout->addLayout(footerLayout);
|
||||
QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::accepted, closePrefabDialog.get(), &QDialog::accept);
|
||||
QObject::connect(prefabSaveConfirmationButtons, &QDialogButtonBox::rejected, closePrefabDialog.get(), &QDialog::reject);
|
||||
QObject::connect(
|
||||
prefabSaveConfirmationButtons, &QDialogButtonBox::clicked, closePrefabDialog.get(),
|
||||
[closePrefabDialogWeakPtr, prefabSaveConfirmationButtons](QAbstractButton* button)
|
||||
{
|
||||
int prefabSaveSelection = prefabSaveConfirmationButtons->buttonRole(button);
|
||||
closePrefabDialogWeakPtr.lock()->done(prefabSaveSelection);
|
||||
});
|
||||
AzQtComponents::StyleManager::setStyleSheet(closePrefabDialog.get(), QStringLiteral("style:Editor.qss"));
|
||||
closePrefabDialog->setLayout(contentLayout);
|
||||
return closePrefabDialog;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AzQtComponents::Card> PrefabIntegrationManager::ConstructUnsavedPrefabsCard(TemplateId templateId)
|
||||
{
|
||||
FlowLayout* unsavedPrefabsLayout = new FlowLayout(AzToolsFramework::GetActiveWindow());
|
||||
|
||||
AZStd::set<AZ::IO::PathView> dirtyTemplatePaths = s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId);
|
||||
|
||||
for (AZ::IO::PathView dirtyTemplatePath : dirtyTemplatePaths)
|
||||
{
|
||||
QLabel* prefabNameLabel =
|
||||
new QLabel(QString("<u>%1</u>").arg(dirtyTemplatePath.Filename().Native().data()), AzToolsFramework::GetActiveWindow());
|
||||
prefabNameLabel->setObjectName(UnsavedPrefabFileName);
|
||||
prefabNameLabel->setWordWrap(true);
|
||||
prefabNameLabel->setToolTip(dirtyTemplatePath.Native().data());
|
||||
prefabNameLabel->setProperty("FilePath", dirtyTemplatePath.Native().data());
|
||||
unsavedPrefabsLayout->addWidget(prefabNameLabel);
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AzQtComponents::Card> unsavedPrefabsContainer = AZStd::make_unique<AzQtComponents::Card>(AzToolsFramework::GetActiveWindow());
|
||||
unsavedPrefabsContainer->setObjectName(SaveDependentPrefabsCard);
|
||||
unsavedPrefabsContainer->setTitle("Unsaved Prefabs");
|
||||
unsavedPrefabsContainer->header()->setHasContextMenu(false);
|
||||
unsavedPrefabsContainer->header()->setIcon(QIcon(QStringLiteral(":/Entity/prefab_edit.svg")));
|
||||
|
||||
QFrame* unsavedPrefabsFrame = new QFrame(unsavedPrefabsContainer.get());
|
||||
unsavedPrefabsFrame->setLayout(unsavedPrefabsLayout);
|
||||
QScrollArea* unsavedPrefabsScrollArea = new QScrollArea(unsavedPrefabsContainer.get());
|
||||
unsavedPrefabsScrollArea->setWidget(unsavedPrefabsFrame);
|
||||
unsavedPrefabsScrollArea->setWidgetResizable(true);
|
||||
unsavedPrefabsContainer->setContentWidget(unsavedPrefabsScrollArea);
|
||||
|
||||
return AZStd::move(unsavedPrefabsContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,15 @@
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserSourceDropBus.h>
|
||||
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/LevelRootUiHandler.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabEditManager.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationBus.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/Card.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
@@ -49,6 +52,7 @@ namespace AzToolsFramework
|
||||
, public AssetBrowser::AssetBrowserSourceDropBus::Handler
|
||||
, public PrefabInstanceContainerNotificationBus::Handler
|
||||
, public PrefabIntegrationInterface
|
||||
, public QObject
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(PrefabIntegrationManager, AZ::SystemAllocator, 0);
|
||||
@@ -72,6 +76,8 @@ namespace AzToolsFramework
|
||||
|
||||
// PrefabIntegrationInterface...
|
||||
AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) override;
|
||||
int ExecuteClosePrefabDialog(TemplateId templateId) override;
|
||||
void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override;
|
||||
|
||||
private:
|
||||
// Manages the Edit Mode UI for prefabs
|
||||
@@ -124,12 +130,19 @@ namespace AzToolsFramework
|
||||
|
||||
static AZ::u32 GetSliceFlags(const AZ::Edit::ElementData* editData, const AZ::Edit::ClassData* classData);
|
||||
|
||||
AZStd::shared_ptr<QDialog> ConstructClosePrefabDialog(TemplateId templateId);
|
||||
AZStd::unique_ptr<AzQtComponents::Card> ConstructUnsavedPrefabsCard(TemplateId templateId);
|
||||
AZStd::unique_ptr<QDialog> ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference);
|
||||
void SavePrefabsInDialog(QDialog* unsavedPrefabsDialog);
|
||||
|
||||
|
||||
static const AZStd::string s_prefabFileExtension;
|
||||
|
||||
static EditorEntityUiInterface* s_editorEntityUiInterface;
|
||||
static PrefabPublicInterface* s_prefabPublicInterface;
|
||||
static PrefabEditInterface* s_prefabEditInterface;
|
||||
static PrefabLoaderInterface* s_prefabLoaderInterface;
|
||||
static PrefabSystemComponentInterface* s_prefabSystemComponentInterface;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,25 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
{
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
|
||||
{
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Down;
|
||||
}
|
||||
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Up;
|
||||
}
|
||||
}
|
||||
|
||||
return AzFramework::ClickDetector::ClickEvent::Nil;
|
||||
}
|
||||
|
||||
float ManipulatorLineBoundWidth(const AzFramework::ViewportId viewportId /*= AzFramework::InvalidViewportId*/)
|
||||
{
|
||||
float lineBoundWidth = 0.0f;
|
||||
|
||||
@@ -250,8 +250,6 @@ namespace AzToolsFramework
|
||||
virtual AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) = 0;
|
||||
//! Return the terrain height given a world position in 2d (xy plane).
|
||||
virtual float TerrainHeight(const AZ::Vector2& position) = 0;
|
||||
//! Given the current view frustum (viewport) return all visible entities.
|
||||
virtual void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) = 0;
|
||||
//! Is the user holding a modifier key to move the manipulator space from local to world.
|
||||
virtual bool ShowingWorldSpace() = 0;
|
||||
//! Return the widget to use as the parent for the viewport context menu.
|
||||
@@ -269,7 +267,20 @@ namespace AzToolsFramework
|
||||
//! Type to inherit to implement MainEditorViewportInteractionRequests.
|
||||
using MainEditorViewportInteractionRequestBus = AZ::EBus<MainEditorViewportInteractionRequests, ViewportEBusTraits>;
|
||||
|
||||
//! Viewport requests for managing the viewport's cursor state.
|
||||
//! Editor entity requests to be made about the viewport.
|
||||
class EditorEntityViewportInteractionRequests
|
||||
{
|
||||
public:
|
||||
//! Given the current view frustum (viewport) return all visible entities.
|
||||
virtual void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) = 0;
|
||||
|
||||
protected:
|
||||
~EditorEntityViewportInteractionRequests() = default;
|
||||
};
|
||||
|
||||
using EditorEntityViewportInteractionRequestBus = AZ::EBus<EditorEntityViewportInteractionRequests, ViewportEBusTraits>;
|
||||
|
||||
//! Viewport requests for managing the viewport cursor state.
|
||||
class ViewportMouseCursorRequests
|
||||
{
|
||||
public:
|
||||
@@ -321,23 +332,8 @@ namespace AzToolsFramework
|
||||
|
||||
//! Maps a mouse interaction event to a ClickDetector event.
|
||||
//! @note Function only cares about up or down events, all other events are mapped to Nil (ignored).
|
||||
inline AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
{
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
|
||||
{
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Down;
|
||||
}
|
||||
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Up;
|
||||
}
|
||||
}
|
||||
return AzFramework::ClickDetector::ClickEvent::Nil;
|
||||
}
|
||||
AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
|
||||
|
||||
//! Wrap EBus call to retrieve manipulator line bound width.
|
||||
//! @note It is possible to pass AzFramework::InvalidViewportId (the default) to perform a Broadcast as opposed to a targeted Event.
|
||||
|
||||
+15
-18
@@ -9,8 +9,8 @@
|
||||
#include "EditorBoxSelect.h"
|
||||
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
@@ -19,11 +19,15 @@ namespace AzToolsFramework
|
||||
static const AZ::Color s_boxSelectColor = AZ::Color(1.0f, 1.0f, 1.0f, 0.4f);
|
||||
static const float s_boxSelectLineWidth = 2.0f;
|
||||
|
||||
void EditorBoxSelect::HandleMouseInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
void EditorBoxSelect::HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
{
|
||||
m_cursorPositionAtDownEvent = mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates;
|
||||
}
|
||||
|
||||
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
|
||||
|
||||
const auto selectClickEvent = ClickDetectorEventFromViewportInteraction(mouseInteraction);
|
||||
@@ -35,12 +39,7 @@ namespace AzToolsFramework
|
||||
m_leftMouseDown(mouseInteraction);
|
||||
}
|
||||
|
||||
m_boxSelectRegion = QRect
|
||||
{
|
||||
ViewportInteraction::QPointFromScreenPoint(
|
||||
mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates),
|
||||
QSize { 0, 0 }
|
||||
};
|
||||
m_boxSelectRegion = QRect{ ViewportInteraction::QPointFromScreenPoint(m_cursorPositionAtDownEvent), QSize{ 0, 0 } };
|
||||
}
|
||||
|
||||
if (m_boxSelectRegion)
|
||||
@@ -87,11 +86,11 @@ namespace AzToolsFramework
|
||||
AZ::Vector2 viewportSize = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId).m_viewportSize;
|
||||
|
||||
debugDisplay.DrawWireQuad2d(
|
||||
AZ::Vector2(
|
||||
aznumeric_cast<float>(m_boxSelectRegion->x()), aznumeric_cast<float>(m_boxSelectRegion->y())) / viewportSize,
|
||||
AZ::Vector2(aznumeric_cast<float>(m_boxSelectRegion->x()), aznumeric_cast<float>(m_boxSelectRegion->y())) / viewportSize,
|
||||
AZ::Vector2(
|
||||
aznumeric_cast<float>(m_boxSelectRegion->x()) + aznumeric_cast<float>(m_boxSelectRegion->width()),
|
||||
aznumeric_cast<float>(m_boxSelectRegion->y()) + aznumeric_cast<float>(m_boxSelectRegion->height())) / viewportSize,
|
||||
aznumeric_cast<float>(m_boxSelectRegion->y()) + aznumeric_cast<float>(m_boxSelectRegion->height())) /
|
||||
viewportSize,
|
||||
0.f);
|
||||
|
||||
debugDisplay.DepthTestOn();
|
||||
@@ -101,8 +100,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void EditorBoxSelect::DisplayScene(
|
||||
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
|
||||
void EditorBoxSelect::DisplayScene(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
|
||||
{
|
||||
if (m_displayScene)
|
||||
{
|
||||
@@ -122,15 +120,14 @@ namespace AzToolsFramework
|
||||
m_mouseMove = mouseMove;
|
||||
}
|
||||
|
||||
void EditorBoxSelect::InstallLeftMouseUp(
|
||||
const AZStd::function<void()>& leftMouseUp)
|
||||
void EditorBoxSelect::InstallLeftMouseUp(const AZStd::function<void()>& leftMouseUp)
|
||||
{
|
||||
m_leftMouseUp = leftMouseUp;
|
||||
}
|
||||
|
||||
void EditorBoxSelect::InstallDisplayScene(
|
||||
const AZStd::function<void(const AzFramework::ViewportInfo& viewportInfo,
|
||||
AzFramework::DebugDisplayRequests& debugDisplay)>& displayScene)
|
||||
const AZStd::function<void(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)>&
|
||||
displayScene)
|
||||
{
|
||||
m_displayScene = displayScene;
|
||||
}
|
||||
|
||||
@@ -81,5 +81,6 @@ namespace AzToolsFramework
|
||||
ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< Modifier keys active on the previous frame.
|
||||
AzFramework::ClickDetector m_clickDetector; //!< Utility type to detect if a mouse click or move has occurred.
|
||||
AzFramework::CursorState m_cursorState; //!< Utility type to track the current cursor position (and movement/delta).
|
||||
AzFramework::ScreenPoint m_cursorPositionAtDownEvent; //!< The position of the cursor when first potentially starting a box select.
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+18
-8
@@ -19,7 +19,7 @@
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
// default ray length for picking in the viewport
|
||||
static const float s_pickRayLength = 1000.0f;
|
||||
static const float EditorPickRayLength = 1000.0f;
|
||||
|
||||
AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
|
||||
{
|
||||
@@ -60,16 +60,27 @@ namespace AzToolsFramework
|
||||
return screenPosition;
|
||||
}
|
||||
|
||||
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
|
||||
bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
const AZ::Vector3 rayScaledDir = mouseInteraction.m_mousePick.m_rayDirection * s_pickRayLength;
|
||||
const AZ::Vector3 rayScaledDir = direction * EditorPickRayLength;
|
||||
|
||||
AZ::Vector3 startNormal;
|
||||
float t, end;
|
||||
return AZ::Intersect::IntersectRayAABB(
|
||||
mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0;
|
||||
AZ::Vector3 startNormal;
|
||||
if (AZ::Intersect::IntersectRayAABB(origin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0)
|
||||
{
|
||||
distance = t * EditorPickRayLength;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
|
||||
{
|
||||
float unused;
|
||||
return AabbIntersectRay(mouseInteraction.m_mousePick.m_rayOrigin, mouseInteraction.m_mousePick.m_rayDirection, aabb, unused);
|
||||
}
|
||||
|
||||
bool PickEntity(
|
||||
@@ -117,8 +128,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
float scaling = 1.0f;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
scaling, viewportId,
|
||||
&ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor);
|
||||
scaling, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor);
|
||||
|
||||
return scaling;
|
||||
}
|
||||
|
||||
+4
@@ -46,6 +46,10 @@ namespace AzToolsFramework
|
||||
//! in screen space intersected an aabb in world space.
|
||||
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb);
|
||||
|
||||
//! Wrapper to perform an intersection between a ray and an aabb.
|
||||
//! Note: direction should be normalized (it is scaled internally by the editor pick distance).
|
||||
bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance);
|
||||
|
||||
//! Return if a mouse interaction (pick ray) did intersect the tested EntityId.
|
||||
bool PickEntity(
|
||||
AZ::EntityId entityId, const ViewportInteraction::MouseInteraction& mouseInteraction, float& closestDistance, int viewportId);
|
||||
|
||||
+42
-34
@@ -44,39 +44,46 @@ namespace AzToolsFramework
|
||||
|
||||
AZ_CVAR(
|
||||
float,
|
||||
cl_viewportGizmoAxisLineWidth,
|
||||
ed_viewportGizmoAxisLineWidth,
|
||||
4.0f,
|
||||
nullptr,
|
||||
AZ::ConsoleFunctorFlags::Null,
|
||||
"The width of the line for the viewport axis gizmo");
|
||||
AZ_CVAR(
|
||||
float,
|
||||
cl_viewportGizmoAxisLineLength,
|
||||
ed_viewportGizmoAxisLineLength,
|
||||
0.7f,
|
||||
nullptr,
|
||||
AZ::ConsoleFunctorFlags::Null,
|
||||
"The length of the line for the viewport axis gizmo");
|
||||
AZ_CVAR(
|
||||
float,
|
||||
cl_viewportGizmoAxisLabelOffset,
|
||||
ed_viewportGizmoAxisLabelOffset,
|
||||
1.15f,
|
||||
nullptr,
|
||||
AZ::ConsoleFunctorFlags::Null,
|
||||
"The offset of the label for the viewport axis gizmo");
|
||||
AZ_CVAR(
|
||||
float,
|
||||
cl_viewportGizmoAxisLabelSize,
|
||||
ed_viewportGizmoAxisLabelSize,
|
||||
1.0f,
|
||||
nullptr,
|
||||
AZ::ConsoleFunctorFlags::Null,
|
||||
"The size of each label for the viewport axis gizmo");
|
||||
AZ_CVAR(
|
||||
AZ::Vector2,
|
||||
cl_viewportGizmoAxisScreenPosition,
|
||||
ed_viewportGizmoAxisScreenPosition,
|
||||
AZ::Vector2(0.045f, 0.9f),
|
||||
nullptr,
|
||||
AZ::ConsoleFunctorFlags::Null,
|
||||
"The screen position of the gizmo in normalized (0-1) ndc space");
|
||||
AZ_CVAR(
|
||||
bool,
|
||||
ed_viewportStickySelect,
|
||||
true,
|
||||
nullptr,
|
||||
AZ::ConsoleFunctorFlags::Null,
|
||||
"Sticky select implies a single click will not change selection with an entity already selected");
|
||||
|
||||
// strings related to new viewport interaction model (EditorTransformComponentSelection)
|
||||
static const char* const s_togglePivotTitleRightClick = "Toggle pivot";
|
||||
@@ -991,14 +998,19 @@ namespace AzToolsFramework
|
||||
|
||||
// ask the visible entity data cache if the entity is selectable in the viewport
|
||||
// (useful in the context of drawing when we only care about entities we can see)
|
||||
static bool SelectableInVisibleViewportCache(const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId)
|
||||
// note: return the index if it is selectable, nullopt otherwise
|
||||
static AZStd::optional<size_t> SelectableInVisibleViewportCache(
|
||||
const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId)
|
||||
{
|
||||
if (auto entityIndex = entityDataCache.GetVisibleEntityIndexFromId(entityId))
|
||||
{
|
||||
return entityDataCache.IsVisibleEntitySelectableInViewport(*entityIndex);
|
||||
if (entityDataCache.IsVisibleEntitySelectableInViewport(*entityIndex))
|
||||
{
|
||||
return *entityIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
static AZ::ComponentId GetTransformComponentId(const AZ::EntityId entityId)
|
||||
@@ -1709,17 +1721,17 @@ namespace AzToolsFramework
|
||||
m_pivotOverrideFrame.Reset();
|
||||
}
|
||||
|
||||
bool EditorTransformComponentSelection::SelectDeselect(const AZ::EntityId entityIdUnderCursor)
|
||||
bool EditorTransformComponentSelection::SelectDeselect(const AZ::EntityId entityId)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (entityIdUnderCursor.IsValid())
|
||||
if (entityId.IsValid())
|
||||
{
|
||||
if (IsEntitySelectedInternal(entityIdUnderCursor, m_selectedEntityIds))
|
||||
if (IsEntitySelectedInternal(entityId, m_selectedEntityIds))
|
||||
{
|
||||
if (!UndoRedoOperationInProgress())
|
||||
{
|
||||
RemoveEntityFromSelection(entityIdUnderCursor);
|
||||
RemoveEntityFromSelection(entityId);
|
||||
|
||||
const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds);
|
||||
|
||||
@@ -1742,7 +1754,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
if (!UndoRedoOperationInProgress())
|
||||
{
|
||||
AddEntityToSelection(entityIdUnderCursor);
|
||||
AddEntityToSelection(entityId);
|
||||
|
||||
const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds);
|
||||
|
||||
@@ -1783,25 +1795,21 @@ namespace AzToolsFramework
|
||||
|
||||
// for entities selected with no bounds of their own (just TransformComponent)
|
||||
// check selection against the selection indicator aabb
|
||||
for (AZ::EntityId entityId : m_selectedEntityIds)
|
||||
for (const AZ::EntityId& entityId : m_selectedEntityIds)
|
||||
{
|
||||
if (!SelectableInVisibleViewportCache(*m_entityDataCache, entityId))
|
||||
if (const auto entityIndex = SelectableInVisibleViewportCache(*m_entityDataCache, entityId); entityIndex.has_value())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const AZ::Transform& worldFromLocal = m_entityDataCache->GetVisibleEntityTransform(*entityIndex);
|
||||
const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode));
|
||||
const AZ::Vector3 scaledSize =
|
||||
AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState);
|
||||
|
||||
AZ::Transform worldFromLocal;
|
||||
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode));
|
||||
|
||||
const AZ::Vector3 scaledSize =
|
||||
AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState);
|
||||
|
||||
if (AabbIntersectMouseRay(
|
||||
mouseInteraction.m_mouseInteraction, AZ::Aabb::CreateFromMinMax(boxPosition - scaledSize, boxPosition + scaledSize)))
|
||||
{
|
||||
m_cachedEntityIdUnderCursor = entityId;
|
||||
if (AabbIntersectMouseRay(
|
||||
mouseInteraction.m_mouseInteraction,
|
||||
AZ::Aabb::CreateFromMinMax(boxPosition - scaledSize, boxPosition + scaledSize)))
|
||||
{
|
||||
m_cachedEntityIdUnderCursor = entityId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3490,7 +3498,7 @@ namespace AzToolsFramework
|
||||
const auto cameraProjection = AzFramework::CameraProjection(gizmoCameraState);
|
||||
|
||||
// screen space offset to move the 2d gizmo around
|
||||
const AZ::Vector2 screenOffset = AZ::Vector2(cl_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f);
|
||||
const AZ::Vector2 screenOffset = AZ::Vector2(ed_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f);
|
||||
|
||||
// map from a position in world space (relative to the the gizmo camera near the origin) to a position in
|
||||
// screen space
|
||||
@@ -3502,7 +3510,7 @@ namespace AzToolsFramework
|
||||
};
|
||||
|
||||
// get all important axis positions in screen space
|
||||
const float lineLength = cl_viewportGizmoAxisLineLength;
|
||||
const float lineLength = ed_viewportGizmoAxisLineLength;
|
||||
const auto gizmoStart = calculateGizmoAxis(AZ::Vector3::CreateZero());
|
||||
const auto gizmoEndAxisX = calculateGizmoAxis(-AZ::Vector3::CreateAxisX() * lineLength);
|
||||
const auto gizmoEndAxisY = calculateGizmoAxis(-AZ::Vector3::CreateAxisY() * lineLength);
|
||||
@@ -3513,7 +3521,7 @@ namespace AzToolsFramework
|
||||
const AZ::Vector2 gizmoAxisZ = gizmoEndAxisZ - gizmoStart;
|
||||
|
||||
// draw the axes of the gizmo
|
||||
debugDisplay.SetLineWidth(cl_viewportGizmoAxisLineWidth);
|
||||
debugDisplay.SetLineWidth(ed_viewportGizmoAxisLineWidth);
|
||||
debugDisplay.SetColor(AZ::Colors::Red);
|
||||
debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisX, 1.0f);
|
||||
debugDisplay.SetColor(AZ::Colors::Lime);
|
||||
@@ -3522,14 +3530,14 @@ namespace AzToolsFramework
|
||||
debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisZ, 1.0f);
|
||||
debugDisplay.SetLineWidth(1.0f);
|
||||
|
||||
const float labelOffset = cl_viewportGizmoAxisLabelOffset;
|
||||
const float labelOffset = ed_viewportGizmoAxisLabelOffset;
|
||||
const float screenScale = GetScreenDisplayScaling(viewportId);
|
||||
const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
|
||||
|
||||
// draw the label of of each axis for the gizmo
|
||||
const float labelSize = cl_viewportGizmoAxisLabelSize;
|
||||
const float labelSize = ed_viewportGizmoAxisLabelSize;
|
||||
debugDisplay.SetColor(AZ::Colors::White);
|
||||
debugDisplay.Draw2dTextLabel(labelXScreenPosition.GetX(), labelXScreenPosition.GetY(), labelSize, "X", true);
|
||||
debugDisplay.Draw2dTextLabel(labelYScreenPosition.GetX(), labelYScreenPosition.GetY(), labelSize, "Y", true);
|
||||
|
||||
+18
-19
@@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/optional.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
@@ -32,6 +33,8 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
AZ_CVAR_EXTERNED(bool, ed_viewportStickySelect);
|
||||
|
||||
class EditorVisibleEntityDataCache;
|
||||
|
||||
using EntityIdSet = AZStd::unordered_set<AZ::EntityId>; //!< Alias for unordered_set of EntityIds.
|
||||
@@ -170,14 +173,11 @@ namespace AzToolsFramework
|
||||
|
||||
//! ViewportInteraction::ViewportSelectionRequests
|
||||
//! Intercept all viewport mouse events and respond to inputs.
|
||||
bool HandleMouseInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
|
||||
bool HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
|
||||
void DisplayViewportSelection(
|
||||
const AzFramework::ViewportInfo& viewportInfo,
|
||||
AzFramework::DebugDisplayRequests& debugDisplay) override;
|
||||
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
|
||||
void DisplayViewportSelection2d(
|
||||
const AzFramework::ViewportInfo& viewportInfo,
|
||||
AzFramework::DebugDisplayRequests& debugDisplay) override;
|
||||
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
|
||||
|
||||
//! Add an entity to the current selection
|
||||
void AddEntityToSelection(AZ::EntityId entityId);
|
||||
@@ -206,7 +206,7 @@ namespace AzToolsFramework
|
||||
bool IsEntitySelected(AZ::EntityId entityId) const;
|
||||
void SetSelectedEntities(const EntityIdList& entityIds);
|
||||
void DeselectEntities();
|
||||
bool SelectDeselect(AZ::EntityId entityIdUnderCursor);
|
||||
bool SelectDeselect(AZ::EntityId entityId);
|
||||
|
||||
void RefreshSelectedEntityIds();
|
||||
void RefreshSelectedEntityIds(const EntityIdList& selectedEntityIds);
|
||||
@@ -253,11 +253,10 @@ namespace AzToolsFramework
|
||||
void SnapSelectedEntitiesToWorldGrid(float gridSize) override;
|
||||
|
||||
// EditorManipulatorCommandUndoRedoRequestBus ...
|
||||
void UndoRedoEntityManipulatorCommand(
|
||||
AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override;
|
||||
void UndoRedoEntityManipulatorCommand(AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override;
|
||||
|
||||
// EditorContextMenuBus...
|
||||
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2 & point, int flags) override;
|
||||
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
|
||||
int GetMenuPosition() const override;
|
||||
AZStd::string GetMenuIdentifier() const override;
|
||||
|
||||
@@ -266,8 +265,7 @@ namespace AzToolsFramework
|
||||
|
||||
// ToolsApplicationNotificationBus ...
|
||||
void BeforeEntitySelectionChanged() override;
|
||||
void AfterEntitySelectionChanged(
|
||||
const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override;
|
||||
void AfterEntitySelectionChanged(const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override;
|
||||
|
||||
// TransformNotificationBus ...
|
||||
void OnTransformChanged(const AZ::Transform& localTM, const AZ::Transform& worldTM) override;
|
||||
@@ -318,7 +316,8 @@ namespace AzToolsFramework
|
||||
EntityIdManipulators m_entityIdManipulators; //!< Mapping from a Manipulator to potentially many EntityIds.
|
||||
|
||||
EditorBoxSelect m_boxSelect; //!< Type responsible for handling box select.
|
||||
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand; //!< Track adjustments to manipulator translation and orientation (during mouse press/move).
|
||||
//! Track adjustments to manipulator translation and orientation (during mouse press/move).
|
||||
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand;
|
||||
AZStd::vector<AZStd::unique_ptr<QAction>> m_actions; //!< What actions are tied to this handler.
|
||||
ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< What modifiers were held last frame.
|
||||
EditorContextMenu m_contextMenu; //!< Viewport right click context menu.
|
||||
@@ -328,8 +327,10 @@ namespace AzToolsFramework
|
||||
ReferenceFrame m_referenceFrame = ReferenceFrame::Parent; //!< What reference frame is the Manipulator currently operating in.
|
||||
Frame m_axisPreview; //!< Axes of entity at the time of mouse down to indicate delta of translation.
|
||||
bool m_triedToRefresh = false; //!< Did a refresh event occur to recalculate the current Manipulator transform.
|
||||
bool m_didSetSelectedEntities = false; //!< Was EditorTransformComponentSelection responsible for the most recent entity selection change.
|
||||
bool m_selectedEntityIdsAndManipulatorsDirty = false; //!< Do the active manipulators need to recalculated after a modification (lock/visibility etc).
|
||||
//! Was EditorTransformComponentSelection responsible for the most recent entity selection change.
|
||||
bool m_didSetSelectedEntities = false;
|
||||
//! Do the active manipulators need to recalculated after a modification (lock/visibility etc).
|
||||
bool m_selectedEntityIdsAndManipulatorsDirty = false;
|
||||
bool m_transformChangedInternally = false; //!< Was an OnTransformChanged event triggered internally or not.
|
||||
ViewportUi::ClusterId m_transformModeClusterId; //!< Id of the Viewport UI cluster for changing transform mode.
|
||||
ViewportUi::ButtonId m_translateButtonId; //!< Id of the Viewport UI button for translate mode.
|
||||
@@ -363,15 +364,13 @@ namespace AzToolsFramework
|
||||
|
||||
//! Calculate the orientation for a group of entities based on the incoming reference frame.
|
||||
template<typename EntityIdMap>
|
||||
PivotOrientationResult CalculatePivotOrientationForEntityIds(
|
||||
const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame);
|
||||
PivotOrientationResult CalculatePivotOrientationForEntityIds(const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame);
|
||||
|
||||
//! Calculate the orientation for a group of entities based on the incoming
|
||||
//! reference frame with possible pivot override.
|
||||
template<typename EntityIdMap>
|
||||
PivotOrientationResult CalculateSelectionPivotOrientation(
|
||||
const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame,
|
||||
const ReferenceFrame referenceFrame);
|
||||
const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame, const ReferenceFrame referenceFrame);
|
||||
|
||||
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation, bool& internal);
|
||||
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation, bool& internal);
|
||||
|
||||
+2
-2
@@ -161,8 +161,8 @@ namespace AzToolsFramework
|
||||
|
||||
// request list of visible entities from authoritative system
|
||||
EntityIdList nextVisibleEntityIds;
|
||||
ViewportInteraction::MainEditorViewportInteractionRequestBus::Event(
|
||||
viewportInfo.m_viewportId, &ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::FindVisibleEntities,
|
||||
ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
|
||||
viewportInfo.m_viewportId, &ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
|
||||
nextVisibleEntityIds);
|
||||
|
||||
// only bother resorting if we know the lists have changed
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
static const char ErrorChannel[] = "ArchiveComponent_Linux";
|
||||
[[maybe_unused]] static const char ErrorChannel[] = "ArchiveComponent_Linux";
|
||||
|
||||
static const char ZipExePath[] = R"(/usr/bin/zip)";
|
||||
static const char UnzipExePath[] = R"(/usr/bin/unzip)";
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ComponentModeTestDoubles.h"
|
||||
#include "ComponentModeTestFixture.h"
|
||||
#include "ComponentModeTestDoubles.h"
|
||||
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
|
||||
@@ -15,17 +15,15 @@ namespace UnitTest
|
||||
{
|
||||
void ComponentModeTestFixture::SetUpEditorFixtureImpl()
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
using namespace AzToolsFramework::ComponentModeFramework;
|
||||
namespace AztfCmf = AzToolsFramework::ComponentModeFramework;
|
||||
|
||||
auto* app = GetApplication();
|
||||
ASSERT_TRUE(app);
|
||||
|
||||
app->RegisterComponentDescriptor(PlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AnotherPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(DependentPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::PlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::AnotherPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::DependentPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(
|
||||
TestComponentModeComponent<OverrideMouseInteractionComponentMode>::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(IncompatiblePlaceholderEditorComponent::CreateDescriptor());
|
||||
AztfCmf::TestComponentModeComponent<AztfCmf::OverrideMouseInteractionComponentMode>::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::IncompatiblePlaceholderEditorComponent::CreateDescriptor());
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Math/IntersectSegment.h>
|
||||
#include <AzCore/Math/ToString.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
#include <AzFramework/Entity/EntityContext.h>
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzFramework/Visibility/BoundsBus.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
|
||||
@@ -20,10 +22,12 @@
|
||||
#include <AzManipulatorTestFramework/ViewportInteraction.h>
|
||||
#include <AzQtComponents/Components/GlobalEventFilter.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityActionComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityModel.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorLockComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorVisibilityComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
@@ -32,6 +36,7 @@
|
||||
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
|
||||
#include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
|
||||
@@ -46,6 +51,14 @@ namespace AZ
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
AzToolsFramework::EntityIdList SelectedEntities()
|
||||
{
|
||||
AzToolsFramework::EntityIdList selectedEntitiesBefore;
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
|
||||
selectedEntitiesBefore, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities);
|
||||
return selectedEntitiesBefore;
|
||||
}
|
||||
|
||||
class EditorEntityVisibilityCacheFixture : public ToolsApplicationFixture
|
||||
{
|
||||
public:
|
||||
@@ -110,6 +123,80 @@ namespace UnitTest
|
||||
EXPECT_FALSE(m_cache.IsVisibleEntityVisible(m_cache.GetVisibleEntityIndexFromId(m_entityIds[2]).value()));
|
||||
}
|
||||
|
||||
//! Basic component that implements BoundsRequestBus and EditorComponentSelectionRequestsBus to be compatible
|
||||
//! with the Editor visibility system.
|
||||
//! Note: Used for simulating selection (picking) in the viewport.
|
||||
class BoundsTestComponent
|
||||
: public AzToolsFramework::Components::EditorComponentBase
|
||||
, public AzFramework::BoundsRequestBus::Handler
|
||||
, public AzToolsFramework::EditorComponentSelectionRequestsBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_EDITOR_COMPONENT(
|
||||
BoundsTestComponent, "{E6312E9D-8489-4677-9980-C93C328BC92C}", AzToolsFramework::Components::EditorComponentBase);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
// AZ::Component overrides ...
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
|
||||
// EditorComponentSelectionRequestsBus overrides ...
|
||||
AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override;
|
||||
bool EditorSelectionIntersectRayViewport(
|
||||
const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override;
|
||||
bool SupportsEditorRayIntersect() override;
|
||||
|
||||
// BoundsRequestBus overrides ...
|
||||
AZ::Aabb GetWorldBounds() override;
|
||||
AZ::Aabb GetLocalBounds() override;
|
||||
};
|
||||
|
||||
AZ::Aabb BoundsTestComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo)
|
||||
{
|
||||
return GetWorldBounds();
|
||||
}
|
||||
|
||||
bool BoundsTestComponent::EditorSelectionIntersectRayViewport(
|
||||
[[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance)
|
||||
{
|
||||
return AzToolsFramework::AabbIntersectRay(src, dir, GetWorldBounds(), distance);
|
||||
}
|
||||
|
||||
bool BoundsTestComponent::SupportsEditorRayIntersect()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void BoundsTestComponent::Activate()
|
||||
{
|
||||
AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId());
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId());
|
||||
}
|
||||
|
||||
void BoundsTestComponent::Deactivate()
|
||||
{
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
|
||||
AzFramework::BoundsRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
AZ::Aabb BoundsTestComponent::GetWorldBounds()
|
||||
{
|
||||
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(worldFromLocal, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
return GetLocalBounds().GetTransformedAabb(worldFromLocal);
|
||||
}
|
||||
|
||||
AZ::Aabb BoundsTestComponent::GetLocalBounds()
|
||||
{
|
||||
return AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.5f), AZ::Vector3(0.5f));
|
||||
}
|
||||
|
||||
// Fixture to support testing EditorTransformComponentSelection functionality on an Entity selection.
|
||||
class EditorTransformComponentSelectionFixture : public ToolsApplicationFixture
|
||||
{
|
||||
@@ -120,27 +207,52 @@ namespace UnitTest
|
||||
m_entityIds.push_back(m_entityId1);
|
||||
}
|
||||
|
||||
void ArrangeIndividualRotatedEntitySelection(const AZ::Quaternion& orientation);
|
||||
AZStd::optional<AZ::Transform> GetManipulatorTransform() const;
|
||||
void RefreshManipulators(AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType);
|
||||
void SetTransformMode(AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode);
|
||||
void OverrideManipulatorOrientation(const AZ::Quaternion& orientation);
|
||||
void OverrideManipulatorTranslation(const AZ::Vector3& translation);
|
||||
|
||||
public:
|
||||
AZ::EntityId m_entityId1;
|
||||
AzToolsFramework::EntityIdList m_entityIds;
|
||||
};
|
||||
|
||||
void EditorTransformComponentSelectionFixture::ArrangeIndividualRotatedEntitySelection(const AZ::Quaternion& orientation)
|
||||
class EditorTransformComponentSelectionViewportPickingFixture : public ToolsApplicationFixture
|
||||
{
|
||||
for (auto entityId : m_entityIds)
|
||||
public:
|
||||
void SetUpEditorFixtureImpl() override
|
||||
{
|
||||
auto* app = GetApplication();
|
||||
// register a simple component implementing BoundsRequestBus and EditorComponentSelectionRequestsBus
|
||||
app->RegisterComponentDescriptor(BoundsTestComponent::CreateDescriptor());
|
||||
|
||||
auto createEntityWithBoundsFn = [](const char* entityName)
|
||||
{
|
||||
AZ::Entity* entity = nullptr;
|
||||
AZ::EntityId entityId = CreateDefaultEditorEntity(entityName, &entity);
|
||||
|
||||
entity->Deactivate();
|
||||
entity->CreateComponent<BoundsTestComponent>();
|
||||
entity->Activate();
|
||||
|
||||
return entityId;
|
||||
};
|
||||
|
||||
m_entityId1 = createEntityWithBoundsFn("Entity1");
|
||||
m_entityId2 = createEntityWithBoundsFn("Entity2");
|
||||
m_entityId3 = createEntityWithBoundsFn("Entity3");
|
||||
}
|
||||
|
||||
public:
|
||||
AZ::EntityId m_entityId1;
|
||||
AZ::EntityId m_entityId2;
|
||||
AZ::EntityId m_entityId3;
|
||||
};
|
||||
|
||||
void ArrangeIndividualRotatedEntitySelection(const AzToolsFramework::EntityIdList& entityIds, const AZ::Quaternion& orientation)
|
||||
{
|
||||
for (auto entityId : entityIds)
|
||||
{
|
||||
AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, orientation);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::Transform> EditorTransformComponentSelectionFixture::GetManipulatorTransform() const
|
||||
AZStd::optional<AZ::Transform> GetManipulatorTransform()
|
||||
{
|
||||
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
|
||||
|
||||
@@ -151,8 +263,7 @@ namespace UnitTest
|
||||
return manipulatorTransform;
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelectionFixture::RefreshManipulators(
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType)
|
||||
void RefreshManipulators(const AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType)
|
||||
{
|
||||
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
|
||||
|
||||
@@ -160,8 +271,7 @@ namespace UnitTest
|
||||
AzToolsFramework::GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::RefreshManipulators, refreshType);
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelectionFixture::SetTransformMode(
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode)
|
||||
void SetTransformMode(const AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode)
|
||||
{
|
||||
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
|
||||
|
||||
@@ -169,7 +279,7 @@ namespace UnitTest
|
||||
AzToolsFramework::GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::SetTransformMode, transformMode);
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelectionFixture::OverrideManipulatorOrientation(const AZ::Quaternion& orientation)
|
||||
void OverrideManipulatorOrientation(const AZ::Quaternion& orientation)
|
||||
{
|
||||
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
|
||||
|
||||
@@ -178,7 +288,7 @@ namespace UnitTest
|
||||
orientation);
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelectionFixture::OverrideManipulatorTranslation(const AZ::Vector3& translation)
|
||||
void OverrideManipulatorTranslation(const AZ::Vector3& translation)
|
||||
{
|
||||
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
|
||||
|
||||
@@ -190,7 +300,7 @@ namespace UnitTest
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EditorTransformComponentSelection Tests
|
||||
|
||||
TEST_F(EditorTransformComponentSelectionFixture, Focus_is_not_changed_while_switching_viewport_interaction_request_instance)
|
||||
TEST_F(EditorTransformComponentSelectionFixture, FocusIsNotChangedWhileSwitchingViewportInteractionRequestInstance)
|
||||
{
|
||||
// setup a dummy widget and make it the active window to ensure focus in/out events are fired
|
||||
auto dummyWidget = AZStd::make_unique<QWidget>();
|
||||
@@ -239,7 +349,7 @@ namespace UnitTest
|
||||
// Given
|
||||
AzToolsFramework::SelectEntity(m_entityId1);
|
||||
|
||||
ArrangeIndividualRotatedEntitySelection(AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)));
|
||||
ArrangeIndividualRotatedEntitySelection(m_entityIds, AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)));
|
||||
RefreshManipulators(EditorTransformComponentSelectionRequestBus::Events::RefreshType::All);
|
||||
|
||||
SetTransformMode(EditorTransformComponentSelectionRequestBus::Events::Mode::Rotation);
|
||||
@@ -286,7 +396,7 @@ namespace UnitTest
|
||||
AzToolsFramework::SelectEntity(m_entityId1);
|
||||
|
||||
const AZ::Quaternion initialEntityOrientation = AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f));
|
||||
ArrangeIndividualRotatedEntitySelection(initialEntityOrientation);
|
||||
ArrangeIndividualRotatedEntitySelection(m_entityIds, initialEntityOrientation);
|
||||
|
||||
// assign new orientation to manipulator which does not match entity orientation
|
||||
OverrideManipulatorOrientation(AZ::Quaternion::CreateRotationZ(AZ::DegToRad(90.0f)));
|
||||
@@ -478,6 +588,227 @@ namespace UnitTest
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
// fixture for use with the indirect manipulator test framework
|
||||
using EditorTransformComponentSelectionViewportPickingManipulatorTestFixture =
|
||||
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionViewportPickingFixture>;
|
||||
|
||||
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickWithNoSelectionWillSelectEntity)
|
||||
{
|
||||
AzToolsFramework::ed_viewportStickySelect = true;
|
||||
|
||||
// the initial starting position of the entity
|
||||
const auto initialTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f));
|
||||
AZ::TransformBus::Event(m_entityId1, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorld);
|
||||
|
||||
// initial camera position (looking down the negative x-axis)
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
|
||||
|
||||
using ::testing::Eq;
|
||||
auto selectedEntitiesBefore = SelectedEntities();
|
||||
EXPECT_TRUE(selectedEntitiesBefore.empty());
|
||||
|
||||
// calculate the position in screen space of the initial entity position
|
||||
const auto initialPositionScreen = AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState);
|
||||
|
||||
// click the entity in the viewport
|
||||
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(initialPositionScreen)->MouseLButtonDown()->MouseLButtonUp();
|
||||
|
||||
// entity is selected
|
||||
auto selectedEntitiesAfter = SelectedEntities();
|
||||
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
|
||||
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
|
||||
}
|
||||
|
||||
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickOffEntityWithSelectionWillNotDeselectEntity)
|
||||
{
|
||||
AzToolsFramework::ed_viewportStickySelect = true;
|
||||
|
||||
// the initial starting position of the entity
|
||||
AZ::TransformBus::Event(
|
||||
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
|
||||
|
||||
// position in space above the entity
|
||||
const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f);
|
||||
|
||||
// initial camera position (looking down the negative x-axis)
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
|
||||
|
||||
AzToolsFramework::SelectEntity(m_entityId1);
|
||||
|
||||
// calculate the position in screen space of the initial position of the entity
|
||||
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 not deselected
|
||||
using ::testing::Eq;
|
||||
auto selectedEntitiesAfter = SelectedEntities();
|
||||
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
|
||||
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
|
||||
SingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity)
|
||||
{
|
||||
AzToolsFramework::ed_viewportStickySelect = true;
|
||||
|
||||
// the initial starting position of the entity
|
||||
AZ::TransformBus::Event(
|
||||
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
|
||||
|
||||
const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f));
|
||||
AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity);
|
||||
|
||||
// initial camera position (looking down the negative x-axis)
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
|
||||
|
||||
AzToolsFramework::SelectEntity(m_entityId1);
|
||||
|
||||
// calculate the position in screen space of the second entity
|
||||
const auto initialPositionScreenSecondEntity =
|
||||
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
|
||||
|
||||
// click the entity in the viewport
|
||||
m_actionDispatcher->CameraState(m_cameraState)
|
||||
->MousePosition(initialPositionScreenSecondEntity)
|
||||
->MouseLButtonDown()
|
||||
->MouseLButtonUp();
|
||||
|
||||
// entity selection was not changed
|
||||
using ::testing::Eq;
|
||||
auto selectedEntitiesAfter = SelectedEntities();
|
||||
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
|
||||
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
|
||||
CtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection)
|
||||
{
|
||||
AzToolsFramework::ed_viewportStickySelect = true;
|
||||
|
||||
// the initial starting position of the entity
|
||||
AZ::TransformBus::Event(
|
||||
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
|
||||
|
||||
const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f));
|
||||
AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity);
|
||||
|
||||
// initial camera position (looking down the negative x-axis)
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
|
||||
|
||||
AzToolsFramework::SelectEntity(m_entityId1);
|
||||
|
||||
// calculate the position in screen space of the second entity
|
||||
const auto initialPositionScreenSecondEntity =
|
||||
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
|
||||
|
||||
// click the entity in the viewport
|
||||
m_actionDispatcher->CameraState(m_cameraState)
|
||||
->MousePosition(initialPositionScreenSecondEntity)
|
||||
->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,
|
||||
CtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection)
|
||||
{
|
||||
AzToolsFramework::ed_viewportStickySelect = true;
|
||||
|
||||
// the initial starting position of the entity
|
||||
AZ::TransformBus::Event(
|
||||
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
|
||||
|
||||
const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f));
|
||||
AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity);
|
||||
|
||||
// initial camera position (looking down the negative x-axis)
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
|
||||
|
||||
AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2 });
|
||||
|
||||
// calculate the position in screen space of the second entity
|
||||
const auto initialPositionScreenSecondEntity =
|
||||
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
|
||||
|
||||
// click the entity in the viewport
|
||||
m_actionDispatcher->CameraState(m_cameraState)
|
||||
->MousePosition(initialPositionScreenSecondEntity)
|
||||
->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, DISABLED_BoxSelectWithNoInitialSelectionAddsEntitiesToSelection)
|
||||
{
|
||||
AzToolsFramework::ed_viewportStickySelect = true;
|
||||
|
||||
// the initial starting position of the entities
|
||||
AZ::TransformBus::Event(
|
||||
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
|
||||
AZ::TransformBus::Event(
|
||||
m_entityId2, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 14.0f, 10.0f)));
|
||||
AZ::TransformBus::Event(
|
||||
m_entityId3, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 16.0f, 10.0f)));
|
||||
|
||||
// initial camera position (looking down the negative x-axis)
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
|
||||
|
||||
using ::testing::Eq;
|
||||
auto selectedEntitiesBefore = SelectedEntities();
|
||||
EXPECT_THAT(selectedEntitiesBefore.size(), Eq(0));
|
||||
|
||||
// calculate the position in screen space of where to begin and end the box select action
|
||||
const auto beginningPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState);
|
||||
const auto middlePositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 15.0f, 10.0f), m_cameraState);
|
||||
const auto endingPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState);
|
||||
|
||||
// perform a box select in the viewport
|
||||
m_actionDispatcher->CameraState(m_cameraState)
|
||||
->MousePosition(beginningPositionWorldBoxSelectStart)
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(middlePositionWorldBoxSelectStart)
|
||||
->MousePosition(endingPositionWorldBoxSelectStart)
|
||||
->MouseLButtonUp();
|
||||
|
||||
// entities are selected
|
||||
using ::testing::UnorderedElementsAre;
|
||||
auto selectedEntitiesAfter = SelectedEntities();
|
||||
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3));
|
||||
}
|
||||
|
||||
using EditorTransformComponentSelectionManipulatorTestFixture =
|
||||
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionFixture>;
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ namespace AZ
|
||||
case TextureMapType::Bump:
|
||||
return m_normalMap;
|
||||
default:
|
||||
AZ_Assert(false, "Invalid Texture map requested.")
|
||||
AZ_Assert(false, "Invalid Texture map requested.");
|
||||
return m_empty;
|
||||
}
|
||||
}
|
||||
@@ -255,7 +255,7 @@ namespace AZ
|
||||
m_normalMap = texture;
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "Invalid Texture map requested.")
|
||||
AZ_Assert(false, "Invalid Texture map requested.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -599,7 +599,7 @@ namespace AZ
|
||||
|
||||
if (!materialNode)
|
||||
{
|
||||
AZ_Assert(false, "Attempted to add material to invalid xml document.")
|
||||
AZ_Assert(false, "Attempted to add material to invalid xml document.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -351,7 +351,7 @@ namespace GridMate
|
||||
DataSetBase* dataset = descriptor->GetDataSet(this, i);
|
||||
if (!dataset)
|
||||
{
|
||||
AZ_Assert(false, "How can we have a dirty dataset that doesn't exist?")
|
||||
AZ_Assert(false, "How can we have a dirty dataset that doesn't exist?");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace GridMate
|
||||
// Create Callback
|
||||
AZStd::weak_ptr<TargetCallbackBase> CreateCallback(AZ::u64 revision)
|
||||
{
|
||||
AZ_Assert(IsAckEnabled(), "ACK disabled.") //Shouldn't happen
|
||||
AZ_Assert(IsAckEnabled(), "ACK disabled."); //Shouldn't happen
|
||||
AZ_Assert(m_replicaRevision <= revision, "Cannot decrease replica revision");
|
||||
|
||||
if(!m_callback || m_callback->m_revision != revision)
|
||||
|
||||
@@ -1583,7 +1583,7 @@ GridSession::OnStateCreate(HSM& sm, const HSM::Event& e)
|
||||
|
||||
// Bind member replica
|
||||
bool isAdded = AddMember(m_myMember);
|
||||
AZ_Error("GridMate", isAdded, "Failed to add my replica, check the number of open slots!")
|
||||
AZ_Error("GridMate", isAdded, "Failed to add my replica, check the number of open slots!");
|
||||
if (!isAdded)
|
||||
{
|
||||
sm.Transition(SS_DELETE);
|
||||
|
||||
@@ -698,7 +698,7 @@ namespace GridMate
|
||||
static void* UserDataCopier(const void* sourceData, unsigned int sourceDataSize)
|
||||
{
|
||||
(void)sourceDataSize;
|
||||
AZ_Assert(sizeof(T) == sourceDataSize, "Data size %d doesn't match the type size %d", sourceDataSize, sizeof(T))
|
||||
AZ_Assert(sizeof(T) == sourceDataSize, "Data size %d doesn't match the type size %d", sourceDataSize, sizeof(T));
|
||||
return azcreate(T, (*static_cast<const T*>(sourceData)), GridMateAllocatorMP, "UserDataCopier");
|
||||
}
|
||||
template<class T>
|
||||
|
||||
@@ -626,11 +626,8 @@ namespace O3DELauncher
|
||||
AZ_TracePrintf("Launcher", "Application is configured for VFS");
|
||||
AZ_TracePrintf("Launcher", "Log and cache files will be written to the Cache directory on your host PC");
|
||||
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
const char* message = "If your game does not run, check any of the following:\n"
|
||||
"\t- Verify the remote_ip address is correct in bootstrap.cfg";
|
||||
#endif
|
||||
|
||||
constexpr const char* message = "If your game does not run, check any of the following:\n"
|
||||
"\t- Verify the remote_ip address is correct in bootstrap.cfg";
|
||||
if (mainInfo.m_additionalVfsResolution)
|
||||
{
|
||||
AZ_TracePrintf("Launcher", "%s\n%s", message, mainInfo.m_additionalVfsResolution)
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/AzCore_Traits_Platform.h>
|
||||
|
||||
// Description : Linux/Mac port support for Win32API calls
|
||||
#if !defined(WIN32)
|
||||
#if AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS
|
||||
|
||||
#include "platform.h" // Note: This should be first to get consistent debugging definitions
|
||||
|
||||
@@ -1391,4 +1392,4 @@ __finddata64_t::~__finddata64_t()
|
||||
}
|
||||
#endif //defined(APPLE) || defined(LINUX)
|
||||
|
||||
#endif // !defined(WIN32)
|
||||
#endif // AZ_TRAIT_LEGACY_CRYCOMMON_USE_WINDOWS_STUBS
|
||||
|
||||
@@ -131,7 +131,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include "SystemEventDispatcher.h"
|
||||
#include "HMDBus.h"
|
||||
|
||||
#include "zlib.h"
|
||||
#include "RemoteConsole/RemoteConsole.h"
|
||||
|
||||
#include <PNoise3.h>
|
||||
|
||||
@@ -178,7 +178,7 @@ void CSystem::LogVersion()
|
||||
strftime(s, 128, "%d %b %y (%H %M %S)", today);
|
||||
#endif
|
||||
|
||||
const SFileVersion& ver = GetFileVersion();
|
||||
[[maybe_unused]] const SFileVersion& ver = GetFileVersion();
|
||||
|
||||
CryLogAlways("BackupNameAttachment=\" Build(%d) %s\" -- used by backup system\n", ver.v[0], s); // read by CreateBackupFile()
|
||||
|
||||
@@ -249,7 +249,7 @@ void CSystem::LogVersion()
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::LogBuildInfo()
|
||||
{
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
[[maybe_unused]] auto projectName = AZ::Utils::GetProjectName();
|
||||
CryLogAlways("GameName: %s", projectName.c_str());
|
||||
CryLogAlways("BuildTime: " __DATE__ " " __TIME__);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user