Merge remote-tracking branch 'upstream/development' into nvsickle/OutlinerDuplicateEntryFixes
This commit is contained in:
@@ -33,7 +33,6 @@ ly_add_target(
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
Legacy::CryCommon
|
||||
3rdParty::zlib
|
||||
PUBLIC
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Gui
|
||||
@@ -105,7 +104,6 @@ ly_add_target(
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::tiff
|
||||
3rdParty::squish-ccr
|
||||
3rdParty::zlib
|
||||
3rdParty::AWSNativeSDK::STS
|
||||
Legacy::CryCommon
|
||||
Legacy::EditorCommon
|
||||
|
||||
@@ -278,17 +278,16 @@ void CFolderTreeCtrl::LoadTreeRec(const QString& currentFolder)
|
||||
|
||||
void CFolderTreeCtrl::AddItem(const QString& path)
|
||||
{
|
||||
QString folder;
|
||||
QString fileNameWithoutExtension;
|
||||
QString ext;
|
||||
|
||||
Path::Split(path, folder, fileNameWithoutExtension, ext);
|
||||
AZ::IO::FixedMaxPath folder{ AZ::IO::PathView(path.toUtf8().constData()) };
|
||||
AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Stem();
|
||||
folder = folder.ParentPath();
|
||||
|
||||
auto regex = QRegExp(m_fileNameSpec, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
if (regex.exactMatch(path))
|
||||
{
|
||||
CTreeItem* folderTreeItem = CreateFolderItems(folder);
|
||||
folderTreeItem->AddChild(fileNameWithoutExtension, path, eTreeImage_File);
|
||||
CTreeItem* folderTreeItem = CreateFolderItems(QString::fromUtf8(folder.c_str(), static_cast<int>(folder.Native().size())));
|
||||
folderTreeItem->AddChild(QString::fromUtf8(fileNameWithoutExtension.c_str(),
|
||||
static_cast<int>(fileNameWithoutExtension.Native().size())), path, eTreeImage_File);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
|
||||
// AzToolsFramework
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
|
||||
|
||||
// AzQtComponents
|
||||
@@ -166,15 +167,14 @@ LevelEditorMenuHandler::LevelEditorMenuHandler(MainWindow* mainWindow, QtViewPan
|
||||
m_mainWindow->menuBar()->setNativeMenuBar(true);
|
||||
#endif
|
||||
|
||||
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
|
||||
AzToolsFramework::GetEntityContextId());
|
||||
ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId());
|
||||
EditorMenuRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
LevelEditorMenuHandler::~LevelEditorMenuHandler()
|
||||
{
|
||||
EditorMenuRequestBus::Handler::BusDisconnect();
|
||||
ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void LevelEditorMenuHandler::Initialize()
|
||||
@@ -487,8 +487,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
|
||||
editMenu.AddAction(AzToolsFramework::EditPivot);
|
||||
editMenu.AddAction(AzToolsFramework::EditReset);
|
||||
editMenu.AddAction(AzToolsFramework::EditResetManipulator);
|
||||
editMenu.AddAction(AzToolsFramework::EditResetLocal);
|
||||
editMenu.AddAction(AzToolsFramework::EditResetWorld);
|
||||
|
||||
// Hide Selection
|
||||
editMenu.AddAction(AzToolsFramework::HideSelection);
|
||||
@@ -1186,36 +1184,44 @@ void LevelEditorMenuHandler::AddDisableActionInSimModeListener(QAction* action)
|
||||
}));
|
||||
}
|
||||
|
||||
void LevelEditorMenuHandler::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
void LevelEditorMenuHandler::OnEditorModeActivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
||||
if (!menuWrapper.isNull())
|
||||
if (mode == ViewportEditorMode::Component)
|
||||
{
|
||||
// copy of menu actions
|
||||
auto actions = menuWrapper.Get()->actions();
|
||||
// remove all non-reserved edit menu options
|
||||
actions.erase(
|
||||
std::remove_if(actions.begin(), actions.end(), [](QAction* action)
|
||||
{
|
||||
return !action->property("Reserved").toBool();
|
||||
}),
|
||||
actions.end());
|
||||
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
||||
!menuWrapper.isNull())
|
||||
{
|
||||
// copy of menu actions
|
||||
auto actions = menuWrapper.Get()->actions();
|
||||
// remove all non-reserved edit menu options
|
||||
actions.erase(
|
||||
std::remove_if(actions.begin(), actions.end(), [](QAction* action)
|
||||
{
|
||||
return !action->property("Reserved").toBool();
|
||||
}),
|
||||
actions.end());
|
||||
|
||||
// clear and update the menu with new actions
|
||||
menuWrapper.Get()->clear();
|
||||
menuWrapper.Get()->addActions(actions);
|
||||
// clear and update the menu with new actions
|
||||
menuWrapper.Get()->clear();
|
||||
menuWrapper.Get()->addActions(actions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LevelEditorMenuHandler::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
void LevelEditorMenuHandler::OnEditorModeDeactivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
RestoreEditMenuToDefault();
|
||||
if (mode == ViewportEditorMode::Component)
|
||||
{
|
||||
RestoreEditMenuToDefault();
|
||||
}
|
||||
}
|
||||
|
||||
void LevelEditorMenuHandler::AddEditMenuAction(QAction* action)
|
||||
{
|
||||
auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
||||
if (!menuWrapper.isNull())
|
||||
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
||||
!menuWrapper.isNull())
|
||||
{
|
||||
menuWrapper.Get()->addAction(action);
|
||||
}
|
||||
@@ -1239,8 +1245,8 @@ void LevelEditorMenuHandler::AddMenuAction(AZStd::string_view categoryId, QActio
|
||||
|
||||
void LevelEditorMenuHandler::RestoreEditMenuToDefault()
|
||||
{
|
||||
auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
||||
if (!menuWrapper.isNull())
|
||||
if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId);
|
||||
!menuWrapper.isNull())
|
||||
{
|
||||
menuWrapper.Get()->clear();
|
||||
PopulateEditMenu(menuWrapper);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <QPointer>
|
||||
#include "ActionManager.h"
|
||||
#include "QtViewPaneManager.h"
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
#endif
|
||||
|
||||
class MainWindow;
|
||||
@@ -28,7 +28,7 @@ struct QtViewPane;
|
||||
|
||||
class LevelEditorMenuHandler
|
||||
: public QObject
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
|
||||
, private AzToolsFramework::EditorMenuRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -88,9 +88,11 @@ private:
|
||||
|
||||
void AddDisableActionInSimModeListener(QAction* action);
|
||||
|
||||
// EditorComponentModeNotificationBus
|
||||
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
// ViewportEditorModeNotificationsBus overrides ...
|
||||
void OnEditorModeActivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
void OnEditorModeDeactivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
|
||||
// EditorMenuRequestBus
|
||||
void AddEditMenuAction(QAction* action) override;
|
||||
|
||||
@@ -33,6 +33,7 @@ public:
|
||||
protected:
|
||||
void SetupEnvironment() override
|
||||
{
|
||||
AttachEditorCoreAZEnvironment(AZ::Environment::GetInstance());
|
||||
m_allocatorScope.ActivateAllocators();
|
||||
m_cryPak = new NiceMock<CryPakMock>();
|
||||
|
||||
@@ -49,6 +50,7 @@ protected:
|
||||
{
|
||||
delete m_cryPak;
|
||||
m_allocatorScope.DeactivateAllocators();
|
||||
DetachEditorCoreAZEnvironment();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,22 +5,29 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#include "EditorDefs.h"
|
||||
#include <AzTest/AzTest.h>
|
||||
#include "Util/PathUtil.h"
|
||||
#include <CrySystemBus.h>
|
||||
|
||||
TEST(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <Util/PathUtil.h>
|
||||
namespace UnitTest
|
||||
{
|
||||
// There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
|
||||
QString pngExtension(".png");
|
||||
class PathUtil
|
||||
: public ScopedAllocatorSetupFixture
|
||||
{
|
||||
};
|
||||
|
||||
// Create a string of lenth AZ_MAX_PATH_LEN that ends in .png
|
||||
QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
|
||||
longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
|
||||
Path::GamePathToFullPath(longStringMaxPath);
|
||||
TEST_F(PathUtil, GamePathToFullPath_DoesNotBufferOverflow)
|
||||
{
|
||||
// There are no test assertions in this test because the purpose is just to verify that the test runs without crashing
|
||||
QString pngExtension(".png");
|
||||
|
||||
QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
|
||||
longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
|
||||
Path::GamePathToFullPath(longStringMaxPathPlusOne);
|
||||
// Create a string of length AZ_MAX_PATH_LEN that ends in .png
|
||||
QString longStringMaxPath(AZ_MAX_PATH_LEN, 'x');
|
||||
longStringMaxPath.replace(longStringMaxPath.length() - pngExtension.length(), longStringMaxPath.length(), pngExtension);
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
Path::GamePathToFullPath(longStringMaxPath);
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
|
||||
|
||||
QString longStringMaxPathPlusOne(AZ_MAX_PATH_LEN + 1, 'x');
|
||||
longStringMaxPathPlusOne.replace(longStringMaxPathPlusOne.length() - pngExtension.length(), longStringMaxPathPlusOne.length(), pngExtension);
|
||||
Path::GamePathToFullPath(longStringMaxPathPlusOne);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2124,6 +2124,8 @@ bool CCryEditApp::FixDanglingSharedMemory(const QString& sharedMemName) const
|
||||
|
||||
int CCryEditApp::ExitInstance(int exitCode)
|
||||
{
|
||||
AZ_TracePrintf("Exit", "Called ExitInstance() with exit code: 0x%x", exitCode);
|
||||
|
||||
if (m_pEditor)
|
||||
{
|
||||
m_pEditor->OnBeginShutdownSequence();
|
||||
@@ -2642,7 +2644,7 @@ void CCryEditApp::OnFileResaveSlices()
|
||||
sliceAssetInfos.reserve(5000);
|
||||
AZ::Data::AssetCatalogRequests::AssetEnumerationCB sliceCountCb = [&sliceAssetInfos]([[maybe_unused]] const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info)
|
||||
{
|
||||
// Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @devroot@)
|
||||
// Only add slices and nothing that has been temporarily added to the catalog with a macro in it (ie @engroot@)
|
||||
if (info.m_assetType == azrtti_typeid<AZ::SliceAsset>() && info.m_relativePath[0] != '@')
|
||||
{
|
||||
sliceAssetInfos.push_back(info);
|
||||
|
||||
@@ -1108,7 +1108,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
|
||||
if (QFileInfo(filename).isRelative())
|
||||
{
|
||||
// Resolving the path through resolvepath would normalize and lowcase it, and in this case, we don't want that.
|
||||
fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@devassets@"))).absoluteFilePath(fullPathName));
|
||||
fullPathName = Path::ToUnixPath(QDir(QString::fromUtf8(gEnv->pFileIO->GetAlias("@projectroot@"))).absoluteFilePath(fullPathName));
|
||||
}
|
||||
|
||||
if (!CFileUtil::OverwriteFile(fullPathName))
|
||||
@@ -1273,7 +1273,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename)
|
||||
if (savedEntities)
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AzToolsFramework, "CCryEditDoc::SaveLevel Updated PakFile levelEntities.editor_xml");
|
||||
pakFile.UpdateFile("LevelEntities.editor_xml", entitySaveBuffer.begin(), static_cast<int>(entitySaveBuffer.size()));
|
||||
pakFile.UpdateFile("levelentities.editor_xml", entitySaveBuffer.begin(), static_cast<int>(entitySaveBuffer.size()));
|
||||
|
||||
// Save XML archive to pak file.
|
||||
bool bSaved = xmlAr.SaveToPak(Path::GetPath(tempSaveFile), pakFile);
|
||||
@@ -1501,7 +1501,7 @@ bool CCryEditDoc::LoadEntitiesFromLevel(const QString& levelPakFile)
|
||||
bool pakOpened = pakSystem->OpenPack(levelPakFile.toUtf8().data());
|
||||
if (pakOpened)
|
||||
{
|
||||
const QString entityFilename = Path::GetPath(levelPakFile) + "LevelEntities.editor_xml";
|
||||
const QString entityFilename = Path::GetPath(levelPakFile) + "levelentities.editor_xml";
|
||||
|
||||
CCryFile entitiesFile;
|
||||
if (entitiesFile.Open(entityFilename.toUtf8().data(), "rt"))
|
||||
@@ -2159,7 +2159,7 @@ bool CCryEditDoc::LoadXmlArchiveArray(TDocMultiArchive& arrXmlAr, const QString&
|
||||
xmlAr.bLoading = true;
|
||||
|
||||
// bound to the level folder, as if it were the assets folder.
|
||||
// this mounts (whateverlevelname.ly) as @assets@/Levels/whateverlevelname/ and thus it works...
|
||||
// this mounts (whateverlevelname.ly) as @products@/Levels/whateverlevelname/ and thus it works...
|
||||
bool openLevelPakFileSuccess = pIPak->OpenPack(levelPath.toUtf8().data(), absoluteLevelPath.toUtf8().data());
|
||||
if (!openLevelPakFileSuccess)
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ CPythonScriptsDialog::CPythonScriptsDialog(QWidget* parent)
|
||||
{
|
||||
AZ::IO::Path newSourcePath = jsonSourcePathPointer;
|
||||
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
|
||||
// any relative path is underneath the @assets@ alias
|
||||
// any relative path is underneath the @products@ alias
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
AZ::IO::FixedMaxPath replacedAliasPath;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
// Editor
|
||||
#include "CryEdit.h"
|
||||
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CEditorFileMonitor::CEditorFileMonitor()
|
||||
{
|
||||
@@ -177,26 +179,14 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
|
||||
// Make file relative to PrimaryCD folder.
|
||||
QString filename = rChange.filename;
|
||||
|
||||
// Remove game directory if present in path.
|
||||
const QString rootPath =
|
||||
QDir::fromNativeSeparators(QString::fromLatin1(Path::GetEditingRootFolder().c_str()));
|
||||
if (filename.startsWith(rootPath, Qt::CaseInsensitive))
|
||||
{
|
||||
filename = filename.right(filename.length() - rootPath.length());
|
||||
}
|
||||
// Make path relative to the the project directory
|
||||
AZ::IO::Path projectPath{ AZ::Utils::GetProjectPath() };
|
||||
AZ::IO::FixedMaxPath projectRelativeFilePath = AZ::IO::PathView(filename.toUtf8().constData()).LexicallyProximate(
|
||||
projectPath);
|
||||
|
||||
// Make sure there is no leading slash
|
||||
if (!filename.isEmpty() && (filename[0] == '\\' || filename[0] == '/'))
|
||||
if (!projectRelativeFilePath.empty())
|
||||
{
|
||||
filename = filename.mid(1);
|
||||
}
|
||||
|
||||
if (!filename.isEmpty())
|
||||
{
|
||||
//remove game name. Make it relative to the game folder
|
||||
const QString filenameRelGame = RemoveGameName(filename);
|
||||
const int extIndex = filename.lastIndexOf('.');
|
||||
const QString ext = filename.right(filename.length() - 1 - extIndex);
|
||||
AZ::IO::PathView ext = projectRelativeFilePath.Extension();
|
||||
|
||||
// Check for File Monitor callback
|
||||
std::vector<SFileChangeCallback>::iterator iter;
|
||||
@@ -207,15 +197,11 @@ void CEditorFileMonitor::OnFileMonitorChange(const SFileChangeInfo& rChange)
|
||||
// We compare against length of callback string, so we get directory matches as well as full filenames
|
||||
if (sCallback.pListener)
|
||||
{
|
||||
if (sCallback.extension == "*" || ext.compare(sCallback.extension, Qt::CaseInsensitive) == 0)
|
||||
if (sCallback.extension == "*" || AZ::IO::PathView(sCallback.extension.toUtf8().constData()) == ext)
|
||||
{
|
||||
if (filenameRelGame.compare(sCallback.item, Qt::CaseInsensitive) == 0)
|
||||
if (AZ::IO::PathView(sCallback.item.toUtf8().constData()) == projectRelativeFilePath)
|
||||
{
|
||||
sCallback.pListener->OnFileChange(qPrintable(filenameRelGame), IFileChangeListener::EChangeType(rChange.changeType));
|
||||
}
|
||||
else if (filename.compare(sCallback.item, Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
sCallback.pListener->OnFileChange(qPrintable(filename), IFileChangeListener::EChangeType(rChange.changeType));
|
||||
sCallback.pListener->OnFileChange(qPrintable(projectRelativeFilePath.c_str()), IFileChangeListener::EChangeType(rChange.changeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,8 @@ namespace SandboxEditor
|
||||
cameras.AddCamera(m_firstPersonPanCamera);
|
||||
cameras.AddCamera(m_firstPersonTranslateCamera);
|
||||
cameras.AddCamera(m_firstPersonScrollCamera);
|
||||
cameras.AddCamera(m_pivotCamera);
|
||||
cameras.AddCamera(m_firstPersonFocusCamera);
|
||||
cameras.AddCamera(m_orbitCamera);
|
||||
});
|
||||
|
||||
return controller;
|
||||
@@ -111,6 +112,7 @@ namespace SandboxEditor
|
||||
viewportId, &AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Events::BeginCursorCapture);
|
||||
}
|
||||
};
|
||||
|
||||
const auto showCursor = [viewportId = m_viewportId]
|
||||
{
|
||||
if (SandboxEditor::CameraCaptureCursorForLook())
|
||||
@@ -133,7 +135,7 @@ namespace SandboxEditor
|
||||
m_firstPersonRotateCamera->SetActivationEndedFn(showCursor);
|
||||
|
||||
m_firstPersonPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(
|
||||
SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivot);
|
||||
SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivotLook);
|
||||
|
||||
m_firstPersonPanCamera->m_panSpeedFn = []
|
||||
{
|
||||
@@ -153,7 +155,7 @@ namespace SandboxEditor
|
||||
const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds();
|
||||
|
||||
m_firstPersonTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
|
||||
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot);
|
||||
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivotLook);
|
||||
|
||||
m_firstPersonTranslateCamera->m_translateSpeedFn = []
|
||||
{
|
||||
@@ -165,90 +167,111 @@ namespace SandboxEditor
|
||||
return SandboxEditor::CameraBoostMultiplier();
|
||||
};
|
||||
|
||||
m_firstPersonScrollCamera = AZStd::make_shared<AzFramework::ScrollTranslationCameraInput>();
|
||||
m_firstPersonScrollCamera = AZStd::make_shared<AzFramework::LookScrollTranslationCameraInput>();
|
||||
|
||||
m_firstPersonScrollCamera->m_scrollSpeedFn = []
|
||||
{
|
||||
return SandboxEditor::CameraScrollSpeed();
|
||||
};
|
||||
|
||||
m_pivotCamera = AZStd::make_shared<AzFramework::PivotCameraInput>(SandboxEditor::CameraPivotChannelId());
|
||||
const auto pivotFn = []
|
||||
{
|
||||
// use the manipulator transform as the pivot point
|
||||
AZStd::optional<AZ::Transform> entityPivot;
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
|
||||
entityPivot, AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
|
||||
|
||||
m_pivotCamera->SetPivotFn(
|
||||
[]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
|
||||
if (entityPivot.has_value())
|
||||
{
|
||||
// use the manipulator transform as the pivot point
|
||||
AZStd::optional<AZ::Transform> entityPivot;
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
|
||||
entityPivot, AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
|
||||
return entityPivot->GetTranslation();
|
||||
}
|
||||
|
||||
// otherwise just use the identity
|
||||
return entityPivot.value_or(AZ::Transform::CreateIdentity()).GetTranslation();
|
||||
// otherwise just use the identity
|
||||
return AZ::Vector3::CreateZero();
|
||||
};
|
||||
|
||||
m_firstPersonFocusCamera =
|
||||
AZStd::make_shared<AzFramework::FocusCameraInput>(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusLook);
|
||||
|
||||
m_firstPersonFocusCamera->SetPivotFn(pivotFn);
|
||||
|
||||
m_orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>(SandboxEditor::CameraOrbitChannelId());
|
||||
|
||||
m_orbitCamera->SetPivotFn(
|
||||
[pivotFn]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
|
||||
{
|
||||
return pivotFn();
|
||||
});
|
||||
|
||||
m_pivotRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(SandboxEditor::CameraPivotLookChannelId());
|
||||
m_orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(SandboxEditor::CameraOrbitLookChannelId());
|
||||
|
||||
m_pivotRotateCamera->m_rotateSpeedFn = []
|
||||
m_orbitRotateCamera->m_rotateSpeedFn = []
|
||||
{
|
||||
return SandboxEditor::CameraRotateSpeed();
|
||||
};
|
||||
|
||||
m_pivotRotateCamera->m_invertYawFn = []
|
||||
m_orbitRotateCamera->m_invertYawFn = []
|
||||
{
|
||||
return SandboxEditor::CameraPivotYawRotationInverted();
|
||||
return SandboxEditor::CameraOrbitYawRotationInverted();
|
||||
};
|
||||
|
||||
m_pivotTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
|
||||
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffset);
|
||||
m_orbitTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(
|
||||
translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffsetOrbit);
|
||||
|
||||
m_pivotTranslateCamera->m_translateSpeedFn = []
|
||||
m_orbitTranslateCamera->m_translateSpeedFn = []
|
||||
{
|
||||
return SandboxEditor::CameraTranslateSpeed();
|
||||
};
|
||||
|
||||
m_pivotTranslateCamera->m_boostMultiplierFn = []
|
||||
m_orbitTranslateCamera->m_boostMultiplierFn = []
|
||||
{
|
||||
return SandboxEditor::CameraBoostMultiplier();
|
||||
};
|
||||
|
||||
m_pivotDollyScrollCamera = AZStd::make_shared<AzFramework::PivotDollyScrollCameraInput>();
|
||||
m_orbitDollyScrollCamera = AZStd::make_shared<AzFramework::OrbitDollyScrollCameraInput>();
|
||||
|
||||
m_pivotDollyScrollCamera->m_scrollSpeedFn = []
|
||||
m_orbitDollyScrollCamera->m_scrollSpeedFn = []
|
||||
{
|
||||
return SandboxEditor::CameraScrollSpeed();
|
||||
};
|
||||
|
||||
m_pivotDollyMoveCamera = AZStd::make_shared<AzFramework::PivotDollyMotionCameraInput>(SandboxEditor::CameraPivotDollyChannelId());
|
||||
m_orbitDollyMoveCamera = AZStd::make_shared<AzFramework::OrbitDollyMotionCameraInput>(SandboxEditor::CameraOrbitDollyChannelId());
|
||||
|
||||
m_pivotDollyMoveCamera->m_motionSpeedFn = []
|
||||
m_orbitDollyMoveCamera->m_motionSpeedFn = []
|
||||
{
|
||||
return SandboxEditor::CameraDollyMotionSpeed();
|
||||
};
|
||||
|
||||
m_pivotPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(
|
||||
SandboxEditor::CameraPivotPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffset);
|
||||
m_orbitPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(
|
||||
SandboxEditor::CameraOrbitPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffsetOrbit);
|
||||
|
||||
m_pivotPanCamera->m_panSpeedFn = []
|
||||
m_orbitPanCamera->m_panSpeedFn = []
|
||||
{
|
||||
return SandboxEditor::CameraPanSpeed();
|
||||
};
|
||||
|
||||
m_pivotPanCamera->m_invertPanXFn = []
|
||||
m_orbitPanCamera->m_invertPanXFn = []
|
||||
{
|
||||
return SandboxEditor::CameraPanInvertedX();
|
||||
};
|
||||
|
||||
m_pivotPanCamera->m_invertPanYFn = []
|
||||
m_orbitPanCamera->m_invertPanYFn = []
|
||||
{
|
||||
return SandboxEditor::CameraPanInvertedY();
|
||||
};
|
||||
|
||||
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotRotateCamera);
|
||||
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotTranslateCamera);
|
||||
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyScrollCamera);
|
||||
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyMoveCamera);
|
||||
m_pivotCamera->m_pivotCameras.AddCamera(m_pivotPanCamera);
|
||||
m_orbitFocusCamera =
|
||||
AZStd::make_shared<AzFramework::FocusCameraInput>(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusOrbit);
|
||||
|
||||
m_orbitFocusCamera->SetPivotFn(pivotFn);
|
||||
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitRotateCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitTranslateCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyScrollCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyMoveCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitPanCamera);
|
||||
m_orbitCamera->m_orbitCameras.AddCamera(m_orbitFocusCamera);
|
||||
}
|
||||
|
||||
void EditorModularViewportCameraComposer::OnEditorModularViewportCameraComposerSettingsChanged()
|
||||
@@ -257,12 +280,14 @@ namespace SandboxEditor
|
||||
m_firstPersonTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
|
||||
m_firstPersonPanCamera->SetPanInputChannelId(SandboxEditor::CameraFreePanChannelId());
|
||||
m_firstPersonRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraFreeLookChannelId());
|
||||
m_firstPersonFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId());
|
||||
|
||||
m_pivotCamera->SetPivotInputChannelId(SandboxEditor::CameraPivotChannelId());
|
||||
m_pivotTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
|
||||
m_pivotPanCamera->SetPanInputChannelId(SandboxEditor::CameraPivotPanChannelId());
|
||||
m_pivotRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraPivotLookChannelId());
|
||||
m_pivotDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraPivotDollyChannelId());
|
||||
m_orbitCamera->SetOrbitInputChannelId(SandboxEditor::CameraOrbitChannelId());
|
||||
m_orbitTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds);
|
||||
m_orbitPanCamera->SetPanInputChannelId(SandboxEditor::CameraOrbitPanChannelId());
|
||||
m_orbitRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraOrbitLookChannelId());
|
||||
m_orbitDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraOrbitDollyChannelId());
|
||||
m_orbitFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId());
|
||||
}
|
||||
|
||||
void EditorModularViewportCameraComposer::OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId)
|
||||
|
||||
@@ -41,13 +41,15 @@ namespace SandboxEditor
|
||||
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_firstPersonRotateCamera;
|
||||
AZStd::shared_ptr<AzFramework::PanCameraInput> m_firstPersonPanCamera;
|
||||
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_firstPersonTranslateCamera;
|
||||
AZStd::shared_ptr<AzFramework::ScrollTranslationCameraInput> m_firstPersonScrollCamera;
|
||||
AZStd::shared_ptr<AzFramework::PivotCameraInput> m_pivotCamera;
|
||||
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_pivotRotateCamera;
|
||||
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_pivotTranslateCamera;
|
||||
AZStd::shared_ptr<AzFramework::PivotDollyScrollCameraInput> m_pivotDollyScrollCamera;
|
||||
AZStd::shared_ptr<AzFramework::PivotDollyMotionCameraInput> m_pivotDollyMoveCamera;
|
||||
AZStd::shared_ptr<AzFramework::PanCameraInput> m_pivotPanCamera;
|
||||
AZStd::shared_ptr<AzFramework::LookScrollTranslationCameraInput> m_firstPersonScrollCamera;
|
||||
AZStd::shared_ptr<AzFramework::FocusCameraInput> m_firstPersonFocusCamera;
|
||||
AZStd::shared_ptr<AzFramework::OrbitCameraInput> m_orbitCamera;
|
||||
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_orbitRotateCamera;
|
||||
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_orbitTranslateCamera;
|
||||
AZStd::shared_ptr<AzFramework::OrbitDollyScrollCameraInput> m_orbitDollyScrollCamera;
|
||||
AZStd::shared_ptr<AzFramework::OrbitDollyMotionCameraInput> m_orbitDollyMoveCamera;
|
||||
AZStd::shared_ptr<AzFramework::PanCameraInput> m_orbitPanCamera;
|
||||
AZStd::shared_ptr<AzFramework::FocusCameraInput> m_orbitFocusCamera;
|
||||
|
||||
AzFramework::ViewportId m_viewportId;
|
||||
};
|
||||
|
||||
@@ -73,7 +73,7 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
|
||||
->Field("TranslateSmoothing", &CameraMovementSettings::m_translateSmoothing)
|
||||
->Field("TranslateSmoothness", &CameraMovementSettings::m_translateSmoothness)
|
||||
->Field("CaptureCursorLook", &CameraMovementSettings::m_captureCursorLook)
|
||||
->Field("PivotYawRotationInverted", &CameraMovementSettings::m_pivotYawRotationInverted)
|
||||
->Field("OrbitYawRotationInverted", &CameraMovementSettings::m_orbitYawRotationInverted)
|
||||
->Field("PanInvertedX", &CameraMovementSettings::m_panInvertedX)
|
||||
->Field("PanInvertedY", &CameraMovementSettings::m_panInvertedY);
|
||||
|
||||
@@ -86,12 +86,13 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
|
||||
->Field("TranslateUp", &CameraInputSettings::m_translateUpChannelId)
|
||||
->Field("TranslateDown", &CameraInputSettings::m_translateDownChannelId)
|
||||
->Field("Boost", &CameraInputSettings::m_boostChannelId)
|
||||
->Field("Pivot", &CameraInputSettings::m_pivotChannelId)
|
||||
->Field("Orbit", &CameraInputSettings::m_orbitChannelId)
|
||||
->Field("FreeLook", &CameraInputSettings::m_freeLookChannelId)
|
||||
->Field("FreePan", &CameraInputSettings::m_freePanChannelId)
|
||||
->Field("PivotLook", &CameraInputSettings::m_pivotLookChannelId)
|
||||
->Field("PivotDolly", &CameraInputSettings::m_pivotDollyChannelId)
|
||||
->Field("PivotPan", &CameraInputSettings::m_pivotPanChannelId);
|
||||
->Field("OrbitLook", &CameraInputSettings::m_orbitLookChannelId)
|
||||
->Field("OrbitDolly", &CameraInputSettings::m_orbitDollyChannelId)
|
||||
->Field("OrbitPan", &CameraInputSettings::m_orbitPanChannelId)
|
||||
->Field("Focus", &CameraInputSettings::m_focusChannelId);
|
||||
|
||||
serialize.Class<CEditorPreferencesPage_ViewportCamera>()
|
||||
->Version(1)
|
||||
@@ -143,8 +144,8 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
|
||||
->Attribute(AZ::Edit::Attributes::Min, minValue)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &CameraMovementSettings::TranslateSmoothingVisibility)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_pivotYawRotationInverted, "Camera Pivot Yaw Inverted",
|
||||
"Inverted yaw rotation while pivoting")
|
||||
AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_orbitYawRotationInverted, "Camera Orbit Yaw Inverted",
|
||||
"Inverted yaw rotation while orbiting")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_panInvertedX, "Invert Pan X",
|
||||
"Invert direction of pan in local X axis")
|
||||
@@ -185,8 +186,8 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
|
||||
"Key/button to move the camera more quickly")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotChannelId, "Pivot",
|
||||
"Key/button to begin the camera pivot behavior")
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitChannelId, "Orbit",
|
||||
"Key/button to begin the camera orbit behavior")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freeLookChannelId, "Free Look",
|
||||
@@ -196,24 +197,27 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freePanChannelId, "Free Pan", "Key/button to begin camera free pan")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotLookChannelId, "Pivot Look",
|
||||
"Key/button to begin camera pivot look")
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitLookChannelId, "Orbit Look",
|
||||
"Key/button to begin camera orbit look")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotDollyChannelId, "Pivot Dolly",
|
||||
"Key/button to begin camera pivot dolly")
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitDollyChannelId, "Orbit Dolly",
|
||||
"Key/button to begin camera orbit dolly")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotPanChannelId, "Pivot Pan",
|
||||
"Key/button to begin camera pivot pan")
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitPanChannelId, "Orbit Pan",
|
||||
"Key/button to begin camera orbit pan")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_focusChannelId, "Focus", "Key/button to focus camera orbit")
|
||||
->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames);
|
||||
|
||||
editContext->Class<CEditorPreferencesPage_ViewportCamera>("Viewport Preferences", "Viewport Preferences")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportCamera::m_cameraMovementSettings,
|
||||
"Camera Movement Settings", "Camera Movement Settings")
|
||||
AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportCamera::m_cameraMovementSettings, "Camera Movement Settings",
|
||||
"Camera Movement Settings")
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_ViewportCamera::m_cameraInputSettings, "Camera Input Settings",
|
||||
"Camera Input Settings");
|
||||
@@ -264,7 +268,7 @@ void CEditorPreferencesPage_ViewportCamera::OnApply()
|
||||
SandboxEditor::SetCameraTranslateSmoothness(m_cameraMovementSettings.m_translateSmoothness);
|
||||
SandboxEditor::SetCameraTranslateSmoothingEnabled(m_cameraMovementSettings.m_translateSmoothing);
|
||||
SandboxEditor::SetCameraCaptureCursorForLook(m_cameraMovementSettings.m_captureCursorLook);
|
||||
SandboxEditor::SetCameraPivotYawRotationInverted(m_cameraMovementSettings.m_pivotYawRotationInverted);
|
||||
SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_orbitYawRotationInverted);
|
||||
SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_panInvertedX);
|
||||
SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_panInvertedY);
|
||||
|
||||
@@ -275,12 +279,13 @@ void CEditorPreferencesPage_ViewportCamera::OnApply()
|
||||
SandboxEditor::SetCameraTranslateUpChannelId(m_cameraInputSettings.m_translateUpChannelId);
|
||||
SandboxEditor::SetCameraTranslateDownChannelId(m_cameraInputSettings.m_translateDownChannelId);
|
||||
SandboxEditor::SetCameraTranslateBoostChannelId(m_cameraInputSettings.m_boostChannelId);
|
||||
SandboxEditor::SetCameraPivotChannelId(m_cameraInputSettings.m_pivotChannelId);
|
||||
SandboxEditor::SetCameraOrbitChannelId(m_cameraInputSettings.m_orbitChannelId);
|
||||
SandboxEditor::SetCameraFreeLookChannelId(m_cameraInputSettings.m_freeLookChannelId);
|
||||
SandboxEditor::SetCameraFreePanChannelId(m_cameraInputSettings.m_freePanChannelId);
|
||||
SandboxEditor::SetCameraPivotLookChannelId(m_cameraInputSettings.m_pivotLookChannelId);
|
||||
SandboxEditor::SetCameraPivotDollyChannelId(m_cameraInputSettings.m_pivotDollyChannelId);
|
||||
SandboxEditor::SetCameraPivotPanChannelId(m_cameraInputSettings.m_pivotPanChannelId);
|
||||
SandboxEditor::SetCameraOrbitLookChannelId(m_cameraInputSettings.m_orbitLookChannelId);
|
||||
SandboxEditor::SetCameraOrbitDollyChannelId(m_cameraInputSettings.m_orbitDollyChannelId);
|
||||
SandboxEditor::SetCameraOrbitPanChannelId(m_cameraInputSettings.m_orbitPanChannelId);
|
||||
SandboxEditor::SetCameraFocusChannelId(m_cameraInputSettings.m_focusChannelId);
|
||||
|
||||
SandboxEditor::EditorModularViewportCameraComposerNotificationBus::Broadcast(
|
||||
&SandboxEditor::EditorModularViewportCameraComposerNotificationBus::Events::OnEditorModularViewportCameraComposerSettingsChanged);
|
||||
@@ -299,7 +304,7 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings()
|
||||
m_cameraMovementSettings.m_translateSmoothness = SandboxEditor::CameraTranslateSmoothness();
|
||||
m_cameraMovementSettings.m_translateSmoothing = SandboxEditor::CameraTranslateSmoothingEnabled();
|
||||
m_cameraMovementSettings.m_captureCursorLook = SandboxEditor::CameraCaptureCursorForLook();
|
||||
m_cameraMovementSettings.m_pivotYawRotationInverted = SandboxEditor::CameraPivotYawRotationInverted();
|
||||
m_cameraMovementSettings.m_orbitYawRotationInverted = SandboxEditor::CameraOrbitYawRotationInverted();
|
||||
m_cameraMovementSettings.m_panInvertedX = SandboxEditor::CameraPanInvertedX();
|
||||
m_cameraMovementSettings.m_panInvertedY = SandboxEditor::CameraPanInvertedY();
|
||||
|
||||
@@ -310,10 +315,11 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings()
|
||||
m_cameraInputSettings.m_translateUpChannelId = SandboxEditor::CameraTranslateUpChannelId().GetName();
|
||||
m_cameraInputSettings.m_translateDownChannelId = SandboxEditor::CameraTranslateDownChannelId().GetName();
|
||||
m_cameraInputSettings.m_boostChannelId = SandboxEditor::CameraTranslateBoostChannelId().GetName();
|
||||
m_cameraInputSettings.m_pivotChannelId = SandboxEditor::CameraPivotChannelId().GetName();
|
||||
m_cameraInputSettings.m_orbitChannelId = SandboxEditor::CameraOrbitChannelId().GetName();
|
||||
m_cameraInputSettings.m_freeLookChannelId = SandboxEditor::CameraFreeLookChannelId().GetName();
|
||||
m_cameraInputSettings.m_freePanChannelId = SandboxEditor::CameraFreePanChannelId().GetName();
|
||||
m_cameraInputSettings.m_pivotLookChannelId = SandboxEditor::CameraPivotLookChannelId().GetName();
|
||||
m_cameraInputSettings.m_pivotDollyChannelId = SandboxEditor::CameraPivotDollyChannelId().GetName();
|
||||
m_cameraInputSettings.m_pivotPanChannelId = SandboxEditor::CameraPivotPanChannelId().GetName();
|
||||
m_cameraInputSettings.m_orbitLookChannelId = SandboxEditor::CameraOrbitLookChannelId().GetName();
|
||||
m_cameraInputSettings.m_orbitDollyChannelId = SandboxEditor::CameraOrbitDollyChannelId().GetName();
|
||||
m_cameraInputSettings.m_orbitPanChannelId = SandboxEditor::CameraOrbitPanChannelId().GetName();
|
||||
m_cameraInputSettings.m_focusChannelId = SandboxEditor::CameraFocusChannelId().GetName();
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
float m_translateSmoothness;
|
||||
bool m_translateSmoothing;
|
||||
bool m_captureCursorLook;
|
||||
bool m_pivotYawRotationInverted;
|
||||
bool m_orbitYawRotationInverted;
|
||||
bool m_panInvertedX;
|
||||
bool m_panInvertedY;
|
||||
|
||||
@@ -80,12 +80,13 @@ private:
|
||||
AZStd::string m_translateUpChannelId;
|
||||
AZStd::string m_translateDownChannelId;
|
||||
AZStd::string m_boostChannelId;
|
||||
AZStd::string m_pivotChannelId;
|
||||
AZStd::string m_orbitChannelId;
|
||||
AZStd::string m_freeLookChannelId;
|
||||
AZStd::string m_freePanChannelId;
|
||||
AZStd::string m_pivotLookChannelId;
|
||||
AZStd::string m_pivotDollyChannelId;
|
||||
AZStd::string m_pivotPanChannelId;
|
||||
AZStd::string m_orbitLookChannelId;
|
||||
AZStd::string m_orbitDollyChannelId;
|
||||
AZStd::string m_orbitPanChannelId;
|
||||
AZStd::string m_focusChannelId;
|
||||
};
|
||||
|
||||
CameraMovementSettings m_cameraMovementSettings;
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace SandboxEditor
|
||||
constexpr AZStd::string_view CameraRotateSpeedSetting = "/Amazon/Preferences/Editor/Camera/RotateSpeed";
|
||||
constexpr AZStd::string_view CameraScrollSpeedSetting = "/Amazon/Preferences/Editor/Camera/DollyScrollSpeed";
|
||||
constexpr AZStd::string_view CameraDollyMotionSpeedSetting = "/Amazon/Preferences/Editor/Camera/DollyMotionSpeed";
|
||||
constexpr AZStd::string_view CameraPivotYawRotationInvertedSetting = "/Amazon/Preferences/Editor/Camera/YawRotationInverted";
|
||||
constexpr AZStd::string_view CameraOrbitYawRotationInvertedSetting = "/Amazon/Preferences/Editor/Camera/YawRotationInverted";
|
||||
constexpr AZStd::string_view CameraPanInvertedXSetting = "/Amazon/Preferences/Editor/Camera/PanInvertedX";
|
||||
constexpr AZStd::string_view CameraPanInvertedYSetting = "/Amazon/Preferences/Editor/Camera/PanInvertedY";
|
||||
constexpr AZStd::string_view CameraPanSpeedSetting = "/Amazon/Preferences/Editor/Camera/PanSpeed";
|
||||
@@ -44,12 +44,13 @@ namespace SandboxEditor
|
||||
constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId";
|
||||
constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId";
|
||||
constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId";
|
||||
constexpr AZStd::string_view CameraPivotIdSetting = "/Amazon/Preferences/Editor/Camera/PivotId";
|
||||
constexpr AZStd::string_view CameraOrbitIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitId";
|
||||
constexpr AZStd::string_view CameraFreeLookIdSetting = "/Amazon/Preferences/Editor/Camera/FreeLookId";
|
||||
constexpr AZStd::string_view CameraFreePanIdSetting = "/Amazon/Preferences/Editor/Camera/FreePanId";
|
||||
constexpr AZStd::string_view CameraPivotLookIdSetting = "/Amazon/Preferences/Editor/Camera/PivotLookId";
|
||||
constexpr AZStd::string_view CameraPivotDollyIdSetting = "/Amazon/Preferences/Editor/Camera/PivotDollyId";
|
||||
constexpr AZStd::string_view CameraPivotPanIdSetting = "/Amazon/Preferences/Editor/Camera/PivotPanId";
|
||||
constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId";
|
||||
constexpr AZStd::string_view CameraOrbitDollyIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitDollyId";
|
||||
constexpr AZStd::string_view CameraOrbitPanIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitPanId";
|
||||
constexpr AZStd::string_view CameraFocusIdSetting = "/Amazon/Preferences/Editor/Camera/FocusId";
|
||||
|
||||
template<typename T>
|
||||
void SetRegistry(const AZStd::string_view setting, T&& value)
|
||||
@@ -239,14 +240,14 @@ namespace SandboxEditor
|
||||
SetRegistry(CameraDollyMotionSpeedSetting, speed);
|
||||
}
|
||||
|
||||
bool CameraPivotYawRotationInverted()
|
||||
bool CameraOrbitYawRotationInverted()
|
||||
{
|
||||
return GetRegistry(CameraPivotYawRotationInvertedSetting, false);
|
||||
return GetRegistry(CameraOrbitYawRotationInvertedSetting, false);
|
||||
}
|
||||
|
||||
void SetCameraPivotYawRotationInverted(const bool inverted)
|
||||
void SetCameraOrbitYawRotationInverted(const bool inverted)
|
||||
{
|
||||
SetRegistry(CameraPivotYawRotationInvertedSetting, inverted);
|
||||
SetRegistry(CameraOrbitYawRotationInvertedSetting, inverted);
|
||||
}
|
||||
|
||||
bool CameraPanInvertedX()
|
||||
@@ -403,14 +404,14 @@ namespace SandboxEditor
|
||||
SetRegistry(CameraTranslateBoostIdSetting, cameraTranslateBoostId);
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId CameraPivotChannelId()
|
||||
AzFramework::InputChannelId CameraOrbitChannelId()
|
||||
{
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraPivotIdSetting, AZStd::string("keyboard_key_modifier_alt_l")).c_str());
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraOrbitIdSetting, AZStd::string("keyboard_key_modifier_alt_l")).c_str());
|
||||
}
|
||||
|
||||
void SetCameraPivotChannelId(AZStd::string_view cameraPivotId)
|
||||
void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId)
|
||||
{
|
||||
SetRegistry(CameraPivotIdSetting, cameraPivotId);
|
||||
SetRegistry(CameraOrbitIdSetting, cameraOrbitId);
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId CameraFreeLookChannelId()
|
||||
@@ -433,33 +434,43 @@ namespace SandboxEditor
|
||||
SetRegistry(CameraFreePanIdSetting, cameraFreePanId);
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId CameraPivotLookChannelId()
|
||||
AzFramework::InputChannelId CameraOrbitLookChannelId()
|
||||
{
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraPivotLookIdSetting, AZStd::string("mouse_button_left")).c_str());
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str());
|
||||
}
|
||||
|
||||
void SetCameraPivotLookChannelId(AZStd::string_view cameraPivotLookId)
|
||||
void SetCameraOrbitLookChannelId(AZStd::string_view cameraOrbitLookId)
|
||||
{
|
||||
SetRegistry(CameraPivotLookIdSetting, cameraPivotLookId);
|
||||
SetRegistry(CameraOrbitLookIdSetting, cameraOrbitLookId);
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId CameraPivotDollyChannelId()
|
||||
AzFramework::InputChannelId CameraOrbitDollyChannelId()
|
||||
{
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraPivotDollyIdSetting, AZStd::string("mouse_button_right")).c_str());
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraOrbitDollyIdSetting, AZStd::string("mouse_button_right")).c_str());
|
||||
}
|
||||
|
||||
void SetCameraPivotDollyChannelId(AZStd::string_view cameraPivotDollyId)
|
||||
void SetCameraOrbitDollyChannelId(AZStd::string_view cameraOrbitDollyId)
|
||||
{
|
||||
SetRegistry(CameraPivotDollyIdSetting, cameraPivotDollyId);
|
||||
SetRegistry(CameraOrbitDollyIdSetting, cameraOrbitDollyId);
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId CameraPivotPanChannelId()
|
||||
AzFramework::InputChannelId CameraOrbitPanChannelId()
|
||||
{
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraPivotPanIdSetting, AZStd::string("mouse_button_middle")).c_str());
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraOrbitPanIdSetting, AZStd::string("mouse_button_middle")).c_str());
|
||||
}
|
||||
|
||||
void SetCameraPivotPanChannelId(AZStd::string_view cameraPivotPanId)
|
||||
void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId)
|
||||
{
|
||||
SetRegistry(CameraPivotPanIdSetting, cameraPivotPanId);
|
||||
SetRegistry(CameraOrbitPanIdSetting, cameraOrbitPanId);
|
||||
}
|
||||
|
||||
AzFramework::InputChannelId CameraFocusChannelId()
|
||||
{
|
||||
return AzFramework::InputChannelId(GetRegistry(CameraFocusIdSetting, AZStd::string("keyboard_key_alphanumeric_X")).c_str());
|
||||
}
|
||||
|
||||
void SetCameraFocusChannelId(AZStd::string_view cameraFocusId)
|
||||
{
|
||||
SetRegistry(CameraFocusIdSetting, cameraFocusId);
|
||||
}
|
||||
} // namespace SandboxEditor
|
||||
|
||||
@@ -71,8 +71,8 @@ namespace SandboxEditor
|
||||
SANDBOX_API float CameraDollyMotionSpeed();
|
||||
SANDBOX_API void SetCameraDollyMotionSpeed(float speed);
|
||||
|
||||
SANDBOX_API bool CameraPivotYawRotationInverted();
|
||||
SANDBOX_API void SetCameraPivotYawRotationInverted(bool inverted);
|
||||
SANDBOX_API bool CameraOrbitYawRotationInverted();
|
||||
SANDBOX_API void SetCameraOrbitYawRotationInverted(bool inverted);
|
||||
|
||||
SANDBOX_API bool CameraPanInvertedX();
|
||||
SANDBOX_API void SetCameraPanInvertedX(bool inverted);
|
||||
@@ -119,8 +119,8 @@ namespace SandboxEditor
|
||||
SANDBOX_API AzFramework::InputChannelId CameraTranslateBoostChannelId();
|
||||
SANDBOX_API void SetCameraTranslateBoostChannelId(AZStd::string_view cameraTranslateBoostId);
|
||||
|
||||
SANDBOX_API AzFramework::InputChannelId CameraPivotChannelId();
|
||||
SANDBOX_API void SetCameraPivotChannelId(AZStd::string_view cameraPivotId);
|
||||
SANDBOX_API AzFramework::InputChannelId CameraOrbitChannelId();
|
||||
SANDBOX_API void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId);
|
||||
|
||||
SANDBOX_API AzFramework::InputChannelId CameraFreeLookChannelId();
|
||||
SANDBOX_API void SetCameraFreeLookChannelId(AZStd::string_view cameraFreeLookId);
|
||||
@@ -128,12 +128,15 @@ namespace SandboxEditor
|
||||
SANDBOX_API AzFramework::InputChannelId CameraFreePanChannelId();
|
||||
SANDBOX_API void SetCameraFreePanChannelId(AZStd::string_view cameraFreePanId);
|
||||
|
||||
SANDBOX_API AzFramework::InputChannelId CameraPivotLookChannelId();
|
||||
SANDBOX_API void SetCameraPivotLookChannelId(AZStd::string_view cameraPivotLookId);
|
||||
SANDBOX_API AzFramework::InputChannelId CameraOrbitLookChannelId();
|
||||
SANDBOX_API void SetCameraOrbitLookChannelId(AZStd::string_view cameraOrbitLookId);
|
||||
|
||||
SANDBOX_API AzFramework::InputChannelId CameraPivotDollyChannelId();
|
||||
SANDBOX_API void SetCameraPivotDollyChannelId(AZStd::string_view cameraPivotDollyId);
|
||||
SANDBOX_API AzFramework::InputChannelId CameraOrbitDollyChannelId();
|
||||
SANDBOX_API void SetCameraOrbitDollyChannelId(AZStd::string_view cameraOrbitDollyId);
|
||||
|
||||
SANDBOX_API AzFramework::InputChannelId CameraPivotPanChannelId();
|
||||
SANDBOX_API void SetCameraPivotPanChannelId(AZStd::string_view cameraPivotPanId);
|
||||
SANDBOX_API AzFramework::InputChannelId CameraOrbitPanChannelId();
|
||||
SANDBOX_API void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId);
|
||||
|
||||
SANDBOX_API AzFramework::InputChannelId CameraFocusChannelId();
|
||||
SANDBOX_API void SetCameraFocusChannelId(AZStd::string_view cameraFocusId);
|
||||
} // namespace SandboxEditor
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "Objects/EntityObject.h"
|
||||
|
||||
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#define MUSIC_LEVEL_LIBRARY_FILE "Music.xml"
|
||||
|
||||
@@ -35,8 +35,6 @@ struct IDisplayViewport
|
||||
*/
|
||||
virtual float GetDistanceToLine(const Vec3& lineP1, const Vec3& lineP2, const QPoint& point) const = 0;
|
||||
|
||||
virtual CBaseObjectsCache* GetVisibleObjectsCache() = 0;
|
||||
|
||||
enum EAxis
|
||||
{
|
||||
AXIS_NONE,
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace UnitTest
|
||||
|
||||
m_rootWidget = AZStd::make_unique<QWidget>();
|
||||
m_rootWidget->setFixedSize(WidgetSize);
|
||||
m_rootWidget->move(0, 0); // explicitly set the widget to be in the upper left corner
|
||||
|
||||
m_controllerList = AZStd::make_shared<AzFramework::ViewportControllerList>();
|
||||
m_controllerList->RegisterViewportContext(TestViewportId);
|
||||
@@ -344,4 +345,51 @@ namespace UnitTest
|
||||
// Clean-up
|
||||
HaltCollaborators();
|
||||
}
|
||||
|
||||
// test to verify deltas and cursor positions are handled correctly when the widget is moved
|
||||
TEST_F(ModularViewportCameraControllerFixture, CameraDoesNotStutterAfterWidgetIsMoved)
|
||||
{
|
||||
// Given
|
||||
PrepareCollaborators();
|
||||
SandboxEditor::SetCameraCaptureCursorForLook(true);
|
||||
|
||||
const float deltaTime = 1.0f / 60.0f;
|
||||
|
||||
// When
|
||||
// move cursor to the center of the screen
|
||||
auto start = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2);
|
||||
MouseMove(m_rootWidget.get(), start, QPoint(0, 0));
|
||||
m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
|
||||
|
||||
// move camera right
|
||||
const auto mouseDelta = QPoint(200, 0);
|
||||
MousePressAndMove(m_rootWidget.get(), start, mouseDelta, Qt::MouseButton::RightButton);
|
||||
m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
|
||||
|
||||
QTest::mouseRelease(m_rootWidget.get(), Qt::MouseButton::RightButton, Qt::NoModifier, start + mouseDelta);
|
||||
|
||||
// update the position of the widget
|
||||
const auto offset = QPoint(500, 500);
|
||||
m_rootWidget->move(offset);
|
||||
|
||||
// move cursor back to widget center
|
||||
MouseMove(m_rootWidget.get(), start, QPoint(0, 0));
|
||||
m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
|
||||
|
||||
// move camera left
|
||||
MousePressAndMove(m_rootWidget.get(), start, -mouseDelta, Qt::MouseButton::RightButton);
|
||||
m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() });
|
||||
|
||||
// Then
|
||||
// ensure the camera rotation has returned to the identity
|
||||
const AZ::Quaternion cameraRotation = m_cameraViewportContextView->GetCameraTransform().GetRotation();
|
||||
const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromQuaternion(cameraRotation));
|
||||
|
||||
using ::testing::FloatNear;
|
||||
EXPECT_THAT(eulerAngles.GetX(), FloatNear(0.0f, 0.001f));
|
||||
EXPECT_THAT(eulerAngles.GetZ(), FloatNear(0.0f, 0.001f));
|
||||
|
||||
// Clean-up
|
||||
HaltCollaborators();
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -98,6 +98,7 @@ AZ_POP_DISABLE_WARNING
|
||||
#include "ActionManager.h"
|
||||
|
||||
#include <ImGuiBus.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
#include <LmbrCentral/Audio/AudioSystemComponentBus.h>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
@@ -30,13 +30,11 @@
|
||||
#include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h"
|
||||
|
||||
#include <AzCore/Console/Console.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
|
||||
AZ_CVAR_EXTERNED(bool, ed_visibility_logTiming);
|
||||
|
||||
AZ_CVAR(
|
||||
bool, ed_visibility_use, true, nullptr, AZ::ConsoleFunctorFlags::Null,
|
||||
"Enable/disable using the new IVisibilitySystem for Entity visibility determination");
|
||||
|
||||
/*!
|
||||
* Class Description used for object templates.
|
||||
* This description filled from Xml template files.
|
||||
@@ -76,17 +74,6 @@ public:
|
||||
int GameCreationOrder() override { return superType->GameCreationOrder(); };
|
||||
};
|
||||
|
||||
void CBaseObjectsCache::AddObject(CBaseObject* object)
|
||||
{
|
||||
m_objects.push_back(object);
|
||||
if (object->GetType() == OBJTYPE_AZENTITY)
|
||||
{
|
||||
auto componentEntityObject = static_cast<CComponentEntityObject*>(object);
|
||||
m_entityIds.push_back(componentEntityObject->GetAssociatedEntityId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CObjectManager implementation.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -122,14 +109,13 @@ CObjectManager::CObjectManager()
|
||||
m_objectsByName.reserve(1024);
|
||||
LoadRegistry();
|
||||
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
|
||||
AzToolsFramework::GetEntityContextId());
|
||||
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CObjectManager::~CObjectManager()
|
||||
{
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
|
||||
|
||||
m_bExiting = true;
|
||||
SaveRegistry();
|
||||
@@ -1267,25 +1253,8 @@ void CObjectManager::Display(DisplayContext& dc)
|
||||
UpdateVisibilityList();
|
||||
}
|
||||
|
||||
bool viewIsDirty = dc.settings->IsDisplayHelpers(); // displaying helpers require computing all the bound boxes and things anyway.
|
||||
|
||||
if (!viewIsDirty)
|
||||
if (dc.settings->IsDisplayHelpers())
|
||||
{
|
||||
if (CBaseObjectsCache* cache = dc.view->GetVisibleObjectsCache())
|
||||
{
|
||||
// if the current rendering viewport has an out-of-date cache serial number, it needs to be refreshed too.
|
||||
// views set their cache empty when they indicate they need to force a refresh.
|
||||
if ((cache->GetObjectCount() == 0) || (cache->GetSerialNumber() != m_visibilitySerialNumber))
|
||||
{
|
||||
viewIsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (viewIsDirty)
|
||||
{
|
||||
FindDisplayableObjects(dc, true); // this also actually draws the helpers.
|
||||
|
||||
// Also broadcast for anyone else that needs to draw global debug to do so now
|
||||
AzFramework::DebugDisplayEventBus::Broadcast(&AzFramework::DebugDisplayEvents::DrawGlobalDebugInfo);
|
||||
}
|
||||
@@ -1296,94 +1265,14 @@ void CObjectManager::Display(DisplayContext& dc)
|
||||
}
|
||||
}
|
||||
|
||||
void CObjectManager::ForceUpdateVisibleObjectCache(DisplayContext& dc)
|
||||
void CObjectManager::ForceUpdateVisibleObjectCache([[maybe_unused]] DisplayContext& dc)
|
||||
{
|
||||
FindDisplayableObjects(dc, false);
|
||||
AZ_Assert(false, "CObjectManager::ForceUpdateVisibleObjectCache is legacy/deprecated and should not be used.");
|
||||
}
|
||||
|
||||
void CObjectManager::FindDisplayableObjects(DisplayContext& dc, [[maybe_unused]] bool bDisplay)
|
||||
void CObjectManager::FindDisplayableObjects([[maybe_unused]] DisplayContext& dc, [[maybe_unused]] bool bDisplay)
|
||||
{
|
||||
// if the new IVisibilitySystem is being used, do not run this logic
|
||||
if (ed_visibility_use)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_PROFILE_FUNCTION(Editor);
|
||||
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
CBaseObjectsCache* pDispayedViewObjects = dc.view->GetVisibleObjectsCache();
|
||||
if (!pDispayedViewObjects)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pDispayedViewObjects->SetSerialNumber(m_visibilitySerialNumber); // update viewport to be latest serial number
|
||||
|
||||
AABB bbox;
|
||||
bbox.min.zero();
|
||||
bbox.max.zero();
|
||||
|
||||
pDispayedViewObjects->ClearObjects();
|
||||
pDispayedViewObjects->Reserve(static_cast<int>(m_visibleObjects.size()));
|
||||
|
||||
if (dc.flags & DISPLAY_2D)
|
||||
{
|
||||
int numVis = static_cast<int>(m_visibleObjects.size());
|
||||
for (int i = 0; i < numVis; i++)
|
||||
{
|
||||
CBaseObject* obj = m_visibleObjects[i];
|
||||
|
||||
obj->GetBoundBox(bbox);
|
||||
if (dc.box.IsIntersectBox(bbox))
|
||||
{
|
||||
pDispayedViewObjects->AddObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CSelectionGroup* pSelection = GetSelection();
|
||||
if (pSelection && pSelection->GetCount() > 1)
|
||||
{
|
||||
AABB mergedAABB;
|
||||
mergedAABB.Reset();
|
||||
for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i)
|
||||
{
|
||||
CBaseObject* pObj(pSelection->GetObject(i));
|
||||
if (pObj == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AABB aabb;
|
||||
pObj->GetBoundBox(aabb);
|
||||
mergedAABB.Add(aabb);
|
||||
}
|
||||
|
||||
pSelection->GetObject(0)->CBaseObject::DrawDimensions(dc, &mergedAABB);
|
||||
}
|
||||
|
||||
int numVis = static_cast<int>(m_visibleObjects.size());
|
||||
for (int i = 0; i < numVis; i++)
|
||||
{
|
||||
CBaseObject* obj = m_visibleObjects[i];
|
||||
|
||||
if (obj)
|
||||
{
|
||||
if ((dc.flags & DISPLAY_SELECTION_HELPERS) || obj->IsSelected())
|
||||
{
|
||||
pDispayedViewObjects->AddObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ed_visibility_logTiming && !ed_visibility_use)
|
||||
{
|
||||
auto stop = std::chrono::steady_clock::now();
|
||||
std::chrono::duration<double> diff = stop - start;
|
||||
AZ_Printf("Visibility", "FindDisplayableObjects (old) - Duration: %f", diff);
|
||||
}
|
||||
AZ_Assert(false, "CObjectManager::FindDisplayableObjects is legacy/deprecated and should not be used.");
|
||||
}
|
||||
|
||||
void CObjectManager::BeginEditParams(CBaseObject* obj, int flags)
|
||||
@@ -1630,214 +1519,24 @@ bool CObjectManager::HitTestObject(CBaseObject* obj, HitContext& hc)
|
||||
return (bSelectionHelperHit || obj->HitTest(hc));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CObjectManager::HitTest(HitContext& hitInfo)
|
||||
bool CObjectManager::HitTest([[maybe_unused]] HitContext& hitInfo)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Editor);
|
||||
|
||||
hitInfo.object = nullptr;
|
||||
hitInfo.dist = FLT_MAX;
|
||||
hitInfo.axis = 0;
|
||||
hitInfo.manipulatorMode = 0;
|
||||
|
||||
HitContext hcOrg = hitInfo;
|
||||
if (hcOrg.view)
|
||||
{
|
||||
hcOrg.view->GetPerpendicularAxis(nullptr, &hcOrg.b2DViewport);
|
||||
}
|
||||
hcOrg.rayDir = hcOrg.rayDir.GetNormalized();
|
||||
|
||||
HitContext hc = hcOrg;
|
||||
|
||||
float mindist = FLT_MAX;
|
||||
|
||||
if (!hitInfo.bIgnoreAxis && !hc.bUseSelectionHelpers)
|
||||
{
|
||||
// Test gizmos.
|
||||
if (m_gizmoManager->HitTest(hc))
|
||||
{
|
||||
if (hc.axis != 0)
|
||||
{
|
||||
hitInfo.object = hc.object;
|
||||
hitInfo.gizmo = hc.gizmo;
|
||||
hitInfo.axis = hc.axis;
|
||||
hitInfo.manipulatorMode = hc.manipulatorMode;
|
||||
hitInfo.dist = hc.dist;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hitInfo.bOnlyGizmo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only HitTest objects, that where previously Displayed.
|
||||
CBaseObjectsCache* pDispayedViewObjects = hitInfo.view->GetVisibleObjectsCache();
|
||||
|
||||
const bool iconsPrioritized = true; // Force icons to always be prioritized over other things you hit. Can change to be a configurable option in the future.
|
||||
|
||||
CBaseObject* selected = nullptr;
|
||||
const char* name = nullptr;
|
||||
bool iconHit = false;
|
||||
int numVis = pDispayedViewObjects->GetObjectCount();
|
||||
for (int i = 0; i < numVis; i++)
|
||||
{
|
||||
CBaseObject* obj = pDispayedViewObjects->GetObject(i);
|
||||
|
||||
if (obj == hitInfo.pExcludedObject)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (HitTestObject(obj, hc))
|
||||
{
|
||||
if (m_selectCallback && !m_selectCallback->CanSelectObject(obj))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if this object is nearest.
|
||||
if (hc.axis != 0)
|
||||
{
|
||||
hitInfo.object = obj;
|
||||
hitInfo.axis = hc.axis;
|
||||
hitInfo.dist = hc.dist;
|
||||
return true;
|
||||
}
|
||||
|
||||
// When prioritizing icons, we don't allow non-icon hits to beat icon hits
|
||||
if (iconsPrioritized && iconHit && !hc.iconHit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hc.dist < mindist || (!iconHit && hc.iconHit))
|
||||
{
|
||||
if (hc.iconHit)
|
||||
{
|
||||
iconHit = true;
|
||||
}
|
||||
|
||||
mindist = hc.dist;
|
||||
name = hc.name;
|
||||
selected = obj;
|
||||
}
|
||||
|
||||
// Clear the object pointer if an object was hit, not just if the collision
|
||||
// was closer than any previous. Not all paths from HitTestObject set the object pointer and so you could get
|
||||
// an object from a previous (rejected) result but with collision information about a closer hit.
|
||||
hc.object = nullptr;
|
||||
hc.iconHit = false;
|
||||
|
||||
// If use deep selection
|
||||
if (hitInfo.pDeepSelection)
|
||||
{
|
||||
hitInfo.pDeepSelection->AddObject(hc.dist, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected)
|
||||
{
|
||||
hitInfo.object = selected;
|
||||
hitInfo.dist = mindist;
|
||||
hitInfo.name = name;
|
||||
hitInfo.iconHit = iconHit;
|
||||
return true;
|
||||
}
|
||||
AZ_Assert(false, "CObjectManager::HitTest is legacy/deprecated and should not be used.");
|
||||
return false;
|
||||
}
|
||||
void CObjectManager::FindObjectsInRect(CViewport* view, const QRect& rect, std::vector<GUID>& guids)
|
||||
|
||||
void CObjectManager::FindObjectsInRect(
|
||||
[[maybe_unused]] CViewport* view, [[maybe_unused]] const QRect& rect, [[maybe_unused]] std::vector<GUID>& guids)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Editor);
|
||||
|
||||
if (rect.width() < 1 || rect.height() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HitContext hc;
|
||||
hc.view = view;
|
||||
hc.b2DViewport = view->GetType() != ET_ViewportCamera;
|
||||
hc.rect = rect;
|
||||
hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
|
||||
|
||||
guids.clear();
|
||||
|
||||
CBaseObjectsCache* pDispayedViewObjects = view->GetVisibleObjectsCache();
|
||||
|
||||
int numVis = pDispayedViewObjects->GetObjectCount();
|
||||
for (int i = 0; i < numVis; ++i)
|
||||
{
|
||||
CBaseObject* pObj = pDispayedViewObjects->GetObject(i);
|
||||
|
||||
HitTestObjectAgainstRect(pObj, view, hc, guids);
|
||||
}
|
||||
AZ_Assert(false, "CObjectManager::FindObjectsInRect is legacy/deprecated and should not be used.");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CObjectManager::SelectObjectsInRect(CViewport* view, const QRect& rect, bool bSelect)
|
||||
void CObjectManager::SelectObjectsInRect(
|
||||
[[maybe_unused]] CViewport* view, [[maybe_unused]] const QRect& rect, [[maybe_unused]] bool bSelect)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Editor);
|
||||
|
||||
// Ignore too small rectangles.
|
||||
if (rect.width() < 1 || rect.height() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CUndo undo("Select Object(s)");
|
||||
|
||||
HitContext hc;
|
||||
hc.view = view;
|
||||
hc.b2DViewport = view->GetType() != ET_ViewportCamera;
|
||||
hc.rect = rect;
|
||||
hc.bUseSelectionHelpers = view->GetAdvancedSelectModeFlag();
|
||||
|
||||
bool isUndoRecording = GetIEditor()->IsUndoRecording();
|
||||
if (isUndoRecording)
|
||||
{
|
||||
m_processingBulkSelect = true;
|
||||
}
|
||||
|
||||
CBaseObjectsCache* displayedViewObjects = view->GetVisibleObjectsCache();
|
||||
int numVis = displayedViewObjects->GetObjectCount();
|
||||
|
||||
// Tracking the previous selection allows proper undo/redo functionality of additional
|
||||
// selections (CTRL + drag select)
|
||||
AZStd::unordered_set<const CBaseObject*> previousSelection;
|
||||
|
||||
for (int i = 0; i < numVis; ++i)
|
||||
{
|
||||
CBaseObject* object = displayedViewObjects->GetObject(i);
|
||||
|
||||
if (object->IsSelected())
|
||||
{
|
||||
previousSelection.insert(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This will update m_currSelection
|
||||
SelectObjectInRect(object, view, hc, bSelect);
|
||||
|
||||
// Legacy undo/redo does not go through the Ebus system and must be done individually
|
||||
if (isUndoRecording && object->GetType() != OBJTYPE_AZENTITY)
|
||||
{
|
||||
GetIEditor()->RecordUndo(new CUndoBaseObjectSelect(object, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isUndoRecording && m_currSelection)
|
||||
{
|
||||
// Component Entities can handle undo/redo in bulk due to Ebuses
|
||||
GetIEditor()->RecordUndo(new CUndoBaseObjectBulkSelect(previousSelection, *m_currSelection));
|
||||
}
|
||||
|
||||
m_processingBulkSelect = false;
|
||||
AZ_Assert(false, "CObjectManager::SelectObjectsInRect is legacy/deprecated and should not be used.");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -2608,25 +2307,33 @@ void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitC
|
||||
}
|
||||
}
|
||||
|
||||
void CObjectManager::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
void CObjectManager::OnEditorModeActivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
// hide current gizmo for entity (translate/rotate/scale)
|
||||
IGizmoManager* gizmoManager = GetGizmoManager();
|
||||
const size_t gizmoCount = static_cast<size_t>(gizmoManager->GetGizmoCount());
|
||||
for (size_t i = 0; i < gizmoCount; ++i)
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast<int>(i)));
|
||||
// hide current gizmo for entity (translate/rotate/scale)
|
||||
IGizmoManager* gizmoManager = GetGizmoManager();
|
||||
const size_t gizmoCount = static_cast<size_t>(gizmoManager->GetGizmoCount());
|
||||
for (size_t i = 0; i < gizmoCount; ++i)
|
||||
{
|
||||
gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast<int>(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CObjectManager::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
void CObjectManager::OnEditorModeDeactivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
// show translate/rotate/scale gizmo again
|
||||
if (IGizmoManager* gizmoManager = GetGizmoManager())
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
|
||||
// show translate/rotate/scale gizmo again
|
||||
if (IGizmoManager* gizmoManager = GetGizmoManager())
|
||||
{
|
||||
gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
|
||||
if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject())
|
||||
{
|
||||
gizmoManager->AddGizmo(new CAxisGizmo(selectedObject));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3011,6 +2718,4 @@ namespace AzToolsFramework
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
#include "ObjectManagerEventBus.h"
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <Include/SandboxAPI.h>
|
||||
|
||||
// forward declarations.
|
||||
@@ -52,47 +53,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Array of editor objects.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CBaseObjectsCache
|
||||
{
|
||||
public:
|
||||
int GetObjectCount() const { return static_cast<int>(m_objects.size()); }
|
||||
CBaseObject* GetObject(int nIndex) const { return m_objects[nIndex]; }
|
||||
void AddObject(CBaseObject* object);
|
||||
|
||||
void ClearObjects()
|
||||
{
|
||||
m_objects.clear();
|
||||
m_entityIds.clear();
|
||||
}
|
||||
|
||||
void Reserve(int nCount)
|
||||
{
|
||||
m_objects.reserve(nCount);
|
||||
m_entityIds.reserve(nCount);
|
||||
}
|
||||
|
||||
const AZStd::vector<AZ::EntityId>& GetEntityIdCache() const { return m_entityIds; }
|
||||
|
||||
/// Checksum is used as a dirty flag.
|
||||
unsigned int GetSerialNumber() { return m_serialNumber; }
|
||||
void SetSerialNumber(unsigned int serialNumber) { m_serialNumber = serialNumber; }
|
||||
private:
|
||||
//! List of objects that was displayed at last frame.
|
||||
std::vector<_smart_ptr<CBaseObject> > m_objects;
|
||||
AZStd::vector<AZ::EntityId> m_entityIds;
|
||||
unsigned int m_serialNumber = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* CObjectManager is a singleton object that
|
||||
* manages global set of objects in level.
|
||||
*/
|
||||
class CObjectManager
|
||||
: public IObjectManager
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
|
||||
{
|
||||
public:
|
||||
//! Selection functor callback.
|
||||
@@ -363,9 +330,11 @@ private:
|
||||
|
||||
void FindDisplayableObjects(DisplayContext& dc, bool bDisplay);
|
||||
|
||||
// EditorComponentModeNotificationBus
|
||||
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
// ViewportEditorModeNotificationsBus overrides ...
|
||||
void OnEditorModeActivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
void OnEditorModeDeactivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
|
||||
private:
|
||||
typedef std::map<GUID, CBaseObjectPtr, guid_less_predicate> Objects;
|
||||
|
||||
@@ -142,8 +142,7 @@ void GetSelectedEntitiesSetWithFlattenedHierarchy(AzToolsFramework::EntityIdSet&
|
||||
}
|
||||
|
||||
SandboxIntegrationManager::SandboxIntegrationManager()
|
||||
: m_inObjectPickMode(false)
|
||||
, m_startedUndoRecordingNestingLevel(0)
|
||||
: m_startedUndoRecordingNestingLevel(0)
|
||||
, m_dc(nullptr)
|
||||
, m_notificationWindowManager(new AzToolsFramework::SliceOverridesNotificationWindowManager())
|
||||
{
|
||||
@@ -1000,62 +999,6 @@ void SandboxIntegrationManager::SetupSliceContextMenu_Modify(QMenu* menu, const
|
||||
revertAction->setEnabled(canRevert);
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::HandleObjectModeSelection(const AZ::Vector2& point, [[maybe_unused]] int flags, bool& handled)
|
||||
{
|
||||
// Todo - Use a custom "edit tool". This will eliminate the need for this bus message entirely, which technically
|
||||
// makes this feature less intrusive on Sandbox.
|
||||
// UPDATE: This is now provided by EditorPickEntitySelection when the new Viewport Interaction Model changes are enabled.
|
||||
if (m_inObjectPickMode)
|
||||
{
|
||||
CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport();
|
||||
const QPoint viewPoint(static_cast<int>(point.GetX()), static_cast<int>(point.GetY()));
|
||||
|
||||
HitContext hitInfo;
|
||||
hitInfo.view = view;
|
||||
if (view->HitTest(viewPoint, hitInfo))
|
||||
{
|
||||
if (hitInfo.object && (hitInfo.object->GetType() == OBJTYPE_AZENTITY))
|
||||
{
|
||||
CComponentEntityObject* entityObject = static_cast<CComponentEntityObject*>(hitInfo.object);
|
||||
AzToolsFramework::EditorPickModeRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorPickModeRequests::PickModeSelectEntity, entityObject->GetAssociatedEntityId());
|
||||
}
|
||||
}
|
||||
|
||||
AzToolsFramework::EditorPickModeRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorPickModeRequests::StopEntityPickMode);
|
||||
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::UpdateObjectModeCursor(AZ::u32& cursorId, AZStd::string& cursorStr)
|
||||
{
|
||||
if (m_inObjectPickMode)
|
||||
{
|
||||
cursorId = static_cast<AZ::u64>(STD_CURSOR_HAND);
|
||||
cursorStr = "Pick an entity...";
|
||||
}
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::OnEntityPickModeStarted()
|
||||
{
|
||||
m_inObjectPickMode = true;
|
||||
|
||||
// Currently this object pick mode is activated only via PropertyEntityIdCtrl picker.
|
||||
// When the picker button is clicked, we transfer focus to the viewport so the
|
||||
// spacebar can still be used to activate selection helpers.
|
||||
if (CViewport* view = GetIEditor()->GetViewManager()->GetGameViewport())
|
||||
{
|
||||
view->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::OnEntityPickModeStopped()
|
||||
{
|
||||
m_inObjectPickMode = false;
|
||||
}
|
||||
|
||||
void SandboxIntegrationManager::CreateEditorRepresentation(AZ::Entity* entity)
|
||||
{
|
||||
IEditor* editor = GetIEditor();
|
||||
@@ -1952,7 +1895,7 @@ void SandboxIntegrationManager::MakeSliceFromEntities(const AzToolsFramework::En
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(entitiesAndDescendants,
|
||||
&AzToolsFramework::ToolsApplicationRequestBus::Events::GatherEntitiesAndAllDescendents, entities);
|
||||
|
||||
const AZStd::string slicesAssetsPath = "@devassets@/Slices";
|
||||
const AZStd::string slicesAssetsPath = "@projectroot@/Slices";
|
||||
|
||||
if (!gEnv->pFileIO->Exists(slicesAssetsPath.c_str()))
|
||||
{
|
||||
|
||||
@@ -93,7 +93,6 @@ namespace AzToolsFramework
|
||||
class SandboxIntegrationManager
|
||||
: private AzToolsFramework::ToolsApplicationEvents::Bus::Handler
|
||||
, private AzToolsFramework::EditorRequests::Bus::Handler
|
||||
, private AzToolsFramework::EditorPickModeNotificationBus::Handler
|
||||
, private AzToolsFramework::EditorContextMenuBus::Handler
|
||||
, private AzToolsFramework::EditorWindowRequests::Bus::Handler
|
||||
, private AzFramework::AssetCatalogEventBus::Handler
|
||||
@@ -140,8 +139,6 @@ private:
|
||||
QDockWidget* InstanceViewPane(const char* paneName) override;
|
||||
void CloseViewPane(const char* paneName) override;
|
||||
void BrowseForAssets(AzToolsFramework::AssetBrowser::AssetSelectionModel& selection) override;
|
||||
void HandleObjectModeSelection(const AZ::Vector2& point, int flags, bool& handled) override;
|
||||
void UpdateObjectModeCursor(AZ::u32& cursorId, AZStd::string& cursorStr) override;
|
||||
void CreateEditorRepresentation(AZ::Entity* entity) override;
|
||||
bool DestroyEditorRepresentation(AZ::EntityId entityId, bool deleteAZEntity) override;
|
||||
void CloneSelection(bool& handled) override;
|
||||
@@ -175,10 +172,6 @@ private:
|
||||
QWidget* GetAppMainWindow() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// EditorPickModeNotificationBus
|
||||
void OnEntityPickModeStarted() override;
|
||||
void OnEntityPickModeStopped() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AzToolsFramework::EditorContextMenu::Bus::Handler overrides
|
||||
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
|
||||
@@ -281,7 +274,6 @@ private:
|
||||
private:
|
||||
AZ::Vector2 m_contextMenuViewPoint;
|
||||
|
||||
int m_inObjectPickMode;
|
||||
short m_startedUndoRecordingNestingLevel; // used in OnBegin/EndUndo to ensure we only accept undo's we started recording
|
||||
|
||||
AzToolsFramework::SliceOverridesNotificationWindowManager* m_notificationWindowManager;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/UI/ComponentPalette/ComponentPaletteUtil.hxx>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QLabel>
|
||||
@@ -267,8 +268,7 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags)
|
||||
ToolsApplicationEvents::Bus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(
|
||||
AzToolsFramework::GetEntityContextId());
|
||||
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
@@ -276,7 +276,7 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags)
|
||||
OutlinerWidget::~OutlinerWidget()
|
||||
{
|
||||
AzToolsFramework::EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect();
|
||||
EntityHighlightMessages::Bus::Handler::BusDisconnect();
|
||||
@@ -1335,14 +1335,22 @@ void OutlinerWidget::SetEditorUiEnabled(bool enable)
|
||||
EnableUi(enable);
|
||||
}
|
||||
|
||||
void OutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
void OutlinerWidget::OnEditorModeActivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
EnableUi(false);
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
EnableUi(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector<AZ::Uuid>& componentModeTypes)
|
||||
void OutlinerWidget::OnEditorModeDeactivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
EnableUi(true);
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
EnableUi(true);
|
||||
}
|
||||
}
|
||||
|
||||
void OutlinerWidget::OnSliceInstantiated(const AZ::Data::AssetId& /*sliceAssetId*/, AZ::SliceComponent::SliceInstanceAddress& sliceAddress, const AzFramework::SliceInstantiationTicket& /*ticket*/)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <AzCore/base.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/SliceEditorEntityOwnershipServiceBus.h>
|
||||
@@ -58,7 +58,7 @@ class OutlinerWidget
|
||||
, private AzToolsFramework::EditorEntityContextNotificationBus::Handler
|
||||
, private AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler
|
||||
, private AzToolsFramework::EditorEntityInfoNotificationBus::Handler
|
||||
, private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler
|
||||
, private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
|
||||
, private AzToolsFramework::EditorWindowUIRequestBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
@@ -105,9 +105,11 @@ private:
|
||||
void OnEntityInfoUpdatedAddChildEnd(AZ::EntityId /*parentId*/, AZ::EntityId /*childId*/) override;
|
||||
void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& /*name*/) override;
|
||||
|
||||
// EditorComponentModeNotificationBus
|
||||
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
|
||||
// ViewportEditorModeNotificationsBus overrides ...
|
||||
void OnEditorModeActivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
void OnEditorModeDeactivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override;
|
||||
|
||||
// EditorWindowUIRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
@@ -30,6 +30,7 @@ class CXTPDockingPaneLayout; // Needed for settings.h
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <Util/PathUtil.h>
|
||||
@@ -47,41 +48,6 @@ class CXTPDockingPaneLayout; // Needed for settings.h
|
||||
const char* AssetImporterWindow::s_documentationWebAddress = "http://docs.aws.amazon.com/lumberyard/latest/userguide/char-fbx-importer.html";
|
||||
const AZ::Uuid AssetImporterWindow::s_browseTag = AZ::Uuid::CreateString("{C240D2E1-BFD2-4FFA-BB5B-CC0FA389A5D3}");
|
||||
|
||||
void MakeUserFriendlySourceAssetPath(QString& out, const QString& sourcePath)
|
||||
{
|
||||
char devAssetsRoot[AZ_MAX_PATH_LEN] = { 0 };
|
||||
if (!gEnv->pFileIO->ResolvePath("@devroot@", devAssetsRoot, AZ_MAX_PATH_LEN))
|
||||
{
|
||||
out = sourcePath;
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::replace(devAssetsRoot, devAssetsRoot + AZ_MAX_PATH_LEN- 1, AZ_WRONG_FILESYSTEM_SEPARATOR, AZ_CORRECT_FILESYSTEM_SEPARATOR);
|
||||
|
||||
// Find if the sourcePathArray is a sub directory of the devAssets folder
|
||||
// Keep reference to sourcePathArray long enough to use in PathView
|
||||
QByteArray sourcePathArray = sourcePath.toUtf8();
|
||||
AZ::IO::PathView sourcePathRootView(sourcePathArray.data());
|
||||
AZ::IO::PathView devAssetsRootView(devAssetsRoot);
|
||||
auto [sourcePathIter, devAssetsIter] = AZStd::mismatch(sourcePathRootView.begin(), sourcePathRootView.end(),
|
||||
devAssetsRootView.begin(), devAssetsRootView.end());
|
||||
// If the devAssets path iterator is not equal to the end, then there was a mismistch while comparing it
|
||||
// against the source path indicating that the source path is not a sub-directory
|
||||
if (devAssetsIter != devAssetsRootView.end())
|
||||
{
|
||||
out = sourcePath;
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = aznumeric_cast<int>(strlen(devAssetsRoot));
|
||||
if (sourcePath.at(offset) == AZ_CORRECT_FILESYSTEM_SEPARATOR)
|
||||
{
|
||||
++offset;
|
||||
}
|
||||
out = sourcePath.right(sourcePath.length() - offset);
|
||||
|
||||
}
|
||||
|
||||
AssetImporterWindow::AssetImporterWindow()
|
||||
: AssetImporterWindow(nullptr)
|
||||
{
|
||||
@@ -102,7 +68,7 @@ AssetImporterWindow::AssetImporterWindow(QWidget* parent)
|
||||
|
||||
AssetImporterWindow::~AssetImporterWindow()
|
||||
{
|
||||
AZ_Assert(m_processingOverlayIndex == AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
AZ_Assert(m_processingOverlayIndex == AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
"Processing overlay (and potentially background thread) still active at destruction.");
|
||||
AZ_Assert(!m_processingOverlay, "Processing overlay (and potentially background thread) still active at destruction.");
|
||||
}
|
||||
@@ -133,7 +99,7 @@ void AssetImporterWindow::OpenFile(const AZStd::string& filePath)
|
||||
QMessageBox::warning(this, "In progress", "Unable to close one or more windows at this time.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
OpenFileInternal(filePath);
|
||||
}
|
||||
|
||||
@@ -146,7 +112,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
|
||||
|
||||
if (m_processingOverlay)
|
||||
{
|
||||
AZ_Assert(m_processingOverlayIndex != AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
AZ_Assert(m_processingOverlayIndex != AZ::SceneAPI::UI::OverlayWidget::s_invalidOverlayIndex,
|
||||
"Processing overlay present, but not the index in the overlay for it.");
|
||||
if (m_processingOverlay->HasProcessingCompleted())
|
||||
{
|
||||
@@ -157,7 +123,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "Processing In Progress", "Unable to close the result window at this time.",
|
||||
QMessageBox::critical(this, "Processing In Progress", "Unable to close the result window at this time.",
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
ev->ignore();
|
||||
return;
|
||||
@@ -165,7 +131,7 @@ void AssetImporterWindow::closeEvent(QCloseEvent* ev)
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "Processing In Progress", "Please wait until processing has completed to try again.",
|
||||
QMessageBox::critical(this, "Processing In Progress", "Please wait until processing has completed to try again.",
|
||||
QMessageBox::Ok, QMessageBox::Ok);
|
||||
ev->ignore();
|
||||
return;
|
||||
@@ -199,7 +165,9 @@ void AssetImporterWindow::Init()
|
||||
// Load the style sheets
|
||||
AzQtComponents::StylesheetPreprocessor styleSheetProcessor(nullptr);
|
||||
|
||||
AZStd::string mainWindowQSSPath = Path::GetEditingRootFolder() + "\\Editor\\Styles\\AssetImporterWindow.qss";
|
||||
auto mainWindowQSSPath = AZ::IO::Path(AZ::Utils::GetEnginePath()) / "Assets";
|
||||
mainWindowQSSPath /= "Editor/Styles/AssetImporterWindow.qss";
|
||||
mainWindowQSSPath.MakePreferred();
|
||||
QFile mainWindowStyleSheetFile(mainWindowQSSPath.c_str());
|
||||
if (mainWindowStyleSheetFile.open(QFile::ReadOnly))
|
||||
{
|
||||
@@ -212,7 +180,7 @@ void AssetImporterWindow::Init()
|
||||
{
|
||||
ui->m_actionInspect->setVisible(false);
|
||||
}
|
||||
|
||||
|
||||
ResetMenuAccess(WindowState::InitialNothingLoaded);
|
||||
|
||||
// Setup the overlay system, and set the root to be the root display. The root display has the browse,
|
||||
@@ -220,7 +188,7 @@ void AssetImporterWindow::Init()
|
||||
m_overlay.reset(aznew AZ::SceneAPI::UI::OverlayWidget(this));
|
||||
m_rootDisplay.reset(aznew ImporterRootDisplay(m_serializeContext));
|
||||
connect(m_rootDisplay.data(), &ImporterRootDisplay::UpdateClicked, this, &AssetImporterWindow::UpdateClicked);
|
||||
|
||||
|
||||
connect(m_overlay.data(), &AZ::SceneAPI::UI::OverlayWidget::LayerAdded, this, &AssetImporterWindow::OverlayLayerAdded);
|
||||
connect(m_overlay.data(), &AZ::SceneAPI::UI::OverlayWidget::LayerRemoved, this, &AssetImporterWindow::OverlayLayerRemoved);
|
||||
|
||||
@@ -242,7 +210,7 @@ void AssetImporterWindow::Init()
|
||||
AZStd::string joinedExtensions;
|
||||
AzFramework::StringFunc::Join(joinedExtensions, extensions.begin(), extensions.end(), " or ");
|
||||
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string::format(
|
||||
"%s files are available for use after placing them in any folder within your game project. "
|
||||
"These files will automatically be processed and may be accessed via the Asset Browser. <a href=\"%s\">Learn more...</a>",
|
||||
@@ -250,13 +218,13 @@ void AssetImporterWindow::Init()
|
||||
|
||||
ui->m_initialPromptFirstLine->setText(firstLineText.c_str());
|
||||
|
||||
AZStd::string secondLineText =
|
||||
AZStd::string secondLineText =
|
||||
AZStd::string::format("To adjust the %s settings, right-click the file in the Asset Browser and select \"Edit Settings\" from the context menu.", joinedExtensions.c_str());
|
||||
ui->m_initialPromptSecondLine->setText(secondLineText.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string firstLineText =
|
||||
AZStd::string::format(
|
||||
"Files are available for use after placing them in any folder within your game project. "
|
||||
"These files will automatically be processed and may be accessed via the Asset Browser. <a href=\"%s\">Learn more...</a>", s_documentationWebAddress);
|
||||
@@ -282,12 +250,12 @@ void AssetImporterWindow::OpenFileInternal(const AZStd::string& filePath)
|
||||
auto asyncLoadHandler = AZStd::make_shared<AZ::SceneAPI::SceneUI::AsyncOperationProcessingHandler>(
|
||||
s_browseTag,
|
||||
[this, filePath]()
|
||||
{
|
||||
m_assetImporterDocument->LoadScene(filePath);
|
||||
{
|
||||
m_assetImporterDocument->LoadScene(filePath);
|
||||
},
|
||||
[this]()
|
||||
{
|
||||
HandleAssetLoadingCompleted();
|
||||
HandleAssetLoadingCompleted();
|
||||
}, this);
|
||||
|
||||
m_processingOverlay.reset(new ProcessingOverlayWidget(m_overlay.data(), ProcessingOverlayWidget::Layout::Loading, s_browseTag));
|
||||
@@ -304,7 +272,7 @@ bool AssetImporterWindow::IsAllowedToChangeSourceFile()
|
||||
return true;
|
||||
}
|
||||
|
||||
QMessageBox messageBox(QMessageBox::Icon::NoIcon, "Unsaved changes",
|
||||
QMessageBox messageBox(QMessageBox::Icon::NoIcon, "Unsaved changes",
|
||||
"You have unsaved changes. Do you want to discard those changes?",
|
||||
QMessageBox::StandardButton::Discard | QMessageBox::StandardButton::Cancel, this);
|
||||
messageBox.exec();
|
||||
@@ -406,7 +374,7 @@ void AssetImporterWindow::OnSceneResetRequested()
|
||||
else
|
||||
{
|
||||
m_assetImporterDocument->ClearScene();
|
||||
AZ_TracePrintf(ErrorWindow, "Manifest reset returned in '%s'",
|
||||
AZ_TracePrintf(ErrorWindow, "Manifest reset returned in '%s'",
|
||||
result.GetResult() == ProcessingResult::Failure ? "Failure" : "Ignored");
|
||||
}
|
||||
},
|
||||
@@ -456,7 +424,7 @@ void AssetImporterWindow::OnInspect()
|
||||
// make sure the inspector doesn't outlive the AssetImporterWindow, since we own the data it will be inspecting.
|
||||
auto* theInspectWidget = aznew AZ::SceneAPI::UI::SceneGraphInspectWidget(*m_assetImporterDocument->GetScene());
|
||||
QObject::connect(this, &QObject::destroyed, theInspectWidget, [theInspectWidget]() { theInspectWidget->window()->close(); } );
|
||||
|
||||
|
||||
m_overlay->PushLayer(label, theInspectWidget, "Scene Inspector", buttons);
|
||||
}
|
||||
|
||||
@@ -483,7 +451,7 @@ void AssetImporterWindow::OverlayLayerRemoved()
|
||||
else
|
||||
{
|
||||
ResetMenuAccess(WindowState::InitialNothingLoaded);
|
||||
|
||||
|
||||
ui->m_initialBrowseContainer->show();
|
||||
m_rootDisplay->hide();
|
||||
}
|
||||
@@ -533,8 +501,9 @@ void AssetImporterWindow::HandleAssetLoadingCompleted()
|
||||
m_fullSourcePath = m_assetImporterDocument->GetScene()->GetSourceFilename();
|
||||
SetTitle(m_fullSourcePath.c_str());
|
||||
|
||||
QString userFriendlyFileName;
|
||||
MakeUserFriendlySourceAssetPath(userFriendlyFileName, m_fullSourcePath.c_str());
|
||||
AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
|
||||
AZ::IO::FixedMaxPath relativeSourcePath = AZ::IO::PathView(m_fullSourcePath).LexicallyProximate(projectPath);
|
||||
auto userFriendlyFileName = QString::fromUtf8(relativeSourcePath.c_str(), static_cast<int>(relativeSourcePath.Native().size()));
|
||||
m_rootDisplay->SetSceneDisplay(userFriendlyFileName, m_assetImporterDocument->GetScene());
|
||||
|
||||
// Once we've browsed to something successfully, we need to hide the initial browse button layer and
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/algorithm.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/Debug/TraceContext.h>
|
||||
@@ -50,22 +52,15 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZStd::string cleanPath = filePath;
|
||||
if (AzFramework::StringFunc::Path::IsRelative(filePath.c_str()))
|
||||
AZ::IO::Path enginePath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
const char* absolutePath = nullptr;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(absolutePath,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Events::GetAbsoluteDevRootFolderPath);
|
||||
AZ_Assert(absolutePath, "Unable to retrieve the dev folder path");
|
||||
AzFramework::StringFunc::Path::Join(absolutePath, cleanPath.c_str(), cleanPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normalizing is not needed if the path is relative as Join(...) will also normalize.
|
||||
AzFramework::StringFunc::Path::Normalize(cleanPath);
|
||||
settingsRegistry->Get(enginePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
}
|
||||
|
||||
auto sceneIt = m_scenes.find(cleanPath);
|
||||
AZ::IO::Path cleanPath = (enginePath / filePath).LexicallyNormal();
|
||||
|
||||
auto sceneIt = m_scenes.find(cleanPath.Native());
|
||||
if (sceneIt != m_scenes.end())
|
||||
{
|
||||
AZStd::shared_ptr<SceneAPI::Containers::Scene> scene = sceneIt->second.lock();
|
||||
@@ -98,14 +93,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SceneAPI::Containers::Scene> scene =
|
||||
AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath, sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid());
|
||||
AssetImportRequest::LoadSceneFromVerifiedPath(cleanPath.Native(), sceneSourceGuid, AssetImportRequest::RequestingApplication::Editor, SceneAPI::SceneCore::LoadingComponent::TYPEINFO_Uuid());
|
||||
if (!scene)
|
||||
{
|
||||
AZ_TracePrintf(Utilities::ErrorWindow, "Failed to load the requested scene.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_scenes.emplace(AZStd::move(cleanPath), scene);
|
||||
m_scenes.emplace(AZStd::move(cleanPath.Native()), scene);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ ly_add_target(
|
||||
EDITOR_COMMON_IMPORTS
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::zlib
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Widgets
|
||||
Legacy::CryCommon
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace ProjectSettingsTool
|
||||
, LastPathBus::Handler()
|
||||
, m_ui(new Ui::ProjectSettingsToolWidget())
|
||||
, m_reconfigureProcess()
|
||||
, m_devRoot(GetDevRoot())
|
||||
, m_projectRoot(GetProjectRoot())
|
||||
, m_projectName(GetProjectName())
|
||||
, m_plistsInitVector(
|
||||
|
||||
@@ -147,7 +147,6 @@ namespace ProjectSettingsTool
|
||||
// The process used to reconfigure settings
|
||||
QProcess m_reconfigureProcess;
|
||||
|
||||
AZStd::string m_devRoot;
|
||||
AZStd::string m_projectRoot;
|
||||
AZStd::string m_projectName;
|
||||
|
||||
|
||||
@@ -27,37 +27,31 @@ namespace
|
||||
}
|
||||
|
||||
template<typename StringType>
|
||||
StringType GetAbsoluteDevRoot()
|
||||
StringType GetAbsoluteEngineRoot()
|
||||
{
|
||||
const char* devRoot = nullptr;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
devRoot,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Handler::GetAbsoluteDevRootFolderPath);
|
||||
AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
|
||||
|
||||
if (!devRoot)
|
||||
if (engineRoot.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
StringType devRootString(devRoot);
|
||||
ToUnixPath(devRootString);
|
||||
return devRootString;
|
||||
StringType engineRootString(engineRoot.c_str());
|
||||
ToUnixPath(engineRootString);
|
||||
return engineRootString;
|
||||
}
|
||||
|
||||
template<typename StringType>
|
||||
StringType GetAbsoluteProjectRoot()
|
||||
{
|
||||
const char* projectRoot = nullptr;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
projectRoot,
|
||||
&AzToolsFramework::AssetSystemRequestBus::Handler::GetAbsoluteDevGameFolderPath);
|
||||
AZ::IO::FixedMaxPath projectRoot = AZ::Utils::GetProjectPath();
|
||||
|
||||
if (!projectRoot)
|
||||
if (projectRoot.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
StringType projectRootString(projectRoot);
|
||||
StringType projectRootString(projectRoot.c_str());
|
||||
ToUnixPath(projectRootString);
|
||||
return projectRootString;
|
||||
}
|
||||
@@ -87,9 +81,9 @@ namespace ProjectSettingsTool
|
||||
return reinterpret_cast<void*>(func);
|
||||
}
|
||||
|
||||
AZStd::string GetDevRoot()
|
||||
AZStd::string GetEngineRoot()
|
||||
{
|
||||
return GetAbsoluteDevRoot<AZStd::string>();
|
||||
return GetAbsoluteEngineRoot<AZStd::string>();
|
||||
}
|
||||
AZStd::string GetProjectRoot()
|
||||
{
|
||||
@@ -104,7 +98,7 @@ namespace ProjectSettingsTool
|
||||
QString SelectXmlFromFileDialog(const QString& currentFile)
|
||||
{
|
||||
// The selected file must be relative to this path
|
||||
QString defaultPath = GetAbsoluteDevRoot<QString>();
|
||||
QString defaultPath = GetAbsoluteEngineRoot<QString>();
|
||||
QString startPath;
|
||||
|
||||
// Choose the starting path for file dialog
|
||||
@@ -139,7 +133,7 @@ namespace ProjectSettingsTool
|
||||
|
||||
QString SelectImageFromFileDialog(const QString& currentFile)
|
||||
{
|
||||
QString defaultPath = QStringLiteral("%1Code%2/Resources/").arg(GetAbsoluteDevRoot<QString>(), ::GetProjectName<QString>());
|
||||
QString defaultPath = QStringLiteral("%1Code%2/Resources/").arg(GetAbsoluteEngineRoot<QString>(), ::GetProjectName<QString>());
|
||||
|
||||
QString startPath;
|
||||
|
||||
@@ -188,7 +182,7 @@ namespace ProjectSettingsTool
|
||||
// Android
|
||||
if (group <= ImageGroup::AndroidPortrait)
|
||||
{
|
||||
root = GetDevRoot() + "/Code/Tools/Android/ProjectBuilder/app_";
|
||||
root = GetEngineRoot() + "/Code/Tools/Android/ProjectBuilder/app_";
|
||||
}
|
||||
//Ios
|
||||
else
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
namespace ProjectSettingsTool
|
||||
{
|
||||
void* ConvertFunctorToVoid(AZStd::pair<QValidator::State, const QString>(*func)(const QString&));
|
||||
AZStd::string GetDevRoot();
|
||||
AZStd::string GetEngineRoot();
|
||||
AZStd::string GetProjectRoot();
|
||||
AZStd::string GetProjectName();
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <AzAssetBrowser/AzAssetBrowserWindow.h>
|
||||
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
|
||||
#include <AzQtComponents/Utilities/AutoSettingsGroup.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
#include <AzToolsFramework/UI/Docking/DockWidgetUtils.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx>
|
||||
@@ -44,11 +45,54 @@
|
||||
#include <AzQtComponents/Buses/ShortcutDispatch.h>
|
||||
#include <AzQtComponents/Utilities/QtViewPaneEffects.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
|
||||
#include "ShortcutDispatcher.h"
|
||||
|
||||
// Helper for EditorComponentModeNotifications to be used
|
||||
// as a member instead of inheriting from EBus directly.
|
||||
class ViewportEditorModeNotificationsBusImpl
|
||||
: public AzToolsFramework::ViewportEditorModeNotificationsBus::Handler
|
||||
{
|
||||
public:
|
||||
// Set the function to be called when entering ComponentMode.
|
||||
void SetEnteredComponentModeFunc(
|
||||
const AZStd::function<void(const AzToolsFramework::ViewportEditorModesInterface&)>& enteredComponentModeFunc)
|
||||
{
|
||||
m_enteredComponentModeFunc = enteredComponentModeFunc;
|
||||
}
|
||||
|
||||
// Set the function to be called when leaving ComponentMode.
|
||||
void SetLeftComponentModeFunc(
|
||||
const AZStd::function<void(const AzToolsFramework::ViewportEditorModesInterface&)>& leftComponentModeFunc)
|
||||
{
|
||||
m_leftComponentModeFunc = leftComponentModeFunc;
|
||||
}
|
||||
|
||||
private:
|
||||
// ViewportEditorModeNotificationsBus overrides ...
|
||||
void OnEditorModeActivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override
|
||||
{
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
m_enteredComponentModeFunc(editorModeState);
|
||||
}
|
||||
}
|
||||
|
||||
void OnEditorModeDeactivated(
|
||||
const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override
|
||||
{
|
||||
if (mode == AzToolsFramework::ViewportEditorMode::Component)
|
||||
{
|
||||
m_leftComponentModeFunc(editorModeState);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::function<void(const AzToolsFramework::ViewportEditorModesInterface&)> m_enteredComponentModeFunc; ///< Function to call when entering ComponentMode.
|
||||
AZStd::function<void(const AzToolsFramework::ViewportEditorModesInterface&)> m_leftComponentModeFunc; ///< Function to call when leaving ComponentMode.
|
||||
};
|
||||
|
||||
struct ViewLayoutState
|
||||
{
|
||||
QVector<QString> viewPanes;
|
||||
@@ -519,16 +563,17 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
|
||||
, m_settings(nullptr)
|
||||
, m_restoreInProgress(false)
|
||||
, m_advancedDockManager(nullptr)
|
||||
, m_componentModeNotifications(AZStd::make_unique<ViewportEditorModeNotificationsBusImpl>())
|
||||
{
|
||||
qRegisterMetaTypeStreamOperators<ViewLayoutState>("ViewLayoutState");
|
||||
qRegisterMetaTypeStreamOperators<QVector<QString> >("QVector<QString>");
|
||||
|
||||
// view pane manager is interested when we enter/exit ComponentMode
|
||||
m_componentModeNotifications.BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
m_componentModeNotifications->BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
m_windowRequest.BusConnect();
|
||||
|
||||
m_componentModeNotifications.SetEnteredComponentModeFunc(
|
||||
[this](const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
m_componentModeNotifications->SetEnteredComponentModeFunc(
|
||||
[this](const AzToolsFramework::ViewportEditorModesInterface&)
|
||||
{
|
||||
// gray out panels when entering ComponentMode
|
||||
SetDefaultActionsEnabled(false, m_registeredPanes, [](QWidget* widget, bool on)
|
||||
@@ -537,8 +582,8 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
|
||||
});
|
||||
});
|
||||
|
||||
m_componentModeNotifications.SetLeftComponentModeFunc(
|
||||
[this](const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/)
|
||||
m_componentModeNotifications->SetLeftComponentModeFunc(
|
||||
[this](const AzToolsFramework::ViewportEditorModesInterface&)
|
||||
{
|
||||
// enable panels again when leaving ComponentMode
|
||||
SetDefaultActionsEnabled(true, m_registeredPanes, [](QWidget* widget, bool on)
|
||||
@@ -563,7 +608,7 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent)
|
||||
QtViewPaneManager::~QtViewPaneManager()
|
||||
{
|
||||
m_windowRequest.BusDisconnect();
|
||||
m_componentModeNotifications.BusDisconnect();
|
||||
m_componentModeNotifications->BusDisconnect();
|
||||
}
|
||||
|
||||
static bool lessThan(const QtViewPane& v1, const QtViewPane& v2)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <AzQtComponents/Components/DockTabWidget.h>
|
||||
#include <AzQtComponents/Components/StyledDockWidget.h>
|
||||
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/API/EditorWindowRequestBus.h>
|
||||
|
||||
#include <QObject>
|
||||
@@ -34,6 +33,7 @@
|
||||
#endif
|
||||
|
||||
class QMainWindow;
|
||||
class ViewportEditorModeNotificationsBusImpl;
|
||||
struct ViewLayoutState;
|
||||
|
||||
namespace AzQtComponents
|
||||
@@ -245,9 +245,9 @@ private:
|
||||
|
||||
QPointer<AzQtComponents::FancyDocking> m_advancedDockManager;
|
||||
|
||||
using EditorComponentModeNotificationBusImpl = AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBusImpl;
|
||||
EditorComponentModeNotificationBusImpl m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so
|
||||
//!< QtViewPaneManager does not need to inherit directly from it. */
|
||||
AZStd::unique_ptr<ViewportEditorModeNotificationsBusImpl>
|
||||
m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so
|
||||
//!< QtViewPaneManager does not need to inherit directly from it. */
|
||||
|
||||
using EditorWindowRequestBusImpl = AzToolsFramework::EditorWindowRequestBusImpl;
|
||||
EditorWindowRequestBusImpl m_windowRequest; //!< Helper for EditorWindowRequestBus so
|
||||
|
||||
@@ -935,8 +935,9 @@ void SEditorSettings::LoadDefaultGamePaths()
|
||||
searchPaths[EDITOR_PATH_MATERIALS].push_back((Path::GetEditingGameDataFolder() + "/Materials").c_str());
|
||||
}
|
||||
|
||||
AZStd::string iconsPath;
|
||||
AZ::StringFunc::Path::Join(Path::GetEditingRootFolder().c_str(), "Editor/UI/Icons", iconsPath);
|
||||
auto iconsPath = AZ::IO::Path(AZ::Utils::GetEnginePath()) / "Assets";
|
||||
iconsPath /= "Editor/UI/Icons";
|
||||
iconsPath.MakePreferred();
|
||||
searchPaths[EDITOR_PATH_UI_ICONS].push_back(iconsPath.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange()
|
||||
// Enable/disable the 'remove'/'update' button properly.
|
||||
bool bNoSelection = !m_ui->m_renderList->selectionModel()->hasSelection();
|
||||
m_ui->BATCH_RENDER_REMOVE_SEQ->setEnabled(bNoSelection ? false : true);
|
||||
|
||||
|
||||
CheckForEnableUpdateButton();
|
||||
|
||||
if (bNoSelection)
|
||||
@@ -360,7 +360,7 @@ void CSequenceBatchRenderDialog::OnRenderItemSelChange()
|
||||
cvarsText += item.cvars[static_cast<int>(i)];
|
||||
cvarsText += "\r\n";
|
||||
}
|
||||
m_ui->m_cvarsEdit->setPlainText(cvarsText);
|
||||
m_ui->m_cvarsEdit->setPlainText(cvarsText);
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::CheckForEnableUpdateButton()
|
||||
@@ -494,7 +494,7 @@ void CSequenceBatchRenderDialog::OnSavePreset()
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::stashActiveViewportResolution()
|
||||
{
|
||||
{
|
||||
// stash active resolution in global vars
|
||||
activeViewportWidth = resolutions[0][0];
|
||||
activeViewportHeight = resolutions[0][1];
|
||||
@@ -502,7 +502,7 @@ void CSequenceBatchRenderDialog::stashActiveViewportResolution()
|
||||
if (activeViewport)
|
||||
{
|
||||
activeViewport->GetDimensions(&activeViewportWidth, &activeViewportHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::OnGo()
|
||||
@@ -640,7 +640,7 @@ void CSequenceBatchRenderDialog::OnResolutionSelected()
|
||||
int defaultH;
|
||||
const QString currentCustomResText = m_ui->m_resolutionCombo->currentText();
|
||||
GetResolutionFromCustomResText(currentCustomResText.toStdString().c_str(), defaultW, defaultH);
|
||||
|
||||
|
||||
CCustomResolutionDlg resDlg(defaultW, defaultH, this);
|
||||
if (resDlg.exec() == QDialog::Accepted)
|
||||
{
|
||||
@@ -752,7 +752,7 @@ bool CSequenceBatchRenderDialog::LoadOutputOptions(const QString& pathname)
|
||||
{
|
||||
const QString customResText = resolutionNode->getContent();
|
||||
m_ui->m_resolutionCombo->setItemText(curSel, customResText);
|
||||
|
||||
|
||||
GetResolutionFromCustomResText(customResText.toStdString().c_str(), m_customResW, m_customResH);
|
||||
}
|
||||
m_ui->m_resolutionCombo->setCurrentIndex(curSel);
|
||||
@@ -907,12 +907,12 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
|
||||
folder += "/";
|
||||
folder += itemText;
|
||||
|
||||
// If this is a relative path, prepend the @assets@ folder to match where the Renderer is going
|
||||
// If this is a relative path, prepend the @products@ folder to match where the Renderer is going
|
||||
// to dump the frame buffer image captures.
|
||||
if (AzFramework::StringFunc::Path::IsRelative(folder.toUtf8().data()))
|
||||
{
|
||||
AZStd::string absolutePath;
|
||||
AZStd::string assetsRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@assets@");
|
||||
AZStd::string assetsRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@");
|
||||
AzFramework::StringFunc::Path::Join(assetsRoot.c_str(), folder.toUtf8().data(), absolutePath);
|
||||
folder = absolutePath.c_str();
|
||||
}
|
||||
@@ -962,7 +962,7 @@ void CSequenceBatchRenderDialog::CaptureItemStart()
|
||||
m_renderContext.cvarDisplayInfoBU = cvarDebugInfo->GetIVal();
|
||||
if (renderItem.disableDebugInfo && cvarDebugInfo->GetIVal())
|
||||
{
|
||||
const int DISPLAY_INFO_OFF = 0;
|
||||
const int DISPLAY_INFO_OFF = 0;
|
||||
cvarDebugInfo->Set(DISPLAY_INFO_OFF);
|
||||
}
|
||||
}
|
||||
@@ -1100,13 +1100,13 @@ void CSequenceBatchRenderDialog::OnUpdateEnd(IAnimSequence* sequence)
|
||||
sequence->SetActiveDirector(m_renderContext.pActiveDirectorBU);
|
||||
|
||||
const auto imageFormat = m_ui->m_imageFormatCombo->currentText();
|
||||
|
||||
|
||||
SRenderItem renderItem = m_renderItems[m_renderContext.currentItemIndex];
|
||||
if (m_bFFMPEGCommandAvailable && renderItem.bCreateVideo)
|
||||
{
|
||||
// Create a video using the ffmpeg plug-in from captured images.
|
||||
m_renderContext.processingFFMPEG = true;
|
||||
|
||||
|
||||
AZStd::string outputFolder = m_renderContext.captureOptions.folder;
|
||||
auto future = QtConcurrent::run(
|
||||
[renderItem, outputFolder, imageFormat]
|
||||
@@ -1238,7 +1238,7 @@ void CSequenceBatchRenderDialog::OnKickIdleTimout()
|
||||
}
|
||||
|
||||
void CSequenceBatchRenderDialog::OnKickIdle()
|
||||
{
|
||||
{
|
||||
if (m_renderContext.captureState == CaptureState::WarmingUpAfterResChange)
|
||||
{
|
||||
OnUpdateWarmingUpAfterResChange();
|
||||
@@ -1254,7 +1254,7 @@ void CSequenceBatchRenderDialog::OnKickIdle()
|
||||
else if (m_renderContext.captureState == CaptureState::Capturing)
|
||||
{
|
||||
OnUpdateCapturing();
|
||||
}
|
||||
}
|
||||
else if (m_renderContext.captureState == CaptureState::End)
|
||||
{
|
||||
OnUpdateEnd(m_renderContext.endingSequence);
|
||||
|
||||
@@ -101,13 +101,13 @@ public:
|
||||
|
||||
if (fresh.size() < m_stackNames.size())
|
||||
{
|
||||
beginRemoveRows(createIndex(-1, -1), static_cast<int>(fresh.size()), static_cast<int>(m_stackNames.size() - 1));
|
||||
beginRemoveRows(QModelIndex(), static_cast<int>(fresh.size()), static_cast<int>(m_stackNames.size() - 1));
|
||||
m_stackNames = fresh;
|
||||
endRemoveRows();
|
||||
}
|
||||
else
|
||||
{
|
||||
beginInsertRows(createIndex(-1, -1), static_cast<int>(m_stackNames.size()), static_cast<int>(fresh.size() - 1));
|
||||
beginInsertRows(QModelIndex(), static_cast<int>(m_stackNames.size()), static_cast<int>(fresh.size() - 1));
|
||||
m_stackNames = fresh;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
+33
-167
@@ -11,9 +11,9 @@
|
||||
|
||||
#include "PathUtil.h"
|
||||
|
||||
#include <AzCore/IO/SystemFile.h> // for AZ_MAX_PATH_LEN
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> // for ebus events
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzFramework/API/ApplicationAPI.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
@@ -179,7 +179,7 @@ namespace Path
|
||||
EBUS_EVENT_RESULT(engineRoot, AzFramework::ApplicationRequests::Bus, GetEngineRoot);
|
||||
return QString(engineRoot);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString& ReplaceFilename(const QString& strFilepath, const QString& strFilename, QString& strOutputFilename, bool bCallCaselessPath)
|
||||
{
|
||||
@@ -216,30 +216,21 @@ namespace Path
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QString GetResolvedUserSandboxFolder()
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
gEnv->pFileIO->ResolvePath(GetUserSandboxFolder().toUtf8().data(), resolvedPath, AZ_MAX_PATH_LEN);
|
||||
return QString::fromLatin1(resolvedPath);
|
||||
AZ::IO::FixedMaxPath userSandboxFolderPath;
|
||||
gEnv->pFileIO->ResolvePath(userSandboxFolderPath, GetUserSandboxFolder().toUtf8().constData());
|
||||
return QString::fromUtf8(userSandboxFolderPath.c_str(), static_cast<int>(userSandboxFolderPath.Native().size()));
|
||||
}
|
||||
|
||||
// internal function, you should use GetEditingGameDataFolder instead.
|
||||
AZStd::string GetGameAssetsFolder()
|
||||
{
|
||||
const char* resultValue = nullptr;
|
||||
EBUS_EVENT_RESULT(resultValue, AzToolsFramework::AssetSystemRequestBus, GetAbsoluteDevGameFolderPath);
|
||||
if (!resultValue)
|
||||
AZ::IO::Path projectPath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if ((gEnv) && (gEnv->pFileIO))
|
||||
{
|
||||
resultValue = gEnv->pFileIO->GetAlias("@devassets@");
|
||||
}
|
||||
settingsRegistry->Get(projectPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath);
|
||||
}
|
||||
|
||||
if (!resultValue)
|
||||
{
|
||||
resultValue = ".";
|
||||
}
|
||||
|
||||
return resultValue;
|
||||
return projectPath.Native();
|
||||
}
|
||||
|
||||
/// Get the data folder
|
||||
@@ -258,26 +249,6 @@ namespace Path
|
||||
return str;
|
||||
}
|
||||
|
||||
//! Get the root folder (in source control or other writable assets) where you should save root data.
|
||||
AZStd::string GetEditingRootFolder()
|
||||
{
|
||||
const char* resultValue = nullptr;
|
||||
EBUS_EVENT_RESULT(resultValue, AzToolsFramework::AssetSystemRequestBus, GetAbsoluteDevRootFolderPath);
|
||||
|
||||
if (!resultValue)
|
||||
{
|
||||
if ((gEnv) && (gEnv->pFileIO))
|
||||
{
|
||||
resultValue = gEnv->pFileIO->GetAlias("@devassets@");
|
||||
}
|
||||
}
|
||||
if (!resultValue)
|
||||
{
|
||||
resultValue = ".";
|
||||
}
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
|
||||
AZStd::string MakeModPathFromGamePath(const char* relGamePath)
|
||||
{
|
||||
@@ -335,165 +306,60 @@ namespace Path
|
||||
return "";
|
||||
}
|
||||
|
||||
bool relPathfound = false;
|
||||
bool relPathFound = false;
|
||||
AZStd::string relativePath;
|
||||
AZStd::string fullAssetPath(fullPath.toUtf8().data());
|
||||
EBUS_EVENT_RESULT(relPathfound, AzToolsFramework::AssetSystemRequestBus, GetRelativeProductPathFromFullSourceOrProductPath, fullAssetPath, relativePath);
|
||||
EBUS_EVENT_RESULT(relPathFound, AzToolsFramework::AssetSystemRequestBus, GetRelativeProductPathFromFullSourceOrProductPath, fullAssetPath, relativePath);
|
||||
|
||||
if (relPathfound)
|
||||
if (relPathFound)
|
||||
{
|
||||
// do not normalize this path, it will already be an appropriate asset ID.
|
||||
return CaselessPaths(relativePath.c_str());
|
||||
}
|
||||
|
||||
char rootpath[_MAX_PATH] = { 0 };
|
||||
azstrcpy(rootpath, _MAX_PATH, Path::GetEditingRootFolder().c_str());
|
||||
|
||||
if (bRelativeToGameFolder)
|
||||
{
|
||||
azstrcpy(rootpath, _MAX_PATH, Path::GetEditingGameDataFolder().c_str());
|
||||
}
|
||||
|
||||
QString rootPathNormalized(rootpath);
|
||||
QString srcPathNormalized(fullPath);
|
||||
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
// avoid confusing PathRelativePathTo
|
||||
rootPathNormalized.replace('/', '\\');
|
||||
srcPathNormalized.replace('/', '\\');
|
||||
#endif
|
||||
AZ::IO::FixedMaxPath rootPath = bRelativeToGameFolder ? AZ::Utils::GetProjectPath() : AZ::Utils::GetEnginePath();
|
||||
AZ::IO::FixedMaxPath resolvedFullPath;
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedFullPath, fullPath.toUtf8().constData());
|
||||
|
||||
// Create relative path
|
||||
char resolvedSrcPath[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(srcPathNormalized.toUtf8().data(), resolvedSrcPath, AZ_MAX_PATH_LEN);
|
||||
QByteArray path = QDir(rootPathNormalized).relativeFilePath(resolvedSrcPath).toUtf8();
|
||||
if (path.isEmpty())
|
||||
{
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
// The following code is required because the windows PathRelativePathTo function will always return "./SomePath" instead of just "SomePath"
|
||||
// Only remove single dot (.) and slash parts of a path, never the double dot (..)
|
||||
const char* pBuffer = path.data();
|
||||
bool bHasDot = false;
|
||||
while (*pBuffer && pBuffer != path.end())
|
||||
{
|
||||
switch (*pBuffer)
|
||||
{
|
||||
case '.':
|
||||
if (bHasDot)
|
||||
{
|
||||
// Found a double dot, rewind and stop removing
|
||||
pBuffer--;
|
||||
break;
|
||||
}
|
||||
// Fall through intended
|
||||
case '/':
|
||||
case '\\':
|
||||
bHasDot = (*pBuffer == '.');
|
||||
pBuffer++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
QString relPath = pBuffer;
|
||||
return CaselessPaths(relPath);
|
||||
return CaselessPaths(resolvedFullPath.LexicallyProximate(rootPath).MakePreferred().c_str());
|
||||
}
|
||||
|
||||
QString GamePathToFullPath(const QString& path)
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
AZ_Warning("GamePathToFullPath", path.size() <= AZ_MAX_PATH_LEN, "Path exceeds maximum path length of %d", AZ_MAX_PATH_LEN);
|
||||
if ((gEnv) && (gEnv->pFileIO) && gEnv->pCryPak && path.size() <= AZ_MAX_PATH_LEN)
|
||||
AZ_Warning("GamePathToFullPath", path.size() <= AZ::IO::MaxPathLength, "Path exceeds maximum path length of %zu", AZ::IO::MaxPathLength);
|
||||
if (path.size() <= AZ::IO::MaxPathLength)
|
||||
{
|
||||
// first, adjust the file name for mods:
|
||||
bool fullPathfound = false;
|
||||
AZStd::string assetFullPath;
|
||||
AZStd::string adjustedFilePath = path.toUtf8().data();
|
||||
AssetSystemRequestBus::BroadcastResult(fullPathfound, &AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath, adjustedFilePath, assetFullPath);
|
||||
if (fullPathfound)
|
||||
bool fullPathFound = false;
|
||||
AZ::IO::Path assetFullPath;
|
||||
AZ::IO::Path adjustedFilePath = path.toUtf8().constData();
|
||||
AssetSystemRequestBus::BroadcastResult(fullPathFound, &AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath,
|
||||
adjustedFilePath.Native(), assetFullPath.Native());
|
||||
if (fullPathFound)
|
||||
{
|
||||
//if the bus message succeeds than normalize and lowercase the path
|
||||
AzFramework::StringFunc::Path::Normalize(assetFullPath);
|
||||
return assetFullPath.c_str();
|
||||
//if the bus message succeeds than normalize
|
||||
return assetFullPath.LexicallyNormal().c_str();
|
||||
}
|
||||
// if the bus message didn't succeed, 'guess' the source assets:
|
||||
// if the bus message didn't succeed, check if he path exist as a resolved path
|
||||
else
|
||||
{
|
||||
// Not all systems have been converted to use local paths. Some editor files save XML files directly, and a full or correctly aliased path is already passed in.
|
||||
// If the path passed in exists already, then return the resolved filepath
|
||||
if (AZ::IO::FileIOBase::GetDirectInstance()->Exists(adjustedFilePath.c_str()))
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(adjustedFilePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength);
|
||||
return QString::fromUtf8(resolvedPath);
|
||||
AZ::IO::FixedMaxPath resolvedPath;
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(resolvedPath, adjustedFilePath);
|
||||
return QString::fromUtf8(resolvedPath.c_str(), static_cast<int>(resolvedPath.Native().size()));
|
||||
}
|
||||
// if we get here it means that the Asset Processor does not know about this file. most of the time we should never get here
|
||||
// the rest of this code just does a bunch of heuristic guesses in case of missing files or if the user has hand-edited
|
||||
// the asset cache by moving files in via some other means or external process.
|
||||
if (adjustedFilePath[0] != '@')
|
||||
{
|
||||
const char* prefix = (adjustedFilePath[0] == '/' || adjustedFilePath[0] == '\\') ? "@devassets@" : "@devassets@/";
|
||||
adjustedFilePath = prefix + adjustedFilePath;
|
||||
}
|
||||
|
||||
char szAdjustedFile[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
|
||||
gEnv->pFileIO->ResolvePath(adjustedFilePath.c_str(), szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile));
|
||||
|
||||
if ((azstrnicmp(szAdjustedFile, "@devassets@", 11) == 0) && ((szAdjustedFile[11] == '/') || (szAdjustedFile[11] == '\\')))
|
||||
{
|
||||
if (!gEnv->pCryPak->IsFileExist(szAdjustedFile))
|
||||
{
|
||||
AZStd::string newName(szAdjustedFile);
|
||||
AzFramework::StringFunc::Replace(newName, "@devassets@", "@devroot@/engine", false);
|
||||
|
||||
if (gEnv->pCryPak->IsFileExist(newName.c_str()))
|
||||
{
|
||||
azstrcpy(szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile), newName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// getting tricky here, try @devroot@ alone, in case its 'editor'
|
||||
AzFramework::StringFunc::Replace(newName, "@devassets@", "@devroot@", false);
|
||||
if (gEnv->pCryPak->IsFileExist(szAdjustedFile))
|
||||
{
|
||||
azstrcpy(szAdjustedFile, AZ_ARRAY_SIZE(szAdjustedFile), newName.c_str());
|
||||
}
|
||||
// give up, best guess is just @devassets@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we should very rarely actually get to this point in the code.
|
||||
|
||||
// szAdjustedFile may contain an alias at this point. (@assets@/blah.whatever)
|
||||
// there is a case in which the loose asset exists only within a pak file for some reason
|
||||
// this is not recommended but it is possible.in that case, we want to return the original szAdjustedFile
|
||||
// without touching it or resolving it so that crypak can open it successfully.
|
||||
char adjustedPath[AZ_MAX_PATH_LEN + PathUtil::maxAliasLength] = { 0 };
|
||||
if (gEnv->pFileIO->ResolvePath(szAdjustedFile, adjustedPath, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength)) // resolve to full path
|
||||
{
|
||||
if ((gEnv->pCryPak->IsFileExist(adjustedPath)) || (!gEnv->pCryPak->IsFileExist(szAdjustedFile)))
|
||||
{
|
||||
// note that if we get here, then EITHER
|
||||
// the file exists as a loose asset in the actual adjusted path
|
||||
// OR the file does not exist in the original passed-in aliased name (like '@assets@/whatever')
|
||||
// in which case we may as well just resolve the path to a full path and return it.
|
||||
assetFullPath = adjustedPath;
|
||||
AzFramework::StringFunc::Path::Normalize(assetFullPath);
|
||||
azstrcpy(szAdjustedFile, AZ_MAX_PATH_LEN + PathUtil::maxAliasLength, assetFullPath.c_str());
|
||||
}
|
||||
// if the above case succeeded then it means that the file does NOT exist loose
|
||||
// but DOES exist in a pak, in which case we leave szAdjustedFile with the alias on the front of it, meaning
|
||||
// fopens via crypak will actually succeed.
|
||||
}
|
||||
return szAdjustedFile;
|
||||
return path;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
return QString{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,9 +44,6 @@ namespace Path
|
||||
//! always returns a full path
|
||||
EDITOR_CORE_API AZStd::string GetEditingGameDataFolder();
|
||||
|
||||
//! Get the root folder (in source control or other writable assets) where you should save root data.
|
||||
EDITOR_CORE_API AZStd::string GetEditingRootFolder();
|
||||
|
||||
//! Set the current mod NAME for editing purposes. After doing this the above functions will take this into account
|
||||
//! name only, please!
|
||||
EDITOR_CORE_API void SetModName(const char* input);
|
||||
@@ -69,93 +66,6 @@ namespace Path
|
||||
return strPath;
|
||||
}
|
||||
|
||||
//! Split full file name to path and filename
|
||||
//! @param filepath [IN] Full file name inclusing path.
|
||||
//! @param path [OUT] Extracted file path.
|
||||
//! @param file [OUT] Extracted file (with extension).
|
||||
inline void Split(const QString& filepath, QString& path, QString& file)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.toUtf8().data(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
|
||||
#else
|
||||
_splitpath(filepath.toUtf8().data(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath(path_buffer, 0, 0, fname, ext);
|
||||
#endif
|
||||
file = path_buffer;
|
||||
}
|
||||
inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& file)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), 0, 0, 0, 0);
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), 0, 0, fname, ext);
|
||||
#else
|
||||
_splitpath(filepath.c_str(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
path = path_buffer;
|
||||
_makepath(path_buffer, 0, 0, fname, ext);
|
||||
#endif
|
||||
file = path_buffer;
|
||||
}
|
||||
|
||||
//! Split full file name to path and filename
|
||||
//! @param filepath [IN] Full file name inclusing path.
|
||||
//! @param path [OUT] Extracted file path.
|
||||
//! @param filename [OUT] Extracted file (without extension).
|
||||
//! @param ext [OUT] Extracted files extension.
|
||||
inline void Split(const QString& filepath, QString& path, QString& filename, QString& fext)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.toUtf8().data(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
#else
|
||||
_splitpath(filepath.toUtf8().data(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
#endif
|
||||
path = path_buffer;
|
||||
filename = fname;
|
||||
fext = ext;
|
||||
}
|
||||
inline void Split(const AZStd::string& filepath, AZStd::string& path, AZStd::string& filename, AZStd::string& fext)
|
||||
{
|
||||
char path_buffer[_MAX_PATH];
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
#ifdef AZ_COMPILER_MSVC
|
||||
_splitpath_s(filepath.c_str(), drive, AZ_ARRAY_SIZE(drive), dir, AZ_ARRAY_SIZE(dir), fname, AZ_ARRAY_SIZE(fname), ext, AZ_ARRAY_SIZE(ext));
|
||||
_makepath_s(path_buffer, AZ_ARRAY_SIZE(path_buffer), drive, dir, 0, 0);
|
||||
#else
|
||||
_splitpath(filepath.c_str(), drive, dir, fname, ext);
|
||||
_makepath(path_buffer, drive, dir, 0, 0);
|
||||
#endif
|
||||
path = path_buffer;
|
||||
filename = fname;
|
||||
fext = ext;
|
||||
}
|
||||
|
||||
//! Split path into segments
|
||||
//! @param filepath [IN] path
|
||||
inline QStringList SplitIntoSegments(const QString& path)
|
||||
|
||||
@@ -119,7 +119,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile&
|
||||
_smart_ptr<IXmlStringData> pXmlStrData = root->getXMLData(5000000);
|
||||
|
||||
// Save xml file.
|
||||
QString xmlFilename = "Level.editor_xml";
|
||||
QString xmlFilename = "level.editor_xml";
|
||||
pakFile.UpdateFile(xmlFilename.toUtf8().data(), (void*)pXmlStrData->GetString(), static_cast<int>(pXmlStrData->GetStringLength()));
|
||||
|
||||
if (pakFile.GetArchive())
|
||||
@@ -134,7 +134,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile&
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CXmlArchive::LoadFromPak(const QString& levelPath, CPakFile& pakFile)
|
||||
{
|
||||
QString xmlFilename = QDir(levelPath).absoluteFilePath("Level.editor_xml");
|
||||
QString xmlFilename = QDir(levelPath).absoluteFilePath("level.editor_xml");
|
||||
root = XmlHelpers::LoadXmlFromFile(xmlFilename.toUtf8().data());
|
||||
if (!root)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
|
||||
// Editor
|
||||
#include "ViewManager.h"
|
||||
@@ -173,8 +174,6 @@ QtViewport::QtViewport(QWidget* parent)
|
||||
|
||||
m_bAdvancedSelectMode = false;
|
||||
|
||||
m_pVisibleObjectsCache = new CBaseObjectsCache;
|
||||
|
||||
m_constructionPlane.SetPlane(Vec3_OneZ, Vec3_Zero);
|
||||
m_constructionPlaneAxisX = Vec3_Zero;
|
||||
m_constructionPlaneAxisY = Vec3_Zero;
|
||||
@@ -204,8 +203,6 @@ QtViewport::QtViewport(QWidget* parent)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
QtViewport::~QtViewport()
|
||||
{
|
||||
delete m_pVisibleObjectsCache;
|
||||
|
||||
GetIEditor()->GetViewManager()->UnregisterViewport(this);
|
||||
}
|
||||
|
||||
@@ -376,11 +373,6 @@ void QtViewport::OnDeactivate()
|
||||
void QtViewport::ResetContent()
|
||||
{
|
||||
m_pMouseOverObject = nullptr;
|
||||
|
||||
// Need to clear visual object cache.
|
||||
// Right after loading new level, some code(e.g. OnMouseMove) access invalid
|
||||
// previous level object before cache updated.
|
||||
GetVisibleObjectsCache()->ClearObjects();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -398,11 +390,8 @@ void QtViewport::Update()
|
||||
m_viewportUi.Update();
|
||||
|
||||
m_bAdvancedSelectMode = false;
|
||||
bool bSpaceClick = false;
|
||||
{
|
||||
bSpaceClick = CheckVirtualKey(Qt::Key_Space) & !CheckVirtualKey(Qt::Key_Shift) /*& !CheckVirtualKey(Qt::Key_Control)*/;
|
||||
}
|
||||
if (bSpaceClick && hasFocus())
|
||||
|
||||
if (CheckVirtualKey(Qt::Key_Space) && !CheckVirtualKey(Qt::Key_Shift) && hasFocus())
|
||||
{
|
||||
m_bAdvancedSelectMode = true;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public:
|
||||
|
||||
virtual Vec3 SnapToGrid(const Vec3& vec) = 0;
|
||||
|
||||
//! Get selection procision tolerance.
|
||||
//! Get selection precision tolerance.
|
||||
virtual float GetSelectionTolerance() const = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -491,10 +491,6 @@ public:
|
||||
void ResetCursor() override;
|
||||
void SetSupplementaryCursorStr(const QString& str) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Return visble objects cache.
|
||||
CBaseObjectsCache* GetVisibleObjectsCache() override { return m_pVisibleObjectsCache; };
|
||||
|
||||
void RegisterRenderListener(IRenderListener* piListener) override;
|
||||
bool UnregisterRenderListener(IRenderListener* piListener) override;
|
||||
bool IsRenderListenerRegistered(IRenderListener* piListener) override;
|
||||
@@ -612,8 +608,6 @@ protected:
|
||||
int m_nLastUpdateFrame;
|
||||
int m_nLastMouseMoveFrame;
|
||||
|
||||
CBaseObjectsCache* m_pVisibleObjectsCache;
|
||||
|
||||
QRect m_rcClient;
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
|
||||
@@ -173,6 +173,7 @@ namespace AZ
|
||||
|
||||
if (assetTracker)
|
||||
{
|
||||
assetTracker->FixUpAsset(*instance);
|
||||
assetTracker->AddAsset(*instance);
|
||||
}
|
||||
|
||||
@@ -185,7 +186,20 @@ namespace AZ
|
||||
return context.Report(result, message);
|
||||
}
|
||||
|
||||
void SerializedAssetTracker::AddAsset(Asset<AssetData>& asset)
|
||||
void SerializedAssetTracker::SetAssetFixUp(AssetFixUp assetFixUpCallback)
|
||||
{
|
||||
m_assetFixUpCallback = AZStd::move(assetFixUpCallback);
|
||||
}
|
||||
|
||||
void SerializedAssetTracker::FixUpAsset(Asset<AssetData>& asset)
|
||||
{
|
||||
if (m_assetFixUpCallback)
|
||||
{
|
||||
m_assetFixUpCallback(asset);
|
||||
}
|
||||
}
|
||||
|
||||
void SerializedAssetTracker::AddAsset(Asset<AssetData> asset)
|
||||
{
|
||||
m_serializedAssets.emplace_back(asset);
|
||||
}
|
||||
@@ -199,5 +213,6 @@ namespace AZ
|
||||
{
|
||||
return m_serializedAssets;
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
} // namespace AZ
|
||||
|
||||
@@ -39,13 +39,18 @@ namespace AZ
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(SerializedAssetTracker, "{1E067091-8C0A-44B1-A455-6E97663F6963}");
|
||||
using AssetFixUp = AZStd::function<void(Asset<AssetData>& asset)>;
|
||||
|
||||
void AddAsset(Asset<AssetData>& asset);
|
||||
void SetAssetFixUp(AssetFixUp assetFixUpCallback);
|
||||
void FixUpAsset(Asset<AssetData>& asset);
|
||||
|
||||
void AddAsset(Asset<AssetData> asset);
|
||||
AZStd::vector<Asset<AssetData>>& GetTrackedAssets();
|
||||
const AZStd::vector<Asset<AssetData>>& GetTrackedAssets() const;
|
||||
|
||||
private:
|
||||
AZStd::vector<Asset<AssetData>> m_serializedAssets;
|
||||
AssetFixUp m_assetFixUpCallback;
|
||||
};
|
||||
} // namespace Data
|
||||
} // namespace AZ
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <AzCore/Console/LoggerSystemComponent.h>
|
||||
#include <AzCore/EBus/EventSchedulerSystemComponent.h>
|
||||
#include <AzCore/Task/TaskGraphSystemComponent.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxySystemComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -44,6 +45,10 @@ namespace AZ
|
||||
EventSchedulerSystemComponent::CreateDescriptor(),
|
||||
TaskGraphSystemComponent::CreateDescriptor(),
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
Statistics::StatisticalProfilerProxySystemComponent::CreateDescriptor(),
|
||||
#endif
|
||||
|
||||
#if !defined(AZCORE_EXCLUDE_LUA)
|
||||
ScriptSystemComponent::CreateDescriptor(),
|
||||
#endif // #if !defined(AZCORE_EXCLUDE_LUA)
|
||||
@@ -58,6 +63,10 @@ namespace AZ
|
||||
azrtti_typeid<LoggerSystemComponent>(),
|
||||
azrtti_typeid<EventSchedulerSystemComponent>(),
|
||||
azrtti_typeid<TaskGraphSystemComponent>(),
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
azrtti_typeid<Statistics::StatisticalProfilerProxySystemComponent>(),
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1367,9 +1367,6 @@ namespace AZ
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Tick
|
||||
//=========================================================================
|
||||
void ComponentApplication::Tick(float deltaOverride /*= -1.f*/)
|
||||
{
|
||||
{
|
||||
@@ -1397,9 +1394,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Tick
|
||||
//=========================================================================
|
||||
void ComponentApplication::TickSystem()
|
||||
{
|
||||
AZ_PROFILE_SCOPE(System, "Component application tick");
|
||||
@@ -1547,5 +1541,4 @@ namespace AZ
|
||||
AZ::SettingsRegistryScriptUtils::ReflectSettingsRegistryToBehaviorContext(*behaviorContext);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
|
||||
@@ -476,15 +476,16 @@ namespace AZ
|
||||
|
||||
// Responsible for using the Json Serialization Issue Callback system
|
||||
// to determine when a JSON Patch or JSON Merge Patch modifies a value
|
||||
// at a path underneath the IConsole::ConsoleRootCommandKey JSON pointer
|
||||
// at a path underneath the IConsole::ConsoleRuntimeCommandKey JSON pointer
|
||||
JsonSerializationResult::ResultCode operator()(AZStd::string_view message,
|
||||
JsonSerializationResult::ResultCode result, AZStd::string_view path)
|
||||
{
|
||||
AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator };
|
||||
AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator };
|
||||
if (result.GetTask() == JsonSerializationResult::Tasks::Merge
|
||||
&& result.GetProcessing() == JsonSerializationResult::Processing::Completed
|
||||
&& inputKey.IsRelativeTo(consoleRootCommandKey))
|
||||
&& (inputKey.IsRelativeTo(consoleRootCommandKey) || inputKey.IsRelativeTo(consoleAutoexecCommandKey)))
|
||||
{
|
||||
if (auto type = m_settingsRegistry.GetType(path); type != SettingsRegistryInterface::Type::NoType)
|
||||
{
|
||||
@@ -510,12 +511,24 @@ namespace AZ
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
|
||||
AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleRuntimeCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator };
|
||||
AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator };
|
||||
// The ConsoleRootComamndKey is not a command itself so strictly children keys are being examined
|
||||
if (inputKey.IsRelativeTo(consoleRootCommandKey) && inputKey != consoleRootCommandKey)
|
||||
|
||||
// Abuses the IsRelativeToFuncton function of the path class to extract the console
|
||||
// command from the settings registry objects
|
||||
FixedValueString command;
|
||||
if (inputKey != consoleRuntimeCommandKey && inputKey.IsRelativeTo(consoleRuntimeCommandKey))
|
||||
{
|
||||
command = inputKey.LexicallyRelative(consoleRuntimeCommandKey).Native();
|
||||
}
|
||||
else if (inputKey != consoleAutoexecCommandKey && inputKey.IsRelativeTo(consoleAutoexecCommandKey))
|
||||
{
|
||||
command = inputKey.LexicallyRelative(consoleAutoexecCommandKey).Native();
|
||||
}
|
||||
|
||||
if (!command.empty())
|
||||
{
|
||||
FixedValueString command = inputKey.LexicallyRelative(consoleRootCommandKey).Native();
|
||||
ConsoleCommandContainer commandArgs;
|
||||
// Argument string which stores the value from the Settings Registry long enough
|
||||
// to pass into the PerformCommand. The ConsoleCommandContainer stores string_views
|
||||
@@ -603,9 +616,10 @@ namespace AZ
|
||||
|
||||
void Console::RegisterCommandInvokerWithSettingsRegistry(AZ::SettingsRegistryInterface& settingsRegistry)
|
||||
{
|
||||
// Make sure the there is a JSON object at the path of AZ::IConsole::ConsoleRootCommandKey
|
||||
// Make sure the there is a JSON object at the ConsoleRuntimeCommandKey or ConsoleAutoexecKey
|
||||
// So that JSON Patch is able to add values underneath that object (JSON Patch doesn't create intermediate objects)
|
||||
settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } }}})",
|
||||
settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } } })"
|
||||
R"(,"O3DE": { "Autoexec": { "ConsoleCommands": {} } } })",
|
||||
SettingsRegistryInterface::Format::JsonMergePatch);
|
||||
m_consoleCommandKeyHandler = settingsRegistry.RegisterNotifier(ConsoleCommandKeyNotificationHandler{ settingsRegistry, *this });
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace AZ
|
||||
|
||||
using FunctorVisitor = AZStd::function<void(ConsoleFunctorBase*)>;
|
||||
|
||||
inline static constexpr AZStd::string_view ConsoleRootCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands";
|
||||
inline static constexpr AZStd::string_view ConsoleRuntimeCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands";
|
||||
inline static constexpr AZStd::string_view ConsoleAutoexecCommandKey = "/O3DE/Autoexec/ConsoleCommands";
|
||||
|
||||
IConsole() = default;
|
||||
virtual ~IConsole() = default;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Module/Environment.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxy.h>
|
||||
|
||||
AZ_DEFINE_BUDGET(Animation);
|
||||
AZ_DEFINE_BUDGET(Audio);
|
||||
@@ -30,8 +31,7 @@ namespace AZ::Debug
|
||||
};
|
||||
|
||||
Budget::Budget(const char* name)
|
||||
: m_name{ name }
|
||||
, m_crc{ Crc32(name) }
|
||||
: Budget( name, Crc32(name) )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ namespace AZ::Debug
|
||||
, m_crc{ crc }
|
||||
{
|
||||
m_impl = aznew BudgetImpl;
|
||||
if (auto statsProfiler = Interface<Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
statsProfiler->RegisterProfilerId(m_crc);
|
||||
}
|
||||
}
|
||||
|
||||
Budget::~Budget()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Debug/Budget.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxy.h>
|
||||
|
||||
#ifdef USE_PIX
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
@@ -44,7 +45,10 @@
|
||||
#define AZ_PROFILE_INTERVAL_START(...)
|
||||
#define AZ_PROFILE_INTERVAL_START_COLORED(...)
|
||||
#define AZ_PROFILE_INTERVAL_END(...)
|
||||
#define AZ_PROFILE_INTERVAL_SCOPED(...)
|
||||
#define AZ_PROFILE_INTERVAL_SCOPED(budget, scopeNameId, ...) \
|
||||
static constexpr AZ::Crc32 AZ_JOIN(blockId, __LINE__)(scopeNameId); \
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope AZ_JOIN(scope, __LINE__)(AZ_CRC_CE(#budget), AZ_JOIN(blockId, __LINE__));
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef AZ_PROFILE_DATAPOINT
|
||||
|
||||
@@ -46,5 +46,23 @@ namespace AZ
|
||||
private:
|
||||
AZStd::sys_time_t m_timeStamp;
|
||||
};
|
||||
|
||||
//! Utility type that updates the given variable with the lifetime of the object in cycles.
|
||||
//! Useful for quick scope based timing.
|
||||
struct ScopedTimer
|
||||
{
|
||||
explicit ScopedTimer(AZStd::sys_time_t& variable)
|
||||
: m_variable(variable)
|
||||
{
|
||||
m_timer.Stamp();
|
||||
}
|
||||
~ScopedTimer()
|
||||
{
|
||||
m_variable = m_timer.GetDeltaTimeInTicks();
|
||||
}
|
||||
|
||||
AZStd::sys_time_t& m_variable;
|
||||
Timer m_timer;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,8 @@ namespace AZ
|
||||
|
||||
void Debug::Trace::Terminate(int exitCode)
|
||||
{
|
||||
AZ_TracePrintf("Exit", "Called Terminate() with exit code: 0x%x", exitCode);
|
||||
AZ::Debug::Trace::PrintCallstack("Exit");
|
||||
Platform::Terminate(exitCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -160,8 +160,8 @@ namespace AZ
|
||||
/**
|
||||
* Locking primitive that is used when executing events in the event queue.
|
||||
*/
|
||||
using EventQueueMutexType = typename AZStd::Utils::if_c<AZStd::is_same<typename Traits::EventQueueMutexType, NullMutex>::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType
|
||||
MutexType, typename Traits::EventQueueMutexType>::type;
|
||||
using EventQueueMutexType = AZStd::conditional_t<AZStd::is_same<typename Traits::EventQueueMutexType, NullMutex>::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType
|
||||
MutexType, typename Traits::EventQueueMutexType>;
|
||||
|
||||
/**
|
||||
* Pointer to an address on the bus.
|
||||
@@ -180,14 +180,22 @@ namespace AZ
|
||||
* `<BusName>::ExecuteQueuedEvents()`.
|
||||
* By default, the event queue is disabled.
|
||||
*/
|
||||
static const bool EnableEventQueue = Traits::EnableEventQueue;
|
||||
static const bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault;
|
||||
static const bool EnableQueuedReferences = Traits::EnableQueuedReferences;
|
||||
static constexpr bool EnableEventQueue = Traits::EnableEventQueue;
|
||||
static constexpr bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault;
|
||||
static constexpr bool EnableQueuedReferences = Traits::EnableQueuedReferences;
|
||||
|
||||
/**
|
||||
* True if the EBus supports more than one address. Otherwise, false.
|
||||
*/
|
||||
static const bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
|
||||
static constexpr bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
|
||||
|
||||
/**
|
||||
* Template Lock Guard class that wraps around the Mutex
|
||||
* The EBus uses for Dispatching Events.
|
||||
* This is not the EBus Context Mutex if LocklessDispatch is true
|
||||
*/
|
||||
template <typename DispatchMutex>
|
||||
using DispatchLockGuard = typename Traits::template DispatchLockGuard<DispatchMutex, Traits::LocklessDispatch>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -460,7 +468,7 @@ namespace AZ
|
||||
using BusPtr = typename Traits::BusPtr;
|
||||
|
||||
/**
|
||||
* Helper to queue an event by BusIdType only when function queueing is enabled
|
||||
* Helper to queue an event by BusIdType only when function queueing is enabled
|
||||
* @param id Address ID. Handlers that are connected to this ID will receive the event.
|
||||
* @param func Function pointer of the event to dispatch.
|
||||
* @param args Function arguments that are passed to each handler.
|
||||
@@ -581,7 +589,7 @@ namespace AZ
|
||||
, public EBusBroadcaster<Bus, Traits>
|
||||
, public EBusEventer<Bus, Traits>
|
||||
, public EBusEventEnumerator<Bus, Traits>
|
||||
, public AZStd::Utils::if_c<Traits::EnableEventQueue, EBusEventQueue<Bus, Traits>, EBusNullQueue>::type
|
||||
, public AZStd::conditional_t<Traits::EnableEventQueue, EBusEventQueue<Bus, Traits>, EBusNullQueue>
|
||||
{
|
||||
};
|
||||
|
||||
@@ -599,7 +607,7 @@ namespace AZ
|
||||
: public EventDispatcher<Bus, Traits>
|
||||
, public EBusBroadcaster<Bus, Traits>
|
||||
, public EBusBroadcastEnumerator<Bus, Traits>
|
||||
, public AZStd::Utils::if_c<Traits::EnableEventQueue, EBusBroadcastQueue<Bus, Traits>, EBusNullQueue>::type
|
||||
, public AZStd::conditional_t<Traits::EnableEventQueue, EBusBroadcastQueue<Bus, Traits>, EBusNullQueue>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* that Open 3D Engine uses to dispatch notifications and receive requests.
|
||||
* EBuses are configurable and support many different use cases.
|
||||
* For more information about %EBuses, see AZ::EBus in this guide and
|
||||
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
|
||||
* [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
|
||||
* in the *Open 3D Engine Developer Guide*.
|
||||
*/
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace AZ
|
||||
* @endcode
|
||||
*
|
||||
* For more information about %EBuses, see EBus in this guide and
|
||||
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
|
||||
* [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
|
||||
* in the *Open 3D Engine Developer Guide*.
|
||||
*/
|
||||
struct EBusTraits
|
||||
@@ -77,9 +77,11 @@ namespace AZ
|
||||
public:
|
||||
/**
|
||||
* Allocator used by the EBus.
|
||||
* The default setting is AZStd::allocator, which uses AZ::SystemAllocator.
|
||||
* The default setting is Internal EBusEnvironmentAllocator
|
||||
* EBus code stores their Context instances in static memory
|
||||
* Therfore the configured allocator must last as long as the EBus in a module
|
||||
*/
|
||||
using AllocatorType = AZStd::allocator;
|
||||
using AllocatorType = AZ::Internal::EBusEnvironmentAllocator;
|
||||
|
||||
/**
|
||||
* Defines how many handlers can connect to an address on the EBus
|
||||
@@ -236,6 +238,17 @@ namespace AZ
|
||||
* code before or after an event.
|
||||
*/
|
||||
using EventProcessingPolicy = EBusEventProcessingPolicy;
|
||||
|
||||
/**
|
||||
* Template Lock Guard class that wraps around the Mutex
|
||||
* The EBus Context uses the LockGuard when dispatching
|
||||
* (either AZStd::scoped_lock<MutexType> or NullLockGuard<MutexType>)
|
||||
* The IsLocklessDispatch bool is there to defer evaluation of the LocklessDispatch constant
|
||||
* Otherwise the value above in EBusTraits.h is always used and not the value
|
||||
* that the derived trait class sets.
|
||||
*/
|
||||
template <typename DispatchMutex, bool IsLocklessDispatch>
|
||||
using DispatchLockGuard = AZStd::conditional_t<IsLocklessDispatch, AZ::Internal::NullLockGuard<DispatchMutex>, AZStd::scoped_lock<DispatchMutex>>;
|
||||
};
|
||||
|
||||
namespace Internal
|
||||
@@ -259,8 +272,8 @@ namespace AZ
|
||||
*
|
||||
* EBuses are configurable and support many different use cases.
|
||||
* For more information about EBuses, see
|
||||
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
|
||||
* and [Components and EBuses: Best Practices ](http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-components-ebuses-best-practices.html)
|
||||
* [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
|
||||
* and [Components and EBuses: Best Practices ](https://o3de.org/docs/user-guide/components/development/entity-system-pg-components-ebuses-best-practices/)
|
||||
* in the *Open 3D Engine Developer Guide*.
|
||||
*
|
||||
* ## How Components Use EBuses
|
||||
@@ -496,6 +509,14 @@ namespace AZ
|
||||
*/
|
||||
static const bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
|
||||
|
||||
/**
|
||||
* Template Lock Guard class that wraps around the Mutex
|
||||
* The EBus uses for Dispatching Events.
|
||||
* This is not EBus Context Mutex when LocklessDispatch is set
|
||||
*/
|
||||
template <typename DispatchMutex>
|
||||
using DispatchLockGuard = typename ImplTraits::template DispatchLockGuard<DispatchMutex>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Check to help identify common mistakes
|
||||
/// @cond EXCLUDE_DOCS
|
||||
@@ -620,11 +641,11 @@ namespace AZ
|
||||
using ContextMutexType = AZStd::conditional_t<BusTraits::LocklessDispatch && AZStd::is_same_v<MutexType, AZ::NullMutex>, AZStd::shared_mutex, MutexType>;
|
||||
|
||||
/**
|
||||
* The scoped lock guard to use (either AZStd::scoped_lock<MutexType> or NullLockGuard<MutexType>
|
||||
* The scoped lock guard to use
|
||||
* during broadcast/event dispatch.
|
||||
* @see EBusTraits::LocklessDispatch
|
||||
*/
|
||||
using DispatchLockGuard = AZStd::conditional_t<BusTraits::LocklessDispatch, AZ::Internal::NullLockGuard<ContextMutexType>, AZStd::scoped_lock<ContextMutexType>>;
|
||||
using DispatchLockGuard = DispatchLockGuard<ContextMutexType>;
|
||||
|
||||
/**
|
||||
* The scoped lock guard to use during connection. Some specialized policies execute handler methods which
|
||||
@@ -704,6 +725,11 @@ namespace AZ
|
||||
static Context& GetOrCreateContext(bool trackCallstack=true);
|
||||
|
||||
static bool IsInDispatch(Context* context = GetContext(false));
|
||||
|
||||
/**
|
||||
* Returns whether the EBus context is in the middle of a dispatch on the current thread
|
||||
*/
|
||||
static bool IsInDispatchThisThread(Context* context = GetContext(false));
|
||||
/// @cond EXCLUDE_DOCS
|
||||
struct RouterCallstackEntry
|
||||
: public CallstackEntry
|
||||
@@ -1208,6 +1234,13 @@ AZ_POP_DISABLE_WARNING
|
||||
return context != nullptr && context->m_dispatches > 0;
|
||||
}
|
||||
|
||||
template<class Interface, class Traits>
|
||||
bool EBus<Interface, Traits>::IsInDispatchThisThread(Context* context)
|
||||
{
|
||||
return context != nullptr && context->s_callstack != nullptr
|
||||
&& context->s_callstack->m_prev != nullptr;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
template<class Interface, class Traits>
|
||||
EBus<Interface, Traits>::RouterCallstackEntry::RouterCallstackEntry(Iterator it, const BusIdType* busId, bool isQueued, bool isReverse)
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace AZ
|
||||
virtual AZ::u64 ModificationTime(HandleType fileHandle) = 0;
|
||||
virtual AZ::u64 ModificationTime(const char* filePath) = 0;
|
||||
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
virtual Result Size(const char* filePath, AZ::u64& size) = 0;
|
||||
virtual Result Size(HandleType fileHandle, AZ::u64& size) = 0;
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace AZ
|
||||
/// note: the callback will contain the full concatenated path (filePath + slash + fileName)
|
||||
/// not just the individual file name found.
|
||||
/// note: if the file path of the found file corresponds to a registered ALIAS, the longest matching alias will be returned
|
||||
/// so expect return values like @assets@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// so expect return values like @products@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// note: if rootPath is specified the implementation has the option of substituting it for the current directory
|
||||
/// as would be the case on a file server.
|
||||
typedef AZStd::function<bool(const char*)> FindFilesCallbackType;
|
||||
@@ -206,13 +206,18 @@ namespace AZ
|
||||
|
||||
// Alias system
|
||||
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @root@, etc.
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @products@, etc.
|
||||
virtual void SetAlias(const char* alias, const char* path) = 0;
|
||||
/// ClearAlias - Removes an alias from the path resolution system
|
||||
virtual void ClearAlias(const char* alias) = 0;
|
||||
/// GetAlias - Returns the destination path for a given alias, or nullptr if the alias does not exist
|
||||
virtual const char* GetAlias(const char* alias) const = 0;
|
||||
|
||||
/// SetDeprecateAlias - Adds a deprecated alias with path resolution which points to a new alias
|
||||
/// When the DeprecatedAlias is used an Error is logged and the alias is resolved to the path
|
||||
/// specified by the new alais
|
||||
virtual void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) = 0;
|
||||
|
||||
/// Shorten the given path if it contains an alias. it will always pick the longest alias match.
|
||||
/// note that it re-uses the buffer, since the data can only get smaller and we don't want to internally allocate memory if we
|
||||
/// can avoid it.
|
||||
@@ -230,8 +235,8 @@ namespace AZ
|
||||
|
||||
//! ResolvePath - Replaces any aliases in path with their values and stores the result in resolvedPath,
|
||||
//! also ensures that the path is absolute
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @assets@ is used
|
||||
//! which has the effect of making the path relative to the @assets@/ folder
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @products@ is used
|
||||
//! which has the effect of making the path relative to the @products@/ folder
|
||||
//! returns true if path was resolved, false otherwise
|
||||
//! note that all of the above file-finding and opening functions automatically resolve the path before operating
|
||||
//! so you should not need to call this except in very exceptional circumstances where you absolutely need to
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace AZ::IO
|
||||
// These functions can't be called after a request has been queued.
|
||||
//
|
||||
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -62,9 +62,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -84,8 +84,8 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -106,9 +106,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -138,7 +138,7 @@ namespace AZ::IO
|
||||
//! @result A smart pointer to the newly created request with the cancel command.
|
||||
virtual FileRequestPtr Cancel(FileRequestPtr target) = 0;
|
||||
|
||||
//! Sets a request to the cancel command.
|
||||
//! Sets a request to the cancel command.
|
||||
//! When this request completes it's not guaranteed to have canceled the target request. Not all requests can be canceled and requests
|
||||
//! that already processing may complete. It's recommended to let the target request handle the completion of the request as normal
|
||||
//! and handle cancellation by checking the status on the target request is set to IStreamerTypes::RequestStatus::Canceled.
|
||||
@@ -177,7 +177,7 @@ namespace AZ::IO
|
||||
//! DestroyDedicatedCache is called. Typical use of a dedicated cache is for files that have their own compression
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to create a dedicated cache.
|
||||
virtual FileRequestPtr CreateDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -186,25 +186,25 @@ namespace AZ::IO
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param request The request that will store the command to create a dedicated cache.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& CreateDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to destroy a dedicated cache.
|
||||
virtual FileRequestPtr DestroyDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param request The request that will store the command to destroy a dedicated cache.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& DestroyDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Clears a file from all caches in use by Streamer.
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to flush a file from all caches.
|
||||
virtual FileRequestPtr FlushCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace AZ::IO
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param request The request that will store the command to flush a file from all caches.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& FlushCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -334,7 +334,7 @@ namespace AZ::IO
|
||||
//
|
||||
|
||||
//! Collect statistics from all the components that make up Streamer.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! Data is collected lockless from involved threads and might be slightly
|
||||
//! out of date in some cases.
|
||||
//! @param statistics The container where statistics will be added to.
|
||||
|
||||
@@ -98,6 +98,11 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const noexcept;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// decomposition
|
||||
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
|
||||
//! "/O3DE/foo/bar/name.txt"
|
||||
@@ -178,7 +183,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -238,7 +243,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
@@ -253,24 +258,23 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
friend class BasicPath;
|
||||
friend struct AZStd::hash<PathView>;
|
||||
|
||||
template <typename PathResultType>
|
||||
static constexpr void MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base);
|
||||
|
||||
struct PathIterable;
|
||||
|
||||
static constexpr void MakeRelativeTo(PathIterable& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept;
|
||||
|
||||
//! Returns a structure that provides a view of the path parts which can be used for iteration
|
||||
//! Only the path parts that correspond to creating an normalized path is returned
|
||||
//! This function is useful for returning a "view" into a normalized path without the need
|
||||
//! to allocate memory for the heap
|
||||
static constexpr PathIterable GetNormalPathParts(const AZ::IO::PathView& path) noexcept;
|
||||
// joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
// If the input path is absolute it will replace the current PathIterable otherwise
|
||||
// the input path will be appended to the Path Iterable structure
|
||||
// For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
// If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
// If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
// If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
// If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
//! joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
//! If the input path is absolute it will replace the current PathIterable otherwise
|
||||
//! the input path will be appended to the Path Iterable structure
|
||||
//! For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
//! If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
//! If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
//! If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
//! If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept;
|
||||
|
||||
constexpr int ComparePathView(const PathView& other) const;
|
||||
@@ -325,32 +329,32 @@ namespace AZ::IO
|
||||
constexpr BasicPath(BasicPath&& other) = default;
|
||||
|
||||
// Conversion constructor for other types of BasicPath instantiations
|
||||
constexpr BasicPath(const PathView& other);
|
||||
constexpr BasicPath(const PathView& other) noexcept;
|
||||
|
||||
// String constructors
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const string_type& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const string_type& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by moving the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(string_type&& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(string_type&& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(AZStd::string_view src) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separators it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(AZStd::string_view src, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const value_type* pathString) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const value_type* pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a empty Path with the preferred separator set to the parameter
|
||||
explicit constexpr BasicPath(const char preferredSeparator) noexcept;
|
||||
@@ -371,7 +375,7 @@ namespace AZ::IO
|
||||
constexpr BasicPath& operator=(BasicPath&& other) = default;
|
||||
|
||||
// conversion assignment operator
|
||||
constexpr BasicPath& operator=(const PathView& pathView);
|
||||
constexpr BasicPath& operator=(const PathView& pathView) noexcept;
|
||||
constexpr BasicPath& operator=(const string_type& str) noexcept;
|
||||
constexpr BasicPath& operator=(string_type&& str) noexcept;
|
||||
constexpr BasicPath& operator=(AZStd::string_view str) noexcept;
|
||||
@@ -477,6 +481,12 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
AZStd::string StringAsPosix() const;
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// compare
|
||||
//! Performs a compare of each of the path parts for equivalence
|
||||
//! Each part of the path is compare using string comparison
|
||||
@@ -574,7 +584,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -616,7 +626,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
|
||||
@@ -240,6 +240,14 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
constexpr AZStd::fixed_string<MaxPathLength> PathView::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), AZ::IO::WindowsPathSeparator, AZ::IO::PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
// decomposition
|
||||
constexpr auto PathView::RootName() const -> PathView
|
||||
{
|
||||
@@ -473,8 +481,7 @@ namespace AZ::IO
|
||||
return lhs.Compare(rhs) >= 0;
|
||||
}
|
||||
|
||||
template <typename PathResultType>
|
||||
constexpr void PathView::MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base)
|
||||
constexpr void PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept
|
||||
{
|
||||
const bool exactCaseCompare = path.m_preferred_separator == PosixPathSeparator
|
||||
|| base.m_preferred_separator == PosixPathSeparator;
|
||||
@@ -492,13 +499,11 @@ namespace AZ::IO
|
||||
if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare);
|
||||
res != 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -512,7 +517,6 @@ namespace AZ::IO
|
||||
}
|
||||
if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -530,7 +534,7 @@ namespace AZ::IO
|
||||
// If there is no mismatch, return ".".
|
||||
if (!pathParser && !pathParserBase)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -539,27 +543,25 @@ namespace AZ::IO
|
||||
int elemCount = parser::DetermineLexicalElementCount(pathParserBase);
|
||||
if (elemCount < 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
// if elemCount == 0 and (pathParser == end() || pathParser->empty()), returns path("."); otherwise
|
||||
if (elemCount == 0 && (pathParser.AtEnd() || *pathParser == ""))
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
// return a path constructed with 'n' dot-dot elements, followed by the
|
||||
// elements of '*this' after the mismatch.
|
||||
pathResult = PathResultType(path.m_preferred_separator);
|
||||
while (elemCount--)
|
||||
{
|
||||
pathResult /= "..";
|
||||
pathIterable.emplace_back("..", parser::PathPartKind::PK_DotDot);
|
||||
}
|
||||
for (; pathParser; ++pathParser)
|
||||
{
|
||||
pathResult /= *pathParser;
|
||||
pathIterable.emplace_back(*pathParser, parser::ClassifyPathPart(pathParser));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,7 +675,7 @@ namespace AZ::IO
|
||||
// Basic Path implementation
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other)
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other) noexcept
|
||||
: m_path(other.m_path)
|
||||
, m_preferred_separator(other.m_preferred_separator) {}
|
||||
|
||||
@@ -726,6 +728,7 @@ namespace AZ::IO
|
||||
: m_path(first, last)
|
||||
, m_preferred_separator(preferredSeparator) {}
|
||||
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::operator PathView() const noexcept
|
||||
{
|
||||
@@ -733,7 +736,7 @@ namespace AZ::IO
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) -> BasicPath&
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) noexcept -> BasicPath&
|
||||
{
|
||||
m_path = other.m_path;
|
||||
m_preferred_separator = other.m_preferred_separator;
|
||||
@@ -974,13 +977,13 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::MakePreferred() -> BasicPath&
|
||||
{
|
||||
if (m_preferred_separator != '/')
|
||||
if (m_preferred_separator != PosixPathSeparator)
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '/', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), PosixPathSeparator, m_preferred_separator);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '\\', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), WindowsPathSeparator, m_preferred_separator);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1033,6 +1036,24 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
// Returns a copy of the path with the path separators converted to PosixPathSeparator
|
||||
template <typename StringType>
|
||||
AZStd::string BasicPath<StringType>::StringAsPosix() const
|
||||
{
|
||||
AZStd::string resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr AZStd::fixed_string<MaxPathLength> BasicPath<StringType>::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr void BasicPath<StringType>::swap(BasicPath& rhs) noexcept
|
||||
{
|
||||
@@ -1234,6 +1255,7 @@ namespace AZ::IO
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1241,7 +1263,13 @@ namespace AZ::IO
|
||||
constexpr auto BasicPath<StringType>::LexicallyRelative(const PathView& base) const -> BasicPath
|
||||
{
|
||||
BasicPath pathResult(m_preferred_separator);
|
||||
static_cast<PathView>(*this).MakeRelativeTo(pathResult, *this, base);
|
||||
PathView::PathIterable pathIterable;
|
||||
PathView::MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1355,7 +1383,7 @@ namespace AZ::IO
|
||||
return !basePathParts.empty() || !thisPathParts.IsAbsolute();
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyNormal() const
|
||||
constexpr auto PathView::LexicallyNormal() const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
PathIterable pathIterable = GetNormalPathParts(*this);
|
||||
@@ -1367,21 +1395,28 @@ namespace AZ::IO
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyRelative(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyRelative(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
MakeRelativeTo(pathResult, *this, base);
|
||||
PathIterable pathIterable;
|
||||
MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyProximate(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyProximate(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath result = LexicallyRelative(base);
|
||||
if (result.empty())
|
||||
FixedMaxPath pathResult = LexicallyRelative(base);
|
||||
if (pathResult.empty())
|
||||
{
|
||||
return FixedMaxPath(*this);
|
||||
}
|
||||
return result;
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ namespace AZ::IO
|
||||
|
||||
constexpr void clear() noexcept;
|
||||
|
||||
friend constexpr auto PathView::GetNormalPathParts(const AZ::IO::PathView&) noexcept -> PathIterable;
|
||||
friend constexpr auto PathView::AppendNormalPathParts(PathIterable& pathIterable, const AZ::IO::PathView&) noexcept -> void;
|
||||
friend constexpr auto PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView&, const AZ::IO::PathView&) noexcept -> void;
|
||||
PartKindArray m_parts{};
|
||||
size_t m_size{};
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Platform
|
||||
SystemFile::SizeType Length(FileHandleType handle, const SystemFile* systemFile);
|
||||
|
||||
bool Exists(const char* fileName);
|
||||
bool IsDirectory(const char* filePath);
|
||||
void FindFiles(const char* filter, SystemFile::FindFileCB cb);
|
||||
AZ::u64 ModificationTime(const char* fileName);
|
||||
SystemFile::SizeType Length(const char* fileName);
|
||||
@@ -235,6 +236,11 @@ bool SystemFile::Exists(const char* fileName)
|
||||
return Platform::Exists(fileName);
|
||||
}
|
||||
|
||||
bool SystemFile::IsDirectory(const char* filePath)
|
||||
{
|
||||
return Platform::IsDirectory(filePath);
|
||||
}
|
||||
|
||||
void SystemFile::FindFiles(const char* filter, FindFileCB cb)
|
||||
{
|
||||
Platform::FindFiles(filter, cb);
|
||||
|
||||
@@ -99,6 +99,8 @@ namespace AZ
|
||||
// Utility functions
|
||||
/// Check if a file or directory exists.
|
||||
static bool Exists(const char* path);
|
||||
/// Check if path is a directory
|
||||
static bool IsDirectory(const char* path);
|
||||
/// FindFiles
|
||||
typedef AZStd::function<bool /* true to continue to enumerate otherwise false */ (const char* /* fileName*/, bool /* true if file, false if folder*/)> FindFileCB;
|
||||
static void FindFiles(const char* filter, FindFileCB cb);
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
|
||||
AZ_CVAR(float, cl_jobThreadsConcurrencyRatio, 0.6f, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine creates at initialization");
|
||||
AZ_CVAR(uint32_t, cl_jobThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system number of hardware threads that are reserved for O3DE system threads");
|
||||
AZ_CVAR(uint32_t, cl_jobThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system minimum number of worker threads to create after scaling the number of hw threads");
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//=========================================================================
|
||||
@@ -46,9 +54,10 @@ namespace AZ
|
||||
JobManagerThreadDesc threadDesc;
|
||||
|
||||
int numberOfWorkerThreads = m_numberOfWorkerThreads;
|
||||
if (numberOfWorkerThreads <= 0)
|
||||
if (numberOfWorkerThreads <= 0) // spawn default number of threads
|
||||
{
|
||||
numberOfWorkerThreads = AZ::GetMin(static_cast<unsigned int>(desc.m_workerThreads.capacity()), AZStd::thread::hardware_concurrency());
|
||||
uint32_t scaledHardwareThreads = Threading::CalcNumWorkerThreads(cl_jobThreadsConcurrencyRatio, cl_jobThreadsMinNumber, cl_jobThreadsNumReserved);
|
||||
numberOfWorkerThreads = AZ::GetMin(static_cast<unsigned int>(desc.m_workerThreads.capacity()), scaledHardwareThreads);
|
||||
#if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
|
||||
numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS);
|
||||
#endif // (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AZ
|
||||
*/
|
||||
int m_stackSize;
|
||||
|
||||
JobManagerThreadDesc(int cpuId = -1, int priority = -100000, int stackSize = -1)
|
||||
JobManagerThreadDesc(int cpuId = -1, int priority = 0, int stackSize = -1)
|
||||
: m_cpuId(cpuId)
|
||||
, m_priority(priority)
|
||||
, m_stackSize(stackSize)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
@@ -135,18 +135,12 @@ namespace AZ
|
||||
{
|
||||
stringLength = strlen(uuidString);
|
||||
}
|
||||
if (stringLength > MaxPermissiveStringSize)
|
||||
{
|
||||
if (!skipWarnings)
|
||||
{
|
||||
AZ_Warning("Math", false, "Can't create UUID from string length %zu over maximum %zu", stringLength, MaxPermissiveStringSize);
|
||||
}
|
||||
return Uuid::CreateNull();
|
||||
}
|
||||
|
||||
size_t newLength{ 0 };
|
||||
char createString[MaxPermissiveStringSize];
|
||||
|
||||
for (size_t curPos = 0; curPos < stringLength; ++curPos)
|
||||
// Loop until we get to the end of the string OR stop once we've accumulated a full UUID string worth of data
|
||||
for (size_t curPos = 0; curPos < stringLength && newLength < ValidUuidStringLength; ++curPos)
|
||||
{
|
||||
char curChar = uuidString[curPos];
|
||||
switch (curChar)
|
||||
|
||||
@@ -42,8 +42,9 @@ namespace AZ
|
||||
//VER_AZ_RANDOM_CRC32 = 6, // 0 1 1 0
|
||||
};
|
||||
|
||||
static constexpr int ValidUuidStringLength = 32; /// Number of characters (data only, no extra formatting) in a valid UUID string
|
||||
static const size_t MaxStringBuffer = 39; /// 32 Uuid + 4 dashes + 2 brackets + 1 terminate
|
||||
|
||||
|
||||
Uuid() {}
|
||||
Uuid(const char* string, size_t stringLength = 0) { *this = CreateString(string, stringLength); }
|
||||
|
||||
|
||||
@@ -180,6 +180,13 @@ namespace AZ
|
||||
bool IsGreaterEqualThan(const Vector2& v) const;
|
||||
//! @}
|
||||
|
||||
//! Floor/Ceil/Round functions, operate on each component individually, result will be a new Vector2.
|
||||
//! @{
|
||||
Vector2 GetFloor() const;
|
||||
Vector2 GetCeil() const;
|
||||
Vector2 GetRound() const; // Ties to even (banker's rounding)
|
||||
//! @}
|
||||
|
||||
//! Min/Max functions, operate on each component individually, result will be a new Vector2.
|
||||
//! @{
|
||||
Vector2 GetMin(const Vector2& v) const;
|
||||
|
||||
@@ -398,6 +398,24 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetFloor() const
|
||||
{
|
||||
return Vector2(Simd::Vec2::Floor(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetCeil() const
|
||||
{
|
||||
return Vector2(Simd::Vec2::Ceil(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetRound() const
|
||||
{
|
||||
return Vector2(Simd::Vec2::Round(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetMin(const Vector2& v) const
|
||||
{
|
||||
#if AZ_TRAIT_USE_PLATFORM_SIMD_SCALAR
|
||||
|
||||
@@ -211,6 +211,13 @@ namespace AZ
|
||||
bool IsGreaterEqualThan(const Vector3& rhs) const;
|
||||
//! @}
|
||||
|
||||
//! Floor/Ceil/Round functions, operate on each component individually, result will be a new Vector3.
|
||||
//! @{
|
||||
Vector3 GetFloor() const;
|
||||
Vector3 GetCeil() const;
|
||||
Vector3 GetRound() const; // Ties to even (banker's rounding)
|
||||
//! @}
|
||||
|
||||
//! Min/Max functions, operate on each component individually, result will be a new Vector3.
|
||||
//! @{
|
||||
Vector3 GetMin(const Vector3& v) const;
|
||||
|
||||
@@ -481,6 +481,24 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetFloor() const
|
||||
{
|
||||
return Vector3(Simd::Vec3::Floor(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetCeil() const
|
||||
{
|
||||
return Vector3(Simd::Vec3::Ceil(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetRound() const
|
||||
{
|
||||
return Vector3(Simd::Vec3::Round(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetMin(const Vector3& v) const
|
||||
{
|
||||
#if AZ_TRAIT_USE_PLATFORM_SIMD_SCALAR
|
||||
|
||||
@@ -189,6 +189,13 @@ namespace AZ
|
||||
bool IsGreaterEqualThan(const Vector4& rhs) const;
|
||||
//! @}
|
||||
|
||||
//! Floor/Ceil/Round functions, operate on each component individually, result will be a new Vector4.
|
||||
//! @{
|
||||
Vector4 GetFloor() const;
|
||||
Vector4 GetCeil() const;
|
||||
Vector4 GetRound() const; // Ties to even (banker's rounding)
|
||||
//! @}
|
||||
|
||||
//! Min/Max functions, operate on each component individually, result will be a new Vector4.
|
||||
//! @{
|
||||
Vector4 GetMin(const Vector4& v) const;
|
||||
|
||||
@@ -464,6 +464,24 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetFloor() const
|
||||
{
|
||||
return Vector4(Simd::Vec4::Floor(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetCeil() const
|
||||
{
|
||||
return Vector4(Simd::Vec4::Ceil(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetRound() const
|
||||
{
|
||||
return Vector4(Simd::Vec4::Round(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetMin(const Vector4& v) const
|
||||
{
|
||||
#if AZ_TRAIT_USE_PLATFORM_SIMD_SCALAR
|
||||
|
||||
@@ -34,7 +34,9 @@ namespace AZ
|
||||
friend IAllocator;
|
||||
friend class AllocatorBase;
|
||||
friend class Debug::AllocationRecords;
|
||||
friend class AZ::Internal::EnvironmentVariableHolder<AllocatorManager>;
|
||||
template<typename T, typename... Args> friend constexpr auto AZStd::construct_at(T*, Args&&... args)
|
||||
->AZStd::enable_if_t<AZStd::is_void_v<AZStd::void_t<decltype(new (AZStd::declval<void*>()) T(AZStd::forward<Args>(args)...))>>, T*>;
|
||||
template<typename T> constexpr friend void AZStd::destroy_at(T*);
|
||||
|
||||
public:
|
||||
typedef AZStd::function<void (IAllocator* allocator, size_t /*byteSize*/, size_t /*alignment*/, int/* flags*/, const char* /*name*/, const char* /*fileName*/, int lineNum /*=0*/)> OutOfMemoryCBType;
|
||||
|
||||
@@ -251,16 +251,15 @@ namespace AZ
|
||||
class EnvironmentVariableHolder
|
||||
: public EnvironmentVariableHolderBase
|
||||
{
|
||||
void ConstructImpl(const AZStd::true_type& /* AZStd::has_trivial_constructor<T> */)
|
||||
{
|
||||
memset(&m_value, 0, sizeof(T));
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void ConstructImpl(const AZStd::false_type& /* AZStd::has_trivial_constructor<T> */, Args&&... args)
|
||||
void ConstructImpl(Args&&... args)
|
||||
{
|
||||
// Construction of non-trivial types is left up to the type's constructor.
|
||||
new(&m_value) T(AZStd::forward<Args>(args)...);
|
||||
// Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object
|
||||
#if __cpp_lib_launder
|
||||
AZStd::construct_at(std::launder(reinterpret_cast<T*>(&m_value)), AZStd::forward<Args>(args)...);
|
||||
#else
|
||||
AZStd::construct_at(reinterpret_cast<T*>(&m_value), AZStd::forward<Args>(args)...);
|
||||
#endif
|
||||
}
|
||||
static void DestructDispatchNoLock(EnvironmentVariableHolderBase *base, DestroyTarget selfDestruct)
|
||||
{
|
||||
@@ -274,10 +273,12 @@ namespace AZ
|
||||
AZ_Assert(self->m_isConstructed, "Variable is not constructed. Please check your logic and guard if needed!");
|
||||
self->m_isConstructed = false;
|
||||
self->m_moduleOwner = nullptr;
|
||||
if constexpr(!AZStd::is_trivially_destructible_v<T>)
|
||||
{
|
||||
reinterpret_cast<T*>(&self->m_value)->~T();
|
||||
}
|
||||
// Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object
|
||||
#if __cpp_lib_launder
|
||||
AZStd::destroy_at(std::launder(reinterpret_cast<T*>(&self->m_value)));
|
||||
#else
|
||||
AZStd::destroy_at(reinterpret_cast<T*>(&self->m_value));
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
EnvironmentVariableHolder(u32 guid, bool isOwnershipTransfer, Environment::AllocatorInterface* allocator)
|
||||
@@ -303,24 +304,13 @@ namespace AZ
|
||||
UnregisterAndDestroy(DestructDispatchNoLock, moduleRelease);
|
||||
}
|
||||
|
||||
void Construct()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::spin_mutex> lock(m_mutex);
|
||||
if (!m_isConstructed)
|
||||
{
|
||||
ConstructImpl(AZStd::is_trivially_constructible<T>{});
|
||||
m_isConstructed = true;
|
||||
m_moduleOwner = Environment::GetModuleId();
|
||||
}
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void Construct(Args&&... args)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::spin_mutex> lock(m_mutex);
|
||||
if (!m_isConstructed)
|
||||
{
|
||||
ConstructImpl(typename AZStd::false_type(), AZStd::forward<Args>(args)...);
|
||||
ConstructImpl(AZStd::forward<Args>(args)...);
|
||||
m_isConstructed = true;
|
||||
m_moduleOwner = Environment::GetModuleId();
|
||||
}
|
||||
@@ -333,7 +323,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// variable storage
|
||||
typename AZStd::aligned_storage<sizeof(T), AZStd::alignment_of<T>::value>::type m_value;
|
||||
AZStd::aligned_storage_for_t<T> m_value;
|
||||
static int s_moduleUseCount;
|
||||
};
|
||||
|
||||
@@ -468,6 +458,11 @@ namespace AZ
|
||||
Get() = value;
|
||||
}
|
||||
|
||||
void Set(T&& value)
|
||||
{
|
||||
Get() = AZStd::move(value);
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return IsValid();
|
||||
|
||||
@@ -42,7 +42,10 @@ namespace AZ
|
||||
AZ_Assert(m_useCount > 0, "m_useCount is already 0!");
|
||||
if (m_useCount.fetch_sub(1) == 1)
|
||||
{
|
||||
AZ::NameDictionary::Instance().TryReleaseName(hash);
|
||||
if (AZ::NameDictionary::IsReady())
|
||||
{
|
||||
AZ::NameDictionary::Instance().TryReleaseName(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,23 +21,18 @@ namespace AZ
|
||||
|
||||
namespace NameDictionaryInternal
|
||||
{
|
||||
static AZ::EnvironmentVariable<NameDictionary*> s_instance = nullptr;
|
||||
static AZ::EnvironmentVariable<NameDictionary> s_instance = nullptr;
|
||||
}
|
||||
|
||||
void NameDictionary::Create()
|
||||
{
|
||||
using namespace NameDictionaryInternal;
|
||||
|
||||
AZ_Assert(!s_instance || !s_instance.Get(), "NameDictionary already created!");
|
||||
AZ_Assert(!s_instance, "NameDictionary already created!");
|
||||
|
||||
if (!s_instance)
|
||||
{
|
||||
s_instance = AZ::Environment::CreateVariable<NameDictionary*>(NameDictionaryInstanceName);
|
||||
}
|
||||
|
||||
if (!s_instance.Get())
|
||||
{
|
||||
s_instance.Set(aznew NameDictionary());
|
||||
s_instance = AZ::Environment::CreateVariable<NameDictionary>(NameDictionaryInstanceName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +41,7 @@ namespace AZ
|
||||
using namespace NameDictionaryInternal;
|
||||
|
||||
AZ_Assert(s_instance, "NameDictionary not created!");
|
||||
delete (*s_instance);
|
||||
*s_instance = nullptr;
|
||||
s_instance.Reset();
|
||||
}
|
||||
|
||||
bool NameDictionary::IsReady()
|
||||
@@ -56,10 +50,10 @@ namespace AZ
|
||||
|
||||
if (!s_instance)
|
||||
{
|
||||
s_instance = Environment::FindVariable<NameDictionary*>(NameDictionaryInstanceName);
|
||||
s_instance = Environment::FindVariable<NameDictionary>(NameDictionaryInstanceName);
|
||||
}
|
||||
|
||||
return s_instance && *s_instance;
|
||||
return s_instance.IsConstructed();
|
||||
}
|
||||
|
||||
NameDictionary& NameDictionary::Instance()
|
||||
@@ -68,12 +62,12 @@ namespace AZ
|
||||
|
||||
if (!s_instance)
|
||||
{
|
||||
s_instance = Environment::FindVariable<NameDictionary*>(NameDictionaryInstanceName);
|
||||
s_instance = Environment::FindVariable<NameDictionary>(NameDictionaryInstanceName);
|
||||
}
|
||||
|
||||
AZ_Assert(s_instance && *s_instance, "NameDictionary has not been initialized yet.");
|
||||
AZ_Assert(s_instance.IsConstructed(), "NameDictionary has not been initialized yet.");
|
||||
|
||||
return *(*s_instance);
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
NameDictionary::NameDictionary()
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
|
||||
namespace MaterialEditor
|
||||
namespace MaterialEditor
|
||||
{
|
||||
class MaterialEditorCoreComponent;
|
||||
}
|
||||
@@ -34,14 +34,14 @@ namespace AZ
|
||||
{
|
||||
class NameData;
|
||||
};
|
||||
|
||||
|
||||
//! Maintains a list of unique strings for Name objects.
|
||||
//! The main benefit of the Name system is very fast string equality comparison, because every
|
||||
//! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not
|
||||
//! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not
|
||||
//! collide. It also saves memory by removing duplicate strings.
|
||||
//!
|
||||
//! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't
|
||||
//! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names
|
||||
//! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't
|
||||
//! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names
|
||||
//! that already exist.
|
||||
class NameDictionary final
|
||||
{
|
||||
@@ -51,7 +51,10 @@ namespace AZ
|
||||
friend Name;
|
||||
friend Internal::NameData;
|
||||
friend UnitTest::NameDictionaryTester;
|
||||
|
||||
template<typename T, typename... Args> friend constexpr auto AZStd::construct_at(T*, Args&&... args)
|
||||
-> AZStd::enable_if_t<AZStd::is_void_v<AZStd::void_t<decltype(new (AZStd::declval<void*>()) T(AZStd::forward<Args>(args)...))>>, T*>;
|
||||
template<typename T> constexpr friend void AZStd::destroy_at(T*);
|
||||
|
||||
public:
|
||||
|
||||
static void Create();
|
||||
@@ -62,7 +65,7 @@ namespace AZ
|
||||
|
||||
//! Makes a Name from the provided raw string. If an entry already exists in the dictionary, it is shared.
|
||||
//! Otherwise, it is added to the internal dictionary.
|
||||
//!
|
||||
//!
|
||||
//! @param name The name to resolve against the dictionary.
|
||||
//! @return A Name instance holding a dictionary entry associated with the provided raw string.
|
||||
Name MakeName(AZStd::string_view name);
|
||||
@@ -84,13 +87,13 @@ namespace AZ
|
||||
// Attempts to release the name from the dictionary, but checks to make sure
|
||||
// a reference wasn't taken by another thread.
|
||||
void TryReleaseName(Name::Hash hash);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Calculates a hash for the provided name string.
|
||||
// Does not attempt to resolve hash collisions; that is handled elsewhere.
|
||||
Name::Hash CalcHash(AZStd::string_view name);
|
||||
|
||||
|
||||
AZStd::unordered_map<Name::Hash, Internal::NameData*> m_dictionary;
|
||||
mutable AZStd::shared_mutex m_sharedMutex;
|
||||
};
|
||||
|
||||
@@ -204,14 +204,14 @@ namespace AZ
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0;
|
||||
//! Register a function that will be called before a file is merged.
|
||||
//! @callback The function to call before a file is merged.
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0;
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) = 0;
|
||||
|
||||
//! Register a function that will be called after a file is merged.
|
||||
//! @callback The function to call after a file is merged.
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0;
|
||||
//! Register a function that will be called after a file is merged.
|
||||
//! @callback The function to call after a file is merged.
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0;
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) = 0;
|
||||
|
||||
//! Gets the boolean value at the provided path.
|
||||
//! @param result The target to write the result to.
|
||||
|
||||
@@ -276,7 +276,9 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return engineRoot;
|
||||
}
|
||||
|
||||
return {};
|
||||
// Fall back to using the project root as the engine root if the engine path could not be reconciled
|
||||
// by checking the project.json "engine" string within o3de_manifest.json "engine_paths" object
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry)
|
||||
@@ -309,7 +311,13 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
return {};
|
||||
// Step 3 Check for a "Cache" directory by scanning upwards from the executable directory
|
||||
if (auto candidateRoot = Internal::ScanUpRootLocator("Cache");
|
||||
!candidateRoot.empty() && AZ::IO::SystemFile::IsDirectory(candidateRoot.c_str()))
|
||||
{
|
||||
projectRoot = AZStd::move(candidateRoot);
|
||||
}
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
AZStd::string_view ConfigParserSettings::DefaultCommentPrefixFilter(AZStd::string_view line)
|
||||
@@ -538,7 +546,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetExecutableDirectory();
|
||||
registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
|
||||
|
||||
// Engine root folder - corresponds to the @engroot@ and @devroot@ aliases
|
||||
// Engine root folder - corresponds to the @engroot@ and @engroot@ aliases
|
||||
AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry);
|
||||
registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native());
|
||||
|
||||
@@ -562,7 +570,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
}
|
||||
|
||||
// Project path - corresponds to the @devassets@ alias
|
||||
// Project path - corresponds to the @projectroot@ alias
|
||||
// NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded.
|
||||
path = engineRoot / projectPathValue;
|
||||
|
||||
@@ -654,7 +662,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache: root - same as the @root@ alias, this is the starting path for cache files.
|
||||
// Cache: root - same as the @products@ alias, this is the starting path for cache files.
|
||||
path = normalizedProjectPath / "Cache";
|
||||
registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native());
|
||||
path /= assetPlatform;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistryVisitorUtils.h>
|
||||
|
||||
|
||||
namespace AZ::SettingsRegistryVisitorUtils
|
||||
{
|
||||
// Field Visitor implementation
|
||||
FieldVisitor::FieldVisitor() = default;
|
||||
FieldVisitor::FieldVisitor(VisitFieldType visitFieldType)
|
||||
: m_visitFieldType{ visitFieldType }
|
||||
{
|
||||
}
|
||||
|
||||
auto FieldVisitor::Traverse(AZStd::string_view path, AZStd::string_view valueName,
|
||||
VisitAction action, Type type) -> VisitResponse
|
||||
{
|
||||
// A default response skip prevents visiting grand children(depth 2 or lower)
|
||||
VisitResponse visitResponse = VisitResponse::Skip;
|
||||
if (action == VisitAction::Begin)
|
||||
{
|
||||
// Invoke FieldVisitor override if the root path has been set
|
||||
if (m_rootPath.has_value())
|
||||
{
|
||||
Visit(path, valueName, type);
|
||||
}
|
||||
// To make sure only the direct children are visited(depth 1)
|
||||
// set the root path once and set the VisitReponsoe
|
||||
// to Continue to recurse into is fields
|
||||
if (!m_rootPath.has_value())
|
||||
{
|
||||
bool visitableFieldType{};
|
||||
switch (m_visitFieldType)
|
||||
{
|
||||
case VisitFieldType::Array:
|
||||
visitableFieldType = type == Type::Array;
|
||||
break;
|
||||
case VisitFieldType::Object:
|
||||
visitableFieldType = type == Type::Object;
|
||||
break;
|
||||
case VisitFieldType::ArrayOrObject:
|
||||
visitableFieldType = type == Type::Array || type ==Type::Object;
|
||||
break;
|
||||
default:
|
||||
AZ_Error("FieldVisitor", false, "The field visitation type value is invalid");
|
||||
break;
|
||||
}
|
||||
|
||||
if (visitableFieldType)
|
||||
{
|
||||
m_rootPath = path;
|
||||
visitResponse = VisitResponse::Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (action == VisitAction::Value)
|
||||
{
|
||||
// Invoke FieldVisitor override if the root path has been set
|
||||
if (m_rootPath.has_value())
|
||||
{
|
||||
Visit(path, valueName, type);
|
||||
}
|
||||
}
|
||||
else if (action == VisitAction::End)
|
||||
{
|
||||
// Reset m_rootPath back to null when the root path has finished being visited
|
||||
if (m_rootPath.has_value() && *m_rootPath == path)
|
||||
{
|
||||
m_rootPath = AZStd::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return visitResponse;
|
||||
}
|
||||
|
||||
// Array Visitor implementation
|
||||
ArrayVisitor::ArrayVisitor()
|
||||
: FieldVisitor(VisitFieldType::Array)
|
||||
{
|
||||
}
|
||||
|
||||
// Object Visitor implementation
|
||||
ObjectVisitor::ObjectVisitor()
|
||||
: FieldVisitor(VisitFieldType::Object)
|
||||
{
|
||||
}
|
||||
|
||||
// Generic VisitField Callback implemention
|
||||
template <typename BaseVisitor>
|
||||
bool VisitFieldCallback(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
struct VisitFieldVisitor
|
||||
: BaseVisitor
|
||||
{
|
||||
using BaseVisitor::Visit;
|
||||
VisitFieldVisitor(const VisitorCallback& visitCallback)
|
||||
: m_visitCallback{ visitCallback }
|
||||
{}
|
||||
|
||||
void Visit(AZStd::string_view path, AZStd::string_view fieldIndex, typename BaseVisitor::Type type) override
|
||||
{
|
||||
m_visitCallback(path, fieldIndex, type);
|
||||
}
|
||||
|
||||
const VisitorCallback& m_visitCallback;
|
||||
};
|
||||
|
||||
VisitFieldVisitor visitor{ visitCallback };
|
||||
return settingsRegistry.Visit(visitor, path);
|
||||
}
|
||||
|
||||
// VisitField implementation
|
||||
bool VisitField(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
return VisitFieldCallback<FieldVisitor>(settingsRegistry, visitCallback, path);
|
||||
}
|
||||
|
||||
// VisitArray implementation
|
||||
bool VisitArray(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
return VisitFieldCallback<ArrayVisitor>(settingsRegistry, visitCallback, path);
|
||||
}
|
||||
|
||||
// VisitObject implementation
|
||||
bool VisitObject(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
return VisitFieldCallback<ObjectVisitor>(settingsRegistry, visitCallback, path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
|
||||
|
||||
namespace AZ::SettingsRegistryVisitorUtils
|
||||
{
|
||||
//! Interface for visiting the fields of an array or object
|
||||
//! To access the values, use the SettingsRegistryInterface Get/GetObject methods
|
||||
struct FieldVisitor
|
||||
: public AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse;
|
||||
using VisitAction = AZ::SettingsRegistryInterface::VisitAction;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
|
||||
FieldVisitor();
|
||||
|
||||
// Bring the base class visitor functions into scope
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
virtual void Visit(AZStd::string_view path, AZStd::string_view arrayIndex, Type type) = 0;
|
||||
|
||||
protected:
|
||||
// VisitFieldType is used for filtering the type of referenced by the root path
|
||||
enum class VisitFieldType
|
||||
{
|
||||
Array,
|
||||
Object,
|
||||
ArrayOrObject
|
||||
};
|
||||
FieldVisitor(const VisitFieldType visitFieldType);
|
||||
private:
|
||||
VisitResponse Traverse(AZStd::string_view path, AZStd::string_view valueName,
|
||||
VisitAction action, Type type) override;
|
||||
|
||||
VisitFieldType m_visitFieldType{ VisitFieldType::ArrayOrObject };
|
||||
AZStd::optional<AZ::SettingsRegistryInterface::FixedValueString> m_rootPath;
|
||||
};
|
||||
|
||||
//! Interface for visiting the fields of an array
|
||||
//! To access the values, use the SettingsRegistryInterface Get/GetObject methods
|
||||
struct ArrayVisitor
|
||||
: public FieldVisitor
|
||||
{
|
||||
ArrayVisitor();
|
||||
};
|
||||
|
||||
//! Interface for visiting the fields of an object
|
||||
//! To access the values, use the SettingsRegistryInterface Get/GetObject methods
|
||||
struct ObjectVisitor
|
||||
: public FieldVisitor
|
||||
{
|
||||
ObjectVisitor();
|
||||
};
|
||||
|
||||
//! Signature of callback funcition invoked when visiting an element of an array or object
|
||||
using VisitorCallback = AZStd::function<void(AZStd::string_view path, AZStd::string_view fieldName,
|
||||
AZ::SettingsRegistryInterface::Type)>;
|
||||
|
||||
//! Invokes the visitor callback for each element of either the array or object at @path
|
||||
//! If @path is not an array or object, then no elements are visited
|
||||
//! This function will not recurse into children of elements
|
||||
//! @visitCallback functor that is invoked for each array or object element found
|
||||
bool VisitField(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path);
|
||||
//! Invokes the visitor callback for each element of the array at @path
|
||||
//! If @path is not an array, then no elements are visited
|
||||
//! This function will not recurse into children of elements
|
||||
//! @visitCallback functor that is invoked for each array element found
|
||||
bool VisitArray(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path);
|
||||
//! Invokes the visitor callback for each element of the object at @path
|
||||
//! If @path is not an object, then no elements are visited
|
||||
//! This function will not recurse into children of elements
|
||||
//! @visitCallback functor that is invoked for each object element found
|
||||
bool VisitObject(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "RunningStatisticsManager.h"
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
namespace Statistics
|
||||
{
|
||||
bool RunningStatisticsManager::ContainsStatistic(const AZStd::string& name)
|
||||
{
|
||||
auto iterator = m_statisticsNamesToIndexMap.find(name);
|
||||
return iterator != m_statisticsNamesToIndexMap.end();
|
||||
}
|
||||
|
||||
bool RunningStatisticsManager::AddStatistic(const AZStd::string& name, const AZStd::string& units)
|
||||
{
|
||||
if (ContainsStatistic(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AddStatisticValidated(name, units);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::RemoveStatistic(const AZStd::string& name)
|
||||
{
|
||||
auto iterator = m_statisticsNamesToIndexMap.find(name);
|
||||
if (iterator == m_statisticsNamesToIndexMap.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
AZ::u32 itemIndex = iterator->second;
|
||||
m_statistics.erase(m_statistics.begin() + itemIndex);
|
||||
m_statisticsNamesToIndexMap.erase(iterator);
|
||||
//Update the indices in m_statisticsNamesToIndexMap.
|
||||
while (itemIndex < m_statistics.size())
|
||||
{
|
||||
const AZStd::string& statName = m_statistics[itemIndex].GetName();
|
||||
m_statisticsNamesToIndexMap[statName] = itemIndex;
|
||||
++itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::ResetStatistic(const AZStd::string& name)
|
||||
{
|
||||
NamedRunningStatistic* stat = GetStatistic(name);
|
||||
if (!stat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
stat->Reset();
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::ResetAllStatistics()
|
||||
{
|
||||
for (NamedRunningStatistic& stat : m_statistics)
|
||||
{
|
||||
stat.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::PushSampleForStatistic(const AZStd::string& name, double value)
|
||||
{
|
||||
NamedRunningStatistic* stat = GetStatistic(name);
|
||||
if (!stat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
stat->PushSample(value);
|
||||
}
|
||||
|
||||
NamedRunningStatistic* RunningStatisticsManager::GetStatistic(const AZStd::string& name, AZ::u32* indexOut)
|
||||
{
|
||||
auto iterator = m_statisticsNamesToIndexMap.find(name);
|
||||
if (iterator == m_statisticsNamesToIndexMap.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const AZ::u32 index = iterator->second;
|
||||
if (indexOut)
|
||||
{
|
||||
*indexOut = index;
|
||||
}
|
||||
return &m_statistics[index];
|
||||
}
|
||||
|
||||
const AZStd::vector<NamedRunningStatistic>& RunningStatisticsManager::GetAllStatistics() const
|
||||
{
|
||||
return m_statistics;
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::AddStatisticValidated(const AZStd::string& name, const AZStd::string& units)
|
||||
{
|
||||
m_statistics.emplace_back(NamedRunningStatistic(name, units));
|
||||
const AZ::u32 itemIndex = static_cast<AZ::u32>(m_statistics.size() - 1);
|
||||
m_statisticsNamesToIndexMap[name] = itemIndex;
|
||||
}
|
||||
|
||||
}//namespace Statistics
|
||||
}//namespace AzFramework
|
||||
@@ -8,7 +8,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/BusImpl.h> //Just to get AZ::NullMutex
|
||||
#include <AzCore/std/chrono/types.h>
|
||||
#include <AzCore/Statistics/StatisticsManager.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
@@ -37,8 +36,7 @@ namespace AZ
|
||||
//! are some things to consider when working with the StatisticalProfilerProxy:
|
||||
//! The StatisticalProfilerProxy OWNS an array of StatisticalProfiler<AZStd::string, AZStd::shared_spin_mutex>.
|
||||
//! You can "manage" one of those StatisticalProfiler by getting a reference to it and
|
||||
//! add Running statistics etc. See The TerrainProfilers mentioned above to see concrete use
|
||||
//! cases on how to work with the StatisticalProfilerProxy.
|
||||
//! add Running statistics etc.
|
||||
template <class StatIdType = AZStd::string, class MutexType = AZ::NullMutex>
|
||||
class StatisticalProfiler
|
||||
{
|
||||
|
||||
@@ -7,28 +7,12 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/chrono/types.h>
|
||||
#include <AzCore/std/parallel/shared_spin_mutex.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
#include <AzCore/std/containers/bitset.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Statistics/StatisticalProfiler.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/parallel/shared_spin_mutex.h>
|
||||
|
||||
|
||||
#if defined(AZ_STATISTICAL_PROFILING_ENABLED)
|
||||
|
||||
#if defined(AZ_PROFILE_SCOPE)
|
||||
#undef AZ_PROFILE_SCOPE
|
||||
#endif // #if defined(AZ_PROFILE_SCOPE)
|
||||
|
||||
#define AZ_PROFILE_SCOPE(profiler, scopeNameId) \
|
||||
static const AZStd::string AZ_JOIN(blockName, __LINE__)(scopeNameId); \
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope AZ_JOIN(scope, __LINE__)(profiler, AZ_JOIN(blockName, __LINE__));
|
||||
|
||||
#endif //#if defined(AZ_STATISTICAL_PROFILING_ENABLED)
|
||||
|
||||
namespace AZ::Statistics
|
||||
{
|
||||
using StatisticalProfilerId = uint32_t;
|
||||
@@ -65,7 +49,7 @@ namespace AZ::Statistics
|
||||
public:
|
||||
AZ_TYPE_INFO(StatisticalProfilerProxy, "{1103D0EB-1C32-4854-B9D9-40A2D65BDBD2}");
|
||||
|
||||
using StatIdType = AZStd::string;
|
||||
using StatIdType = AZ::Crc32;
|
||||
using StatisticalProfilerType = StatisticalProfiler<StatIdType, AZStd::shared_spin_mutex>;
|
||||
|
||||
//! A Convenience class used to measure time performance of scopes of code
|
||||
@@ -94,6 +78,7 @@ namespace AZ::Statistics
|
||||
}
|
||||
m_startTime = AZStd::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
~TimedScope()
|
||||
{
|
||||
if (!m_profilerProxy)
|
||||
@@ -122,7 +107,6 @@ namespace AZ::Statistics
|
||||
|
||||
StatisticalProfilerProxy()
|
||||
{
|
||||
// TODO:BUDGETS Query available budgets at registration time and create an associated profiler per type
|
||||
AZ::Interface<StatisticalProfilerProxy>::Register(this);
|
||||
}
|
||||
|
||||
@@ -135,30 +119,54 @@ namespace AZ::Statistics
|
||||
StatisticalProfilerProxy(StatisticalProfilerProxy&&) = delete;
|
||||
StatisticalProfilerProxy& operator=(StatisticalProfilerProxy&&) = delete;
|
||||
|
||||
void RegisterProfilerId(StatisticalProfilerId id)
|
||||
{
|
||||
m_profilers.try_emplace(id, ProfilerInfo());
|
||||
}
|
||||
|
||||
bool IsProfilerActive(StatisticalProfilerId id) const
|
||||
{
|
||||
return m_activeProfilersFlag[static_cast<AZStd::size_t>(id)];
|
||||
auto iter = m_profilers.find(id);
|
||||
return (iter != m_profilers.end()) ? iter->second.m_enabled : false;
|
||||
}
|
||||
|
||||
StatisticalProfilerType& GetProfiler(StatisticalProfilerId id)
|
||||
{
|
||||
return m_profilers[static_cast<AZStd::size_t>(id)];
|
||||
auto iter = m_profilers.try_emplace(id, ProfilerInfo()).first;
|
||||
return iter->second.m_profiler;
|
||||
}
|
||||
|
||||
void ActivateProfiler(StatisticalProfilerId id, bool activate)
|
||||
void ActivateProfiler(StatisticalProfilerId id, bool activate, bool autoCreate = true)
|
||||
{
|
||||
m_activeProfilersFlag[static_cast<AZStd::size_t>(id)] = activate;
|
||||
if (autoCreate)
|
||||
{
|
||||
auto iter = m_profilers.try_emplace(id, ProfilerInfo()).first;
|
||||
iter->second.m_enabled = activate;
|
||||
}
|
||||
else if (auto iter = m_profilers.find(id); iter != m_profilers.end())
|
||||
{
|
||||
iter->second.m_enabled = activate;
|
||||
}
|
||||
}
|
||||
|
||||
void PushSample(StatisticalProfilerId id, const StatIdType& statId, double value)
|
||||
{
|
||||
m_profilers[static_cast<AZStd::size_t>(id)].PushSample(statId, value);
|
||||
if (auto iter = m_profilers.find(id); iter != m_profilers.end())
|
||||
{
|
||||
iter->second.m_profiler.PushSample(statId, value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO:BUDGETS the number of bits allocated here must be based on the number of budgets available at profiler registration time
|
||||
AZStd::bitset<128> m_activeProfilersFlag;
|
||||
AZStd::vector<StatisticalProfilerType> m_profilers;
|
||||
struct ProfilerInfo
|
||||
{
|
||||
StatisticalProfilerType m_profiler;
|
||||
bool m_enabled{ false };
|
||||
};
|
||||
|
||||
using ProfilerMap = AZStd::unordered_map<StatisticalProfilerId, ProfilerInfo>;
|
||||
|
||||
ProfilerMap m_profilers;
|
||||
}; // class StatisticalProfilerProxy
|
||||
|
||||
}; // namespace AZ::Statistics
|
||||
|
||||
@@ -308,11 +308,11 @@ namespace AZ
|
||||
|
||||
void TaskExecutor::SetInstance(TaskExecutor* executor)
|
||||
{
|
||||
if (!executor)
|
||||
if (!executor) // allow unsetting the executor
|
||||
{
|
||||
s_executor.Reset();
|
||||
}
|
||||
else if (!s_executor) // ignore any calls to set after the first (this happens in unit tests that create new system entities)
|
||||
else if (!s_executor) // ignore any extra executors after the first (this happens during unit tests)
|
||||
{
|
||||
s_executor = AZ::Environment::CreateVariable<TaskExecutor*>(s_executorName, executor);
|
||||
}
|
||||
|
||||
@@ -11,9 +11,15 @@
|
||||
#include <AzCore/Task/TaskGraphSystemComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
|
||||
// Create a cvar as a central location for experimentation with switching from the Job system to TaskGraph system.
|
||||
AZ_CVAR(bool, cl_activateTaskGraph, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Flag clients of TaskGraph to switch between jobs/taskgraph (Note does not disable task graph system)");
|
||||
AZ_CVAR(float, cl_taskGraphThreadsConcurrencyRatio, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph calculate the number of worker threads to spawn by scaling the number of hw threads, value is clamped between 0.0f and 1.0f");
|
||||
AZ_CVAR(uint32_t, cl_taskGraphThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph number of hardware threads that are reserved for O3DE system threads. Value is clamped between 0 and the number of logical cores in the system");
|
||||
AZ_CVAR(uint32_t, cl_taskGraphThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph minimum number of worker threads to create after scaling the number of hw threads");
|
||||
|
||||
static constexpr uint32_t TaskExecutorServiceCrc = AZ_CRC_CE("TaskExecutorService");
|
||||
|
||||
namespace AZ
|
||||
@@ -24,8 +30,8 @@ namespace AZ
|
||||
|
||||
if (Interface<TaskGraphActiveInterface>::Get() == nullptr)
|
||||
{
|
||||
Interface<TaskGraphActiveInterface>::Register(this);
|
||||
m_taskExecutor = aznew TaskExecutor();
|
||||
Interface<TaskGraphActiveInterface>::Register(this); // small window that another thread can try to use taskgraph between this line and the set instance.
|
||||
m_taskExecutor = aznew TaskExecutor(Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved));
|
||||
TaskExecutor::SetInstance(m_taskExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
namespace AZ::Threading
|
||||
{
|
||||
uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads)
|
||||
{
|
||||
const uint32_t maxHardwareThreads = AZStd::thread::hardware_concurrency();
|
||||
const uint32_t numReservedThreads = AZ::GetMin<uint32_t>(reservedNumThreads, maxHardwareThreads); // protect against num reserved being bigger than the number of hw threads
|
||||
const uint32_t maxWorkerThreads = maxHardwareThreads - numReservedThreads;
|
||||
const float requestedWorkerThreads = AZ::GetClamp<float>(workerThreadsRatio, 0.0f, 1.0f) * static_cast<float>(maxWorkerThreads);
|
||||
const uint32_t requestedWorkerThreadsRounded = AZStd::lround(requestedWorkerThreads);
|
||||
const uint32_t numWorkerThreads = AZ::GetMax<uint32_t>(minNumWorkerThreads, requestedWorkerThreadsRounded);
|
||||
return numWorkerThreads;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
namespace AZ::Threading
|
||||
{
|
||||
//! Calculates the number of worker threads a system should use based on the number of hardware threads a device has.
|
||||
//! result = max (minNumWorkerThreads, workerThreadsRatio * (num_hardware_threads - reservedNumThreads))
|
||||
//! @param workerThreadsRatio scale applied to the calculated maximum number of threads available after reserved threads have been accounted for. Clamped between 0 and 1.
|
||||
//! @param minNumWorkerThreads minimum value that will be returned. Value is unclamped and can be more than num_hardware_threads.
|
||||
//! @param reservedNumThreads number of hardware threads to reserve for O3DE system threads. Value clamped to num_hardware_threads.
|
||||
//! @return number of worker threads for the calling system to allocate
|
||||
uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads);
|
||||
};
|
||||
@@ -13,14 +13,26 @@
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/std/time.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//! This is a strong typedef for representing a millisecond value since application start.
|
||||
AZ_TYPE_SAFE_INTEGRAL(TimeMs, int64_t);
|
||||
|
||||
//! This is a strong typedef for representing a microsecond value since application start.
|
||||
//! Using int64_t as the underlying type, this is good to represent approximately 292,471 years
|
||||
AZ_TYPE_SAFE_INTEGRAL(TimeUs, int64_t);
|
||||
|
||||
//! @class ITime
|
||||
//! @brief This is an AZ::Interface<> for managing time related operations.
|
||||
//! AZ::ITime and associated types may not operate in realtime. These abstractions are to allow our application
|
||||
//! simulation to operate both slower and faster than realtime in a well defined and user controllable manner
|
||||
//! The rate at which time passes for AZ::ITime is controlled by the cvar t_scale
|
||||
//! t_scale == 0 means simulation time should halt
|
||||
//! 0 < t_scale < 1 will cause time to pass slower than realtime, with t_scale 0.1 being roughly 1/10th realtime
|
||||
//! t_scale == 1 will cause time to pass at roughly realtime
|
||||
//! t_scale > 1 will cause time to pass faster than normal, with t_scale 10 being roughly 10x realtime
|
||||
class ITime
|
||||
{
|
||||
public:
|
||||
@@ -33,6 +45,10 @@ namespace AZ
|
||||
//! @return the number of milliseconds that have elapsed since application start
|
||||
virtual TimeMs GetElapsedTimeMs() const = 0;
|
||||
|
||||
//! Returns the number of microseconds since application start.
|
||||
//! @return the number of microseconds that have elapsed since application start
|
||||
virtual TimeUs GetElapsedTimeUs() const = 0;
|
||||
|
||||
AZ_DISABLE_COPY_MOVE(ITime);
|
||||
};
|
||||
|
||||
@@ -51,6 +67,53 @@ namespace AZ
|
||||
{
|
||||
return AZ::Interface<ITime>::Get()->GetElapsedTimeMs();
|
||||
}
|
||||
}
|
||||
|
||||
//! This is a simple convenience wrapper
|
||||
inline TimeUs GetElapsedTimeUs()
|
||||
{
|
||||
return AZ::Interface<ITime>::Get()->GetElapsedTimeUs();
|
||||
}
|
||||
|
||||
//! Converts from milliseconds to microseconds
|
||||
inline TimeUs TimeMsToUs(TimeMs value)
|
||||
{
|
||||
return static_cast<TimeUs>(value * static_cast<TimeMs>(1000));
|
||||
}
|
||||
|
||||
//! Converts from microseconds to milliseconds
|
||||
inline TimeMs TimeUsToMs(TimeUs value)
|
||||
{
|
||||
return static_cast<TimeMs>(value / static_cast<TimeUs>(1000));
|
||||
}
|
||||
|
||||
//! Converts from milliseconds to seconds
|
||||
inline float TimeMsToSeconds(TimeMs value)
|
||||
{
|
||||
return static_cast<float>(value) / 1000.0f;
|
||||
}
|
||||
|
||||
//! Converts from microseconds to seconds
|
||||
inline float TimeUsToSeconds(TimeUs value)
|
||||
{
|
||||
return static_cast<float>(value) / 1000000.0f;
|
||||
}
|
||||
|
||||
//! Converts from milliseconds to AZStd::chrono::time_point
|
||||
inline auto TimeMsToChrono(TimeMs value)
|
||||
{
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoValue = AZStd::chrono::milliseconds(aznumeric_cast<int64_t>(value));
|
||||
return epoch + chronoValue;
|
||||
}
|
||||
|
||||
//! Converts from microseconds to AZStd::chrono::time_point
|
||||
inline auto TimeUsToChrono(TimeUs value)
|
||||
{
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoValue = AZStd::chrono::microseconds(aznumeric_cast<int64_t>(value));
|
||||
return epoch + chronoValue;
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(AZ::TimeMs);
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(AZ::TimeUs);
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace AZ
|
||||
|
||||
TimeSystemComponent::TimeSystemComponent()
|
||||
{
|
||||
m_lastInvokedTimeMs = static_cast<TimeMs>(AZStd::GetTimeNowMicroSecond() / 1000);
|
||||
m_lastInvokedTimeUs = static_cast<TimeUs>(AZStd::GetTimeNowMicroSecond());
|
||||
AZ::Interface<ITime>::Register(this);
|
||||
ITimeRequestBus::Handler::BusConnect();
|
||||
}
|
||||
@@ -58,18 +58,23 @@ namespace AZ
|
||||
|
||||
TimeMs TimeSystemComponent::GetElapsedTimeMs() const
|
||||
{
|
||||
TimeMs currentTime = static_cast<TimeMs>(AZStd::GetTimeNowMicroSecond() / 1000);
|
||||
TimeMs deltaTime = currentTime - m_lastInvokedTimeMs;
|
||||
return TimeUsToMs(GetElapsedTimeUs());
|
||||
}
|
||||
|
||||
TimeUs TimeSystemComponent::GetElapsedTimeUs() const
|
||||
{
|
||||
TimeUs currentTime = static_cast<TimeUs>(AZStd::GetTimeNowMicroSecond());
|
||||
TimeUs deltaTime = currentTime - m_lastInvokedTimeUs;
|
||||
|
||||
if (t_scale != 1.0f)
|
||||
{
|
||||
float floatDelta = static_cast<float>(deltaTime) * t_scale;
|
||||
deltaTime = static_cast<TimeMs>(static_cast<int64_t>(floatDelta));
|
||||
deltaTime = static_cast<TimeUs>(static_cast<int64_t>(floatDelta));
|
||||
}
|
||||
|
||||
m_accumulatedTimeMs += deltaTime;
|
||||
m_lastInvokedTimeMs = currentTime;
|
||||
m_accumulatedTimeUs += deltaTime;
|
||||
m_lastInvokedTimeUs = currentTime;
|
||||
|
||||
return m_accumulatedTimeMs;
|
||||
return m_accumulatedTimeUs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,12 @@ namespace AZ
|
||||
//! ITime overrides.
|
||||
//! @{
|
||||
TimeMs GetElapsedTimeMs() const override;
|
||||
TimeUs GetElapsedTimeUs() const override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
|
||||
mutable TimeMs m_lastInvokedTimeMs = TimeMs{0};
|
||||
mutable TimeMs m_accumulatedTimeMs = TimeMs{0};
|
||||
mutable TimeUs m_lastInvokedTimeUs = TimeUs{0};
|
||||
mutable TimeUs m_accumulatedTimeUs = TimeUs{0};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
MOCK_METHOD2(SetAlias, void(const char* alias, const char* path));
|
||||
MOCK_METHOD1(ClearAlias, void(const char* alias));
|
||||
MOCK_CONST_METHOD1(GetAlias, const char*(const char* alias));
|
||||
MOCK_METHOD2(SetDeprecatedAlias, void(AZStd::string_view, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, AZStd::optional<AZ::u64>(char* inOutBuffer, AZ::u64 bufferLength));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, bool(AZ::IO::FixedMaxPath& aliasPath, const AZ::IO::PathView& path));
|
||||
MOCK_CONST_METHOD3(ResolvePath, bool(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize));
|
||||
|
||||
@@ -51,6 +51,20 @@ namespace AZ::Utils
|
||||
return executableDirectory;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
if (ConvertToAbsolutePath(srcPath.c_str(), absolutePath.data(), absolutePath.capacity()))
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
{
|
||||
AZ::IO::FixedMaxPath o3deManifestPath = GetO3deManifestDirectory();
|
||||
|
||||
@@ -104,6 +104,7 @@ namespace AZ
|
||||
// Attempts the supplied path to an absolute path.
|
||||
//! Returns nullopt if path cannot be converted to an absolute path
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path);
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 absolutePathMaxSize);
|
||||
|
||||
//! Save a string to a file. Otherwise returns a failure with error message.
|
||||
AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath);
|
||||
|
||||
@@ -566,6 +566,8 @@ set(FILES
|
||||
Settings/SettingsRegistryMergeUtils.h
|
||||
Settings/SettingsRegistryScriptUtils.cpp
|
||||
Settings/SettingsRegistryScriptUtils.h
|
||||
Settings/SettingsRegistryVisitorUtils.cpp
|
||||
Settings/SettingsRegistryVisitorUtils.h
|
||||
State/HSM.cpp
|
||||
State/HSM.h
|
||||
Statistics/NamedRunningStatistic.h
|
||||
@@ -639,6 +641,8 @@ set(FILES
|
||||
Threading/ThreadSafeDeque.inl
|
||||
Threading/ThreadSafeObject.h
|
||||
Threading/ThreadSafeObject.inl
|
||||
Threading/ThreadUtils.h
|
||||
Threading/ThreadUtils.cpp
|
||||
Time/ITime.h
|
||||
Time/TimeSystemComponent.cpp
|
||||
Time/TimeSystemComponent.h
|
||||
|
||||
@@ -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 <AzCore/std/allocator_stateless.h>
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
|
||||
namespace AZStd
|
||||
{
|
||||
stateless_allocator::stateless_allocator(const char* name)
|
||||
: m_name(name) {}
|
||||
|
||||
const char* stateless_allocator::get_name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void stateless_allocator::set_name(const char* name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
auto stateless_allocator::allocate(size_type byteSize) -> pointer_type
|
||||
{
|
||||
return allocate(byteSize, AZ_DEFAULT_ALIGNMENT, 0);
|
||||
}
|
||||
|
||||
auto stateless_allocator::allocate(size_type byteSize, size_type alignment, int) -> pointer_type
|
||||
{
|
||||
pointer_type address = AZ_OS_MALLOC(byteSize, alignment);
|
||||
|
||||
if (address == nullptr)
|
||||
{
|
||||
AZ_Error("Memory", false, "stateless_allocator ran out of system memory!\n");
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void stateless_allocator::deallocate(pointer_type ptr, size_type)
|
||||
{
|
||||
AZ_OS_FREE(ptr);
|
||||
}
|
||||
|
||||
void stateless_allocator::deallocate(pointer_type ptr, size_type, size_type)
|
||||
{
|
||||
AZ_OS_FREE(ptr);
|
||||
}
|
||||
|
||||
auto stateless_allocator::max_size() const -> size_type
|
||||
{
|
||||
return AZ_CORE_MAX_ALLOCATOR_SIZE;
|
||||
}
|
||||
|
||||
stateless_allocator stateless_allocator::select_on_container_copy_construction() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto stateless_allocator::resize(pointer_type, size_type) -> size_type
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool stateless_allocator::is_lock_free()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool stateless_allocator::is_stale_read_allowed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool stateless_allocator::is_delayed_recycling()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// comparison operators
|
||||
bool operator==(const stateless_allocator&, const stateless_allocator&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const stateless_allocator&, const stateless_allocator&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/base.h>
|
||||
#include <AzCore/std/typetraits/integral_constant.h>
|
||||
#include <AzCore/RTTI/TypeInfoSimple.h>
|
||||
|
||||
namespace AZStd
|
||||
{
|
||||
class stateless_allocator
|
||||
{
|
||||
public:
|
||||
|
||||
AZ_TYPE_INFO(stateless_allocator, "{E4976C53-0B20-4F39-8D41-0A76F59A7D68}");
|
||||
|
||||
using value_type = uint8_t;
|
||||
using pointer_type = void*;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using allow_memory_leaks = AZStd::true_type;
|
||||
|
||||
stateless_allocator(const char* name = "AZStd::stateless_allocator");
|
||||
stateless_allocator(const stateless_allocator& rhs) = default;
|
||||
|
||||
stateless_allocator& operator=(const stateless_allocator& rhs) = default;
|
||||
|
||||
const char* get_name() const;
|
||||
void set_name(const char* name);
|
||||
|
||||
pointer_type allocate(size_type byteSize);
|
||||
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0);
|
||||
void deallocate(pointer_type ptr, size_type alignment);
|
||||
void deallocate(pointer_type ptr, size_type byteSize, size_type alignment);
|
||||
|
||||
// max_size actually returns the true maximum size of a single allocation
|
||||
size_type max_size() const;
|
||||
|
||||
// Returns a copy of the allocator
|
||||
stateless_allocator select_on_container_copy_construction() const;
|
||||
|
||||
//! extensions
|
||||
size_type resize(pointer_type ptr, size_type newSize);
|
||||
|
||||
bool is_lock_free();
|
||||
bool is_stale_read_allowed();
|
||||
bool is_delayed_recycling();
|
||||
|
||||
private:
|
||||
const char* m_name;
|
||||
};
|
||||
|
||||
bool operator==(const stateless_allocator& left, const stateless_allocator& right);
|
||||
bool operator!=(const stateless_allocator& left, const stateless_allocator& right);
|
||||
}
|
||||
@@ -12,6 +12,8 @@ set(FILES
|
||||
allocator.h
|
||||
allocator_ref.h
|
||||
allocator_stack.h
|
||||
allocator_stateless.cpp
|
||||
allocator_stateless.h
|
||||
allocator_static.h
|
||||
allocator_traits.h
|
||||
any.h
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user