Merge branch 'development' of https://github.com/o3de/o3de into sc-editor-asset-redux
This commit is contained in:
@@ -832,7 +832,7 @@ QAction* LevelEditorMenuHandler::CreateViewPaneAction(const QtViewPane* view)
|
||||
|
||||
if (view->m_options.showOnToolsToolbar)
|
||||
{
|
||||
action->setIcon(QIcon(view->m_options.toolbarIcon));
|
||||
action->setIcon(QIcon(view->m_options.toolbarIcon.c_str()));
|
||||
}
|
||||
|
||||
m_actionManager->AddAction(view->m_id, action);
|
||||
|
||||
@@ -45,6 +45,7 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
// AzCore
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/Module/Environment.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
@@ -547,7 +548,6 @@ public:
|
||||
{ "BatchMode", m_bConsoleMode },
|
||||
{ "NullRenderer", m_bNullRenderer },
|
||||
{ "devmode", m_bDeveloperMode },
|
||||
{ "VTUNE", dummy },
|
||||
{ "runpython", m_bRunPythonScript },
|
||||
{ "runpythontest", m_bRunPythonTestScript },
|
||||
{ "version", m_bShowVersionInfo },
|
||||
@@ -1686,6 +1686,11 @@ bool CCryEditApp::InitInstance()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "LegacySystemInterfaceCreated", R"({})");
|
||||
}
|
||||
|
||||
// Process some queued events come from system init
|
||||
// Such as asset catalog loaded notification.
|
||||
// There are some systems need to load configurations from assets for post initialization but before loading level
|
||||
|
||||
@@ -60,15 +60,6 @@
|
||||
#include <LmbrCentral/Audio/AudioSystemComponentBus.h>
|
||||
#include <LmbrCentral/Rendering/EditorLightComponentBus.h> // for LmbrCentral::EditorLightComponentRequestBus
|
||||
|
||||
//#define PROFILE_LOADING_WITH_VTUNE
|
||||
|
||||
// profilers api.
|
||||
//#include "pure.h"
|
||||
#ifdef PROFILE_LOADING_WITH_VTUNE
|
||||
#include "C:\Program Files\Intel\Vtune\Analyzer\Include\VTuneApi.h"
|
||||
#pragma comment(lib,"C:\\Program Files\\Intel\\Vtune\\Analyzer\\Lib\\VTuneApi.lib")
|
||||
#endif
|
||||
|
||||
static const char* kAutoBackupFolder = "_autobackup";
|
||||
static const char* kHoldFolder = "$tmp_hold"; // conform to the ignored file types $tmp[0-9]*_ regex
|
||||
static const char* kSaveBackupFolder = "_savebackup";
|
||||
@@ -408,9 +399,6 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename)
|
||||
|
||||
int t0 = GetTickCount();
|
||||
|
||||
#ifdef PROFILE_LOADING_WITH_VTUNE
|
||||
VTResume();
|
||||
#endif
|
||||
// Load level-specific audio data.
|
||||
AZStd::string levelFileName{ fileName.toUtf8().constData() };
|
||||
AZStd::to_lower(levelFileName.begin(), levelFileName.end());
|
||||
@@ -484,10 +472,6 @@ void CCryEditDoc::Load(TDocMultiArchive& arrXmlAr, const QString& szFilename)
|
||||
|
||||
CSurfaceTypeValidator().Validate();
|
||||
|
||||
#ifdef PROFILE_LOADING_WITH_VTUNE
|
||||
VTPause();
|
||||
#endif
|
||||
|
||||
LogLoadTime(GetTickCount() - t0);
|
||||
// Loaded with success, remove event from log file
|
||||
GetIEditor()->GetSettingsManager()->UnregisterEvent(loadEvent);
|
||||
|
||||
@@ -85,6 +85,7 @@ namespace UnitTest
|
||||
|
||||
m_rootWidget = AZStd::make_unique<QWidget>();
|
||||
m_rootWidget->setFixedSize(QSize(100, 100));
|
||||
QApplication::setActiveWindow(m_rootWidget.get());
|
||||
|
||||
m_controllerList = AZStd::make_shared<AzFramework::ViewportControllerList>();
|
||||
m_controllerList->RegisterViewportContext(TestViewportId);
|
||||
@@ -100,6 +101,8 @@ namespace UnitTest
|
||||
m_controllerList.reset();
|
||||
m_rootWidget.reset();
|
||||
|
||||
QApplication::setActiveWindow(nullptr);
|
||||
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
|
||||
@@ -110,7 +113,7 @@ namespace UnitTest
|
||||
|
||||
const AzFramework::ViewportId ViewportManipulatorControllerFixture::TestViewportId = AzFramework::ViewportId(0);
|
||||
|
||||
TEST_F(ViewportManipulatorControllerFixture, An_event_is_not_propagated_to_the_viewport_when_a_manipulator_handles_it_first)
|
||||
TEST_F(ViewportManipulatorControllerFixture, AnEventIsNotPropagatedToTheViewportWhenAManipulatorHandlesItFirst)
|
||||
{
|
||||
// forward input events to our controller list
|
||||
QObject::connect(
|
||||
@@ -151,4 +154,77 @@ namespace UnitTest
|
||||
|
||||
editorInteractionViewportFake.Disconnect();
|
||||
}
|
||||
|
||||
TEST_F(ViewportManipulatorControllerFixture, ChangingFocusDoesNotClearInput)
|
||||
{
|
||||
bool endedEvent = false;
|
||||
// detect input events and ensure that the Alt key press does not end before the end of the test
|
||||
QObject::connect(
|
||||
m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(),
|
||||
[&endedEvent](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event)
|
||||
{
|
||||
if (inputChannel->GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::ModifierAltL &&
|
||||
inputChannel->IsStateEnded())
|
||||
{
|
||||
endedEvent = true;
|
||||
}
|
||||
});
|
||||
|
||||
// given
|
||||
auto* secondaryWidget = new QWidget(m_rootWidget.get());
|
||||
|
||||
m_rootWidget->show();
|
||||
secondaryWidget->show();
|
||||
|
||||
m_rootWidget->setFocus();
|
||||
|
||||
// simulate a key press when root widget has focus
|
||||
QTest::keyPress(m_rootWidget.get(), Qt::Key_Alt, Qt::KeyboardModifier::AltModifier);
|
||||
|
||||
// when
|
||||
// change focus to secondary widget
|
||||
secondaryWidget->setFocus();
|
||||
|
||||
// then
|
||||
// the alt key was not released (cleared)
|
||||
EXPECT_FALSE(endedEvent);
|
||||
}
|
||||
|
||||
// note: Application State Change includes events such as switching to another application or minimizing
|
||||
// the current application
|
||||
TEST_F(ViewportManipulatorControllerFixture, ApplicationStateChangeDoesClearInput)
|
||||
{
|
||||
bool endedEvent = false;
|
||||
// detect input events and ensure that the Alt key press does not end before the end of the test
|
||||
QObject::connect(
|
||||
m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(),
|
||||
[&endedEvent](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event)
|
||||
{
|
||||
if (inputChannel->GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::AlphanumericW &&
|
||||
inputChannel->IsStateEnded())
|
||||
{
|
||||
endedEvent = true;
|
||||
}
|
||||
});
|
||||
|
||||
// given
|
||||
auto* secondaryWidget = new QWidget(m_rootWidget.get());
|
||||
|
||||
m_rootWidget->show();
|
||||
secondaryWidget->show();
|
||||
|
||||
m_rootWidget->setFocus();
|
||||
|
||||
// simulate a key press when root widget has focus
|
||||
QTest::keyPress(m_rootWidget.get(), Qt::Key_W);
|
||||
|
||||
// when
|
||||
// simulate changing the window state
|
||||
QApplicationStateChangeEvent applicationStateChangeEvent(Qt::ApplicationState::ApplicationInactive);
|
||||
QCoreApplication::sendEvent(m_rootWidget.get(), &applicationStateChangeEvent);
|
||||
|
||||
// then
|
||||
// the key was released (cleared)
|
||||
EXPECT_TRUE(endedEvent);
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <AzToolsFramework/Commands/EntityStateCommand.h>
|
||||
#include <AzToolsFramework/Commands/SelectionCommand.h>
|
||||
#include <AzToolsFramework/Commands/SliceDetachEntityCommand.h>
|
||||
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
|
||||
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
@@ -642,6 +643,9 @@ void SandboxIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, con
|
||||
AzToolsFramework::EntityIdList selected;
|
||||
GetSelectedOrHighlightedEntities(selected);
|
||||
|
||||
bool prefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(prefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
|
||||
QAction* action = nullptr;
|
||||
|
||||
// when nothing is selected, entity is created at root level
|
||||
@@ -658,18 +662,20 @@ void SandboxIntegrationManager::PopulateEditorGlobalContextMenu(QMenu* menu, con
|
||||
// when a single entity is selected, entity is created as its child
|
||||
else if (selected.size() == 1)
|
||||
{
|
||||
action = menu->addAction(QObject::tr("Create entity"));
|
||||
QObject::connect(
|
||||
action, &QAction::triggered, action,
|
||||
[selected]
|
||||
{
|
||||
EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, CreateNewEntityAsChild, selected.front());
|
||||
});
|
||||
auto containerEntityInterface = AZ::Interface<AzToolsFramework::ContainerEntityInterface>::Get();
|
||||
if (!prefabSystemEnabled || (containerEntityInterface && containerEntityInterface->IsContainerOpen(selected.front())))
|
||||
{
|
||||
action = menu->addAction(QObject::tr("Create entity"));
|
||||
QObject::connect(
|
||||
action, &QAction::triggered, action,
|
||||
[selected]
|
||||
{
|
||||
AzToolsFramework::EditorRequestBus::Broadcast(&AzToolsFramework::EditorRequestBus::Handler::CreateNewEntityAsChild, selected.front());
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool prefabSystemEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(prefabSystemEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
|
||||
if (!prefabSystemEnabled)
|
||||
{
|
||||
menu->addSeparator();
|
||||
|
||||
@@ -197,48 +197,46 @@ AssetCatalogModel::~AssetCatalogModel()
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
AZ::Data::AssetType AssetCatalogModel::GetAssetType(QString filename) const
|
||||
AZ::Data::AssetType AssetCatalogModel::GetAssetType(const QString &filename) const
|
||||
{
|
||||
AZ::Data::AssetType returnType = AZ::Uuid::CreateNull();
|
||||
|
||||
// Compare file extensions with the map created from the asset database.
|
||||
int dotIndex = filename.lastIndexOf('.');
|
||||
if (dotIndex >= 0)
|
||||
if (dotIndex < 0)
|
||||
{
|
||||
QString extension = filename.mid(dotIndex);
|
||||
for (auto pair : m_extensionToAssetType)
|
||||
{
|
||||
QString qExtensions = pair.first.c_str();
|
||||
if (qExtensions.indexOf(extension) >= 0)
|
||||
{
|
||||
if (pair.second.size() > 1)
|
||||
{
|
||||
// There are multiple types with this extension. Check each handler to see if they can handle this data type.
|
||||
AZStd::string azFilename = filename.toStdString().c_str();
|
||||
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, MakePathAssetRootRelative, azFilename);
|
||||
AZ::Data::AssetId assetId;
|
||||
EBUS_EVENT_RESULT(assetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, azFilename.c_str(), AZ::Data::s_invalidAssetType, false);
|
||||
return AZ::Uuid::CreateNull();
|
||||
}
|
||||
|
||||
for (AZ::Uuid type : pair.second)
|
||||
{
|
||||
const AZ::Data::AssetHandler* handler = AZ::Data::AssetManager::Instance().GetHandler(type);
|
||||
if (handler && handler->CanHandleAsset(assetId))
|
||||
{
|
||||
returnType = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnType = pair.second[0];
|
||||
break;
|
||||
}
|
||||
QStringRef extension = filename.midRef(dotIndex);
|
||||
for (const auto& pair : m_extensionToAssetType)
|
||||
{
|
||||
QString qExtensions = pair.first.c_str();
|
||||
if (qExtensions.indexOf(extension) < 0 || pair.second.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pair.second.size() == 1)
|
||||
{
|
||||
return pair.second[0];
|
||||
}
|
||||
|
||||
// There are multiple types with this extension. Search for a handler that can handle this data type.
|
||||
AZStd::string azFilename = filename.toStdString().c_str();
|
||||
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, MakePathAssetRootRelative, azFilename);
|
||||
AZ::Data::AssetId assetId;
|
||||
EBUS_EVENT_RESULT(assetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, azFilename.c_str(), AZ::Data::s_invalidAssetType, false);
|
||||
|
||||
for (const AZ::Uuid& type : pair.second)
|
||||
{
|
||||
const AZ::Data::AssetHandler* handler = AZ::Data::AssetManager::Instance().GetHandler(type);
|
||||
if (handler && handler->CanHandleAsset(assetId))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnType;
|
||||
return AZ::Uuid::CreateNull();
|
||||
}
|
||||
|
||||
QStandardItem* AssetCatalogModel::GetPath(QString& path, bool createIfNeeded, QStandardItem* parent)
|
||||
@@ -419,7 +417,7 @@ AssetCatalogEntry* AssetCatalogModel::AddAsset(QString assetPath, AZ::Data::Asse
|
||||
// icons' memory being reclaimed and crashing the Editor.
|
||||
QSize size = fileIcon.actualSize(QSize(16, 16));
|
||||
QIcon deepCopy = fileIcon.pixmap(size).copy(0, 0, size.width(), size.height());
|
||||
|
||||
|
||||
if (!fileIcon.isNull())
|
||||
{
|
||||
m_assetTypeToIcon[assetType] = deepCopy;
|
||||
|
||||
@@ -110,7 +110,7 @@ protected:
|
||||
void SetFilterRegExp(const AZStd::string& filterType, const QRegExp& regExp);
|
||||
void ClearFilterRegExp(const AZStd::string& filterType = AZStd::string());
|
||||
|
||||
AZ::Data::AssetType GetAssetType(QString filename) const;
|
||||
AZ::Data::AssetType GetAssetType(const QString &filename) const;
|
||||
QStandardItem* GetPath(QString& path, bool createIfNeeded, QStandardItem* parent = nullptr);
|
||||
|
||||
void ApplyFilter(QStandardItem* parent);
|
||||
|
||||
@@ -11,7 +11,6 @@ OutlinerWidget #m_display_options
|
||||
{
|
||||
qproperty-icon: url(:/Menu/menu.svg);
|
||||
qproperty-iconSize: 16px 16px;
|
||||
qproperty-flat: true;
|
||||
}
|
||||
|
||||
OutlinerWidget QWidget[PulseHighlight="true"]
|
||||
|
||||
@@ -56,15 +56,21 @@ namespace AZ::ComponentApplicationLifecycle
|
||||
}
|
||||
|
||||
bool RegisterHandler(AZ::SettingsRegistryInterface& settingsRegistry, AZ::SettingsRegistryInterface::NotifyEventHandler& handler,
|
||||
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName)
|
||||
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName, bool autoRegisterEvent)
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
using NotifyEventHandler = AZ::SettingsRegistryInterface::NotifyEventHandler;
|
||||
|
||||
if (!ValidateEvent(settingsRegistry, eventName))
|
||||
// Some systems may attempt to register a handler before the settings registry has been loaded
|
||||
// If so, this flag lets them automatically register an event if it hasn't yet been registered.
|
||||
// RegisterEvent calls validate event.
|
||||
if ((!autoRegisterEvent && !ValidateEvent(settingsRegistry, eventName)) ||
|
||||
(autoRegisterEvent && !RegisterEvent(settingsRegistry, eventName)))
|
||||
{
|
||||
AZ_Warning("ComponentApplicationLifecycle", false, R"(Cannot register event %.*s. Name does is not a field of object "%.*s".)"
|
||||
AZ_Warning(
|
||||
"ComponentApplicationLifecycle", false,
|
||||
R"(Cannot register event %.*s. Name is not a field of object "%.*s".)"
|
||||
R"( Please make sure the entry exists in the '<engine-root>/Registry/application_lifecycle_events.setreg")"
|
||||
" or in *.setreg within the project", AZ_STRING_ARG(eventName), AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey));
|
||||
return false;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace AZ::ComponentApplicationLifecycle
|
||||
{
|
||||
//! Root Key where lifecycle events should be registered under
|
||||
inline constexpr AZStd::string_view ApplicationLifecycleEventRegistrationKey = "/O3DE/Runtime/Application/LifecycleEvents";
|
||||
inline constexpr AZStd::string_view ApplicationLifecycleEventRegistrationKey = "/O3DE/Application/LifecycleEvents";
|
||||
|
||||
|
||||
//! Validates that the event @eventName is stored in the array at ApplicationLifecycleEventRegistrationKey
|
||||
@@ -48,7 +48,9 @@ namespace AZ::ComponentApplicationLifecycle
|
||||
//! if the specified @eventName passes validation
|
||||
//! @param callback will be moved into the handler if the specified @eventName is valid
|
||||
//! @param eventName name of key underneath the ApplicationLifecycleEventRegistrationKey to register
|
||||
//! @param autoRegisterEvent automatically register this event if it hasn't been registered yet. This is useful
|
||||
//! when registering a handler before the settings registry has been loaded.
|
||||
//! @return true if the handler was registered with the SettingsRegistry NotifyEvent
|
||||
bool RegisterHandler(AZ::SettingsRegistryInterface& settingsRegistry, AZ::SettingsRegistryInterface::NotifyEventHandler& handler,
|
||||
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName);
|
||||
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName, bool autoRegisterEvent = false);
|
||||
}
|
||||
|
||||
@@ -7,4 +7,63 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Debug/ProfilerBus.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
|
||||
namespace AZ::Debug
|
||||
{
|
||||
AZStd::string GenerateOutputFile(const char* nameHint)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString captureOutput = GetProfilerCaptureLocation();
|
||||
return AZStd::string::format("%s/capture_%s_%lld.json", captureOutput.c_str(), nameHint, AZStd::GetTimeNowSecond());
|
||||
}
|
||||
|
||||
void ProfilerCaptureFrame([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
if (auto profilerSystem = ProfilerSystemInterface::Get(); profilerSystem)
|
||||
{
|
||||
AZStd::string captureFile = GenerateOutputFile("single");
|
||||
AZLOG_INFO("Setting capture file to %s", captureFile.c_str());
|
||||
profilerSystem->CaptureFrame(captureFile);
|
||||
}
|
||||
}
|
||||
AZ_CONSOLEFREEFUNC(ProfilerCaptureFrame, AZ::ConsoleFunctorFlags::DontReplicate, "Capture a single frame of profiling data");
|
||||
|
||||
void ProfilerStartCapture([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
if (auto profilerSystem = ProfilerSystemInterface::Get(); profilerSystem)
|
||||
{
|
||||
AZStd::string captureFile = GenerateOutputFile("multi");
|
||||
AZLOG_INFO("Setting capture file to %s", captureFile.c_str());
|
||||
profilerSystem->StartCapture(AZStd::move(captureFile));
|
||||
}
|
||||
}
|
||||
AZ_CONSOLEFREEFUNC(ProfilerStartCapture, AZ::ConsoleFunctorFlags::DontReplicate, "Start a multi-frame capture of profiling data");
|
||||
|
||||
void ProfilerEndCapture([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
|
||||
{
|
||||
if (auto profilerSystem = ProfilerSystemInterface::Get(); profilerSystem)
|
||||
{
|
||||
profilerSystem->EndCapture();
|
||||
}
|
||||
}
|
||||
AZ_CONSOLEFREEFUNC(ProfilerEndCapture, AZ::ConsoleFunctorFlags::DontReplicate, "End and dump an in-progress continuous capture");
|
||||
|
||||
AZ::IO::FixedMaxPathString GetProfilerCaptureLocation()
|
||||
{
|
||||
AZ::IO::FixedMaxPathString captureOutput;
|
||||
if (AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry)
|
||||
{
|
||||
settingsRegistry->Get(captureOutput, RegistryKey_ProfilerCaptureLocation);
|
||||
}
|
||||
|
||||
if (captureOutput.empty())
|
||||
{
|
||||
captureOutput = ProfilerCaptureLocationFallback;
|
||||
}
|
||||
|
||||
return captureOutput;
|
||||
}
|
||||
} // namespace AZ::Debug
|
||||
|
||||
@@ -9,11 +9,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Debug
|
||||
{
|
||||
//! settings registry entry for specifying where to output profiler captures
|
||||
static constexpr const char* RegistryKey_ProfilerCaptureLocation = "/O3DE/AzCore/Debug/Profiler/CaptureLocation";
|
||||
|
||||
//! fallback value in the event the settings registry isn't ready or doesn't contain the key
|
||||
static constexpr const char* ProfilerCaptureLocationFallback = "@user@/Profiler";
|
||||
|
||||
/**
|
||||
* ProfilerNotifications provides a profiler event interface that can be used to update listeners on profiler status
|
||||
*/
|
||||
@@ -23,32 +32,38 @@ namespace AZ
|
||||
public:
|
||||
virtual ~ProfilerNotifications() = default;
|
||||
|
||||
virtual void OnProfileSystemInitialized() = 0;
|
||||
//! Notify when the current profiler capture is finished
|
||||
//! @param result Set to true if it's finished successfully
|
||||
//! @param info The output file path or error information which depends on the return.
|
||||
virtual void OnCaptureFinished(bool result, const AZStd::string& info) = 0;
|
||||
};
|
||||
using ProfilerNotificationBus = AZ::EBus<ProfilerNotifications>;
|
||||
|
||||
enum class ProfileFrameAdvanceType
|
||||
{
|
||||
Game,
|
||||
Render,
|
||||
Default = Game
|
||||
};
|
||||
|
||||
/**
|
||||
* ProfilerRequests provides an interface for making profiling system requests
|
||||
*/
|
||||
class ProfilerRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// Allow multiple threads to concurrently make requests
|
||||
using MutexType = AZStd::mutex;
|
||||
|
||||
AZ_RTTI(ProfilerRequests, "{90AEC117-14C1-4BAE-9704-F916E49EF13F}");
|
||||
virtual ~ProfilerRequests() = default;
|
||||
|
||||
virtual bool IsActive() = 0;
|
||||
virtual void FrameAdvance(ProfileFrameAdvanceType type) = 0;
|
||||
//! Getter/setter for the profiler active state
|
||||
virtual bool IsActive() const = 0;
|
||||
virtual void SetActive(bool active) = 0;
|
||||
|
||||
//! Capture a single frame of profiling data
|
||||
virtual bool CaptureFrame(const AZStd::string& outputFilePath) = 0;
|
||||
|
||||
//! Starting/ending a multi-frame capture of profiling data
|
||||
virtual bool StartCapture(AZStd::string outputFilePath) = 0;
|
||||
virtual bool EndCapture() = 0;
|
||||
};
|
||||
using ProfilerRequestBus = AZ::EBus<ProfilerRequests>;
|
||||
}
|
||||
}
|
||||
|
||||
using ProfilerSystemInterface = AZ::Interface<ProfilerRequests>;
|
||||
|
||||
//! helper function for getting the profiler capture location from the settings registry that
|
||||
//! includes fallback handing in the event the registry value can't be determined
|
||||
AZ::IO::FixedMaxPathString GetProfilerCaptureLocation();
|
||||
} // namespace Debug
|
||||
} // namespace AZ
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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/Debug/ProfilerBus.h>
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/RTTI/BehaviorInterfaceProxy.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/EditContextConstants.inl>
|
||||
|
||||
namespace AZ::Debug
|
||||
{
|
||||
static constexpr const char* ProfilerScriptCategory = "Profiler";
|
||||
static constexpr const char* ProfilerScriptModule = "debug";
|
||||
static constexpr AZ::Script::Attributes::ScopeFlags ProfilerScriptScope = AZ::Script::Attributes::ScopeFlags::Automation;
|
||||
|
||||
class ProfilerNotificationBusHandler final
|
||||
: public ProfilerNotificationBus::Handler
|
||||
, public AZ::BehaviorEBusHandler
|
||||
{
|
||||
public:
|
||||
AZ_EBUS_BEHAVIOR_BINDER(ProfilerNotificationBusHandler, "{44161459-B816-4876-95A4-BA16DEC767D6}", AZ::SystemAllocator,
|
||||
OnCaptureFinished
|
||||
);
|
||||
|
||||
void OnCaptureFinished(bool result, const AZStd::string& info) override
|
||||
{
|
||||
Call(FN_OnCaptureFinished, result, info);
|
||||
}
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<ProfilerNotificationBus>("ProfilerNotificationBus")
|
||||
->Attribute(AZ::Script::Attributes::Category, ProfilerScriptCategory)
|
||||
->Attribute(AZ::Script::Attributes::Module, ProfilerScriptModule)
|
||||
->Attribute(AZ::Script::Attributes::Scope, ProfilerScriptScope)
|
||||
->Handler<ProfilerNotificationBusHandler>();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ProfilerSystemScriptProxy
|
||||
: public BehaviorInterfaceProxy<ProfilerRequests>
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ProfilerSystemScriptProxy, "{D671FB70-8B09-4C3A-96CD-06A339F3138E}", BehaviorInterfaceProxy<ProfilerRequests>);
|
||||
|
||||
AZ_BEHAVIOR_INTERFACE(ProfilerSystemScriptProxy, ProfilerRequests);
|
||||
};
|
||||
|
||||
void ProfilerReflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->ConstantProperty("g_ProfilerSystem", ProfilerSystemScriptProxy::GetProxy)
|
||||
->Attribute(AZ::Script::Attributes::Category, ProfilerScriptCategory)
|
||||
->Attribute(AZ::Script::Attributes::Module, ProfilerScriptModule)
|
||||
->Attribute(AZ::Script::Attributes::Scope, ProfilerScriptScope);
|
||||
|
||||
behaviorContext->Class<ProfilerSystemScriptProxy>("ProfilerSystemInterface")
|
||||
->Attribute(AZ::Script::Attributes::Category, ProfilerScriptCategory)
|
||||
->Attribute(AZ::Script::Attributes::Module, ProfilerScriptModule)
|
||||
->Attribute(AZ::Script::Attributes::Scope, ProfilerScriptScope)
|
||||
|
||||
->Method("IsValid", &ProfilerSystemScriptProxy::IsValid)
|
||||
|
||||
->Method("GetCaptureLocation",
|
||||
[](ProfilerSystemScriptProxy*) -> AZStd::string
|
||||
{
|
||||
AZ::IO::FixedMaxPathString captureOutput = GetProfilerCaptureLocation();
|
||||
return AZStd::string(captureOutput.c_str(), captureOutput.length());
|
||||
})
|
||||
|
||||
->Method("IsActive", ProfilerSystemScriptProxy::WrapMethod<&ProfilerRequests::IsActive>())
|
||||
->Method("SetActive", ProfilerSystemScriptProxy::WrapMethod<&ProfilerRequests::SetActive>())
|
||||
|
||||
->Method("CaptureFrame", ProfilerSystemScriptProxy::WrapMethod<&ProfilerRequests::CaptureFrame>())
|
||||
|
||||
->Method("StartCapture", ProfilerSystemScriptProxy::WrapMethod<&ProfilerRequests::StartCapture>())
|
||||
->Method("EndCapture", ProfilerSystemScriptProxy::WrapMethod<&ProfilerRequests::EndCapture>());
|
||||
}
|
||||
|
||||
ProfilerNotificationBusHandler::Reflect(context);
|
||||
}
|
||||
} // namespace AZ::Debug
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
|
||||
namespace Debug
|
||||
{
|
||||
//! Reflects the profiler bus script bindings
|
||||
void ProfilerReflect(AZ::ReflectContext* context);
|
||||
} // namespace Debug
|
||||
} // namespace AZ
|
||||
@@ -27,26 +27,21 @@
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::Debug
|
||||
{
|
||||
namespace Debug
|
||||
struct StackFrame;
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
struct StackFrame;
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
bool AttachDebugger();
|
||||
bool IsDebuggerPresent();
|
||||
void HandleExceptions(bool isEnabled);
|
||||
void DebugBreak();
|
||||
bool AttachDebugger();
|
||||
bool IsDebuggerPresent();
|
||||
void HandleExceptions(bool isEnabled);
|
||||
void DebugBreak();
|
||||
#endif
|
||||
void Terminate(int exitCode);
|
||||
}
|
||||
void Terminate(int exitCode);
|
||||
}
|
||||
|
||||
using namespace AZ::Debug;
|
||||
|
||||
namespace DebugInternal
|
||||
{
|
||||
// other threads can trigger fatals and errors, but the same thread should not, to avoid stack overflow.
|
||||
@@ -60,7 +55,7 @@ namespace AZ
|
||||
// Globals
|
||||
const int g_maxMessageLength = 4096;
|
||||
static const char* g_dbgSystemWnd = "System";
|
||||
Trace Debug::g_tracer;
|
||||
Trace g_tracer;
|
||||
void* g_exceptionInfo = nullptr;
|
||||
|
||||
// Environment var needed to track ignored asserts across systems and disable native UI under certain conditions
|
||||
@@ -616,4 +611,4 @@ namespace AZ
|
||||
val.Set(level);
|
||||
}
|
||||
}
|
||||
} // namspace AZ
|
||||
} // namspace AZ::Debug
|
||||
|
||||
@@ -156,7 +156,10 @@ namespace AZ
|
||||
void StreamerComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
|
||||
{
|
||||
bool isEnabled = false;
|
||||
AZ::Debug::ProfilerRequestBus::BroadcastResult(isEnabled, &AZ::Debug::ProfilerRequests::IsActive);
|
||||
if (auto profilerSystem = AZ::Debug::ProfilerSystemInterface::Get(); profilerSystem)
|
||||
{
|
||||
isEnabled = profilerSystem->IsActive();
|
||||
}
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
|
||||
@@ -383,36 +383,36 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool CmpAllEq(__m128 arg1, __m128 arg2, int32_t mask)
|
||||
{
|
||||
const __m128i compare = CastToInt(CmpNeq(arg1, arg2));
|
||||
return (_mm_movemask_epi8(compare) & mask) == 0;
|
||||
const __m128 compare = CmpEq(arg1, arg2);
|
||||
return (_mm_movemask_ps(compare) & mask) == mask;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool CmpAllLt(__m128 arg1, __m128 arg2, int32_t mask)
|
||||
{
|
||||
const __m128i compare = CastToInt(CmpGtEq(arg1, arg2));
|
||||
return (_mm_movemask_epi8(compare) & mask) == 0;
|
||||
const __m128 compare = CmpLt(arg1, arg2);
|
||||
return (_mm_movemask_ps(compare) & mask) == mask;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool CmpAllLtEq(__m128 arg1, __m128 arg2, int32_t mask)
|
||||
{
|
||||
const __m128i compare = CastToInt(CmpGt(arg1, arg2));
|
||||
return (_mm_movemask_epi8(compare) & mask) == 0;
|
||||
const __m128 compare = CmpLtEq(arg1, arg2);
|
||||
return (_mm_movemask_ps(compare) & mask) == mask;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool CmpAllGt(__m128 arg1, __m128 arg2, int32_t mask)
|
||||
{
|
||||
const __m128i compare = CastToInt(CmpLtEq(arg1, arg2));
|
||||
return (_mm_movemask_epi8(compare) & mask) == 0;
|
||||
const __m128 compare = CmpGt(arg1, arg2);
|
||||
return (_mm_movemask_ps(compare) & mask) == mask;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool CmpAllGtEq(__m128 arg1, __m128 arg2, int32_t mask)
|
||||
{
|
||||
const __m128i compare = CastToInt(CmpLt(arg1, arg2));
|
||||
return (_mm_movemask_epi8(compare) & mask) == 0;
|
||||
const __m128 compare = CmpGtEq(arg1, arg2);
|
||||
return (_mm_movemask_ps(compare) & mask) == mask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -331,31 +331,32 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool Vec1::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllEq(arg1, arg2, 0x000F);
|
||||
// Only check the first bit for Vector1
|
||||
return Sse::CmpAllEq(arg1, arg2, 0b0001);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec1::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLt(arg1, arg2, 0x000F);
|
||||
return Sse::CmpAllLt(arg1, arg2, 0b0001);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec1::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0x000F);
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0b0001);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec1::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGt(arg1, arg2, 0x000F);
|
||||
return Sse::CmpAllGt(arg1, arg2, 0b0001);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec1::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0x000F);
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0b0001);
|
||||
}
|
||||
|
||||
|
||||
@@ -397,7 +398,7 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool Vec1::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllEq(arg1, arg2, 0x000F);
|
||||
return Sse::CmpAllEq(arg1, arg2, 0b0001);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -383,31 +383,32 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool Vec2::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllEq(arg1, arg2, 0x00FF);
|
||||
// Only check the first two bits for Vector2
|
||||
return Sse::CmpAllEq(arg1, arg2, 0b0011);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec2::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLt(arg1, arg2, 0x00FF);
|
||||
return Sse::CmpAllLt(arg1, arg2, 0b0011);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec2::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0x00FF);
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0b0011);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec2::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGt(arg1, arg2, 0x00FF);
|
||||
return Sse::CmpAllGt(arg1, arg2, 0b0011);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec2::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0x00FF);
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0b0011);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -419,31 +419,32 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool Vec3::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllEq(arg1, arg2, 0x0FFF);
|
||||
// Only check the first three bits for Vector3
|
||||
return Sse::CmpAllEq(arg1, arg2, 0b0111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec3::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLt(arg1, arg2, 0x0FFF);
|
||||
return Sse::CmpAllLt(arg1, arg2, 0b0111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec3::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0x0FFF);
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0b0111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec3::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGt(arg1, arg2, 0x0FFF);
|
||||
return Sse::CmpAllGt(arg1, arg2, 0b0111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec3::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0x0FFF);
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0b0111);
|
||||
}
|
||||
|
||||
|
||||
@@ -485,7 +486,7 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool Vec3::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllEq(arg1, arg2, 0x0FFF);
|
||||
return Sse::CmpAllEq(arg1, arg2, 0b0111);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -455,31 +455,32 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool Vec4::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllEq(arg1, arg2, 0xFFFF);
|
||||
// Check the first four bits for Vector4
|
||||
return Sse::CmpAllEq(arg1, arg2, 0b1111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec4::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLt(arg1, arg2, 0xFFFF);
|
||||
return Sse::CmpAllLt(arg1, arg2, 0b1111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec4::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0xFFFF);
|
||||
return Sse::CmpAllLtEq(arg1, arg2, 0b1111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec4::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGt(arg1, arg2, 0xFFFF);
|
||||
return Sse::CmpAllGt(arg1, arg2, 0b1111);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Vec4::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0xFFFF);
|
||||
return Sse::CmpAllGtEq(arg1, arg2, 0b1111);
|
||||
}
|
||||
|
||||
|
||||
@@ -521,7 +522,7 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE bool Vec4::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2)
|
||||
{
|
||||
return Sse::CmpAllEq(arg1, arg2, 0xFFFF);
|
||||
return Sse::CmpAllEq(arg1, arg2, 0b1111);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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/Interface/Interface.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/typetraits/function_traits.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
/**
|
||||
* Utility class for reflecting an AZ::Interface through the BehaviorContext
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* class MyInterface
|
||||
* {
|
||||
* public:
|
||||
* AZ_RTTI(MyInterface, "{BADDF000D-CDCD-CDCD-CDCD-BAAAADF0000D}");
|
||||
* virtual ~MyInterface() = default;
|
||||
*
|
||||
* virtual AZStd::string Foo() = 0;
|
||||
* virtual void Bar(float x, float y) = 0;
|
||||
* };
|
||||
*
|
||||
* class MySystemProxy
|
||||
* : public BehaviorInterfaceProxy<MyInterface>
|
||||
* {
|
||||
* public:
|
||||
* AZ_RTTI(MySystemProxy, "{CDCDCDCD-BAAD-BADD-F00D-CDCDCDCDCDCD}", BehaviorInterfaceProxy<MyInterface>);
|
||||
* AZ_BEHAVIOR_INTERFACE(MySystemProxy, MyInterface);
|
||||
* };
|
||||
*
|
||||
* void Reflect(AZ::ReflectContext* context)
|
||||
* {
|
||||
* if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
* {
|
||||
* behaviorContext->ConstantProperty("g_MySystem", MySystemProxy::GetProxy)
|
||||
* ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
* ->Attribute(AZ::Script::Attributes::Module, "MyModule");
|
||||
*
|
||||
* behaviorContext->Class<MySystemProxy>("MySystemInterface")
|
||||
* ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
* ->Attribute(AZ::Script::Attributes::Module, "MyModule")
|
||||
*
|
||||
* ->Method("Foo", MySystemProxy::WrapMethod<&MyInterface::Foo>())
|
||||
* ->Method("Bar", MySystemProxy::WrapMethod<&MyInterface::Bar>());
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
template<typename T>
|
||||
class BehaviorInterfaceProxy
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(BehaviorInterfaceProxy, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(BehaviorInterfaceProxy<T>, "{E7CC8D27-4499-454E-A7DF-3F72FBECD30D}");
|
||||
|
||||
BehaviorInterfaceProxy() = default;
|
||||
virtual ~BehaviorInterfaceProxy() = default;
|
||||
|
||||
//! Stores the instance which will use the provided shared_ptr deleter when the reference count hits zero
|
||||
BehaviorInterfaceProxy(AZStd::shared_ptr<T> sharedInstance)
|
||||
: m_instance(AZStd::move(sharedInstance))
|
||||
{
|
||||
}
|
||||
|
||||
//! Stores the instance which will perform a no-op deleter when the reference count hits zero
|
||||
BehaviorInterfaceProxy(T* rawIntance)
|
||||
: m_instance(rawIntance, [](T*) {})
|
||||
{
|
||||
}
|
||||
|
||||
//! Returns if the m_instance shared pointer is non-nullptr
|
||||
bool IsValid() const { return m_instance; }
|
||||
|
||||
protected:
|
||||
//! Internal access for use in the derived GetProxy function
|
||||
static T* GetInstance()
|
||||
{
|
||||
T* interfacePtr = AZ::Interface<T>::Get();
|
||||
AZ_Warning("BehaviorInterfaceProxy", interfacePtr,
|
||||
"There is currently no global %s registered with an AZ Interface<T>",
|
||||
AzTypeInfo<T>::Name()
|
||||
);
|
||||
// Don't delete the global instance, it is not owned by the behavior context
|
||||
return interfacePtr;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
struct MethodWrapper
|
||||
{
|
||||
template<typename Proxy, auto Method>
|
||||
static auto WrapMethod()
|
||||
{
|
||||
using ReturnType = AZStd::function_traits_get_result_t<AZStd::remove_cvref_t<decltype(Method)>>;
|
||||
return [](Proxy* proxy, Args... params) -> ReturnType
|
||||
{
|
||||
if (proxy && proxy->IsValid())
|
||||
{
|
||||
return AZStd::invoke(Method, proxy->m_instance, AZStd::forward<Args>(params)...);
|
||||
}
|
||||
return ReturnType();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
AZStd::shared_ptr<T> m_instance;
|
||||
};
|
||||
|
||||
#define AZ_BEHAVIOR_INTERFACE(ProxyType, InterfaceType) \
|
||||
static ProxyType GetProxy() { return GetInstance(); } \
|
||||
template<auto Method> \
|
||||
static auto WrapMethod() { \
|
||||
using FuncTraits = AZStd::function_traits<AZStd::remove_cvref_t<decltype(Method)>>; \
|
||||
return FuncTraits::template expand_args<MethodWrapper>::template WrapMethod<ProxyType, Method>(); \
|
||||
} \
|
||||
ProxyType() = default; \
|
||||
ProxyType(AZStd::shared_ptr<InterfaceType> sharedInstance) : BehaviorInterfaceProxy(sharedInstance) {} \
|
||||
ProxyType(InterfaceType* rawIntance) : BehaviorInterfaceProxy(rawIntance) {}
|
||||
} // namespace AZ
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/Debug/ProfilerReflection.h>
|
||||
#include <AzCore/Debug/TraceReflection.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Math/MathReflection.h>
|
||||
@@ -87,6 +88,8 @@ void ScriptSystemComponent::Activate()
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, "lua");
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, "luac");
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(
|
||||
&AZ::Data::AssetCatalogRequests::EnableCatalogForAsset, AZ::AzTypeInfo<AZ::ScriptAsset>::Uuid());
|
||||
|
||||
if (Data::AssetManager::Instance().IsReady())
|
||||
{
|
||||
@@ -925,6 +928,7 @@ void ScriptSystemComponent::Reflect(ReflectContext* reflection)
|
||||
// reflect default entity
|
||||
MathReflect(behaviorContext);
|
||||
ScriptDebug::Reflect(behaviorContext);
|
||||
Debug::ProfilerReflect(behaviorContext);
|
||||
Debug::TraceReflect(behaviorContext);
|
||||
|
||||
behaviorContext->Class<PlatformID>("Platform")
|
||||
|
||||
@@ -363,7 +363,11 @@ namespace AZ
|
||||
{
|
||||
++m_graphsRemaining;
|
||||
|
||||
event->m_executor = this; // Used to validate event is not waited for inside a job
|
||||
if (event)
|
||||
{
|
||||
event->IncWaitCount();
|
||||
event->m_executor = this; // Used to validate event is not waited for inside a job
|
||||
}
|
||||
|
||||
// Submit all tasks that have no inbound edges
|
||||
for (Internal::Task& task : graph.Tasks())
|
||||
|
||||
@@ -20,6 +20,46 @@ namespace AZ
|
||||
m_semaphore.acquire();
|
||||
}
|
||||
|
||||
void TaskGraphEvent::IncWaitCount()
|
||||
{
|
||||
// guess zero to optimize for single task graph using an event, if multiple are using it then this will take 2+ comp_exch calls
|
||||
int expectedValue = 0;
|
||||
while(!m_waitCount.compare_exchange_weak(expectedValue, expectedValue + 1))
|
||||
{
|
||||
// value will be negative once event is ready to signal or has been signaled. Shouldn't happen.
|
||||
AZ_Assert(expectedValue >= 0, "Called TaskGraphEvent::IncWaitCount on a signalled event");
|
||||
if (expectedValue < 0) // event already signaled, skip
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void TaskGraphEvent::Signal()
|
||||
{
|
||||
// guess one to optimize for single task graph using an event, if multiple are using it then this will take 2+ comp_exch calls
|
||||
int expectedValue = 1;
|
||||
while(!m_waitCount.compare_exchange_weak(expectedValue, expectedValue - 1))
|
||||
{
|
||||
// It's an error for Signal to be called if no one is waiting, or the event has already been signaled
|
||||
AZ_Assert(expectedValue > 0, "Called TaskGraphEvent::Signal when event is either signaled or unused");
|
||||
if (expectedValue < 0) // return if already signaled
|
||||
{
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if (expectedValue == 1) // This call to Signal decremented the value to 0.
|
||||
{
|
||||
expectedValue = 0;
|
||||
// validate no one incremented the wait count and mark signalling state
|
||||
if (m_waitCount.compare_exchange_strong(expectedValue, -1))
|
||||
{
|
||||
m_semaphore.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskToken::PrecedesInternal(TaskToken& comesAfter)
|
||||
{
|
||||
AZ_Assert(!m_parent.m_submitted, "Cannot mutate a TaskGraph that was previously submitted.");
|
||||
|
||||
@@ -61,14 +61,14 @@ namespace AZ
|
||||
uint32_t m_index;
|
||||
};
|
||||
|
||||
// A TaskGraphEvent may be used to block until a task graph has finished executing. Usage
|
||||
// A TaskGraphEvent may be used to block until one or more task graphs has finished executing. Usage
|
||||
// is NOT recommended for the majority of tasks (prefer to simply containing expanding/contracting
|
||||
// the graph without synchronization over the course of the frame). However, the event
|
||||
// is useful for the edges of the computation graph.
|
||||
//
|
||||
// You are responsible for ensuring the event object lifetime exceeds the task graph lifetime.
|
||||
//
|
||||
// After the TaskGraphEvent is signaled, you are allowed to reuse the same TaskGraphEvent
|
||||
// After the TaskGraphEvent is signaled, you are NOT allowed to reuse the same TaskGraphEvent
|
||||
// for a future submission.
|
||||
class TaskGraphEvent
|
||||
{
|
||||
@@ -81,10 +81,12 @@ namespace AZ
|
||||
friend class TaskGraph;
|
||||
friend class TaskExecutor;
|
||||
|
||||
void IncWaitCount();
|
||||
void Signal();
|
||||
|
||||
AZStd::binary_semaphore m_semaphore;
|
||||
TaskExecutor* m_executor = nullptr;
|
||||
AZStd::atomic_int m_waitCount = 0;
|
||||
TaskExecutor* m_executor = nullptr;
|
||||
};
|
||||
|
||||
// The TaskGraph encapsulates a set of tasks and their interdependencies. After adding
|
||||
|
||||
@@ -33,11 +33,6 @@ namespace AZ
|
||||
return m_semaphore.try_acquire_for(AZStd::chrono::milliseconds{ 0 });
|
||||
}
|
||||
|
||||
inline void TaskGraphEvent::Signal()
|
||||
{
|
||||
m_semaphore.release();
|
||||
}
|
||||
|
||||
template<typename Lambda>
|
||||
TaskToken TaskGraph::AddTask(TaskDescriptor const& desc, Lambda&& lambda)
|
||||
{
|
||||
|
||||
@@ -108,6 +108,8 @@ set(FILES
|
||||
Debug/Profiler.inl
|
||||
Debug/Profiler.h
|
||||
Debug/ProfilerBus.h
|
||||
Debug/ProfilerReflection.cpp
|
||||
Debug/ProfilerReflection.h
|
||||
Debug/StackTracer.h
|
||||
Debug/EventTrace.h
|
||||
Debug/EventTrace.cpp
|
||||
@@ -456,6 +458,7 @@ set(FILES
|
||||
RTTI/BehaviorContext.h
|
||||
RTTI/BehaviorContextUtilities.h
|
||||
RTTI/BehaviorContextUtilities.cpp
|
||||
RTTI/BehaviorInterfaceProxy.h
|
||||
RTTI/BehaviorObjectSignals.h
|
||||
RTTI/TypeSafeIntegral.h
|
||||
Script/ScriptAsset.cpp
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::Debug
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
LONG WINAPI ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo);
|
||||
@@ -26,94 +26,91 @@ namespace AZ
|
||||
|
||||
constexpr int g_maxMessageLength = 4096;
|
||||
|
||||
namespace Debug
|
||||
namespace Platform
|
||||
{
|
||||
namespace Platform
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
bool IsDebuggerPresent()
|
||||
bool IsDebuggerPresent()
|
||||
{
|
||||
return ::IsDebuggerPresent() ? true : false;
|
||||
}
|
||||
|
||||
void HandleExceptions(bool isEnabled)
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
return ::IsDebuggerPresent() ? true : false;
|
||||
g_previousExceptionHandler = ::SetUnhandledExceptionFilter(&ExceptionHandler);
|
||||
}
|
||||
|
||||
void HandleExceptions(bool isEnabled)
|
||||
else
|
||||
{
|
||||
if (isEnabled)
|
||||
{
|
||||
g_previousExceptionHandler = ::SetUnhandledExceptionFilter(&ExceptionHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
::SetUnhandledExceptionFilter(g_previousExceptionHandler);
|
||||
g_previousExceptionHandler = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool AttachDebugger()
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Launch vsjitdebugger.exe, this app is always present in System32 folder
|
||||
// with an installation of any version of visual studio.
|
||||
// It will open a debugging dialog asking the user what debugger to use
|
||||
|
||||
STARTUPINFOW startupInfo = {0};
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
PROCESS_INFORMATION processInfo = {0};
|
||||
|
||||
wchar_t cmdline[MAX_PATH];
|
||||
swprintf_s(cmdline, L"vsjitdebugger.exe -p %li", ::GetCurrentProcessId());
|
||||
bool success = ::CreateProcessW(
|
||||
NULL, // No module name (use command line)
|
||||
cmdline, // Command line
|
||||
NULL, // Process handle not inheritable
|
||||
NULL, // Thread handle not inheritable
|
||||
FALSE, // No handle inheritance
|
||||
0, // No creation flags
|
||||
NULL, // Use parent's environment block
|
||||
NULL, // Use parent's starting directory
|
||||
&startupInfo, // Pointer to STARTUPINFO structure
|
||||
&processInfo); // Pointer to PROCESS_INFORMATION structure
|
||||
|
||||
if (success)
|
||||
{
|
||||
::WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
::CloseHandle(processInfo.hProcess);
|
||||
::CloseHandle(processInfo.hThread);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DebugBreak()
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
#endif // AZ_ENABLE_DEBUG_TOOLS
|
||||
|
||||
void Terminate(int exitCode)
|
||||
{
|
||||
TerminateProcess(GetCurrentProcess(), exitCode);
|
||||
}
|
||||
|
||||
void OutputToDebugger([[maybe_unused]] const char* window, const char* message)
|
||||
{
|
||||
AZStd::fixed_wstring<g_maxMessageLength> tmpW;
|
||||
if(window)
|
||||
{
|
||||
AZStd::to_wstring(tmpW, window);
|
||||
tmpW += L": ";
|
||||
OutputDebugStringW(tmpW.c_str());
|
||||
tmpW.clear();
|
||||
}
|
||||
AZStd::to_wstring(tmpW, message);
|
||||
OutputDebugStringW(tmpW.c_str());
|
||||
::SetUnhandledExceptionFilter(g_previousExceptionHandler);
|
||||
g_previousExceptionHandler = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AttachDebugger()
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Launch vsjitdebugger.exe, this app is always present in System32 folder
|
||||
// with an installation of any version of visual studio.
|
||||
// It will open a debugging dialog asking the user what debugger to use
|
||||
|
||||
STARTUPINFOW startupInfo = {0};
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
PROCESS_INFORMATION processInfo = {0};
|
||||
|
||||
wchar_t cmdline[MAX_PATH];
|
||||
swprintf_s(cmdline, L"vsjitdebugger.exe -p %li", ::GetCurrentProcessId());
|
||||
bool success = ::CreateProcessW(
|
||||
NULL, // No module name (use command line)
|
||||
cmdline, // Command line
|
||||
NULL, // Process handle not inheritable
|
||||
NULL, // Thread handle not inheritable
|
||||
FALSE, // No handle inheritance
|
||||
0, // No creation flags
|
||||
NULL, // Use parent's environment block
|
||||
NULL, // Use parent's starting directory
|
||||
&startupInfo, // Pointer to STARTUPINFO structure
|
||||
&processInfo); // Pointer to PROCESS_INFORMATION structure
|
||||
|
||||
if (success)
|
||||
{
|
||||
::WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
::CloseHandle(processInfo.hProcess);
|
||||
::CloseHandle(processInfo.hThread);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DebugBreak()
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
#endif // AZ_ENABLE_DEBUG_TOOLS
|
||||
|
||||
void Terminate(int exitCode)
|
||||
{
|
||||
TerminateProcess(GetCurrentProcess(), exitCode);
|
||||
}
|
||||
|
||||
void OutputToDebugger([[maybe_unused]] const char* window, const char* message)
|
||||
{
|
||||
AZStd::fixed_wstring<g_maxMessageLength> tmpW;
|
||||
if(window)
|
||||
{
|
||||
AZStd::to_wstring(tmpW, window);
|
||||
tmpW += L": ";
|
||||
OutputDebugStringW(tmpW.c_str());
|
||||
tmpW.clear();
|
||||
}
|
||||
AZStd::to_wstring(tmpW, message);
|
||||
OutputDebugStringW(tmpW.c_str());
|
||||
}
|
||||
} // namespace Platform
|
||||
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
|
||||
@@ -187,6 +184,8 @@ namespace AZ
|
||||
azsnprintf(message, g_maxMessageLength, "Exception : 0x%lX - '%s' [%p]\n", ExceptionInfo->ExceptionRecord->ExceptionCode, GetExeptionName(ExceptionInfo->ExceptionRecord->ExceptionCode), ExceptionInfo->ExceptionRecord->ExceptionAddress);
|
||||
Debug::Trace::Instance().Output(nullptr, message);
|
||||
|
||||
Debug::Trace::Instance().PrintCallstack(nullptr, 0, ExceptionInfo->ContextRecord);
|
||||
|
||||
EBUS_EVENT(Debug::TraceMessageDrillerBus, OnException, message);
|
||||
|
||||
bool result = false;
|
||||
@@ -198,7 +197,7 @@ namespace AZ
|
||||
// if someone ever returns TRUE we assume that they somehow handled this exception and continue.
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
Debug::Trace::Instance().PrintCallstack(nullptr, 0, ExceptionInfo->ContextRecord);
|
||||
|
||||
Debug::Trace::Instance().Output(nullptr, "==================================================================\n");
|
||||
|
||||
// allowing continue of execution is not valid here. This handler gets called for serious exceptions.
|
||||
@@ -211,4 +210,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
} // namspace AZ::Debug
|
||||
|
||||
@@ -610,15 +610,16 @@ namespace UnitTest
|
||||
g.Follows(e, f);
|
||||
g.Precedes(d);
|
||||
|
||||
TaskGraphEvent ev;
|
||||
graph.SubmitOnExecutor(*m_executor, &ev);
|
||||
ev.Wait();
|
||||
TaskGraphEvent ev1;
|
||||
graph.SubmitOnExecutor(*m_executor, &ev1);
|
||||
ev1.Wait();
|
||||
|
||||
EXPECT_EQ(3 | 0b100000, x);
|
||||
x = 0;
|
||||
|
||||
graph.SubmitOnExecutor(*m_executor, &ev);
|
||||
ev.Wait();
|
||||
TaskGraphEvent ev2;
|
||||
graph.SubmitOnExecutor(*m_executor, &ev2);
|
||||
ev2.Wait();
|
||||
|
||||
EXPECT_EQ(3 | 0b100000, x);
|
||||
}
|
||||
|
||||
@@ -204,7 +204,6 @@ namespace AzFramework
|
||||
systemEntity->Activate();
|
||||
AZ_Assert(systemEntity->GetState() == AZ::Entity::State::Active, "System Entity failed to activate.");
|
||||
|
||||
|
||||
if (m_isStarted = (systemEntity->GetState() == AZ::Entity::State::Active); m_isStarted)
|
||||
{
|
||||
if (m_startupParameters.m_loadAssetCatalog)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
@@ -363,6 +364,23 @@ namespace AZ::IO
|
||||
, m_mainThreadId{ AZStd::this_thread::get_id() }
|
||||
{
|
||||
CompressionBus::Handler::BusConnect();
|
||||
|
||||
// If the settings registry is not available at this point,
|
||||
// then something catastrophic has happened in the application startup.
|
||||
// That should have been caught and messaged out earlier in startup.
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
// Automatically register the event if it's not registered, because
|
||||
// this system is initialized before the settings registry has loaded the event list.
|
||||
AZ::ComponentApplicationLifecycle::RegisterHandler(
|
||||
*settingsRegistry, m_componentApplicationLifecycleHandler,
|
||||
[this](AZStd::string_view /*path*/, AZ::SettingsRegistryInterface::Type /*type*/)
|
||||
{
|
||||
OnSystemEntityActivated();
|
||||
},
|
||||
"SystemComponentsActivated",
|
||||
/*autoRegisterEvent*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1175,13 +1193,20 @@ namespace AZ::IO
|
||||
}
|
||||
}
|
||||
|
||||
auto bundleManifest = GetBundleManifest(desc.pZip);
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog;
|
||||
auto bundleManifest = GetBundleManifest(desc.pZip);
|
||||
if (bundleManifest)
|
||||
{
|
||||
bundleCatalog = GetBundleCatalog(desc.pZip, bundleManifest->GetCatalogName());
|
||||
}
|
||||
|
||||
// If this archive is loaded before the serialize context is available, then the manifest and catalog will need to be loaded later.
|
||||
if (!bundleManifest || !bundleCatalog)
|
||||
{
|
||||
m_archivesWithCatalogsToLoad.push_back(
|
||||
ArchivesWithCatalogsToLoad(szFullPath, szBindRoot, flags, nextBundle, desc.m_strFileName));
|
||||
}
|
||||
|
||||
bool usePrefabSystemForLevels = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
usePrefabSystemForLevels, &AzFramework::ApplicationRequests::IsPrefabSystemForLevelsEnabled);
|
||||
@@ -1219,12 +1244,17 @@ namespace AZ::IO
|
||||
m_levelOpenEvent.Signal(levelDirs);
|
||||
}
|
||||
|
||||
AZ::IO::ArchiveNotificationBus::Broadcast([](AZ::IO::ArchiveNotifications* archiveNotifications, const char* bundleName,
|
||||
AZStd::shared_ptr<AzFramework::AssetBundleManifest> bundleManifest, const AZ::IO::FixedMaxPath& nextBundle, AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog)
|
||||
if (bundleManifest && bundleCatalog)
|
||||
{
|
||||
archiveNotifications->BundleOpened(bundleName, bundleManifest, nextBundle.c_str(), bundleCatalog);
|
||||
}, desc.m_strFileName.c_str(), bundleManifest, nextBundle, bundleCatalog);
|
||||
|
||||
AZ::IO::ArchiveNotificationBus::Broadcast(
|
||||
[](AZ::IO::ArchiveNotifications* archiveNotifications, const char* bundleName,
|
||||
AZStd::shared_ptr<AzFramework::AssetBundleManifest> bundleManifest, const AZ::IO::FixedMaxPath& nextBundle,
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog)
|
||||
{
|
||||
archiveNotifications->BundleOpened(bundleName, bundleManifest, nextBundle.c_str(), bundleCatalog);
|
||||
},
|
||||
desc.m_strFileName.c_str(), bundleManifest, nextBundle, bundleCatalog);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2138,7 +2168,7 @@ namespace AZ::IO
|
||||
}
|
||||
|
||||
currentDirPattern = currentDir + AZ_FILESYSTEM_SEPARATOR_WILDCARD;
|
||||
currentFilePattern = currentDir + AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING + "levels.pak";
|
||||
currentFilePattern = currentDir + AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING + "level.pak";
|
||||
|
||||
ZipDir::FileEntry* fileEntry = findFile.FindExact(currentFilePattern.c_str());
|
||||
if (fileEntry)
|
||||
@@ -2175,4 +2205,36 @@ namespace AZ::IO
|
||||
|
||||
return catalogInfo;
|
||||
}
|
||||
|
||||
void Archive::OnSystemEntityActivated()
|
||||
{
|
||||
for (const auto& archiveInfo : m_archivesWithCatalogsToLoad)
|
||||
{
|
||||
AZStd::intrusive_ptr<INestedArchive> archive =
|
||||
OpenArchive(archiveInfo.m_fullPath, archiveInfo.m_bindRoot, archiveInfo.m_flags, nullptr);
|
||||
if (!archive)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ZipDir::CachePtr pZip = static_cast<NestedArchive*>(archive.get())->GetCache();
|
||||
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog;
|
||||
auto bundleManifest = GetBundleManifest(pZip);
|
||||
if (bundleManifest)
|
||||
{
|
||||
bundleCatalog = GetBundleCatalog(pZip, bundleManifest->GetCatalogName());
|
||||
}
|
||||
|
||||
AZ::IO::ArchiveNotificationBus::Broadcast(
|
||||
[](AZ::IO::ArchiveNotifications* archiveNotifications, const char* bundleName,
|
||||
AZStd::shared_ptr<AzFramework::AssetBundleManifest> bundleManifest, const AZ::IO::FixedMaxPath& nextBundle,
|
||||
AZStd::shared_ptr<AzFramework::AssetRegistry> bundleCatalog)
|
||||
{
|
||||
archiveNotifications->BundleOpened(bundleName, bundleManifest, nextBundle.c_str(), bundleCatalog);
|
||||
},
|
||||
archiveInfo.m_strFileName.c_str(), bundleManifest, archiveInfo.m_nextBundle, bundleCatalog);
|
||||
}
|
||||
m_archivesWithCatalogsToLoad.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <AzCore/IO/CompressionBus.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/std/parallel/mutex.h>
|
||||
#include <AzCore/std/parallel/lock.h>
|
||||
@@ -271,6 +272,11 @@ namespace AZ::IO
|
||||
ZipDir::CachePtr* pZip = {}) const;
|
||||
private:
|
||||
|
||||
// Archives can't be fully mounted until the system entity has been activated,
|
||||
// because mounting them requires the BundlingSystemComponent and the serialization system
|
||||
// to both be available.
|
||||
void OnSystemEntityActivated();
|
||||
|
||||
bool OpenPackCommon(AZStd::string_view szBindRoot, AZStd::string_view pName, AZStd::intrusive_ptr<AZ::IO::MemoryBlock> pData = nullptr, bool addLevels = true);
|
||||
bool OpenPacksCommon(AZStd::string_view szDir, AZStd::string_view pWildcardIn, AZStd::vector<AZ::IO::FixedMaxPathString>* pFullPaths = nullptr, bool addLevels = true);
|
||||
|
||||
@@ -313,6 +319,8 @@ namespace AZ::IO
|
||||
mutable AZStd::shared_mutex m_csZips;
|
||||
ZipArray m_arrZips;
|
||||
|
||||
AZ::SettingsRegistryInterface::NotifyEventHandler m_componentApplicationLifecycleHandler;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Opened files collector.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -339,5 +347,34 @@ namespace AZ::IO
|
||||
// [LYN-2376] Remove once legacy slice support is removed
|
||||
LevelPackOpenEvent m_levelOpenEvent;
|
||||
LevelPackCloseEvent m_levelCloseEvent;
|
||||
|
||||
// If pak files are loaded before the serialization and bundling system
|
||||
// are ready to go, their asset catalogs can't be loaded.
|
||||
// In this case, cache information about those archives,
|
||||
// and attempt to load the catalogs later, when the required systems are enabled.
|
||||
struct ArchivesWithCatalogsToLoad
|
||||
{
|
||||
ArchivesWithCatalogsToLoad(
|
||||
AZStd::string_view fullPath,
|
||||
AZStd::string_view bindRoot,
|
||||
int flags,
|
||||
AZ::IO::PathView nextBundle,
|
||||
AZ::IO::Path strFileName)
|
||||
: m_fullPath(fullPath)
|
||||
, m_bindRoot(bindRoot)
|
||||
, m_flags(flags)
|
||||
, m_nextBundle(nextBundle)
|
||||
, m_strFileName(strFileName)
|
||||
{
|
||||
}
|
||||
|
||||
AZ::IO::Path m_strFileName;
|
||||
AZStd::string m_fullPath;
|
||||
AZStd::string m_bindRoot;
|
||||
AZ::IO::PathView m_nextBundle;
|
||||
int m_flags;
|
||||
};
|
||||
|
||||
AZStd::vector<ArchivesWithCatalogsToLoad> m_archivesWithCatalogsToLoad;
|
||||
};
|
||||
}
|
||||
|
||||
+5
-13
@@ -229,17 +229,13 @@ namespace AzFramework
|
||||
//! Alias for the EBus implementation of this interface
|
||||
using Bus = AZ::EBus<InputDeviceImplementationRequest<InputDeviceType>>;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create the custom implementations
|
||||
using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Set a custom implementation for this input device type, either for a specific instance
|
||||
//! by addressing the call to an InputDeviceId, or for all existing instances by broadcast.
|
||||
//! Passing InputDeviceType::Implementation::Create as the argument will create the default
|
||||
//! device implementation, while passing nullptr will delete any existing implementation.
|
||||
//! \param[in] createFunction Pointer to the function that will create the implementation.
|
||||
virtual void SetCustomImplementation(CreateFunctionType createFunction) = 0;
|
||||
//! \param[in] implementationFactory Pointer to the function that creates the implementation.
|
||||
virtual void SetCustomImplementation(typename InputDeviceType::ImplementationFactory implementationFactory) = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -267,18 +263,14 @@ namespace AzFramework
|
||||
AZ_DISABLE_COPY_MOVE(InputDeviceImplementationRequestHandler);
|
||||
|
||||
protected:
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create the custom implementations
|
||||
using CreateFunctionType = typename InputDeviceType::Implementation*(*)(InputDeviceType&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! \ref InputDeviceImplementationRequest<InputDeviceType>::SetCustomImplementation
|
||||
AZ_INLINE void SetCustomImplementation(CreateFunctionType createFunction) override
|
||||
AZ_INLINE void SetCustomImplementation(typename InputDeviceType::ImplementationFactory implementationFactory) override
|
||||
{
|
||||
AZStd::unique_ptr<typename InputDeviceType::Implementation> newImplementation;
|
||||
if (createFunction)
|
||||
if (implementationFactory)
|
||||
{
|
||||
newImplementation.reset(createFunction(m_inputDevice));
|
||||
newImplementation.reset(implementationFactory(m_inputDevice));
|
||||
}
|
||||
m_inputDevice.SetImplementation(AZStd::move(newImplementation));
|
||||
}
|
||||
|
||||
+10
-3
@@ -94,7 +94,14 @@ namespace AzFramework
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputDeviceGamepad::InputDeviceGamepad(AZ::u32 index)
|
||||
: InputDevice(InputDeviceId(Name, index))
|
||||
: InputDeviceGamepad(InputDeviceId(Name, index)) // Delegated constructor
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputDeviceGamepad::InputDeviceGamepad(const InputDeviceId& inputDeviceId,
|
||||
ImplementationFactory implementationFactory)
|
||||
: InputDevice(inputDeviceId)
|
||||
, m_allChannelsById()
|
||||
, m_buttonChannelsById()
|
||||
, m_triggerChannelsById()
|
||||
@@ -144,8 +151,8 @@ namespace AzFramework
|
||||
m_thumbStickDirectionChannelsById[channelId] = channel;
|
||||
}
|
||||
|
||||
// Create the platform specific implementation
|
||||
m_pimpl.reset(Implementation::Create(*this));
|
||||
// Create the platform specific or custom implementation
|
||||
m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr);
|
||||
|
||||
// Connect to the haptic feedback request bus
|
||||
InputHapticFeedbackRequestBus::Handler::BusConnect(GetInputDeviceId());
|
||||
|
||||
@@ -182,6 +182,14 @@ namespace AzFramework
|
||||
// Reflection
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Foward declare the internal Implementation class so it can be passed into the constructor
|
||||
class Implementation;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create a custom implementation for this input device
|
||||
using ImplementationFactory = Implementation*(InputDeviceGamepad&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
explicit InputDeviceGamepad();
|
||||
@@ -191,6 +199,13 @@ namespace AzFramework
|
||||
//! \param[in] index Index of the game-pad device
|
||||
explicit InputDeviceGamepad(AZ::u32 index);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
//! \param[in] inputDeviceId Id of the input device
|
||||
//! \param[in] implementationFactory Optional override of the default Implementation::Create
|
||||
explicit InputDeviceGamepad(const InputDeviceId& inputDeviceId,
|
||||
ImplementationFactory implementationFactory = &Implementation::Create);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Disable copying
|
||||
AZ_DISABLE_COPY_MOVE(InputDeviceGamepad);
|
||||
|
||||
+5
-4
@@ -182,8 +182,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputDeviceKeyboard::InputDeviceKeyboard(AzFramework::InputDeviceId id)
|
||||
: InputDevice(id)
|
||||
InputDeviceKeyboard::InputDeviceKeyboard(const InputDeviceId& inputDeviceId,
|
||||
ImplementationFactory implementationFactory)
|
||||
: InputDevice(inputDeviceId)
|
||||
, m_modifierKeyStates(AZStd::make_shared<ModifierKeyStates>())
|
||||
, m_allChannelsById()
|
||||
, m_keyChannelsById()
|
||||
@@ -203,8 +204,8 @@ namespace AzFramework
|
||||
m_keyChannelsById[channelId] = channel;
|
||||
}
|
||||
|
||||
// Create the platform specific implementation
|
||||
m_pimpl.reset(Implementation::Create(*this));
|
||||
// Create the platform specific or custom implementation
|
||||
m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr);
|
||||
|
||||
// Connect to the text entry request bus
|
||||
InputTextEntryRequestBus::Handler::BusConnect(GetInputDeviceId());
|
||||
|
||||
+12
-1
@@ -370,9 +370,20 @@ namespace AzFramework
|
||||
// Reflection
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Foward declare the internal Implementation class so it can be passed into the constructor
|
||||
class Implementation;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create a custom implementation for this input device
|
||||
using ImplementationFactory = Implementation*(InputDeviceKeyboard&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
InputDeviceKeyboard(AzFramework::InputDeviceId id = Id);
|
||||
//! \param[in] inputDeviceId Optional override of the default input device id
|
||||
//! \param[in] implementationFactory Optional override of the default Implementation::Create
|
||||
explicit InputDeviceKeyboard(const InputDeviceId& inputDeviceId = Id,
|
||||
ImplementationFactory implementationFactory = &Implementation::Create);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Disable copying
|
||||
|
||||
@@ -60,8 +60,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputDeviceMotion::InputDeviceMotion()
|
||||
: InputDevice(Id)
|
||||
InputDeviceMotion::InputDeviceMotion(const InputDeviceId& inputDeviceId,
|
||||
ImplementationFactory implementationFactory)
|
||||
: InputDevice(inputDeviceId)
|
||||
, m_allChannelsById()
|
||||
, m_accelerationChannelsById()
|
||||
, m_rotationRateChannelsById()
|
||||
@@ -107,8 +108,8 @@ namespace AzFramework
|
||||
m_orientationChannelsById[channelId] = channel;
|
||||
}
|
||||
|
||||
// Create the platform specific implementation
|
||||
m_pimpl.reset(Implementation::Create(*this));
|
||||
// Create the platform specific or custom implementation
|
||||
m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr);
|
||||
|
||||
// Connect to the motion sensor request bus
|
||||
InputMotionSensorRequestBus::Handler::BusConnect(GetInputDeviceId());
|
||||
|
||||
@@ -126,9 +126,20 @@ namespace AzFramework
|
||||
// Reflection
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Foward declare the internal Implementation class so it can be passed into the constructor
|
||||
class Implementation;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create a custom implementation for this input device
|
||||
using ImplementationFactory = Implementation*(InputDeviceMotion&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
InputDeviceMotion();
|
||||
//! \param[in] inputDeviceId Optional override of the default input device id
|
||||
//! \param[in] implementationFactory Optional override of the default Implementation::Create
|
||||
explicit InputDeviceMotion(const InputDeviceId& inputDeviceId = Id,
|
||||
ImplementationFactory implementationFactory = &Implementation::Create);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Disable copying
|
||||
|
||||
@@ -67,8 +67,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputDeviceMouse::InputDeviceMouse(AzFramework::InputDeviceId id)
|
||||
: InputDevice(id)
|
||||
InputDeviceMouse::InputDeviceMouse(const InputDeviceId& inputDeviceId,
|
||||
ImplementationFactory implementationFactory)
|
||||
: InputDevice(inputDeviceId)
|
||||
, m_allChannelsById()
|
||||
, m_buttonChannelsById()
|
||||
, m_movementChannelsById()
|
||||
@@ -97,8 +98,8 @@ namespace AzFramework
|
||||
m_cursorPositionChannel = aznew InputChannelDeltaWithSharedPosition2D(SystemCursorPosition, *this, m_cursorPositionData2D);
|
||||
m_allChannelsById[SystemCursorPosition] = m_cursorPositionChannel;
|
||||
|
||||
// Create the platform specific implementation
|
||||
m_pimpl.reset(Implementation::Create(*this));
|
||||
// Create the platform specific or custom implementation
|
||||
m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr);
|
||||
|
||||
// Connect to the system cursor request bus
|
||||
InputSystemCursorRequestBus::Handler::BusConnect(GetInputDeviceId());
|
||||
|
||||
@@ -122,9 +122,20 @@ namespace AzFramework
|
||||
// Reflection
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Foward declare the internal Implementation class so it can be passed into the constructor
|
||||
class Implementation;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create a custom implementation for this input device
|
||||
using ImplementationFactory = Implementation*(InputDeviceMouse&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
explicit InputDeviceMouse(AzFramework::InputDeviceId id = Id);
|
||||
//! \param[in] inputDeviceId Optional override of the default input device id
|
||||
//! \param[in] implementationFactory Optional override of the default Implementation::Create
|
||||
explicit InputDeviceMouse(const InputDeviceId& inputDeviceId = Id,
|
||||
ImplementationFactory implementationFactory = &Implementation::Create);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Disable copying
|
||||
|
||||
@@ -59,8 +59,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputDeviceTouch::InputDeviceTouch()
|
||||
: InputDevice(Id)
|
||||
InputDeviceTouch::InputDeviceTouch(const InputDeviceId& inputDeviceId,
|
||||
ImplementationFactory implementationFactory)
|
||||
: InputDevice(inputDeviceId)
|
||||
, m_allChannelsById()
|
||||
, m_touchChannelsById()
|
||||
, m_pimpl(nullptr)
|
||||
@@ -75,8 +76,8 @@ namespace AzFramework
|
||||
m_touchChannelsById[channelId] = channel;
|
||||
}
|
||||
|
||||
// Create the platform specific implementation
|
||||
m_pimpl.reset(Implementation::Create(*this));
|
||||
// Create the platform specific or custom implementation
|
||||
m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -77,9 +77,20 @@ namespace AzFramework
|
||||
// Reflection
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Foward declare the internal Implementation class so it can be passed into the constructor
|
||||
class Implementation;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create a custom implementation for this input device
|
||||
using ImplementationFactory = Implementation*(InputDeviceTouch&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
InputDeviceTouch();
|
||||
//! \param[in] inputDeviceId Optional override of the default input device id
|
||||
//! \param[in] implementationFactory Optional override of the default Implementation::Create
|
||||
explicit InputDeviceTouch(const InputDeviceId& inputDeviceId = Id,
|
||||
ImplementationFactory implementationFactory = &Implementation::Create);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Disable copying
|
||||
|
||||
+5
-4
@@ -51,8 +51,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
InputDeviceVirtualKeyboard::InputDeviceVirtualKeyboard()
|
||||
: InputDevice(Id)
|
||||
InputDeviceVirtualKeyboard::InputDeviceVirtualKeyboard(const InputDeviceId& inputDeviceId,
|
||||
ImplementationFactory implementationFactory)
|
||||
: InputDevice(inputDeviceId)
|
||||
, m_allChannelsById()
|
||||
, m_pimpl()
|
||||
, m_implementationRequestHandler(*this)
|
||||
@@ -65,8 +66,8 @@ namespace AzFramework
|
||||
m_commandChannelsById[channelId] = channel;
|
||||
}
|
||||
|
||||
// Create the platform specific implementation
|
||||
m_pimpl.reset(Implementation::Create(*this));
|
||||
// Create the platform specific or custom implementation
|
||||
m_pimpl.reset(implementationFactory ? implementationFactory(*this) : nullptr);
|
||||
|
||||
// Connect to the text entry request bus
|
||||
InputTextEntryRequestBus::Handler::BusConnect(GetInputDeviceId());
|
||||
|
||||
+12
-1
@@ -69,9 +69,20 @@ namespace AzFramework
|
||||
// Reflection
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Foward declare the internal Implementation class so it can be passed into the constructor
|
||||
class Implementation;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Alias for the function type used to create a custom implementation for this input device
|
||||
using ImplementationFactory = Implementation*(InputDeviceVirtualKeyboard&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//! Constructor
|
||||
InputDeviceVirtualKeyboard();
|
||||
//! \param[in] inputDeviceId Optional override of the default input device id
|
||||
//! \param[in] implementationFactory Optional override of the default Implementation::Create
|
||||
explicit InputDeviceVirtualKeyboard(const InputDeviceId& inputDeviceId = Id,
|
||||
ImplementationFactory implementationFactory = &Implementation::Create);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Disable copying
|
||||
|
||||
@@ -24,17 +24,17 @@ namespace AzFramework
|
||||
IMatchmakingRequests() = default;
|
||||
virtual ~IMatchmakingRequests() = default;
|
||||
|
||||
// Registers a player's acceptance or rejection of a proposed matchmaking.
|
||||
// @param acceptMatchRequest The request of AcceptMatch operation
|
||||
//! Registers a player's acceptance or rejection of a proposed matchmaking.
|
||||
//! @param acceptMatchRequest The request of AcceptMatch operation
|
||||
virtual void AcceptMatch(const AcceptMatchRequest& acceptMatchRequest) = 0;
|
||||
|
||||
// Create a game match for a group of players.
|
||||
// @param startMatchmakingRequest The request of StartMatchmaking operation
|
||||
// @return A unique identifier for a matchmaking ticket
|
||||
//! Create a game match for a group of players.
|
||||
//! @param startMatchmakingRequest The request of StartMatchmaking operation
|
||||
//! @return A unique identifier for a matchmaking ticket
|
||||
virtual AZStd::string StartMatchmaking(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
|
||||
|
||||
// Cancels a matchmaking ticket that is currently being processed.
|
||||
// @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
//! Cancels a matchmaking ticket that is currently being processed.
|
||||
//! @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
virtual void StopMatchmaking(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
|
||||
};
|
||||
|
||||
@@ -48,16 +48,16 @@ namespace AzFramework
|
||||
IMatchmakingAsyncRequests() = default;
|
||||
virtual ~IMatchmakingAsyncRequests() = default;
|
||||
|
||||
// AcceptMatch Async
|
||||
// @param acceptMatchRequest The request of AcceptMatch operation
|
||||
//! AcceptMatch Async
|
||||
//! @param acceptMatchRequest The request of AcceptMatch operation
|
||||
virtual void AcceptMatchAsync(const AcceptMatchRequest& acceptMatchRequest) = 0;
|
||||
|
||||
// StartMatchmaking Async
|
||||
// @param startMatchmakingRequest The request of StartMatchmaking operation
|
||||
//! StartMatchmaking Async
|
||||
//! @param startMatchmakingRequest The request of StartMatchmaking operation
|
||||
virtual void StartMatchmakingAsync(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
|
||||
|
||||
// StopMatchmaking Async
|
||||
// @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
//! StopMatchmaking Async
|
||||
//! @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
virtual void StopMatchmakingAsync(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
|
||||
};
|
||||
|
||||
@@ -76,14 +76,14 @@ namespace AzFramework
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnAcceptMatchAsyncComplete is fired once AcceptMatchAsync completes
|
||||
//! OnAcceptMatchAsyncComplete is fired once AcceptMatchAsync completes
|
||||
virtual void OnAcceptMatchAsyncComplete() = 0;
|
||||
|
||||
// OnStartMatchmakingAsyncComplete is fired once StartMatchmakingAsync completes
|
||||
// @param matchmakingTicketId The unique identifier for the matchmaking ticket
|
||||
//! OnStartMatchmakingAsyncComplete is fired once StartMatchmakingAsync completes
|
||||
//! @param matchmakingTicketId The unique identifier for the matchmaking ticket
|
||||
virtual void OnStartMatchmakingAsyncComplete(const AZStd::string& matchmakingTicketId) = 0;
|
||||
|
||||
// OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
|
||||
//! OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
|
||||
virtual void OnStopMatchmakingAsyncComplete() = 0;
|
||||
};
|
||||
using MatchmakingAsyncRequestNotificationBus = AZ::EBus<MatchmakingAsyncRequestNotifications>;
|
||||
|
||||
@@ -29,17 +29,17 @@ namespace AzFramework
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnMatchAcceptance is fired when match is found and pending on acceptance
|
||||
// Use this notification to accept found match
|
||||
//! OnMatchAcceptance is fired when match is found and pending on acceptance
|
||||
//! Use this notification to accept found match
|
||||
virtual void OnMatchAcceptance() = 0;
|
||||
|
||||
// OnMatchComplete is fired when match is complete
|
||||
//! OnMatchComplete is fired when match is complete
|
||||
virtual void OnMatchComplete() = 0;
|
||||
|
||||
// OnMatchError is fired when match is processed with error
|
||||
//! OnMatchError is fired when match is processed with error
|
||||
virtual void OnMatchError() = 0;
|
||||
|
||||
// OnMatchFailure is fired when match is failed to complete
|
||||
//! OnMatchFailure is fired when match is failed to complete
|
||||
virtual void OnMatchFailure() = 0;
|
||||
};
|
||||
using MatchmakingNotificationBus = AZ::EBus<MatchmakingNotifications>;
|
||||
|
||||
@@ -29,11 +29,11 @@ namespace AzFramework
|
||||
AcceptMatchRequest() = default;
|
||||
virtual ~AcceptMatchRequest() = default;
|
||||
|
||||
// Player response to accept or reject match
|
||||
//! Player response to accept or reject match
|
||||
bool m_acceptMatch;
|
||||
// A list of unique identifiers for players delivering the response
|
||||
//! A list of unique identifiers for players delivering the response
|
||||
AZStd::vector<AZStd::string> m_playerIds;
|
||||
// A unique identifier for a matchmaking ticket
|
||||
//! A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace AzFramework
|
||||
StartMatchmakingRequest() = default;
|
||||
virtual ~StartMatchmakingRequest() = default;
|
||||
|
||||
// A unique identifier for a matchmaking ticket
|
||||
//! A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace AzFramework
|
||||
StopMatchmakingRequest() = default;
|
||||
virtual ~StopMatchmakingRequest() = default;
|
||||
|
||||
// A unique identifier for a matchmaking ticket
|
||||
//! A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -18,16 +18,16 @@ namespace AzFramework
|
||||
//! The properties for handling join session request.
|
||||
struct SessionConnectionConfig
|
||||
{
|
||||
// A unique identifier for registered player in session.
|
||||
//! A unique identifier for registered player in session.
|
||||
AZStd::string m_playerSessionId;
|
||||
|
||||
// The DNS identifier assigned to the instance that is running the session.
|
||||
//! The DNS identifier assigned to the instance that is running the session.
|
||||
AZStd::string m_dnsName;
|
||||
|
||||
// The IP address of the session.
|
||||
//! The IP address of the session.
|
||||
AZStd::string m_ipAddress;
|
||||
|
||||
// The port number for the session.
|
||||
//! The port number for the session.
|
||||
uint16_t m_port = 0;
|
||||
};
|
||||
|
||||
@@ -35,10 +35,10 @@ namespace AzFramework
|
||||
//! The properties for handling player connect/disconnect
|
||||
struct PlayerConnectionConfig
|
||||
{
|
||||
// A unique identifier for player connection.
|
||||
//! A unique identifier for player connection.
|
||||
uint32_t m_playerConnectionId = 0;
|
||||
|
||||
// A unique identifier for registered player in session.
|
||||
//! A unique identifier for registered player in session.
|
||||
AZStd::string m_playerSessionId;
|
||||
};
|
||||
|
||||
@@ -51,12 +51,12 @@ namespace AzFramework
|
||||
ISessionHandlingClientRequests() = default;
|
||||
virtual ~ISessionHandlingClientRequests() = default;
|
||||
|
||||
// Request the player join session
|
||||
// @param sessionConnectionConfig The required properties to handle the player join session process
|
||||
// @return The result of player join session process
|
||||
//! Request the player join session
|
||||
//! @param sessionConnectionConfig The required properties to handle the player join session process
|
||||
//! @return The result of player join session process
|
||||
virtual bool RequestPlayerJoinSession(const SessionConnectionConfig& sessionConnectionConfig) = 0;
|
||||
|
||||
// Request the connected player leave session
|
||||
//! Request the connected player leave session
|
||||
virtual void RequestPlayerLeaveSession() = 0;
|
||||
};
|
||||
|
||||
@@ -69,26 +69,26 @@ namespace AzFramework
|
||||
ISessionHandlingProviderRequests() = default;
|
||||
virtual ~ISessionHandlingProviderRequests() = default;
|
||||
|
||||
// Handle the destroy session process
|
||||
//! Handle the destroy session process
|
||||
virtual void HandleDestroySession() = 0;
|
||||
|
||||
// Validate the player join session process
|
||||
// @param playerConnectionConfig The required properties to validate the player join session process
|
||||
// @return The result of player join session validation
|
||||
//! Validate the player join session process
|
||||
//! @param playerConnectionConfig The required properties to validate the player join session process
|
||||
//! @return The result of player join session validation
|
||||
virtual bool ValidatePlayerJoinSession(const PlayerConnectionConfig& playerConnectionConfig) = 0;
|
||||
|
||||
// Handle the player leave session process
|
||||
// @param playerConnectionConfig The required properties to handle the player leave session process
|
||||
//! Handle the player leave session process
|
||||
//! @param playerConnectionConfig The required properties to handle the player leave session process
|
||||
virtual void HandlePlayerLeaveSession(const PlayerConnectionConfig& playerConnectionConfig) = 0;
|
||||
|
||||
// Retrieves the file location of a pem-encoded TLS certificate for Client to Server communication
|
||||
// @return If successful, returns the file location of TLS certificate file; if not successful, returns
|
||||
// empty string.
|
||||
//! Retrieves the file location of a pem-encoded TLS certificate for Client to Server communication
|
||||
//! @return If successful, returns the file location of TLS certificate file; if not successful, returns
|
||||
//! empty string.
|
||||
virtual AZ::IO::Path GetExternalSessionCertificate() = 0;
|
||||
|
||||
// Retrieves the file location of a pem-encoded TLS certificate for Server to Server communication
|
||||
// @return If successful, returns the file location of TLS certificate file; if not successful, returns
|
||||
// empty string.
|
||||
//! Retrieves the file location of a pem-encoded TLS certificate for Server to Server communication
|
||||
//! @return If successful, returns the file location of TLS certificate file; if not successful, returns
|
||||
//! empty string.
|
||||
virtual AZ::IO::Path GetInternalSessionCertificate() = 0;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -25,22 +25,22 @@ namespace AzFramework
|
||||
ISessionRequests() = default;
|
||||
virtual ~ISessionRequests() = default;
|
||||
|
||||
// Create a session for players to find and join.
|
||||
// @param createSessionRequest The request of CreateSession operation
|
||||
// @return The request id if session creation request succeeds; empty if it fails
|
||||
//! Create a session for players to find and join.
|
||||
//! @param createSessionRequest The request of CreateSession operation
|
||||
//! @return The request id if session creation request succeeds; empty if it fails
|
||||
virtual AZStd::string CreateSession(const CreateSessionRequest& createSessionRequest) = 0;
|
||||
|
||||
// Retrieve all active sessions that match the given search criteria and sorted in specific order.
|
||||
// @param searchSessionsRequest The request of SearchSessions operation
|
||||
// @return The response of SearchSessions operation
|
||||
//! Retrieve all active sessions that match the given search criteria and sorted in specific order.
|
||||
//! @param searchSessionsRequest The request of SearchSessions operation
|
||||
//! @return The response of SearchSessions operation
|
||||
virtual SearchSessionsResponse SearchSessions(const SearchSessionsRequest& searchSessionsRequest) const = 0;
|
||||
|
||||
// Reserve an open player slot in a session, and perform connection from client to server.
|
||||
// @param joinSessionRequest The request of JoinSession operation
|
||||
// @return True if joining session succeeds; False otherwise
|
||||
//! Reserve an open player slot in a session, and perform connection from client to server.
|
||||
//! @param joinSessionRequest The request of JoinSession operation
|
||||
//! @return True if joining session succeeds; False otherwise
|
||||
virtual bool JoinSession(const JoinSessionRequest& joinSessionRequest) = 0;
|
||||
|
||||
// Disconnect player from session.
|
||||
//! Disconnect player from session.
|
||||
virtual void LeaveSession() = 0;
|
||||
};
|
||||
|
||||
@@ -54,19 +54,19 @@ namespace AzFramework
|
||||
ISessionAsyncRequests() = default;
|
||||
virtual ~ISessionAsyncRequests() = default;
|
||||
|
||||
// CreateSession Async
|
||||
// @param createSessionRequest The request of CreateSession operation
|
||||
//! CreateSession Async
|
||||
//! @param createSessionRequest The request of CreateSession operation
|
||||
virtual void CreateSessionAsync(const CreateSessionRequest& createSessionRequest) = 0;
|
||||
|
||||
// SearchSessions Async
|
||||
// @param searchSessionsRequest The request of SearchSessions operation
|
||||
//! SearchSessions Async
|
||||
//! @param searchSessionsRequest The request of SearchSessions operation
|
||||
virtual void SearchSessionsAsync(const SearchSessionsRequest& searchSessionsRequest) const = 0;
|
||||
|
||||
// JoinSession Async
|
||||
// @param joinSessionRequest The request of JoinSession operation
|
||||
//! JoinSession Async
|
||||
//! @param joinSessionRequest The request of JoinSession operation
|
||||
virtual void JoinSessionAsync(const JoinSessionRequest& joinSessionRequest) = 0;
|
||||
|
||||
// LeaveSession Async
|
||||
//! LeaveSession Async
|
||||
virtual void LeaveSessionAsync() = 0;
|
||||
};
|
||||
|
||||
@@ -85,19 +85,19 @@ namespace AzFramework
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnCreateSessionAsyncComplete is fired once CreateSessionAsync completes
|
||||
// @param createSessionResponse The request id if session creation request succeeds; empty if it fails
|
||||
//! OnCreateSessionAsyncComplete is fired once CreateSessionAsync completes
|
||||
//! @param createSessionResponse The request id if session creation request succeeds; empty if it fails
|
||||
virtual void OnCreateSessionAsyncComplete(const AZStd::string& createSessionReponse) = 0;
|
||||
|
||||
// OnSearchSessionsAsyncComplete is fired once SearchSessionsAsync completes
|
||||
// @param searchSessionsResponse The response of SearchSessions call
|
||||
//! OnSearchSessionsAsyncComplete is fired once SearchSessionsAsync completes
|
||||
//! @param searchSessionsResponse The response of SearchSessions call
|
||||
virtual void OnSearchSessionsAsyncComplete(const SearchSessionsResponse& searchSessionsResponse) = 0;
|
||||
|
||||
// OnJoinSessionAsyncComplete is fired once JoinSessionAsync completes
|
||||
// @param joinSessionsResponse True if joining session succeeds; False otherwise
|
||||
//! OnJoinSessionAsyncComplete is fired once JoinSessionAsync completes
|
||||
//! @param joinSessionsResponse True if joining session succeeds; False otherwise
|
||||
virtual void OnJoinSessionAsyncComplete(bool joinSessionsResponse) = 0;
|
||||
|
||||
// OnLeaveSessionAsyncComplete is fired once LeaveSessionAsync completes
|
||||
//! OnLeaveSessionAsyncComplete is fired once LeaveSessionAsync completes
|
||||
virtual void OnLeaveSessionAsyncComplete() = 0;
|
||||
};
|
||||
using SessionAsyncRequestNotificationBus = AZ::EBus<SessionAsyncRequestNotifications>;
|
||||
|
||||
@@ -24,46 +24,46 @@ namespace AzFramework
|
||||
SessionConfig() = default;
|
||||
virtual ~SessionConfig() = default;
|
||||
|
||||
// A time stamp indicating when this session was created. Format is a number expressed in Unix time as milliseconds.
|
||||
//! A time stamp indicating when this session was created. Format is a number expressed in Unix time as milliseconds.
|
||||
uint64_t m_creationTime = 0;
|
||||
|
||||
// A time stamp indicating when this data object was terminated. Same format as creation time.
|
||||
//! A time stamp indicating when this data object was terminated. Same format as creation time.
|
||||
uint64_t m_terminationTime = 0;
|
||||
|
||||
// A unique identifier for a player or entity creating the session.
|
||||
//! A unique identifier for a player or entity creating the session.
|
||||
AZStd::string m_creatorId;
|
||||
|
||||
// A collection of custom properties for a session.
|
||||
//! A collection of custom properties for a session.
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
|
||||
|
||||
// The matchmaking process information that was used to create the session.
|
||||
//! The matchmaking process information that was used to create the session.
|
||||
AZStd::string m_matchmakingData;
|
||||
|
||||
// A unique identifier for the session.
|
||||
//! A unique identifier for the session.
|
||||
AZStd::string m_sessionId;
|
||||
|
||||
// A descriptive label that is associated with a session.
|
||||
//! A descriptive label that is associated with a session.
|
||||
AZStd::string m_sessionName;
|
||||
|
||||
// The DNS identifier assigned to the instance that is running the session.
|
||||
//! The DNS identifier assigned to the instance that is running the session.
|
||||
AZStd::string m_dnsName;
|
||||
|
||||
// The IP address of the session.
|
||||
//! The IP address of the session.
|
||||
AZStd::string m_ipAddress;
|
||||
|
||||
// The port number for the session.
|
||||
//! The port number for the session.
|
||||
uint16_t m_port = 0;
|
||||
|
||||
// The maximum number of players that can be connected simultaneously to the session.
|
||||
//! The maximum number of players that can be connected simultaneously to the session.
|
||||
uint64_t m_maxPlayer = 0;
|
||||
|
||||
// Number of players currently in the session.
|
||||
//! Number of players currently in the session.
|
||||
uint64_t m_currentPlayer = 0;
|
||||
|
||||
// Current status of the session.
|
||||
//! Current status of the session.
|
||||
AZStd::string m_status;
|
||||
|
||||
// Provides additional information about session status.
|
||||
//! Provides additional information about session status.
|
||||
AZStd::string m_statusReason;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -29,42 +29,42 @@ namespace AzFramework
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnSessionHealthCheck is fired in health check process
|
||||
// Use this notification to perform any custom health check
|
||||
// @return True if OnSessionHealthCheck succeeds, false otherwise
|
||||
//! OnSessionHealthCheck is fired in health check process
|
||||
//! Use this notification to perform any custom health check
|
||||
//! @return True if OnSessionHealthCheck succeeds, false otherwise
|
||||
virtual bool OnSessionHealthCheck() = 0;
|
||||
|
||||
// OnCreateSessionBegin is fired at the beginning of session creation process
|
||||
// Use this notification to perform any necessary configuration or initialization before
|
||||
// creating session
|
||||
// @param sessionConfig The properties to describe a session
|
||||
// @return True if OnCreateSessionBegin succeeds, false otherwise
|
||||
//! OnCreateSessionBegin is fired at the beginning of session creation process
|
||||
//! Use this notification to perform any necessary configuration or initialization before
|
||||
//! creating session
|
||||
//! @param sessionConfig The properties to describe a session
|
||||
//! @return True if OnCreateSessionBegin succeeds, false otherwise
|
||||
virtual bool OnCreateSessionBegin(const SessionConfig& sessionConfig) = 0;
|
||||
|
||||
// OnCreateSessionEnd is fired at the end of session creation process
|
||||
// Use this notification to perform any follow-up operation after session is created and active
|
||||
//! OnCreateSessionEnd is fired at the end of session creation process
|
||||
//! Use this notification to perform any follow-up operation after session is created and active
|
||||
virtual void OnCreateSessionEnd() = 0;
|
||||
|
||||
// OnDestroySessionBegin is fired at the beginning of session termination process
|
||||
// Use this notification to perform any cleanup operation before destroying session,
|
||||
// like gracefully disconnect players, cleanup data, etc.
|
||||
// @return True if OnDestroySessionBegin succeeds, false otherwise
|
||||
//! OnDestroySessionBegin is fired at the beginning of session termination process
|
||||
//! Use this notification to perform any cleanup operation before destroying session,
|
||||
//! like gracefully disconnect players, cleanup data, etc.
|
||||
//! @return True if OnDestroySessionBegin succeeds, false otherwise
|
||||
virtual bool OnDestroySessionBegin() = 0;
|
||||
|
||||
// OnDestroySessionEnd is fired at the end of session termination process
|
||||
// Use this notification to perform any follow-up operation after session is destroyed,
|
||||
// like shutdown application process, etc.
|
||||
//! OnDestroySessionEnd is fired at the end of session termination process
|
||||
//! Use this notification to perform any follow-up operation after session is destroyed,
|
||||
//! like shutdown application process, etc.
|
||||
virtual void OnDestroySessionEnd() = 0;
|
||||
|
||||
// OnUpdateSessionBegin is fired at the beginning of session update process
|
||||
// Use this notification to perform any configuration or initialization to handle
|
||||
// the session settings changing
|
||||
// @param sessionConfig The properties to describe a session
|
||||
// @param updateReason The reason for session update
|
||||
//! OnUpdateSessionBegin is fired at the beginning of session update process
|
||||
//! Use this notification to perform any configuration or initialization to handle
|
||||
//! the session settings changing
|
||||
//! @param sessionConfig The properties to describe a session
|
||||
//! @param updateReason The reason for session update
|
||||
virtual void OnUpdateSessionBegin(const SessionConfig& sessionConfig, const AZStd::string& updateReason) = 0;
|
||||
|
||||
// OnUpdateSessionBegin is fired at the end of session update process
|
||||
// Use this notification to perform any follow-up operations after session is updated
|
||||
//! OnUpdateSessionBegin is fired at the end of session update process
|
||||
//! Use this notification to perform any follow-up operations after session is updated
|
||||
virtual void OnUpdateSessionEnd() = 0;
|
||||
};
|
||||
using SessionNotificationBus = AZ::EBus<SessionNotifications>;
|
||||
|
||||
@@ -31,16 +31,16 @@ namespace AzFramework
|
||||
CreateSessionRequest() = default;
|
||||
virtual ~CreateSessionRequest() = default;
|
||||
|
||||
// A unique identifier for a player or entity creating the session.
|
||||
//! A unique identifier for a player or entity creating the session.
|
||||
AZStd::string m_creatorId;
|
||||
|
||||
// A collection of custom properties for a session.
|
||||
//! A collection of custom properties for a session.
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_sessionProperties;
|
||||
|
||||
// A descriptive label that is associated with a session.
|
||||
//! A descriptive label that is associated with a session.
|
||||
AZStd::string m_sessionName;
|
||||
|
||||
// The maximum number of players that can be connected simultaneously to the session.
|
||||
//! The maximum number of players that can be connected simultaneously to the session.
|
||||
uint64_t m_maxPlayer = 0;
|
||||
};
|
||||
|
||||
@@ -54,17 +54,17 @@ namespace AzFramework
|
||||
SearchSessionsRequest() = default;
|
||||
virtual ~SearchSessionsRequest() = default;
|
||||
|
||||
// String containing the search criteria for the session search. If no filter expression is included, the request returns results
|
||||
// for all active sessions.
|
||||
//! String containing the search criteria for the session search. If no filter expression is included, the request returns results
|
||||
//! for all active sessions.
|
||||
AZStd::string m_filterExpression;
|
||||
|
||||
// Instructions on how to sort the search results. If no sort expression is included, the request returns results in random order.
|
||||
//! Instructions on how to sort the search results. If no sort expression is included, the request returns results in random order.
|
||||
AZStd::string m_sortExpression;
|
||||
|
||||
// The maximum number of results to return.
|
||||
//! The maximum number of results to return.
|
||||
uint8_t m_maxResult = 0;
|
||||
|
||||
// A token that indicates the start of the next sequential page of results.
|
||||
//! A token that indicates the start of the next sequential page of results.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
@@ -78,10 +78,10 @@ namespace AzFramework
|
||||
SearchSessionsResponse() = default;
|
||||
virtual ~SearchSessionsResponse() = default;
|
||||
|
||||
// A collection of sessions that match the search criteria and sorted in specific order.
|
||||
//! A collection of sessions that match the search criteria and sorted in specific order.
|
||||
AZStd::vector<SessionConfig> m_sessionConfigs;
|
||||
|
||||
// A token that indicates the start of the next sequential page of results.
|
||||
//! A token that indicates the start of the next sequential page of results.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
@@ -95,13 +95,13 @@ namespace AzFramework
|
||||
JoinSessionRequest() = default;
|
||||
virtual ~JoinSessionRequest() = default;
|
||||
|
||||
// A unique identifier for the session.
|
||||
//! A unique identifier for the session.
|
||||
AZStd::string m_sessionId;
|
||||
|
||||
// A unique identifier for a player. Player IDs are developer-defined.
|
||||
//! A unique identifier for a player. Player IDs are developer-defined.
|
||||
AZStd::string m_playerId;
|
||||
|
||||
// Developer-defined information related to a player.
|
||||
//! Developer-defined information related to a player.
|
||||
AZStd::string m_playerData;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
+19
-13
@@ -10,6 +10,8 @@
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
|
||||
#include <AzFramework/Process/ProcessWatcher.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -24,14 +26,20 @@ namespace AzFramework::AssetSystem::Platform
|
||||
AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory };
|
||||
// In Mac the Editor and game is within a bundle, so the path to the sibling app
|
||||
// has to go up from the Contents/MacOS folder the binary is in
|
||||
assetProcessorPath /= "../../../AssetProcessor.app";
|
||||
assetProcessorPath /= "../../../AssetProcessor.app/Contents/MacOS/AssetProcessor";
|
||||
assetProcessorPath = assetProcessorPath.LexicallyNormal();
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
|
||||
assetProcessorPath =
|
||||
AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_TRAIT_OS_PLATFORM_NAME / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.app";
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if (AZ::IO::FixedMaxPath installedBinariesPath;
|
||||
settingsRegistry->Get(installedBinariesPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder))
|
||||
{
|
||||
// Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure.
|
||||
assetProcessorPath = AZ::IO::FixedMaxPath{ engineRoot } / installedBinariesPath / "AssetProcessor.app/Contents/MacOS/AssetProcessor";
|
||||
}
|
||||
}
|
||||
|
||||
if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str()))
|
||||
{
|
||||
@@ -39,23 +47,21 @@ namespace AzFramework::AssetSystem::Platform
|
||||
}
|
||||
}
|
||||
|
||||
auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"(open -g "%s" --args --start-hidden)", assetProcessorPath.c_str());
|
||||
AZStd::string commandLineParams;
|
||||
// Add the engine path to the launch command if not empty
|
||||
if (!engineRoot.empty())
|
||||
{
|
||||
fullLaunchCommand += R"( --engine-path=")";
|
||||
fullLaunchCommand += engineRoot;
|
||||
fullLaunchCommand += '"';
|
||||
commandLineParams += AZStd::string::format("\"--engine-path=\"%s\"\"", engineRoot.data());
|
||||
}
|
||||
|
||||
// Add the active project path to the launch command if not empty
|
||||
if (!projectPath.empty())
|
||||
{
|
||||
fullLaunchCommand += R"( --project-path=")";
|
||||
fullLaunchCommand += projectPath;
|
||||
fullLaunchCommand += '"';
|
||||
commandLineParams += AZStd::string::format(" \"--regset=/Amazon/AzCore/Bootstrap/project_path=\"%s\"\"", projectPath.data());
|
||||
}
|
||||
|
||||
return system(fullLaunchCommand.c_str()) == 0;
|
||||
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
processLaunchInfo.m_processExecutableString = AZStd::move(assetProcessorPath.Native());
|
||||
processLaunchInfo.m_commandlineParameters = commandLineParams;
|
||||
return AzFramework::ProcessLauncher::LaunchUnwatchedProcess(processLaunchInfo);
|
||||
}
|
||||
}
|
||||
|
||||
+23
@@ -54,6 +54,7 @@ namespace AzFramework
|
||||
RECT m_windowRectToRestoreOnFullScreenExit; //!< The position and size of the window to restore when exiting full screen.
|
||||
UINT m_windowStyleToRestoreOnFullScreenExit; //!< The style(s) of the window to restore when exiting full screen.
|
||||
bool m_isInBorderlessWindowFullScreenState = false; //!< Was a borderless window used to enter full screen state?
|
||||
bool m_shouldEnterFullScreenStateOnActivate = false; //!< Should we enter full screen state when the window is activated?
|
||||
|
||||
using GetDpiForWindowType = UINT(HWND hwnd);
|
||||
GetDpiForWindowType* m_getDpiFunction = nullptr;
|
||||
@@ -249,6 +250,28 @@ namespace AzFramework
|
||||
AzFramework::RawInputNotificationBusWindows::Broadcast(&AzFramework::RawInputNotificationsWindows::OnRawInputCodeUnitUTF16Event, codeUnitUTF16);
|
||||
break;
|
||||
}
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
// Alt-tabbing out of the app while it is in a full screen state does not
|
||||
// work unless we explicitly exit the full screen state upon deactivation,
|
||||
// in which case we want to enter full screen state again upon activation.
|
||||
const bool windowIsNowInactive = (LOWORD(wParam) == WA_INACTIVE);
|
||||
const bool windowFullScreenState = nativeWindowImpl->GetFullScreenState();
|
||||
if (windowIsNowInactive &&
|
||||
windowFullScreenState)
|
||||
{
|
||||
nativeWindowImpl->m_shouldEnterFullScreenStateOnActivate = true;
|
||||
nativeWindowImpl->SetFullScreenState(false);
|
||||
}
|
||||
else if (!windowIsNowInactive &&
|
||||
!windowFullScreenState &&
|
||||
nativeWindowImpl->m_shouldEnterFullScreenStateOnActivate)
|
||||
{
|
||||
nativeWindowImpl->m_shouldEnterFullScreenStateOnActivate = false;
|
||||
nativeWindowImpl->SetFullScreenState(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SYSKEYDOWN:
|
||||
{
|
||||
// Handle ALT+ENTER to toggle full screen unless exclsuive full screen
|
||||
|
||||
@@ -45,6 +45,13 @@ namespace AzGameFramework
|
||||
enginePakPath = AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) / "engine.pak";
|
||||
m_archive->OpenPack("@products@", enginePakPath.Native());
|
||||
}
|
||||
|
||||
// By default, load all archives in the products folder.
|
||||
// If you want to adjust this for your project, make sure that the archive containing
|
||||
// the bootstrap for the settings registry is still loaded here, and any archives containing
|
||||
// assets used early in startup, like default shaders, are loaded here.
|
||||
constexpr AZStd::string_view paksFolder = "@products@/*.pak"; // (@products@ assumed)
|
||||
m_archive->OpenPacks(paksFolder);
|
||||
}
|
||||
|
||||
GameApplication::~GameApplication()
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace AzQtComponents
|
||||
setProperty("HasNoWindowDecorations", true);
|
||||
|
||||
setAttribute(Qt::WA_ShowWithoutActivating);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
m_borderRadius = toastConfiguration.m_borderRadius;
|
||||
if (m_borderRadius > 0)
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace AzQtComponents
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ToastNotification, AZ::SystemAllocator, 0);
|
||||
|
||||
ToastNotification(QWidget* parent, const ToastConfiguration& toastConfiguration);
|
||||
virtual ~ToastNotification();
|
||||
@@ -73,7 +72,7 @@ namespace AzQtComponents
|
||||
|
||||
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
AZStd::chrono::milliseconds m_fadeDuration;
|
||||
AZStd::unique_ptr<Ui::ToastNotification> m_ui;
|
||||
QScopedPointer<Ui::ToastNotification> m_ui;
|
||||
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
|
||||
};
|
||||
} // namespace AzQtComponents
|
||||
|
||||
-1
@@ -27,7 +27,6 @@ namespace AzQtComponents
|
||||
class AZ_QT_COMPONENTS_API ToastConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ToastConfiguration, AZ::SystemAllocator, 0);
|
||||
ToastConfiguration(ToastType toastType, const QString& title, const QString& description);
|
||||
|
||||
bool m_closeOnClick = true;
|
||||
|
||||
@@ -657,13 +657,18 @@ bool SpinBoxWatcher::handleMouseDragStepping(QAbstractSpinBox* spinBox, QEvent*
|
||||
QPoint screenPos = mouseEvent->screenPos().toPoint();
|
||||
const int xPos = screenPos.x();
|
||||
int newXPos = xPos;
|
||||
// cursor bounces on the left and right side of the screen
|
||||
// looks like buggy behaviour so mouse cursor is wrapped
|
||||
// around to the other side of the screen.
|
||||
if (xPos >= screenRect.right())
|
||||
{
|
||||
newXPos = screenRect.right() - 1;
|
||||
// wraps mouse cursor around to the left side of the screen
|
||||
newXPos = screenRect.left() + 1;
|
||||
}
|
||||
else if (xPos <= screenRect.left())
|
||||
{
|
||||
newXPos = screenRect.left() + 1;
|
||||
// wraps mouse cursor around to the right side of the screen
|
||||
newXPos = screenRect.right() - 1;
|
||||
}
|
||||
|
||||
if (newXPos != xPos)
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace AzToolsFramework
|
||||
bool isDisabledInSimMode = false; ///< set to true if the view pane should not be openable from level editor menu when editor is in simulation mode.
|
||||
|
||||
bool showOnToolsToolbar = false; ///< set to true if the view pane should create a button on the tools toolbar to open/close the pane
|
||||
QString toolbarIcon; ///< path to the icon to use for the toolbar button - only used if showOnToolsToolbar is set to true
|
||||
AZStd::string toolbarIcon; ///< path to the icon to use for the toolbar button - only used if showOnToolsToolbar is set to true
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -426,6 +426,8 @@ namespace AzToolsFramework
|
||||
->Property("showInMenu", BehaviorValueProperty(&ViewPaneOptions::showInMenu))
|
||||
->Property("canHaveMultipleInstances", BehaviorValueProperty(&ViewPaneOptions::canHaveMultipleInstances))
|
||||
->Property("isPreview", BehaviorValueProperty(&ViewPaneOptions::isPreview))
|
||||
->Property("showOnToolsToolbar", BehaviorValueProperty(&ViewPaneOptions::showOnToolsToolbar))
|
||||
->Property("toolbarIcon", BehaviorValueProperty(&ViewPaneOptions::toolbarIcon))
|
||||
;
|
||||
|
||||
behaviorContext->EBus<EditorRequestBus>("EditorRequestBus")
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ namespace AzToolsFramework
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
AssetSystemBus::Handler::BusDisconnect();
|
||||
m_assetBrowserModel.release();
|
||||
m_assetBrowserModel.reset();
|
||||
EntryCache::DestroyInstance();
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -26,8 +26,12 @@ namespace AzToolsFramework
|
||||
AZ::Interface<ContainerEntityInterface>::Unregister(this);
|
||||
}
|
||||
|
||||
void ContainerEntitySystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
|
||||
void ContainerEntitySystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<ContainerEntitySystemComponent, AZ::Component>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerEntitySystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
|
||||
+5
-1
@@ -47,8 +47,12 @@ namespace AzToolsFramework
|
||||
AZ::Interface<FocusModeInterface>::Unregister(this);
|
||||
}
|
||||
|
||||
void FocusModeSystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
|
||||
void FocusModeSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<FocusModeSystemComponent, AZ::Component>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void FocusModeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
|
||||
@@ -210,8 +210,8 @@ namespace AzToolsFramework
|
||||
m_enabled = enabled;
|
||||
if (!enabled)
|
||||
{
|
||||
// Send an internal focus change event to reset our input state to fresh if we're disabled.
|
||||
HandleFocusChange(nullptr);
|
||||
// Clear input channels to reset our input state if we're disabled.
|
||||
ClearInputChannels(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (eventType == QEvent::Type::MouseMove)
|
||||
{
|
||||
// clear override cursor when moving outside of the viewport
|
||||
// Clear override cursor when moving outside of the viewport
|
||||
const auto* mouseEvent = static_cast<const QMouseEvent*>(event);
|
||||
if (m_overrideCursor && !m_sourceWidget->geometry().contains(m_sourceWidget->mapFromGlobal(mouseEvent->globalPos())))
|
||||
{
|
||||
@@ -255,6 +255,13 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
// If the application state changes (e.g. we have alt-tabbed or minimized the
|
||||
// main editor window) then ensure all input channels are cleared
|
||||
if (eventType == QEvent::ApplicationStateChange)
|
||||
{
|
||||
ClearInputChannels(event);
|
||||
}
|
||||
|
||||
// Only accept mouse & key release events that originate from an object that is not our target widget,
|
||||
// as we don't want to erroneously intercept user input meant for another component.
|
||||
if (object != m_sourceWidget && eventType != QEvent::Type::KeyRelease && eventType != QEvent::Type::MouseButtonRelease)
|
||||
@@ -264,9 +271,6 @@ namespace AzToolsFramework
|
||||
|
||||
if (eventType == QEvent::FocusIn || eventType == QEvent::FocusOut)
|
||||
{
|
||||
// If our focus changes, go ahead and reset all input devices.
|
||||
HandleFocusChange(event);
|
||||
|
||||
// If we focus in on the source widget and the mouse is contained in its
|
||||
// bounds, refresh the cached cursor position to ensure it is up to date (this
|
||||
// ensures cursor positions are refreshed correctly with context menu focus changes)
|
||||
@@ -451,7 +455,7 @@ namespace AzToolsFramework
|
||||
NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent);
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleFocusChange(QEvent* event)
|
||||
void QtEventToAzInputMapper::ClearInputChannels(QEvent* event)
|
||||
{
|
||||
for (auto& channelData : m_channels)
|
||||
{
|
||||
|
||||
@@ -138,8 +138,9 @@ namespace AzToolsFramework
|
||||
void HandleKeyEvent(QKeyEvent* keyEvent);
|
||||
// Handles mouse wheel events.
|
||||
void HandleWheelEvent(QWheelEvent* wheelEvent);
|
||||
// Handles focus change events.
|
||||
void HandleFocusChange(QEvent* event);
|
||||
|
||||
// Clear all input channels (set all channel states to 'ended').
|
||||
void ClearInputChannels(QEvent* event);
|
||||
|
||||
// Populates m_keyMappings.
|
||||
void InitializeKeyMappings();
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
#include <AzCore/Utils/TypeHash.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceEntityIdMapper.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
|
||||
@@ -565,6 +566,7 @@ namespace AzToolsFramework
|
||||
parentId = m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(editorEntityContextId);
|
||||
}
|
||||
|
||||
// If the parent entity isn't owned by a prefab instance, bail.
|
||||
InstanceOptionalReference owningInstanceOfParentEntity = GetOwnerInstanceByEntityId(parentId);
|
||||
if (!owningInstanceOfParentEntity)
|
||||
{
|
||||
@@ -572,6 +574,14 @@ namespace AzToolsFramework
|
||||
"Cannot add entity because the owning instance of parent entity with id '%llu' could not be found.",
|
||||
static_cast<AZ::u64>(parentId)));
|
||||
}
|
||||
|
||||
// If the parent entity is a closed container, bail.
|
||||
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get(); !containerEntityInterface->IsContainerOpen(parentId))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format(
|
||||
"Cannot add entity because the parent entity (id '%llu') is a closed container entity.",
|
||||
static_cast<AZ::u64>(parentId)));
|
||||
}
|
||||
|
||||
EntityAlias entityAlias = Instance::GenerateEntityAlias();
|
||||
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ namespace AzToolsFramework
|
||||
|
||||
ToastId ToastNotificationsView::CreateToastNotification(const AzQtComponents::ToastConfiguration& toastConfiguration)
|
||||
{
|
||||
AzQtComponents::ToastNotification* notification = aznew AzQtComponents::ToastNotification(parentWidget(), toastConfiguration);
|
||||
AzQtComponents::ToastNotification* notification = new AzQtComponents::ToastNotification(this, toastConfiguration);
|
||||
ToastId toastId = AZ::Entity::MakeId();
|
||||
m_notifications[toastId] = notification;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ AzToolsFramework--EntityOutlinerWidget #m_display_options
|
||||
{
|
||||
qproperty-icon: url(:/stylesheet/img/UI20/menu-centered.svg);
|
||||
qproperty-iconSize: 16px 16px;
|
||||
qproperty-flat: true;
|
||||
}
|
||||
|
||||
AzToolsFramework--EntityOutlinerWidget QTreeView
|
||||
|
||||
+29
-4
@@ -43,6 +43,7 @@
|
||||
#include <AzToolsFramework/API/ComponentEntityObjectBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserSourceDropBus.h>
|
||||
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
@@ -764,10 +765,21 @@ namespace AzToolsFramework
|
||||
return canHandleData;
|
||||
}
|
||||
|
||||
bool EntityOutlinerListModel::CanDropMimeDataAssets(const QMimeData* data, Qt::DropAction /*action*/, int /*row*/, int /*column*/, const QModelIndex& /*parent*/) const
|
||||
bool EntityOutlinerListModel::CanDropMimeDataAssets(
|
||||
const QMimeData* data,
|
||||
[[maybe_unused]] Qt::DropAction action,
|
||||
[[maybe_unused]] int row,
|
||||
[[maybe_unused]] int column,
|
||||
const QModelIndex& parent) const
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
|
||||
// Disable dropping assets on closed container entities.
|
||||
AZ::EntityId parentId = GetEntityFromIndex(parent);
|
||||
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
|
||||
!containerEntityInterface->IsContainerOpen(parentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data->hasFormat(AssetBrowser::AssetBrowserEntry::GetMimeType()))
|
||||
{
|
||||
return DecodeAssetMimeData(data);
|
||||
@@ -788,8 +800,15 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the parent entity is a closed container, bail.
|
||||
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get();
|
||||
!containerEntityInterface->IsContainerOpen(assignParentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Source Files
|
||||
if (sourceFiles.size() > 0)
|
||||
if (!sourceFiles.empty())
|
||||
{
|
||||
// Get position (center of viewport). If no viewport is available, (0,0,0) will be used.
|
||||
AZ::Vector3 viewportCenterPosition = AZ::Vector3::CreateZero();
|
||||
@@ -973,6 +992,12 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the new parent is a closed container, bail.
|
||||
if (auto containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get(); !containerEntityInterface->IsContainerOpen(newParentId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore entities not owned by the editor context. It is assumed that all entities belong
|
||||
// to the same context since multiple selection doesn't span across views.
|
||||
for (const AZ::EntityId& entityId : selectedEntityIds)
|
||||
|
||||
@@ -80,8 +80,9 @@ namespace AzToolsFramework
|
||||
|
||||
private:
|
||||
AZStd::string m_message; //!< Message to display for fading text.
|
||||
float m_opacity = 1.0f; //!< The opacity of the invalid click message.
|
||||
AzFramework::ScreenPoint m_invalidClickPosition; //!< The position to display the invalid click message.
|
||||
float m_opacity = 0.0f; //!< The opacity of the invalid click message.
|
||||
//! The position to display the invalid click message.
|
||||
AzFramework::ScreenPoint m_invalidClickPosition = AzFramework::ScreenPoint(0, 0);
|
||||
};
|
||||
|
||||
//! Interface to begin invalid click feedback (will run all added InvalidClick behaviors).
|
||||
|
||||
@@ -28,9 +28,12 @@ namespace UnitTest
|
||||
return true;
|
||||
}
|
||||
|
||||
void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
|
||||
void BoundsTestComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
// noop
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<BoundsTestComponent, EditorComponentBase>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void BoundsTestComponent::Activate()
|
||||
|
||||
@@ -42,5 +42,4 @@ namespace UnitTest
|
||||
AZ::Aabb GetWorldBounds() override;
|
||||
AZ::Aabb GetLocalBounds() override;
|
||||
};
|
||||
|
||||
} // namespace UnitTest
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#if defined(HAVE_BENCHMARK)
|
||||
|
||||
#include <Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.h>
|
||||
#include <AzFramework/Spawnable/SpawnableEntitiesInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
|
||||
|
||||
namespace Benchmark
|
||||
{
|
||||
using BM_SpawnAllEntities = BM_Spawnable;
|
||||
|
||||
BENCHMARK_DEFINE_F(BM_SpawnAllEntities, SingleEntitySpawnable_SpawnCallVariable)(::benchmark::State& state)
|
||||
{
|
||||
const uint64_t spawnAllEntitiesCallCount = aznumeric_cast<uint64_t>(state.range());
|
||||
const uint64_t entityCountInSourcePrefab = 1;
|
||||
|
||||
SetUpSpawnableAsset(entityCountInSourcePrefab);
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (uint64_t spwanableCounter = 0; spwanableCounter < spawnAllEntitiesCallCount; spwanableCounter++)
|
||||
{
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
|
||||
}
|
||||
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
|
||||
// Destroy the ticket so that this queues a request to delete all the entities spawned with this ticket.
|
||||
state.PauseTiming();
|
||||
delete m_spawnTicket;
|
||||
m_spawnTicket = nullptr;
|
||||
|
||||
// This will process the request to delete all entities spawned with the ticket
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
state.ResumeTiming();
|
||||
}
|
||||
|
||||
state.SetComplexityN(spawnAllEntitiesCallCount);
|
||||
}
|
||||
BENCHMARK_REGISTER_F(BM_SpawnAllEntities, SingleEntitySpawnable_SpawnCallVariable)
|
||||
->RangeMultiplier(10)
|
||||
->Range(100, 10000)
|
||||
->Unit(benchmark::kMillisecond)
|
||||
->Complexity();
|
||||
|
||||
BENCHMARK_DEFINE_F(BM_SpawnAllEntities, SingleSpawnCall_EntityCountVariable)(::benchmark::State& state)
|
||||
{
|
||||
const uint64_t entityCountInSpawnable = aznumeric_cast<uint64_t>(state.range());
|
||||
|
||||
SetUpSpawnableAsset(entityCountInSpawnable);
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
|
||||
// Destroy the ticket so that this queues a request to delete all the entities spawned with this ticket.
|
||||
state.PauseTiming();
|
||||
delete m_spawnTicket;
|
||||
m_spawnTicket = nullptr;
|
||||
|
||||
// This will process the request to delete all entities spawned with the ticket
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
state.ResumeTiming();
|
||||
}
|
||||
|
||||
state.SetComplexityN(entityCountInSpawnable);
|
||||
}
|
||||
BENCHMARK_REGISTER_F(BM_SpawnAllEntities, SingleSpawnCall_EntityCountVariable)
|
||||
->RangeMultiplier(10)
|
||||
->Range(100, 10000)
|
||||
->Unit(benchmark::kMillisecond)
|
||||
->Complexity();
|
||||
|
||||
BENCHMARK_DEFINE_F(BM_SpawnAllEntities, EntityCountVariable_SpawnCallCountVariable)(::benchmark::State& state)
|
||||
{
|
||||
const uint64_t entityCountInSpawnable = aznumeric_cast<uint64_t>(state.range(0));
|
||||
const uint64_t spawnCallCount = aznumeric_cast<uint64_t>(state.range(1));
|
||||
|
||||
SetUpSpawnableAsset(entityCountInSpawnable);
|
||||
|
||||
for (auto _ : state)
|
||||
{
|
||||
state.PauseTiming();
|
||||
m_spawnTicket = new AzFramework::EntitySpawnTicket(m_spawnableAsset);
|
||||
state.ResumeTiming();
|
||||
|
||||
for (uint64_t spawnCallCounter = 0; spawnCallCounter < spawnCallCount; spawnCallCounter++)
|
||||
{
|
||||
AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*m_spawnTicket);
|
||||
}
|
||||
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
|
||||
state.PauseTiming();
|
||||
delete m_spawnTicket;
|
||||
m_spawnTicket = nullptr;
|
||||
m_rootSpawnableInterface->ProcessSpawnableQueue();
|
||||
state.ResumeTiming();
|
||||
}
|
||||
|
||||
state.SetComplexityN(entityCountInSpawnable * spawnCallCount);
|
||||
}
|
||||
// Provide ranges here to compare times for spawning the same number of entities by altering entityCountInSpawnable and spawnCallCount.
|
||||
BENCHMARK_REGISTER_F(BM_SpawnAllEntities, EntityCountVariable_SpawnCallCountVariable)
|
||||
->Args({ 10, 100 })
|
||||
->Args({ 100, 10 })
|
||||
->Args({ 10, 1000 })
|
||||
->Args({ 1000, 10 })
|
||||
->Args({ 100, 1000 })
|
||||
->Args({ 1000, 100 })
|
||||
->Unit(benchmark::kMillisecond)
|
||||
->Complexity();
|
||||
} // namespace Benchmark
|
||||
|
||||
#endif
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#if defined(HAVE_BENCHMARK)
|
||||
|
||||
#include <AzToolsFramework/Prefab/Spawnable/SpawnableUtils.h>
|
||||
#include <Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.h>
|
||||
|
||||
namespace Benchmark
|
||||
{
|
||||
void BM_Spawnable::SetUp(const benchmark::State& state)
|
||||
{
|
||||
SetUpHelper(state);
|
||||
}
|
||||
|
||||
void BM_Spawnable::SetUp(benchmark::State& state)
|
||||
{
|
||||
SetUpHelper(state);
|
||||
}
|
||||
|
||||
void BM_Spawnable::SetUpHelper(const benchmark::State& state)
|
||||
{
|
||||
BM_Prefab::SetUp(state);
|
||||
m_rootSpawnableInterface = AzFramework::RootSpawnableInterface::Get();
|
||||
AZ_Assert(m_rootSpawnableInterface != nullptr, "RootSpawnableInterface isn't found.");
|
||||
}
|
||||
|
||||
void BM_Spawnable::TearDown(const benchmark::State& state)
|
||||
{
|
||||
TearDownHelper(state);
|
||||
}
|
||||
|
||||
void BM_Spawnable::TearDown(benchmark::State& state)
|
||||
{
|
||||
TearDownHelper(state);
|
||||
}
|
||||
|
||||
void BM_Spawnable::TearDownHelper(const benchmark::State& state)
|
||||
{
|
||||
m_spawnableAsset.Release();
|
||||
BM_Prefab::TearDown(state);
|
||||
}
|
||||
|
||||
void BM_Spawnable::SetUpSpawnableAsset(uint64_t entityCount)
|
||||
{
|
||||
AZStd::vector<AZ::Entity*> entities;
|
||||
entities.reserve(entityCount);
|
||||
|
||||
for (uint64_t i = 0; i < entityCount; i++)
|
||||
{
|
||||
entities.emplace_back(CreateEntity("Entity"));
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<Instance> instance = m_prefabSystemComponent->CreatePrefab(AZStd::move(entities), {}, m_pathString);
|
||||
const PrefabDom& prefabDom = m_prefabSystemComponent->FindTemplateDom(instance->GetTemplateId());
|
||||
|
||||
// Lifecycle of spawnable is managed by the asset that's created using it.
|
||||
AzFramework::Spawnable* spawnable = new AzFramework::Spawnable(
|
||||
AZ::Data::AssetId::CreateString("{612F2AB1-30DF-44BB-AFBE-17A85199F09E}:0"), AZ::Data::AssetData::AssetStatus::Ready);
|
||||
AzToolsFramework::Prefab::SpawnableUtils::CreateSpawnable(*spawnable, prefabDom);
|
||||
m_spawnableAsset = AZ::Data::Asset<AzFramework::Spawnable>(spawnable, AZ::Data::AssetLoadBehavior::Default);
|
||||
}
|
||||
} // namespace Benchmark
|
||||
|
||||
#endif
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_BENCHMARK)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzFramework/Spawnable/RootSpawnableInterface.h>
|
||||
#include <Prefab/Benchmark/PrefabBenchmarkFixture.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
class EntitySpawnTicket;
|
||||
class RootSpawnableDefinition;
|
||||
}
|
||||
|
||||
namespace Benchmark
|
||||
{
|
||||
class BM_Spawnable
|
||||
: public Benchmark::BM_Prefab
|
||||
{
|
||||
protected:
|
||||
void SetUp(const benchmark::State& state) override;
|
||||
void SetUp(benchmark::State& state) override;
|
||||
void SetUpHelper(const benchmark::State& state);
|
||||
|
||||
void TearDown(const benchmark::State& state) override;
|
||||
void TearDown(benchmark::State& state) override;
|
||||
void TearDownHelper(const benchmark::State& state);
|
||||
|
||||
void SetUpSpawnableAsset(uint64_t entityCount);
|
||||
|
||||
AZ::Data::Asset<AzFramework::Spawnable> m_spawnableAsset;
|
||||
AzFramework::EntitySpawnTicket* m_spawnTicket;
|
||||
AzFramework::RootSpawnableDefinition* m_rootSpawnableInterface;
|
||||
};
|
||||
} // namespace Benchmark
|
||||
|
||||
#endif
|
||||
@@ -60,6 +60,9 @@ set(FILES
|
||||
Prefab/Benchmark/PrefabLoadBenchmarks.cpp
|
||||
Prefab/Benchmark/PrefabUpdateInstancesBenchmarks.cpp
|
||||
Prefab/Benchmark/SpawnableCreateBenchmarks.cpp
|
||||
Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.h
|
||||
Prefab/Benchmark/Spawnable/SpawnableBenchmarkFixture.cpp
|
||||
Prefab/Benchmark/Spawnable/SpawnAllEntitiesBenchmarks.cpp
|
||||
Prefab/PrefabFocus/PrefabFocusTests.cpp
|
||||
Prefab/MockPrefabFileIOActionValidator.cpp
|
||||
Prefab/MockPrefabFileIOActionValidator.h
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <Launcher.h>
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Component/ComponentApplicationLifecycle.h>
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
@@ -664,6 +665,8 @@ namespace O3DELauncher
|
||||
systemInitParams.pSystem = CreateSystemInterface(systemInitParams);
|
||||
#endif // !defined(AZ_MONOLITHIC_BUILD)
|
||||
|
||||
AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "LegacySystemInterfaceCreated", R"({})");
|
||||
|
||||
ReturnCode status = ReturnCode::Success;
|
||||
|
||||
if (systemInitParams.pSystem)
|
||||
|
||||
@@ -739,24 +739,6 @@ public:
|
||||
#undef GetUserName
|
||||
#endif
|
||||
|
||||
|
||||
struct IProfilingSystem
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~IProfilingSystem() {}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VTune Profiling interface.
|
||||
|
||||
// Summary:
|
||||
// Resumes vtune data collection.
|
||||
virtual void VTuneResume() = 0;
|
||||
// Summary:
|
||||
// Pauses vtune data collection.
|
||||
virtual void VTunePause() = 0;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Description:
|
||||
@@ -851,7 +833,6 @@ struct ISystem
|
||||
virtual IMovieSystem* GetIMovieSystem() = 0;
|
||||
virtual ::IConsole* GetIConsole() = 0;
|
||||
virtual IRemoteConsole* GetIRemoteConsole() = 0;
|
||||
virtual IProfilingSystem* GetIProfilingSystem() = 0;
|
||||
virtual ISystemEventDispatcher* GetISystemEventDispatcher() = 0;
|
||||
|
||||
virtual ITimer* GetITimer() = 0;
|
||||
@@ -1121,8 +1102,8 @@ inline ISystem* GetISystem()
|
||||
|
||||
// Description:
|
||||
// This function must be called once by each module at the beginning, to setup global pointers.
|
||||
extern "C" AZ_DLL_EXPORT void ModuleInitISystem(ISystem* pSystem, const char* moduleName);
|
||||
extern "C" AZ_DLL_EXPORT void ModuleShutdownISystem(ISystem* pSystem);
|
||||
void ModuleInitISystem(ISystem* pSystem, const char* moduleName);
|
||||
void ModuleShutdownISystem(ISystem* pSystem);
|
||||
extern "C" AZ_DLL_EXPORT void InjectEnvironment(void* env);
|
||||
extern "C" AZ_DLL_EXPORT void DetachEnvironment();
|
||||
|
||||
|
||||
@@ -76,8 +76,6 @@ public:
|
||||
::IConsole * ());
|
||||
MOCK_METHOD0(GetIRemoteConsole,
|
||||
IRemoteConsole * ());
|
||||
MOCK_METHOD0(GetIProfilingSystem,
|
||||
IProfilingSystem * ());
|
||||
MOCK_METHOD0(GetISystemEventDispatcher,
|
||||
ISystemEventDispatcher * ());
|
||||
MOCK_METHOD0(GetITimer,
|
||||
|
||||
@@ -96,47 +96,6 @@ unsigned countElements (const std::vector<T>& arrT, const T& x)
|
||||
*/
|
||||
namespace stl
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Compare member of class/struct.
|
||||
//
|
||||
// e.g. Sort Vec3s by x component
|
||||
//
|
||||
// std::sort(vec3s.begin(), vec3s.end(), stl::member_compare<Vec3, float, &Vec3::x>());
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename OWNER_TYPE, typename MEMBER_TYPE, MEMBER_TYPE OWNER_TYPE::* MEMBER_PTR, typename EQUALITY = std::less<MEMBER_TYPE> >
|
||||
struct member_compare
|
||||
{
|
||||
inline bool operator () (const OWNER_TYPE& lhs, const OWNER_TYPE& rhs) const
|
||||
{
|
||||
return EQUALITY()(lhs.*MEMBER_PTR, rhs.*MEMBER_PTR);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Compare member of class/struct against parameter.
|
||||
//
|
||||
// e.g. Find Vec3 with x component less than 1.0
|
||||
//
|
||||
// std::find_if(vec3s.begin(), vec3s.end(), stl::member_compare_param<Vec3, float, &Vec3::x>(1.0f));
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename OWNER_TYPE, typename MEMBER_TYPE, MEMBER_TYPE OWNER_TYPE::* MEMBER_PTR, typename EQUALITY = std::less<MEMBER_TYPE> >
|
||||
struct member_compare_param
|
||||
{
|
||||
inline member_compare_param(const MEMBER_TYPE& _value)
|
||||
: value(_value)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool operator () (const OWNER_TYPE& rhs) const
|
||||
{
|
||||
return EQUALITY()(rhs.*MEMBER_PTR, value);
|
||||
}
|
||||
|
||||
const MEMBER_TYPE& value;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Searches the given entry in the map by key, and if there is none, returns the default value
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -154,48 +113,6 @@ namespace stl
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Inserts and returns a reference to the given value in the map, or returns the current one if it's already there.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <typename Map>
|
||||
inline typename Map::mapped_type& map_insert_or_get(Map& mapKeyToValue, const typename Map::key_type& key, const typename Map::mapped_type& defValue = typename Map::mapped_type())
|
||||
{
|
||||
auto&& iresult = mapKeyToValue.insert(typename Map::value_type(key, defValue));
|
||||
return iresult.first->second;
|
||||
}
|
||||
|
||||
// searches the given entry in the map by key, and if there is none, returns the default value
|
||||
// The values are taken/returned in REFERENCEs rather than values
|
||||
template <typename Key, typename mapped_type, typename Traits, typename Allocator>
|
||||
inline mapped_type& find_in_map_ref(std::map<Key, mapped_type, Traits, Allocator>& mapKeyToValue, const Key& key, mapped_type& valueDefault)
|
||||
{
|
||||
typedef std::map<Key, mapped_type, Traits, Allocator> Map;
|
||||
typename Map::iterator it = mapKeyToValue.find (key);
|
||||
if (it == mapKeyToValue.end())
|
||||
{
|
||||
return valueDefault;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename mapped_type, typename Traits, typename Allocator>
|
||||
inline const mapped_type& find_in_map_ref(const std::map<Key, mapped_type, Traits, Allocator>& mapKeyToValue, const Key& key, const mapped_type& valueDefault)
|
||||
{
|
||||
typedef std::map<Key, mapped_type, Traits, Allocator> Map;
|
||||
typename Map::const_iterator it = mapKeyToValue.find (key);
|
||||
if (it == mapKeyToValue.end())
|
||||
{
|
||||
return valueDefault;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Fills vector with contents of map.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -210,20 +127,6 @@ namespace stl
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Fills vector with contents of set.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Set, class Vector>
|
||||
inline void set_to_vector(const Set& theSet, Vector& array)
|
||||
{
|
||||
array.resize(0);
|
||||
array.reserve(theSet.size());
|
||||
for (typename Set::const_iterator it = theSet.begin(); it != theSet.end(); ++it)
|
||||
{
|
||||
array.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find and erase element from container.
|
||||
// @return true if item was find and erased, false if item not found.
|
||||
@@ -312,48 +215,6 @@ namespace stl
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Push back to container unique element.
|
||||
// @return true if item added, false overwise.
|
||||
template <class CONTAINER, class PREDICATE, typename VALUE>
|
||||
inline bool push_back_unique_if(CONTAINER& container, const PREDICATE& predicate, const VALUE& value)
|
||||
{
|
||||
typename CONTAINER::iterator end = container.end();
|
||||
|
||||
if (AZStd::find_if(container.begin(), end, predicate) == end)
|
||||
{
|
||||
container.push_back(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Push back to container contents of another container
|
||||
template <class Container, class Iter>
|
||||
inline void push_back_range(Container& container, Iter begin, Iter end)
|
||||
{
|
||||
for (Iter it = begin; it != end; ++it)
|
||||
{
|
||||
container.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Push back to container contents of another container, if not already present
|
||||
template <class Container, class Iter>
|
||||
inline void push_back_range_unique(Container& container, Iter begin, Iter end)
|
||||
{
|
||||
for (Iter it = begin; it != end; ++it)
|
||||
{
|
||||
push_back_unique(container, *it);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find element in container.
|
||||
// @return true if item found.
|
||||
@@ -373,107 +234,6 @@ namespace stl
|
||||
return (it == last || value != *it) ? last : it;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find element in a sorted container using binary search with logarithmic efficiency.
|
||||
// @return true if item was inserted.
|
||||
template <class Container, class Value>
|
||||
inline bool binary_insert_unique(Container& container, const Value& value)
|
||||
{
|
||||
typename Container::iterator it = std::lower_bound(container.begin(), container.end(), value);
|
||||
if (it != container.end())
|
||||
{
|
||||
if (*it == value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
container.insert(it, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
container.insert(container.end(), value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Find element in a sorted container using binary search with logarithmic efficiency.
|
||||
// and erases if element found.
|
||||
// @return true if item was erased.
|
||||
template <class Container, class Value>
|
||||
inline bool binary_erase(Container& container, const Value& value)
|
||||
{
|
||||
typename Container::iterator it = std::lower_bound(container.begin(), container.end(), value);
|
||||
if (it != container.end() && *it == value)
|
||||
{
|
||||
container.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename ItT, typename Func>
|
||||
ItT remove_from_heap(ItT begin, ItT end, ItT at, Func order)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
--end;
|
||||
if (at == end)
|
||||
{
|
||||
return at;
|
||||
}
|
||||
|
||||
size_t idx = std::distance(begin, at);
|
||||
swap(*end, *at);
|
||||
|
||||
size_t length = std::distance(begin, end);
|
||||
size_t parent, child;
|
||||
|
||||
if (idx > 0 && order(*(begin + idx / 2), *(begin + idx)))
|
||||
{
|
||||
do
|
||||
{
|
||||
parent = idx / 2;
|
||||
swap(*(begin + idx), *(begin + parent));
|
||||
idx = parent;
|
||||
|
||||
if (idx == 0 || order(*(begin + idx), *(begin + idx / 2)))
|
||||
{
|
||||
return end;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
child = idx * 2 + 1;
|
||||
if (child >= length)
|
||||
{
|
||||
return end;
|
||||
}
|
||||
|
||||
ItT left = begin + child;
|
||||
ItT right = begin + child + 1;
|
||||
|
||||
if (right < end && order(*left, *right))
|
||||
{
|
||||
++child;
|
||||
}
|
||||
|
||||
if (order(*(begin + child), *(begin + idx)))
|
||||
{
|
||||
return end;
|
||||
}
|
||||
|
||||
swap(*(begin + child), *(begin + idx));
|
||||
idx = child;
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
struct container_object_deleter
|
||||
{
|
||||
template<typename T>
|
||||
@@ -506,18 +266,6 @@ namespace stl
|
||||
return type.c_str();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Case sensetive less key for any type convertable to const char*.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
template <class Type>
|
||||
struct less_strcmp
|
||||
{
|
||||
bool operator()(const Type& left, const Type& right) const
|
||||
{
|
||||
return strcmp(constchar_cast(left), constchar_cast(right)) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Case insensetive less key for any type convertable to const char*.
|
||||
template <class Type>
|
||||
@@ -690,89 +438,4 @@ namespace stl
|
||||
stl::free_container(container);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, size_t Length, typename Func>
|
||||
inline void for_each_array(T (&buffer)[Length], Func func)
|
||||
{
|
||||
std::for_each(&buffer[0], &buffer[Length], func);
|
||||
}
|
||||
|
||||
template <typename T, typename D, size_t Length, typename Func>
|
||||
inline void for_each_array(StaticInstance<T, D>(&buffer)[Length], Func func)
|
||||
{
|
||||
for (size_t idx = 0; idx < Length; ++idx)
|
||||
{
|
||||
func(*buffer[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void destruct(T* p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_INTRUSIVE_LINKED_LIST(Class) \
|
||||
template<> \
|
||||
Class * stl::intrusive_linked_list_node<Class>::m_root_intrusive = nullptr;
|
||||
|
||||
// define the maplikestruct, used to approximate the memory requirements for a map node
|
||||
namespace stl
|
||||
{
|
||||
struct MapLikeStruct
|
||||
{
|
||||
bool color;
|
||||
void* parent;
|
||||
void* left;
|
||||
void* right;
|
||||
};
|
||||
}
|
||||
template <class Map>
|
||||
unsigned sizeOfMap(Map& map)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (typename Map::iterator it = map.begin(); it != map.end(); it++)
|
||||
{
|
||||
typename Map::mapped_type& T = it->second;
|
||||
size += T.Size();
|
||||
}
|
||||
size += map.size() * sizeof(stl::MapLikeStruct);
|
||||
return size;
|
||||
}
|
||||
template <class Map>
|
||||
unsigned sizeOfMapStr(Map& map)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (typename Map::iterator it = map.begin(); it != map.end(); it++)
|
||||
{
|
||||
typename Map::mapped_type& T = it->second;
|
||||
size += T.capacity();
|
||||
}
|
||||
size += map.size() * sizeof(stl::MapLikeStruct);
|
||||
return size;
|
||||
}
|
||||
template <class Map>
|
||||
unsigned sizeOfMapP(Map& map)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (typename Map::iterator it = map.begin(); it != map.end(); it++)
|
||||
{
|
||||
typename Map::mapped_type& T = it->second;
|
||||
size += T->Size();
|
||||
}
|
||||
size += map.size() * sizeof(stl::MapLikeStruct);
|
||||
return size;
|
||||
}
|
||||
template <class Map>
|
||||
unsigned sizeOfMapS(Map& map)
|
||||
{
|
||||
unsigned size = 0;
|
||||
for (typename Map::iterator it = map.begin(); it != map.end(); it++)
|
||||
{
|
||||
typename Map::mapped_type& T = it->second;
|
||||
size += sizeof(T);
|
||||
}
|
||||
size += map.size() * sizeof(stl::MapLikeStruct);
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ void InitCRTHandlers() {}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// This is an entry to DLL initialization function that must be called for each loaded module
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
extern "C" AZ_DLL_EXPORT void ModuleInitISystem(ISystem* pSystem, [[maybe_unused]] const char* moduleName)
|
||||
void ModuleInitISystem(ISystem* pSystem, [[maybe_unused]] const char* moduleName)
|
||||
{
|
||||
if (gEnv) // Already registered.
|
||||
{
|
||||
@@ -96,7 +96,7 @@ extern "C" AZ_DLL_EXPORT void ModuleInitISystem(ISystem* pSystem, [[maybe_unused
|
||||
} // if pSystem
|
||||
}
|
||||
|
||||
extern "C" AZ_DLL_EXPORT void ModuleShutdownISystem([[maybe_unused]] ISystem* pSystem)
|
||||
void ModuleShutdownISystem([[maybe_unused]] ISystem* pSystem)
|
||||
{
|
||||
// Unregister with AZ environment.
|
||||
AZ::Environment::Detach();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include <CryAssert.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::Debug
|
||||
{
|
||||
AZ_CVAR_EXTERNED(int, bg_traceLogLevel);
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
if(!hasSetCVar && ready)
|
||||
{
|
||||
// AZ logging only has a concept of 3 levels (error, warning, info) but cry logging has 4 levels (..., messaging). If info level is set, we'll turn on messaging as well
|
||||
int logLevel = AZ::bg_traceLogLevel == AZ::Debug::LogLevel::Info ? 4 : AZ::bg_traceLogLevel;
|
||||
int logLevel = AZ::Debug::bg_traceLogLevel == AZ::Debug::LogLevel::Info ? 4 : AZ::Debug::bg_traceLogLevel;
|
||||
|
||||
gEnv->pConsole->GetCVar("log_WriteToFileVerbosity")->Set(logLevel);
|
||||
hasSetCVar = true;
|
||||
|
||||
@@ -60,13 +60,6 @@
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#if defined(WIN32) || defined(WIN64) || defined(APPLE) || defined(LINUX)
|
||||
#if defined(DEDICATED_SERVER)
|
||||
// enable/disable map load slicing functionality from the build
|
||||
#define MAP_LOADING_SLICING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
@@ -143,9 +143,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
#include <AzFramework/Input/Buses/Notifications/RawInputNotificationBus_Platform.h>
|
||||
|
||||
// To enable profiling with vtune (https://software.intel.com/en-us/intel-vtune-amplifier-xe), make sure the line below is not commented out
|
||||
//#define PROFILE_WITH_VTUNE
|
||||
|
||||
#include <process.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
@@ -154,10 +151,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
|
||||
// profilers api.
|
||||
VTuneFunction VTResume = NULL;
|
||||
VTuneFunction VTPause = NULL;
|
||||
|
||||
// Define global cvars.
|
||||
SSystemCVars g_cvars;
|
||||
|
||||
@@ -516,8 +509,6 @@ void CSystem::ShutDown()
|
||||
|
||||
ShutdownFileSystem();
|
||||
|
||||
ShutdownModuleLibraries();
|
||||
|
||||
EBUS_EVENT(CrySystemEventBus, OnCrySystemPostShutdown);
|
||||
}
|
||||
|
||||
@@ -697,31 +688,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
m_bPaused = false;
|
||||
}
|
||||
|
||||
#ifdef PROFILE_WITH_VTUNE
|
||||
if (m_bInDevMode)
|
||||
{
|
||||
if (VTPause != NULL && VTResume != NULL)
|
||||
{
|
||||
static bool bVtunePaused = true;
|
||||
|
||||
const AzFramework::InputChannel* inputChannelScrollLock = AzFramework::InputChannelRequests::FindInputChannel(AzFramework::InputDeviceKeyboard::Key::WindowsSystemScrollLock);
|
||||
const bool bPaused = (inputChannelScrollLock ? inputChannelScrollLock->IsActive() : false);
|
||||
|
||||
{
|
||||
if (bVtunePaused && !bPaused)
|
||||
{
|
||||
GetIProfilingSystem()->VTuneResume();
|
||||
}
|
||||
if (!bVtunePaused && bPaused)
|
||||
{
|
||||
GetIProfilingSystem()->VTunePause();
|
||||
}
|
||||
bVtunePaused = bPaused;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //PROFILE_WITH_VTUNE
|
||||
|
||||
#ifndef EXCLUDE_UPDATE_ON_CONSOLE
|
||||
if (m_bIgnoreUpdates)
|
||||
{
|
||||
@@ -1255,30 +1221,6 @@ CPNoise3* CSystem::GetNoiseGen()
|
||||
return &m_pNoiseGen;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CProfilingSystem::VTuneResume()
|
||||
{
|
||||
#ifdef PROFILE_WITH_VTUNE
|
||||
if (VTResume)
|
||||
{
|
||||
CryLogAlways("VTune Resume");
|
||||
VTResume();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CProfilingSystem::VTunePause()
|
||||
{
|
||||
#ifdef PROFILE_WITH_VTUNE
|
||||
if (VTPause)
|
||||
{
|
||||
VTPause();
|
||||
CryLogAlways("VTune Pause");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CSystem::OnLanguageCVarChanged(ICVar* language)
|
||||
{
|
||||
|
||||
@@ -105,10 +105,6 @@ struct IDataProbe;
|
||||
|
||||
#define PHSYICS_OBJECT_ENTITY 0
|
||||
|
||||
using VTuneFunction = void (__cdecl *)(void);
|
||||
extern VTuneFunction VTResume;
|
||||
extern VTuneFunction VTPause;
|
||||
|
||||
#define MAX_STREAMING_POOL_INDEX 6
|
||||
#define MAX_THREAD_POOL_INDEX 6
|
||||
|
||||
@@ -139,7 +135,6 @@ struct SSystemCVars
|
||||
int sys_ai;
|
||||
int sys_entitysystem;
|
||||
int sys_trackview;
|
||||
int sys_vtune;
|
||||
float sys_update_profile_time;
|
||||
int sys_limit_phys_thread_count;
|
||||
int sys_MaxFPS;
|
||||
@@ -169,21 +164,6 @@ extern SSystemCVars g_cvars;
|
||||
|
||||
class CSystem;
|
||||
|
||||
struct CProfilingSystem
|
||||
: public IProfilingSystem
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// VTune Profiling interface.
|
||||
|
||||
// Summary:
|
||||
// Resumes vtune data collection.
|
||||
void VTuneResume() override;
|
||||
// Summary:
|
||||
// Pauses vtune data collection.
|
||||
void VTunePause() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
|
||||
class AssetSystem;
|
||||
|
||||
/*
|
||||
@@ -262,7 +242,6 @@ public:
|
||||
IViewSystem* GetIViewSystem() override;
|
||||
ILevelSystem* GetILevelSystem() override;
|
||||
ISystemEventDispatcher* GetISystemEventDispatcher() override { return m_pSystemEventDispatcher; }
|
||||
IProfilingSystem* GetIProfilingSystem() override { return &m_ProfilingSystem; }
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// retrieves the perlin noise singleton instance
|
||||
CPNoise3* GetNoiseGen() override;
|
||||
@@ -324,8 +303,6 @@ public:
|
||||
void SetVersionInfo(const char* const szVersion);
|
||||
#endif
|
||||
|
||||
void ShutdownModuleLibraries();
|
||||
|
||||
#if defined(WIN32)
|
||||
friend LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
@@ -344,8 +321,6 @@ private:
|
||||
// Release all resources.
|
||||
void ShutDown();
|
||||
|
||||
bool LoadEngineDLLs();
|
||||
|
||||
//! @name Initialization routines
|
||||
//@{
|
||||
bool InitConsole();
|
||||
@@ -361,11 +336,8 @@ private:
|
||||
void CreateSystemVars();
|
||||
void CreateAudioVars();
|
||||
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> LoadDLL(const char* dllName);
|
||||
|
||||
void FreeLib(AZStd::unique_ptr<AZ::DynamicModuleHandle>& hLibModule);
|
||||
|
||||
bool UnloadDLL(const char* dllName);
|
||||
void QueryVersionInfo();
|
||||
void LogVersion();
|
||||
void LogBuildInfo();
|
||||
@@ -380,8 +352,6 @@ private:
|
||||
|
||||
void AddCVarGroupDirectory(const AZStd::string& sPath) override;
|
||||
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> LoadDynamiclibrary(const char* dllName) const;
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEM_H_SECTION_3
|
||||
#include AZ_RESTRICTED_FILE(System_h)
|
||||
@@ -437,9 +407,6 @@ private: // ------------------------------------------------------
|
||||
bool m_bDrawConsole; //!< Set to true if OK to draw the console.
|
||||
bool m_bDrawUI; //!< Set to true if OK to draw UI.
|
||||
|
||||
|
||||
std::map<AZ::Crc32, AZStd::unique_ptr<AZ::DynamicModuleHandle> > m_moduleDLLHandles;
|
||||
|
||||
//! current active process
|
||||
IProcess* m_pProcess;
|
||||
|
||||
@@ -564,8 +531,6 @@ private: // ------------------------------------------------------
|
||||
ESystemConfigSpec m_nMaxConfigSpec;
|
||||
ESystemConfigPlatform m_ConfigPlatform;
|
||||
|
||||
CProfilingSystem m_ProfilingSystem;
|
||||
|
||||
// Pause mode.
|
||||
bool m_bPaused;
|
||||
bool m_bNoUpdate;
|
||||
@@ -588,9 +553,7 @@ public:
|
||||
const SFileVersion& GetProductVersion() override;
|
||||
const SFileVersion& GetBuildVersion() override;
|
||||
|
||||
bool InitVTuneProfiler();
|
||||
|
||||
void OpenBasicPaks();
|
||||
void OpenPlatformPaks();
|
||||
void OpenLanguagePak(const char* sLanguage);
|
||||
void OpenLanguageAudioPak(const char* sLanguage);
|
||||
void GetLocalizedPath(const char* sLanguage, AZStd::string& sLocalizedPath);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM) || defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
|
||||
#undef AZ_RESTRICTED_SECTION
|
||||
#define SYSTEMINIT_CPP_SECTION_1 1
|
||||
#define SYSTEMINIT_CPP_SECTION_2 2
|
||||
#define SYSTEMINIT_CPP_SECTION_3 3
|
||||
#define SYSTEMINIT_CPP_SECTION_4 4
|
||||
@@ -70,9 +69,6 @@
|
||||
#include "windows.h"
|
||||
#include <float.h>
|
||||
|
||||
// To enable profiling with vtune (https://software.intel.com/en-us/intel-vtune-amplifier-xe), make sure the line below is not commented out
|
||||
//#define PROFILE_WITH_VTUNE
|
||||
|
||||
#endif //WIN32
|
||||
|
||||
#include <IRenderer.h>
|
||||
@@ -171,34 +167,6 @@ void CryEngineSignalHandler(int signal)
|
||||
|
||||
#define LOCALIZATION_TRANSLATIONS_LIST_FILE_NAME "Libs/Localization/localization.xml"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#if defined(WIN32) || defined(LINUX) || defined(APPLE)
|
||||
# define DLL_MODULE_INIT_ISYSTEM "ModuleInitISystem"
|
||||
# define DLL_MODULE_SHUTDOWN_ISYSTEM "ModuleShutdownISystem"
|
||||
# define DLL_INITFUNC_RENDERER "PackageRenderConstructor"
|
||||
# define DLL_INITFUNC_SOUND "CreateSoundSystem"
|
||||
# define DLL_INITFUNC_FONT "CreateCryFontInterface"
|
||||
# define DLL_INITFUNC_3DENGINE "CreateCry3DEngine"
|
||||
# define DLL_INITFUNC_UI "CreateLyShineInterface"
|
||||
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_1
|
||||
#include AZ_RESTRICTED_FILE(SystemInit_cpp)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
# define DLL_MODULE_INIT_ISYSTEM (LPCSTR)2
|
||||
# define DLL_MODULE_SHUTDOWN_ISYSTEM (LPCSTR)3
|
||||
# define DLL_INITFUNC_RENDERER (LPCSTR)1
|
||||
# define DLL_INITFUNC_RENDERER (LPCSTR)1
|
||||
# define DLL_INITFUNC_SOUND (LPCSTR)1
|
||||
# define DLL_INITFUNC_PHYSIC (LPCSTR)1
|
||||
# define DLL_INITFUNC_FONT (LPCSTR)1
|
||||
# define DLL_INITFUNC_3DENGINE (LPCSTR)1
|
||||
# define DLL_INITFUNC_UI (LPCSTR)1
|
||||
#endif
|
||||
|
||||
#define AZ_TRACE_SYSTEM_WINDOW AZ::Debug::Trace::GetDefaultSystemWindow()
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -292,96 +260,6 @@ static void CmdCrashTest(IConsoleCmdArgs* pArgs)
|
||||
}
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct SysSpecOverrideSink
|
||||
: public ILoadConfigurationEntrySink
|
||||
{
|
||||
virtual void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup)
|
||||
{
|
||||
ICVar* pCvar = gEnv->pConsole->GetCVar(szKey);
|
||||
|
||||
if (pCvar)
|
||||
{
|
||||
const bool wasNotInConfig = ((pCvar->GetFlags() & VF_WASINCONFIG) == 0);
|
||||
bool applyCvar = wasNotInConfig;
|
||||
if (applyCvar == false)
|
||||
{
|
||||
// Special handling for sys_spec_full
|
||||
if (azstricmp(szKey, "sys_spec_full") == 0)
|
||||
{
|
||||
// If it is set to 0 then ignore this request to set to something else
|
||||
// If it is set to 0 then the user wants to changes system spec settings in system.cfg
|
||||
if (pCvar->GetIVal() != 0)
|
||||
{
|
||||
applyCvar = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This could bypass the restricted cvar checks that exist elsewhere depending on
|
||||
// the calling code so we also need check here before setting.
|
||||
bool isConst = pCvar->IsConstCVar();
|
||||
bool isCheat = ((pCvar->GetFlags() & (VF_CHEAT | VF_CHEAT_NOCHECK | VF_CHEAT_ALWAYS_CHECK)) != 0);
|
||||
bool isReadOnly = ((pCvar->GetFlags() & VF_READONLY) != 0);
|
||||
bool isDeprecated = ((pCvar->GetFlags() & VF_DEPRECATED) != 0);
|
||||
bool allowApplyCvar = true;
|
||||
|
||||
if ((isConst || isCheat || isReadOnly) || isDeprecated)
|
||||
{
|
||||
allowApplyCvar = !isDeprecated && (gEnv->pSystem->IsDevMode()) || (gEnv->IsEditor());
|
||||
}
|
||||
|
||||
if ((allowApplyCvar) || ALLOW_CONST_CVAR_MODIFICATIONS)
|
||||
{
|
||||
applyCvar = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (applyCvar)
|
||||
{
|
||||
pCvar->Set(szValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
CryLogAlways("NOT VF_WASINCONFIG Ignoring cvar '%s' new value '%s' old value '%s' group '%s'", szKey, szValue, pCvar->GetString(), szGroup);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CryLogAlways("Can't find cvar '%s' value '%s' group '%s'", szKey, szValue, szGroup);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(CONSOLE)
|
||||
struct SysSpecOverrideSinkConsole
|
||||
: public ILoadConfigurationEntrySink
|
||||
{
|
||||
virtual void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup)
|
||||
{
|
||||
// Ignore platform-specific cvars that should just be executed on the console
|
||||
if (azstricmp(szGroup, "Platform") == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ICVar* pCvar = gEnv->pConsole->GetCVar(szKey);
|
||||
if (pCvar)
|
||||
{
|
||||
pCvar->Set(szValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the cvar doesn't exist, calling this function only saves the value in case it's registered later where
|
||||
// at that point it will be set from the stored value. This is required because otherwise registering the
|
||||
// cvar bypasses any callbacks and uses values directly from the cvar group files.
|
||||
gEnv->pConsole->LoadConfigVar(szKey, szValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static ESystemConfigPlatform GetDevicePlatform()
|
||||
{
|
||||
#if defined(AZ_PLATFORM_WINDOWS) || defined(AZ_PLATFORM_LINUX)
|
||||
@@ -405,117 +283,6 @@ static ESystemConfigPlatform GetDevicePlatform()
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#if !defined(AZ_MONOLITHIC_BUILD)
|
||||
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> CSystem::LoadDynamiclibrary(const char* dllName) const
|
||||
{
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> handle = AZ::DynamicModuleHandle::Create(dllName);
|
||||
|
||||
bool libraryLoaded = handle->Load(false);
|
||||
// We need to inject the environment first thing so that allocators are available immediately
|
||||
InjectEnvironmentFunction injectEnv = handle->GetFunction<InjectEnvironmentFunction>(INJECT_ENVIRONMENT_FUNCTION);
|
||||
if (injectEnv)
|
||||
{
|
||||
auto env = AZ::Environment::GetInstance();
|
||||
injectEnv(env);
|
||||
}
|
||||
|
||||
if (!libraryLoaded)
|
||||
{
|
||||
handle.release();
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> CSystem::LoadDLL(const char* dllName)
|
||||
{
|
||||
AZ_TracePrintf(AZ_TRACE_SYSTEM_WINDOW, "Loading DLL: %s", dllName);
|
||||
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> handle = LoadDynamiclibrary(dllName);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
#if defined(LINUX) || defined(APPLE)
|
||||
AZ_Assert(false, "Error loading dylib: %s, error : %s\n", dllName, dlerror());
|
||||
#else
|
||||
AZ_Assert(false, "Error loading dll: %s, error code %d", dllName, GetLastError());
|
||||
#endif
|
||||
return handle;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// After loading DLL initialize it by calling ModuleInitISystem
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZStd::string moduleName = PathUtil::GetFileName(dllName);
|
||||
|
||||
typedef void*(*PtrFunc_ModuleInitISystem)(ISystem* pSystem, const char* moduleName);
|
||||
PtrFunc_ModuleInitISystem pfnModuleInitISystem = handle->GetFunction<PtrFunc_ModuleInitISystem>(DLL_MODULE_INIT_ISYSTEM);
|
||||
if (pfnModuleInitISystem)
|
||||
{
|
||||
pfnModuleInitISystem(this, moduleName.c_str());
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// TODO:DLL #endif //#if defined(AZ_HAS_DLL_SUPPORT) && !defined(AZ_MONOLITHIC_BUILD)
|
||||
#endif //if !defined(AZ_MONOLITHIC_BUILD)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::LoadEngineDLLs()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::UnloadDLL(const char* dllName)
|
||||
{
|
||||
bool isSuccess = false;
|
||||
|
||||
AZ::Crc32 key(dllName);
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> empty;
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle>& hModule = stl::find_in_map_ref(m_moduleDLLHandles, key, empty);
|
||||
if ((hModule) && (hModule->IsLoaded()))
|
||||
{
|
||||
DetachEnvironmentFunction detachEnv = hModule->GetFunction<DetachEnvironmentFunction>(DETACH_ENVIRONMENT_FUNCTION);
|
||||
if (detachEnv)
|
||||
{
|
||||
detachEnv();
|
||||
}
|
||||
|
||||
isSuccess = hModule->Unload();
|
||||
hModule.release();
|
||||
}
|
||||
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::ShutdownModuleLibraries()
|
||||
{
|
||||
#if !defined(AZ_MONOLITHIC_BUILD)
|
||||
for (auto iterator = m_moduleDLLHandles.begin(); iterator != m_moduleDLLHandles.end(); ++iterator)
|
||||
{
|
||||
typedef void*( * PtrFunc_ModuleShutdownISystem )(ISystem* pSystem);
|
||||
|
||||
PtrFunc_ModuleShutdownISystem pfnModuleShutdownISystem = iterator->second->GetFunction<PtrFunc_ModuleShutdownISystem>(DLL_MODULE_SHUTDOWN_ISYSTEM);
|
||||
if (pfnModuleShutdownISystem)
|
||||
{
|
||||
pfnModuleShutdownISystem(this);
|
||||
}
|
||||
if (iterator->second->IsLoaded())
|
||||
{
|
||||
iterator->second->Unload();
|
||||
}
|
||||
iterator->second.release();
|
||||
}
|
||||
|
||||
m_moduleDLLHandles.clear();
|
||||
|
||||
#endif // !defined(AZ_MONOLITHIC_BUILD)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitConsole()
|
||||
@@ -649,7 +416,7 @@ bool CSystem::InitFileSystem_LoadEngineFolders(const SSystemInitParams&)
|
||||
auto projectName = AZ::Utils::GetProjectName();
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Project Name: %s\n", projectName.empty() ? "None specified" : projectName.c_str());
|
||||
|
||||
OpenBasicPaks();
|
||||
OpenPlatformPaks();
|
||||
|
||||
// Load game-specific folder.
|
||||
LoadConfiguration("game.cfg");
|
||||
@@ -704,33 +471,6 @@ bool CSystem::InitAudioSystem(const SSystemInitParams& initParams)
|
||||
return result;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitVTuneProfiler()
|
||||
{
|
||||
#ifdef PROFILE_WITH_VTUNE
|
||||
|
||||
WIN_HMODULE hModule = LoadDLL("VTuneApi.dll");
|
||||
if (!hModule)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
VTPause = (VTuneFunction) CryGetProcAddress(hModule, "VTPause");
|
||||
VTResume = (VTuneFunction) CryGetProcAddress(hModule, "VTResume");
|
||||
if (!VTPause || !VTResume)
|
||||
{
|
||||
AZ_Assert(false, "VTune did not initialize correctly.")
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf(AZ_TRACE_SYSTEM_WINDOW, "VTune API Initialized");
|
||||
}
|
||||
#endif //PROFILE_WITH_VTUNE
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::InitLocalization()
|
||||
{
|
||||
@@ -786,29 +526,19 @@ void CSystem::InitLocalization()
|
||||
OpenLanguageAudioPak(language.c_str());
|
||||
}
|
||||
|
||||
void CSystem::OpenBasicPaks()
|
||||
void CSystem::OpenPlatformPaks()
|
||||
{
|
||||
static bool bBasicPaksLoaded = false;
|
||||
if (bBasicPaksLoaded)
|
||||
static bool bPlatformPaksLoaded = false;
|
||||
if (bPlatformPaksLoaded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bBasicPaksLoaded = true;
|
||||
|
||||
// open pak files
|
||||
constexpr AZStd::string_view paksFolder = "@products@/*.pak"; // (@products@ assumed)
|
||||
m_env.pCryPak->OpenPacks(paksFolder);
|
||||
|
||||
InlineInitializationProcessing("CSystem::OpenBasicPaks OpenPacks( paksFolder.c_str() )");
|
||||
bPlatformPaksLoaded = true;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Open engine packs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char* const assetsDir = "@products@";
|
||||
|
||||
// After game paks to have same search order as with files on disk
|
||||
m_env.pCryPak->OpenPack(assetsDir, "engine.pak");
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_15
|
||||
@@ -816,6 +546,7 @@ void CSystem::OpenBasicPaks()
|
||||
#endif
|
||||
|
||||
#ifdef AZ_PLATFORM_ANDROID
|
||||
const char* const assetsDir = "@products@";
|
||||
// Load Android Obb files if available
|
||||
const char* obbStorage = AZ::Android::Utils::GetObbStoragePath();
|
||||
AZStd::string mainObbPath = AZStd::move(AZStd::string::format("%s/%s", obbStorage, AZ::Android::Utils::GetObbFileName(true)));
|
||||
@@ -824,7 +555,7 @@ void CSystem::OpenBasicPaks()
|
||||
m_env.pCryPak->OpenPack(assetsDir, patchObbPath.c_str());
|
||||
#endif //AZ_PLATFORM_ANDROID
|
||||
|
||||
InlineInitializationProcessing("CSystem::OpenBasicPaks OpenPacks( Engine... )");
|
||||
InlineInitializationProcessing("CSystem::OpenPlatformPaks OpenPacks( Engine... )");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1328,7 +1059,7 @@ AZ_POP_DISABLE_WARNING
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Open basic pak files after intro movie playback started
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
OpenBasicPaks();
|
||||
OpenPlatformPaks();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AUDIO
|
||||
@@ -1714,8 +1445,6 @@ void CSystem::CreateSystemVars()
|
||||
m_sys_memory_debug = REGISTER_INT("sys_memory_debug", 0, VF_CHEAT,
|
||||
"Enables to activate low memory situation is specific places in the code (argument defines which place), 0=off");
|
||||
|
||||
REGISTER_CVAR2("sys_vtune", &g_cvars.sys_vtune, 0, VF_NULL, "");
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_17
|
||||
#include AZ_RESTRICTED_FILE(SystemInit_cpp)
|
||||
|
||||
@@ -1067,12 +1067,15 @@ namespace AssetProcessor
|
||||
|
||||
if (dropAllTables)
|
||||
{
|
||||
AZ_TracePrintf("AssetDatabase", "Closing existing db connection\n"); // Temporary debug output to help with tracking down a crash
|
||||
// drop all tables by destroying the entire database.
|
||||
m_databaseConnection->Close();
|
||||
|
||||
AZ_TracePrintf("AssetDatabase", "Getting db file path\n"); // Temporary debug output to help with tracking down a crash
|
||||
AZStd::string dbFilePath = GetAssetDatabaseFilePath();
|
||||
if (dbFilePath != ":memory:")
|
||||
{
|
||||
AZ_TracePrintf("AssetDatabase", "Deleting existing db %s\n", dbFilePath.c_str()); // Temporary debug output to help with tracking down a crash
|
||||
// you cannot delete a memory database, but it drops all data when you close it anyway.
|
||||
if (!AZ::IO::SystemFile::Delete(dbFilePath.c_str()))
|
||||
{
|
||||
@@ -1082,7 +1085,7 @@ namespace AssetProcessor
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_TracePrintf("AssetDatabase", "Re-opening connection\n"); // Temporary debug output to help with tracking down a crash
|
||||
if (!m_databaseConnection->Open(dbFilePath, IsReadOnly()))
|
||||
{
|
||||
delete m_databaseConnection;
|
||||
|
||||
@@ -4027,30 +4027,43 @@ namespace AssetProcessor
|
||||
// It is generally called when a source file modified in any way, including when it is added or deleted.
|
||||
// note that this is a "reverse" dependency query - it looks up what depends on a file, not what the file depends on
|
||||
using namespace AzToolsFramework::AssetDatabase;
|
||||
QStringList absoluteSourceFilePathQueue;
|
||||
QSet<QString> absoluteSourceFilePathQueue;
|
||||
QString databasePath;
|
||||
QString scanFolder;
|
||||
|
||||
auto callbackFunction = [&](AzToolsFramework::AssetDatabase::SourceFileDependencyEntry& entry)
|
||||
auto callbackFunction = [this, &absoluteSourceFilePathQueue](SourceFileDependencyEntry& entry)
|
||||
{
|
||||
QString relativeDatabaseName = QString::fromUtf8(entry.m_source.c_str());
|
||||
QString absolutePath = m_platformConfig->FindFirstMatchingFile(relativeDatabaseName);
|
||||
if (!absolutePath.isEmpty())
|
||||
{
|
||||
absoluteSourceFilePathQueue.push_back(absolutePath);
|
||||
absoluteSourceFilePathQueue.insert(absolutePath);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
auto callbackFunctionAbsoluteCheck = [&callbackFunction](SourceFileDependencyEntry& entry)
|
||||
{
|
||||
if (AZ::IO::PathView(entry.m_dependsOnSource.c_str()).IsAbsolute())
|
||||
{
|
||||
return callbackFunction(entry);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// convert to a database path so that the standard function can be called.
|
||||
|
||||
if (m_platformConfig->ConvertToRelativePath(sourcePath, databasePath, scanFolder))
|
||||
{
|
||||
m_stateData->QuerySourceDependencyByDependsOnSource(databasePath.toUtf8().constData(), nullptr, SourceFileDependencyEntry::DEP_Any, callbackFunction);
|
||||
|
||||
}
|
||||
|
||||
return absoluteSourceFilePathQueue;
|
||||
// We'll also check with the absolute path, because we support absolute path dependencies
|
||||
m_stateData->QuerySourceDependencyByDependsOnSource(
|
||||
sourcePath.toUtf8().constData(), nullptr, SourceFileDependencyEntry::DEP_Any, callbackFunctionAbsoluteCheck);
|
||||
|
||||
return absoluteSourceFilePathQueue.values();
|
||||
}
|
||||
|
||||
void AssetProcessorManager::AddSourceToDatabase(AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceDatabaseEntry, const ScanFolderInfo* scanFolder, QString relativeSourceFilePath)
|
||||
|
||||
@@ -159,6 +159,7 @@ namespace AssetProcessor
|
||||
builderDesc.m_busId = m_builderId;
|
||||
builderDesc.m_createJobFunction = AZStd::bind(&SettingsRegistryBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
||||
builderDesc.m_processJobFunction = AZStd::bind(&SettingsRegistryBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
||||
builderDesc.m_version = 1;
|
||||
|
||||
AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDesc);
|
||||
|
||||
@@ -301,7 +302,6 @@ namespace AssetProcessor
|
||||
if (!platformCodes.empty())
|
||||
{
|
||||
AZStd::string_view platform = platformCodes.front();
|
||||
constexpr AZ::u32 productSubID = 0;
|
||||
for (size_t i = 0; i < AZStd::size(specializations); ++i)
|
||||
{
|
||||
const AZ::SettingsRegistryInterface::Specializations& specialization = specializations[i];
|
||||
@@ -413,7 +413,8 @@ namespace AssetProcessor
|
||||
return;
|
||||
}
|
||||
|
||||
outputPath += specialization.GetSpecialization(0); // Append configuration
|
||||
AZStd::string_view specializationString(specialization.GetSpecialization(0));
|
||||
outputPath += specializationString; // Append configuration
|
||||
outputPath += ".setreg";
|
||||
|
||||
AZ::IO::SystemFile file;
|
||||
@@ -430,7 +431,10 @@ namespace AssetProcessor
|
||||
}
|
||||
file.Close();
|
||||
|
||||
response.m_outputProducts.emplace_back(outputPath, m_assetType, productSubID + aznumeric_cast<AZ::u32>(i));
|
||||
AZ::u32 hashedSpecialization = static_cast<AZ::u32>(AZStd::hash<AZStd::string_view>{}(specializationString));
|
||||
AZ_Assert(hashedSpecialization != 0, "Product ID generation failed for specialization %.*s. This can result in a product ID collision with other builders for this asset.",
|
||||
AZ_STRING_ARG(specializationString));
|
||||
response.m_outputProducts.emplace_back(outputPath, m_assetType, hashedSpecialization);
|
||||
response.m_outputProducts.back().m_dependenciesHandled = true;
|
||||
|
||||
outputPath.erase(extensionOffset);
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace AssetProcessor
|
||||
: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
UnitTestUtils::AssertAbsorber* m_errorAbsorber;
|
||||
AZStd::unique_ptr<UnitTestUtils::AssertAbsorber> m_errorAbsorber{};
|
||||
FileStatePassthrough m_fileStateCache;
|
||||
|
||||
void SetUp() override
|
||||
@@ -40,7 +40,7 @@ namespace AssetProcessor
|
||||
m_ownsSysAllocator = true;
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
|
||||
}
|
||||
m_errorAbsorber = new UnitTestUtils::AssertAbsorber();
|
||||
m_errorAbsorber = AZStd::make_unique<UnitTestUtils::AssertAbsorber>();
|
||||
|
||||
m_application = AZStd::make_unique<AzFramework::Application>();
|
||||
|
||||
@@ -60,8 +60,8 @@ namespace AssetProcessor
|
||||
AssetUtilities::ResetAssetRoot();
|
||||
|
||||
m_application.reset();
|
||||
delete m_errorAbsorber;
|
||||
m_errorAbsorber = nullptr;
|
||||
m_errorAbsorber.reset();
|
||||
|
||||
if (m_ownsSysAllocator)
|
||||
{
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
|
||||
|
||||
+138
-41
@@ -241,8 +241,10 @@ void AssetProcessorManagerTest::SetUp()
|
||||
ASSERT_TRUE(m_mockApplicationManager->RegisterAssetRecognizerAsBuilder(rec));
|
||||
m_mockApplicationManager->BusConnect();
|
||||
|
||||
AZ_Printf("UnitTest", "Allocating APM\n")
|
||||
m_assetProcessorManager.reset(new AssetProcessorManager_Test(m_config.get()));
|
||||
m_assertAbsorber.Clear();
|
||||
AZ_Printf("UnitTest", "APM ready\n");
|
||||
m_errorAbsorber->Clear();
|
||||
|
||||
m_isIdling = false;
|
||||
|
||||
@@ -333,9 +335,9 @@ TEST_F(AssetProcessorManagerTest, UnitTestForGettingJobInfoBySourceUUIDSuccess)
|
||||
EXPECT_STRCASEEQ(relFileName.toUtf8().data(), response.m_jobList[0].m_sourceFile.c_str());
|
||||
EXPECT_STRCASEEQ(tempPath.filePath("subfolder1").toUtf8().data(), response.m_jobList[0].m_watchFolder.c_str());
|
||||
|
||||
ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 0);
|
||||
ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0);
|
||||
ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
|
||||
}
|
||||
|
||||
TEST_F(AssetProcessorManagerTest, WarningsAndErrorsReported_SuccessfullySavedToDatabase)
|
||||
@@ -387,9 +389,9 @@ TEST_F(AssetProcessorManagerTest, WarningsAndErrorsReported_SuccessfullySavedToD
|
||||
ASSERT_EQ(response.m_jobList[0].m_warningCount, 11);
|
||||
ASSERT_EQ(response.m_jobList[0].m_errorCount, 22);
|
||||
|
||||
ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 0);
|
||||
ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0);
|
||||
ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1311,8 +1313,8 @@ void PathDependencyTest::SetUp()
|
||||
|
||||
void PathDependencyTest::TearDown()
|
||||
{
|
||||
ASSERT_EQ(m_assertAbsorber.m_numAssertsAbsorbed, 0);
|
||||
ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numAssertsAbsorbed, 0);
|
||||
ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 0);
|
||||
|
||||
AssetProcessorManagerTest::TearDown();
|
||||
}
|
||||
@@ -1616,7 +1618,7 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_SelfReferrentialProductDependency
|
||||
mainFile.m_products.push_back(productAssetId);
|
||||
|
||||
// tell the APM that the asset has been processed and allow it to bubble through its event queue:
|
||||
m_assertAbsorber.Clear();
|
||||
m_errorAbsorber->Clear();
|
||||
m_assetProcessorManager->AssetProcessed(jobDetails.m_jobEntry, processJobResponse);
|
||||
ASSERT_TRUE(BlockUntilIdle(5000));
|
||||
|
||||
@@ -1626,8 +1628,8 @@ TEST_F(PathDependencyTest, AssetProcessed_Impl_SelfReferrentialProductDependency
|
||||
ASSERT_TRUE(dependencyContainer.empty());
|
||||
|
||||
// We are testing 2 different dependencies, so we should get 2 warnings
|
||||
ASSERT_EQ(m_assertAbsorber.m_numWarningsAbsorbed, 2);
|
||||
m_assertAbsorber.Clear();
|
||||
ASSERT_EQ(m_errorAbsorber->m_numWarningsAbsorbed, 2);
|
||||
m_errorAbsorber->Clear();
|
||||
}
|
||||
|
||||
// This test shows the process of deferring resolution of a path dependency works.
|
||||
@@ -1944,8 +1946,8 @@ TEST_F(PathDependencyTest, WildcardDependencies_ExcludePathsExisting_ResolveCorr
|
||||
);
|
||||
|
||||
// Test asset PrimaryFile1 has 4 conflict dependencies
|
||||
ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 4);
|
||||
m_assertAbsorber.Clear();
|
||||
ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 4);
|
||||
m_errorAbsorber->Clear();
|
||||
}
|
||||
|
||||
TEST_F(PathDependencyTest, WildcardDependencies_Deferred_ResolveCorrectly)
|
||||
@@ -2092,8 +2094,8 @@ TEST_F(PathDependencyTest, WildcardDependencies_ExcludedPathDeferred_ResolveCorr
|
||||
// Test asset PrimaryFile1 has 4 conflict dependencies
|
||||
// After test assets dep2 and dep3 are processed,
|
||||
// another 2 errors will be raised because of the confliction
|
||||
ASSERT_EQ(m_assertAbsorber.m_numErrorsAbsorbed, 6);
|
||||
m_assertAbsorber.Clear();
|
||||
ASSERT_EQ(m_errorAbsorber->m_numErrorsAbsorbed, 6);
|
||||
m_errorAbsorber->Clear();
|
||||
}
|
||||
|
||||
void PathDependencyTest::RunWildcardTest(bool useCorrectDatabaseSeparator, AssetBuilderSDK::ProductPathDependencyType pathDependencyType, bool buildDependenciesFirst)
|
||||
@@ -4138,11 +4140,19 @@ struct LockedFileTest
|
||||
switch (message.GetMessageType())
|
||||
{
|
||||
case SourceFileNotificationMessage::MessageType:
|
||||
if (const auto sourceFileMessage = azrtti_cast<const SourceFileNotificationMessage*>(&message);
|
||||
sourceFileMessage != nullptr && sourceFileMessage->m_type == SourceFileNotificationMessage::NotificationType::FileRemoved
|
||||
&& m_callback)
|
||||
if (const auto sourceFileMessage = azrtti_cast<const SourceFileNotificationMessage*>(&message); sourceFileMessage != nullptr &&
|
||||
sourceFileMessage->m_type == SourceFileNotificationMessage::NotificationType::FileRemoved)
|
||||
{
|
||||
m_callback();
|
||||
// The File Remove message will occur before an attempt to delete the file
|
||||
// Wait for more than 1 File Remove message.
|
||||
// This indicates the AP has attempted to delete the file once, failed to do so and is now retrying
|
||||
++m_deleteCounter;
|
||||
|
||||
if(m_deleteCounter > 1 && m_callback)
|
||||
{
|
||||
m_callback();
|
||||
m_callback = {}; // Unset it to be safe, we only intend to run the callback once
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -4166,6 +4176,7 @@ struct LockedFileTest
|
||||
ModtimeScanningTest::TearDown();
|
||||
}
|
||||
|
||||
AZStd::atomic_int m_deleteCounter{ 0 };
|
||||
AZStd::function<void()> m_callback;
|
||||
};
|
||||
|
||||
@@ -4205,6 +4216,10 @@ TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeleteFails)
|
||||
|
||||
TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeletesWhenReleased)
|
||||
{
|
||||
// This test is intended to verify the AP will successfully retry deleting a source asset
|
||||
// when one of its product assets is locked temporarily
|
||||
// We'll lock the file by holding it open
|
||||
|
||||
auto theFile = m_data->m_absolutePath[1].toUtf8();
|
||||
const char* theFileString = theFile.constData();
|
||||
auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString);
|
||||
@@ -4217,19 +4232,22 @@ TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeletesWhenReleased)
|
||||
ASSERT_GT(m_data->m_productPaths.size(), 0);
|
||||
QFile product(productPath);
|
||||
|
||||
// Open the file and keep it open to lock it
|
||||
// We'll start a thread later to unlock the file
|
||||
// This will allow us to test how AP handles trying to delete a locked file
|
||||
ASSERT_TRUE(product.open(QIODevice::ReadOnly));
|
||||
|
||||
// Check if we can delete the file now, if we can't, proceed with the test
|
||||
// If we can, it means the OS running this test doesn't lock open files so there's nothing to test
|
||||
if (!AZ::IO::SystemFile::Delete(productPath.toUtf8().constData()))
|
||||
{
|
||||
AZStd::thread workerThread;
|
||||
m_deleteCounter = 0;
|
||||
|
||||
m_callback = [&product, &workerThread]() {
|
||||
workerThread = AZStd::thread([&product]() {
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(60));
|
||||
product.close();
|
||||
});
|
||||
// Set up a callback which will fire after at least 1 retry
|
||||
// Unlock the file at that point so AP can successfully delete it
|
||||
m_callback = [&product]()
|
||||
{
|
||||
product.close();
|
||||
};
|
||||
|
||||
QMetaObject::invokeMethod(
|
||||
@@ -4239,8 +4257,9 @@ TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeletesWhenReleased)
|
||||
|
||||
EXPECT_FALSE(QFile::exists(productPath));
|
||||
EXPECT_EQ(m_data->m_deletedSources.size(), 1);
|
||||
|
||||
workerThread.join();
|
||||
|
||||
EXPECT_GT(m_deleteCounter, 1); // Make sure the AP tried more than once to delete the file
|
||||
m_errorAbsorber->ExpectAsserts(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4447,9 +4466,9 @@ AssetBuilderSDK::AssetBuilderDesc MockBuilderInfoHandler::CreateBuilderDesc(cons
|
||||
|
||||
void FingerprintTest::SetUp()
|
||||
{
|
||||
AZ_Printf("FingerprintTest", "SetUp start");
|
||||
AZ_Printf("FingerprintTest", "SetUp start\n");
|
||||
AssetProcessorManagerTest::SetUp();
|
||||
AZ_Printf("FingerprintTest", "SetUp self");
|
||||
AZ_Printf("FingerprintTest", "SetUp self\n");
|
||||
|
||||
// We don't want the mock application manager to provide builder descriptors, mockBuilderInfoHandler will provide our own
|
||||
m_mockApplicationManager->BusDisconnect();
|
||||
@@ -4468,23 +4487,23 @@ void FingerprintTest::SetUp()
|
||||
});
|
||||
|
||||
ASSERT_TRUE(UnitTestUtils::CreateDummyFile(m_absolutePath, ""));
|
||||
AZ_Printf("FingerprintTest", "SetUp end");
|
||||
AZ_Printf("FingerprintTest", "SetUp end\n");
|
||||
}
|
||||
|
||||
void FingerprintTest::TearDown()
|
||||
{
|
||||
AZ_Printf("FingerprintTest", "TearDown start");
|
||||
AZ_Printf("FingerprintTest", "TearDown start\n");
|
||||
m_jobResults = AZStd::vector<AssetProcessor::JobDetails>{};
|
||||
m_mockBuilderInfoHandler = {};
|
||||
|
||||
AZ_Printf("FingerprintTest", "TearDown parent");
|
||||
AZ_Printf("FingerprintTest", "TearDown parent\n");
|
||||
AssetProcessorManagerTest::TearDown();
|
||||
AZ_Printf("FingerprintTest", "TearDown end");
|
||||
AZ_Printf("FingerprintTest", "TearDown end\n");
|
||||
}
|
||||
|
||||
void FingerprintTest::RunFingerprintTest(QString builderFingerprint, QString jobFingerprint, bool expectedResult)
|
||||
{
|
||||
AZ_Printf("FingerprintTest", "Fingerprint Test Start");
|
||||
AZ_Printf("FingerprintTest", "Fingerprint Test Start\n");
|
||||
m_mockBuilderInfoHandler.m_builderDesc.m_analysisFingerprint = builderFingerprint.toUtf8().data();
|
||||
m_mockBuilderInfoHandler.m_jobFingerprint = jobFingerprint;
|
||||
QMetaObject::invokeMethod(m_assetProcessorManager.get(), "AssessModifiedFile", Qt::QueuedConnection, Q_ARG(QString, m_absolutePath));
|
||||
@@ -4493,7 +4512,7 @@ void FingerprintTest::RunFingerprintTest(QString builderFingerprint, QString job
|
||||
ASSERT_EQ(m_mockBuilderInfoHandler.m_createJobsCount, 1);
|
||||
ASSERT_EQ(m_jobResults.size(), 1);
|
||||
ASSERT_EQ(m_jobResults[0].m_autoFail, expectedResult);
|
||||
AZ_Printf("FingerprintTest", "Fingerprint Test End");
|
||||
AZ_Printf("FingerprintTest", "Fingerprint Test End\n");
|
||||
}
|
||||
|
||||
TEST_F(FingerprintTest, FingerprintChecking_JobFingerprint_NoBuilderFingerprint)
|
||||
@@ -5318,6 +5337,18 @@ TEST_F(MetadataFileTest, MetadataFile_SourceFileExtensionDifferentCase)
|
||||
ASSERT_EQ(jobDetails.m_jobEntry.m_pathRelativeToWatchFolder, relFileName);
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> QStringListToVector(const QStringList& qstringList)
|
||||
{
|
||||
AZStd::vector<AZStd::string> azVector;
|
||||
// Convert to a vector of AZStd::strings because GTest handles this type better when displaying errors
|
||||
for (const QString& resolvedPath : qstringList)
|
||||
{
|
||||
azVector.emplace_back(resolvedPath.toUtf8().constData());
|
||||
}
|
||||
|
||||
return azVector;
|
||||
}
|
||||
|
||||
bool WildcardSourceDependencyTest::Test(
|
||||
const AZStd::string& dependencyPath, AZStd::vector<AZStd::string>& resolvedPaths)
|
||||
{
|
||||
@@ -5326,15 +5357,18 @@ bool WildcardSourceDependencyTest::Test(
|
||||
AssetBuilderSDK::SourceFileDependency dependency(dependencyPath, AZ::Uuid::CreateNull(), AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards);
|
||||
bool result = m_assetProcessorManager->ResolveSourceFileDependencyPath(dependency, resolvedName, stringlistPaths);
|
||||
|
||||
// Convert to a vector of AZStd::strings because GTest handles this type better when displaying errors
|
||||
for (const QString& resolvedPath : stringlistPaths)
|
||||
{
|
||||
resolvedPaths.emplace_back(resolvedPath.toUtf8().constData());
|
||||
}
|
||||
resolvedPaths = QStringListToVector(stringlistPaths);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> WildcardSourceDependencyTest::FileAddedTest(const QString& path)
|
||||
{
|
||||
auto result = m_assetProcessorManager->GetSourceFilesWhichDependOnSourceFile(path);
|
||||
|
||||
return QStringListToVector(result);
|
||||
}
|
||||
|
||||
void WildcardSourceDependencyTest::SetUp()
|
||||
{
|
||||
AssetProcessorManagerTest::SetUp();
|
||||
@@ -5357,6 +5391,42 @@ void WildcardSourceDependencyTest::SetUp()
|
||||
|
||||
// Add a file in the non-recursive scanfolder. Since its not directly in the scan folder, it should always be ignored
|
||||
UnitTestUtils::CreateDummyFile(tempPath.absoluteFilePath("no_recurse/one/two/three/f.foo"));
|
||||
|
||||
AzToolsFramework::AssetDatabase::SourceFileDependencyEntryContainer dependencies;
|
||||
|
||||
// Relative path wildcard dependency
|
||||
dependencies.push_back(AzToolsFramework::AssetDatabase::SourceFileDependencyEntry(
|
||||
AZ::Uuid::CreateRandom(), "a.foo", "%a.foo",
|
||||
AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_SourceLikeMatch, 0));
|
||||
|
||||
// Absolute path wildcard dependency
|
||||
dependencies.push_back(AzToolsFramework::AssetDatabase::SourceFileDependencyEntry(
|
||||
AZ::Uuid::CreateRandom(), "b.foo", tempPath.absoluteFilePath("%b.foo").toUtf8().constData(),
|
||||
AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_SourceLikeMatch, 0));
|
||||
|
||||
// Test what happens when we have 2 dependencies on the same file
|
||||
dependencies.push_back(AzToolsFramework::AssetDatabase::SourceFileDependencyEntry(
|
||||
AZ::Uuid::CreateRandom(), "folder/one/d.foo", "%c.foo",
|
||||
AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_SourceLikeMatch, 0));
|
||||
|
||||
dependencies.push_back(AzToolsFramework::AssetDatabase::SourceFileDependencyEntry(
|
||||
AZ::Uuid::CreateRandom(), "folder/one/d.foo", tempPath.absoluteFilePath("%c.foo").toUtf8().constData(),
|
||||
AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_SourceLikeMatch, 0));
|
||||
|
||||
#ifdef AZ_PLATFORM_WINDOWS
|
||||
// Test to make sure a relative wildcard dependency doesn't match an absolute path
|
||||
// For example, if the input is C:/project/subfolder1/a.foo
|
||||
// This should not match a wildcard of c%.foo
|
||||
// Take the first character of the tempPath and append %.foo onto it for this test, which should produce something like c%.foo
|
||||
// This only applies to windows because on other OSes if the dependency starts with /, then its an abs path dependency
|
||||
auto test = (tempPath.absolutePath().left(1) + "%.foo");
|
||||
dependencies.push_back(AzToolsFramework::AssetDatabase::SourceFileDependencyEntry(
|
||||
AZ::Uuid::CreateRandom(), "folder/one/d.foo",
|
||||
(test).toUtf8().constData(),
|
||||
AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_SourceLikeMatch, 0));
|
||||
#endif
|
||||
|
||||
ASSERT_TRUE(m_assetProcessorManager->m_stateData->SetSourceFileDependencies(dependencies));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, Relative_Broad)
|
||||
@@ -5455,3 +5525,30 @@ TEST_F(WildcardSourceDependencyTest, Absolute_NoWildcard)
|
||||
ASSERT_FALSE(Test(tempPath.absoluteFilePath("subfolder1/1a.foo").toUtf8().constData(), resolvedPaths));
|
||||
ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre());
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, NewFile_MatchesSavedRelativeDependency)
|
||||
{
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto matches = FileAddedTest(tempPath.absoluteFilePath("subfolder1/1a.foo"));
|
||||
|
||||
ASSERT_THAT(matches, ::testing::UnorderedElementsAre(tempPath.absoluteFilePath("subfolder2/redirected/a.foo").toUtf8().constData()));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, NewFile_MatchesSavedAbsoluteDependency)
|
||||
{
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto matches = FileAddedTest(tempPath.absoluteFilePath("subfolder1/1b.foo"));
|
||||
|
||||
ASSERT_THAT(matches, ::testing::UnorderedElementsAre(tempPath.absoluteFilePath("subfolder2/redirected/b.foo").toUtf8().constData()));
|
||||
}
|
||||
|
||||
TEST_F(WildcardSourceDependencyTest, NewFile_MatchesDuplicatedDependenciesOnce)
|
||||
{
|
||||
QDir tempPath(m_tempDir.path());
|
||||
|
||||
auto matches = FileAddedTest(tempPath.absoluteFilePath("subfolder2/redirected/folder/one/c.foo"));
|
||||
|
||||
ASSERT_THAT(matches, ::testing::UnorderedElementsAre(tempPath.absoluteFilePath("subfolder2/redirected/folder/one/d.foo").toUtf8().constData()));
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ protected:
|
||||
AZStd::unique_ptr<AssetProcessorManager_Test> m_assetProcessorManager;
|
||||
AZStd::unique_ptr<AssetProcessor::MockApplicationManager> m_mockApplicationManager;
|
||||
AZStd::unique_ptr<AssetProcessor::PlatformConfiguration> m_config;
|
||||
UnitTestUtils::AssertAbsorber m_assertAbsorber; // absorb asserts/warnings/errors so that the unit test output is not cluttered
|
||||
QString m_gameName;
|
||||
QDir m_normalizedCacheRootDir;
|
||||
AZStd::atomic_bool m_isIdling;
|
||||
@@ -135,6 +134,7 @@ struct WildcardSourceDependencyTest
|
||||
: AssetProcessorManagerTest
|
||||
{
|
||||
bool Test(const AZStd::string& dependencyPath, AZStd::vector<AZStd::string>& resolvedPaths);
|
||||
AZStd::vector<AZStd::string> FileAddedTest(const QString& path);
|
||||
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
@@ -49,6 +49,12 @@ int main(int argc, char* argv[])
|
||||
AZStd::unique_ptr<AzFramework::ProcessWatcher> shellProcess(AzFramework::ProcessWatcher::LaunchProcess(shellProcessLaunch, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE));
|
||||
shellProcess->WaitForProcessToExit(120);
|
||||
shellProcess.reset();
|
||||
|
||||
parameters = AZStd::string::format("-c \"%s/scripts/o3de.sh register --this-engine\"", enginePath.c_str());
|
||||
shellProcessLaunch.m_commandlineParameters = parameters;
|
||||
shellProcess.reset(AzFramework::ProcessWatcher::LaunchProcess(shellProcessLaunch, AzFramework::ProcessCommunicationType::COMMUNICATOR_TYPE_NONE));
|
||||
shellProcess->WaitForProcessToExit(120);
|
||||
shellProcess.reset();
|
||||
|
||||
AZ::IO::FixedMaxPath projectManagerPath = installedBinariesFolder/"o3de.app"/"Contents"/"MacOS"/"o3de";
|
||||
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
|
||||
@@ -35,3 +35,5 @@ ly_add_target(
|
||||
AZ::AzCore
|
||||
AZ::GridMate
|
||||
)
|
||||
|
||||
ly_add_dependencies(LuaIDE GridHub)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <QProcessEnvironment>
|
||||
#include <QDir>
|
||||
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
namespace ProjectUtils
|
||||
@@ -94,5 +96,10 @@ namespace O3DE::ProjectManager
|
||||
QProcessEnvironment::systemEnvironment(),
|
||||
QObject::tr("Running get_python script..."));
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath GetEditorDirectory()
|
||||
{
|
||||
return AZ::Utils::GetExecutableDirectory();
|
||||
}
|
||||
} // namespace ProjectUtils
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
namespace ProjectUtils
|
||||
@@ -104,5 +107,35 @@ namespace O3DE::ProjectManager
|
||||
QProcessEnvironment::systemEnvironment(),
|
||||
QObject::tr("Running get_python script..."));
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath GetEditorDirectory()
|
||||
{
|
||||
AZ::IO::FixedMaxPath executableDirectory = AZ::Utils::GetExecutableDirectory();
|
||||
AZ::IO::FixedMaxPath editorPath{ executableDirectory };
|
||||
editorPath /= "../../../Editor.app/Contents/MacOS";
|
||||
editorPath = editorPath.LexicallyNormal();
|
||||
if (!AZ::IO::SystemFile::IsDirectory(editorPath.c_str()))
|
||||
{
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
{
|
||||
if (AZ::IO::FixedMaxPath installedBinariesPath;
|
||||
settingsRegistry->Get(installedBinariesPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_InstalledBinaryFolder))
|
||||
{
|
||||
if (AZ::IO::FixedMaxPath engineRootFolder;
|
||||
settingsRegistry->Get(engineRootFolder.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
|
||||
{
|
||||
editorPath = engineRootFolder / installedBinariesPath / "Editor.app/Contents/MacOS";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!AZ::IO::SystemFile::IsDirectory(editorPath.c_str()))
|
||||
{
|
||||
AZ_Error("ProjectManager", false, "Unable to find the Editor app bundle!");
|
||||
}
|
||||
}
|
||||
|
||||
return editorPath;
|
||||
}
|
||||
} // namespace ProjectUtils
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <QProcess>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
namespace ProjectUtils
|
||||
@@ -139,5 +141,10 @@ namespace O3DE::ProjectManager
|
||||
QProcessEnvironment::systemEnvironment(),
|
||||
QObject::tr("Running get_python script..."));
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath GetEditorDirectory()
|
||||
{
|
||||
return AZ::Utils::GetExecutableDirectory();
|
||||
}
|
||||
} // namespace ProjectUtils
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user