Merge remote-tracking branch 'upstream/development' into nvsickle/OutlinerDuplicateEntryFixes
This commit is contained in:
@@ -173,6 +173,7 @@ namespace AZ
|
||||
|
||||
if (assetTracker)
|
||||
{
|
||||
assetTracker->FixUpAsset(*instance);
|
||||
assetTracker->AddAsset(*instance);
|
||||
}
|
||||
|
||||
@@ -185,7 +186,20 @@ namespace AZ
|
||||
return context.Report(result, message);
|
||||
}
|
||||
|
||||
void SerializedAssetTracker::AddAsset(Asset<AssetData>& asset)
|
||||
void SerializedAssetTracker::SetAssetFixUp(AssetFixUp assetFixUpCallback)
|
||||
{
|
||||
m_assetFixUpCallback = AZStd::move(assetFixUpCallback);
|
||||
}
|
||||
|
||||
void SerializedAssetTracker::FixUpAsset(Asset<AssetData>& asset)
|
||||
{
|
||||
if (m_assetFixUpCallback)
|
||||
{
|
||||
m_assetFixUpCallback(asset);
|
||||
}
|
||||
}
|
||||
|
||||
void SerializedAssetTracker::AddAsset(Asset<AssetData> asset)
|
||||
{
|
||||
m_serializedAssets.emplace_back(asset);
|
||||
}
|
||||
@@ -199,5 +213,6 @@ namespace AZ
|
||||
{
|
||||
return m_serializedAssets;
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
} // namespace AZ
|
||||
|
||||
@@ -39,13 +39,18 @@ namespace AZ
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(SerializedAssetTracker, "{1E067091-8C0A-44B1-A455-6E97663F6963}");
|
||||
using AssetFixUp = AZStd::function<void(Asset<AssetData>& asset)>;
|
||||
|
||||
void AddAsset(Asset<AssetData>& asset);
|
||||
void SetAssetFixUp(AssetFixUp assetFixUpCallback);
|
||||
void FixUpAsset(Asset<AssetData>& asset);
|
||||
|
||||
void AddAsset(Asset<AssetData> asset);
|
||||
AZStd::vector<Asset<AssetData>>& GetTrackedAssets();
|
||||
const AZStd::vector<Asset<AssetData>>& GetTrackedAssets() const;
|
||||
|
||||
private:
|
||||
AZStd::vector<Asset<AssetData>> m_serializedAssets;
|
||||
AssetFixUp m_assetFixUpCallback;
|
||||
};
|
||||
} // namespace Data
|
||||
} // namespace AZ
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <AzCore/Console/LoggerSystemComponent.h>
|
||||
#include <AzCore/EBus/EventSchedulerSystemComponent.h>
|
||||
#include <AzCore/Task/TaskGraphSystemComponent.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxySystemComponent.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -44,6 +45,10 @@ namespace AZ
|
||||
EventSchedulerSystemComponent::CreateDescriptor(),
|
||||
TaskGraphSystemComponent::CreateDescriptor(),
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
Statistics::StatisticalProfilerProxySystemComponent::CreateDescriptor(),
|
||||
#endif
|
||||
|
||||
#if !defined(AZCORE_EXCLUDE_LUA)
|
||||
ScriptSystemComponent::CreateDescriptor(),
|
||||
#endif // #if !defined(AZCORE_EXCLUDE_LUA)
|
||||
@@ -58,6 +63,10 @@ namespace AZ
|
||||
azrtti_typeid<LoggerSystemComponent>(),
|
||||
azrtti_typeid<EventSchedulerSystemComponent>(),
|
||||
azrtti_typeid<TaskGraphSystemComponent>(),
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
azrtti_typeid<Statistics::StatisticalProfilerProxySystemComponent>(),
|
||||
#endif
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1367,9 +1367,6 @@ namespace AZ
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Tick
|
||||
//=========================================================================
|
||||
void ComponentApplication::Tick(float deltaOverride /*= -1.f*/)
|
||||
{
|
||||
{
|
||||
@@ -1397,9 +1394,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Tick
|
||||
//=========================================================================
|
||||
void ComponentApplication::TickSystem()
|
||||
{
|
||||
AZ_PROFILE_SCOPE(System, "Component application tick");
|
||||
@@ -1547,5 +1541,4 @@ namespace AZ
|
||||
AZ::SettingsRegistryScriptUtils::ReflectSettingsRegistryToBehaviorContext(*behaviorContext);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
|
||||
@@ -476,15 +476,16 @@ namespace AZ
|
||||
|
||||
// Responsible for using the Json Serialization Issue Callback system
|
||||
// to determine when a JSON Patch or JSON Merge Patch modifies a value
|
||||
// at a path underneath the IConsole::ConsoleRootCommandKey JSON pointer
|
||||
// at a path underneath the IConsole::ConsoleRuntimeCommandKey JSON pointer
|
||||
JsonSerializationResult::ResultCode operator()(AZStd::string_view message,
|
||||
JsonSerializationResult::ResultCode result, AZStd::string_view path)
|
||||
{
|
||||
AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator };
|
||||
AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator };
|
||||
if (result.GetTask() == JsonSerializationResult::Tasks::Merge
|
||||
&& result.GetProcessing() == JsonSerializationResult::Processing::Completed
|
||||
&& inputKey.IsRelativeTo(consoleRootCommandKey))
|
||||
&& (inputKey.IsRelativeTo(consoleRootCommandKey) || inputKey.IsRelativeTo(consoleAutoexecCommandKey)))
|
||||
{
|
||||
if (auto type = m_settingsRegistry.GetType(path); type != SettingsRegistryInterface::Type::NoType)
|
||||
{
|
||||
@@ -510,12 +511,24 @@ namespace AZ
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
|
||||
AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleRuntimeCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator };
|
||||
constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator };
|
||||
AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator };
|
||||
// The ConsoleRootComamndKey is not a command itself so strictly children keys are being examined
|
||||
if (inputKey.IsRelativeTo(consoleRootCommandKey) && inputKey != consoleRootCommandKey)
|
||||
|
||||
// Abuses the IsRelativeToFuncton function of the path class to extract the console
|
||||
// command from the settings registry objects
|
||||
FixedValueString command;
|
||||
if (inputKey != consoleRuntimeCommandKey && inputKey.IsRelativeTo(consoleRuntimeCommandKey))
|
||||
{
|
||||
command = inputKey.LexicallyRelative(consoleRuntimeCommandKey).Native();
|
||||
}
|
||||
else if (inputKey != consoleAutoexecCommandKey && inputKey.IsRelativeTo(consoleAutoexecCommandKey))
|
||||
{
|
||||
command = inputKey.LexicallyRelative(consoleAutoexecCommandKey).Native();
|
||||
}
|
||||
|
||||
if (!command.empty())
|
||||
{
|
||||
FixedValueString command = inputKey.LexicallyRelative(consoleRootCommandKey).Native();
|
||||
ConsoleCommandContainer commandArgs;
|
||||
// Argument string which stores the value from the Settings Registry long enough
|
||||
// to pass into the PerformCommand. The ConsoleCommandContainer stores string_views
|
||||
@@ -603,9 +616,10 @@ namespace AZ
|
||||
|
||||
void Console::RegisterCommandInvokerWithSettingsRegistry(AZ::SettingsRegistryInterface& settingsRegistry)
|
||||
{
|
||||
// Make sure the there is a JSON object at the path of AZ::IConsole::ConsoleRootCommandKey
|
||||
// Make sure the there is a JSON object at the ConsoleRuntimeCommandKey or ConsoleAutoexecKey
|
||||
// So that JSON Patch is able to add values underneath that object (JSON Patch doesn't create intermediate objects)
|
||||
settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } }}})",
|
||||
settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } } })"
|
||||
R"(,"O3DE": { "Autoexec": { "ConsoleCommands": {} } } })",
|
||||
SettingsRegistryInterface::Format::JsonMergePatch);
|
||||
m_consoleCommandKeyHandler = settingsRegistry.RegisterNotifier(ConsoleCommandKeyNotificationHandler{ settingsRegistry, *this });
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace AZ
|
||||
|
||||
using FunctorVisitor = AZStd::function<void(ConsoleFunctorBase*)>;
|
||||
|
||||
inline static constexpr AZStd::string_view ConsoleRootCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands";
|
||||
inline static constexpr AZStd::string_view ConsoleRuntimeCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands";
|
||||
inline static constexpr AZStd::string_view ConsoleAutoexecCommandKey = "/O3DE/Autoexec/ConsoleCommands";
|
||||
|
||||
IConsole() = default;
|
||||
virtual ~IConsole() = default;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/Module/Environment.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxy.h>
|
||||
|
||||
AZ_DEFINE_BUDGET(Animation);
|
||||
AZ_DEFINE_BUDGET(Audio);
|
||||
@@ -30,8 +31,7 @@ namespace AZ::Debug
|
||||
};
|
||||
|
||||
Budget::Budget(const char* name)
|
||||
: m_name{ name }
|
||||
, m_crc{ Crc32(name) }
|
||||
: Budget( name, Crc32(name) )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ namespace AZ::Debug
|
||||
, m_crc{ crc }
|
||||
{
|
||||
m_impl = aznew BudgetImpl;
|
||||
if (auto statsProfiler = Interface<Statistics::StatisticalProfilerProxy>::Get(); statsProfiler)
|
||||
{
|
||||
statsProfiler->RegisterProfilerId(m_crc);
|
||||
}
|
||||
}
|
||||
|
||||
Budget::~Budget()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Debug/Budget.h>
|
||||
#include <AzCore/Statistics/StatisticalProfilerProxy.h>
|
||||
|
||||
#ifdef USE_PIX
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
@@ -44,7 +45,10 @@
|
||||
#define AZ_PROFILE_INTERVAL_START(...)
|
||||
#define AZ_PROFILE_INTERVAL_START_COLORED(...)
|
||||
#define AZ_PROFILE_INTERVAL_END(...)
|
||||
#define AZ_PROFILE_INTERVAL_SCOPED(...)
|
||||
#define AZ_PROFILE_INTERVAL_SCOPED(budget, scopeNameId, ...) \
|
||||
static constexpr AZ::Crc32 AZ_JOIN(blockId, __LINE__)(scopeNameId); \
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope AZ_JOIN(scope, __LINE__)(AZ_CRC_CE(#budget), AZ_JOIN(blockId, __LINE__));
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef AZ_PROFILE_DATAPOINT
|
||||
|
||||
@@ -46,5 +46,23 @@ namespace AZ
|
||||
private:
|
||||
AZStd::sys_time_t m_timeStamp;
|
||||
};
|
||||
|
||||
//! Utility type that updates the given variable with the lifetime of the object in cycles.
|
||||
//! Useful for quick scope based timing.
|
||||
struct ScopedTimer
|
||||
{
|
||||
explicit ScopedTimer(AZStd::sys_time_t& variable)
|
||||
: m_variable(variable)
|
||||
{
|
||||
m_timer.Stamp();
|
||||
}
|
||||
~ScopedTimer()
|
||||
{
|
||||
m_variable = m_timer.GetDeltaTimeInTicks();
|
||||
}
|
||||
|
||||
AZStd::sys_time_t& m_variable;
|
||||
Timer m_timer;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,8 @@ namespace AZ
|
||||
|
||||
void Debug::Trace::Terminate(int exitCode)
|
||||
{
|
||||
AZ_TracePrintf("Exit", "Called Terminate() with exit code: 0x%x", exitCode);
|
||||
AZ::Debug::Trace::PrintCallstack("Exit");
|
||||
Platform::Terminate(exitCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -160,8 +160,8 @@ namespace AZ
|
||||
/**
|
||||
* Locking primitive that is used when executing events in the event queue.
|
||||
*/
|
||||
using EventQueueMutexType = typename AZStd::Utils::if_c<AZStd::is_same<typename Traits::EventQueueMutexType, NullMutex>::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType
|
||||
MutexType, typename Traits::EventQueueMutexType>::type;
|
||||
using EventQueueMutexType = AZStd::conditional_t<AZStd::is_same<typename Traits::EventQueueMutexType, NullMutex>::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType
|
||||
MutexType, typename Traits::EventQueueMutexType>;
|
||||
|
||||
/**
|
||||
* Pointer to an address on the bus.
|
||||
@@ -180,14 +180,22 @@ namespace AZ
|
||||
* `<BusName>::ExecuteQueuedEvents()`.
|
||||
* By default, the event queue is disabled.
|
||||
*/
|
||||
static const bool EnableEventQueue = Traits::EnableEventQueue;
|
||||
static const bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault;
|
||||
static const bool EnableQueuedReferences = Traits::EnableQueuedReferences;
|
||||
static constexpr bool EnableEventQueue = Traits::EnableEventQueue;
|
||||
static constexpr bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault;
|
||||
static constexpr bool EnableQueuedReferences = Traits::EnableQueuedReferences;
|
||||
|
||||
/**
|
||||
* True if the EBus supports more than one address. Otherwise, false.
|
||||
*/
|
||||
static const bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
|
||||
static constexpr bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
|
||||
|
||||
/**
|
||||
* Template Lock Guard class that wraps around the Mutex
|
||||
* The EBus uses for Dispatching Events.
|
||||
* This is not the EBus Context Mutex if LocklessDispatch is true
|
||||
*/
|
||||
template <typename DispatchMutex>
|
||||
using DispatchLockGuard = typename Traits::template DispatchLockGuard<DispatchMutex, Traits::LocklessDispatch>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -460,7 +468,7 @@ namespace AZ
|
||||
using BusPtr = typename Traits::BusPtr;
|
||||
|
||||
/**
|
||||
* Helper to queue an event by BusIdType only when function queueing is enabled
|
||||
* Helper to queue an event by BusIdType only when function queueing is enabled
|
||||
* @param id Address ID. Handlers that are connected to this ID will receive the event.
|
||||
* @param func Function pointer of the event to dispatch.
|
||||
* @param args Function arguments that are passed to each handler.
|
||||
@@ -581,7 +589,7 @@ namespace AZ
|
||||
, public EBusBroadcaster<Bus, Traits>
|
||||
, public EBusEventer<Bus, Traits>
|
||||
, public EBusEventEnumerator<Bus, Traits>
|
||||
, public AZStd::Utils::if_c<Traits::EnableEventQueue, EBusEventQueue<Bus, Traits>, EBusNullQueue>::type
|
||||
, public AZStd::conditional_t<Traits::EnableEventQueue, EBusEventQueue<Bus, Traits>, EBusNullQueue>
|
||||
{
|
||||
};
|
||||
|
||||
@@ -599,7 +607,7 @@ namespace AZ
|
||||
: public EventDispatcher<Bus, Traits>
|
||||
, public EBusBroadcaster<Bus, Traits>
|
||||
, public EBusBroadcastEnumerator<Bus, Traits>
|
||||
, public AZStd::Utils::if_c<Traits::EnableEventQueue, EBusBroadcastQueue<Bus, Traits>, EBusNullQueue>::type
|
||||
, public AZStd::conditional_t<Traits::EnableEventQueue, EBusBroadcastQueue<Bus, Traits>, EBusNullQueue>
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* that Open 3D Engine uses to dispatch notifications and receive requests.
|
||||
* EBuses are configurable and support many different use cases.
|
||||
* For more information about %EBuses, see AZ::EBus in this guide and
|
||||
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
|
||||
* [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
|
||||
* in the *Open 3D Engine Developer Guide*.
|
||||
*/
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace AZ
|
||||
* @endcode
|
||||
*
|
||||
* For more information about %EBuses, see EBus in this guide and
|
||||
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
|
||||
* [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
|
||||
* in the *Open 3D Engine Developer Guide*.
|
||||
*/
|
||||
struct EBusTraits
|
||||
@@ -77,9 +77,11 @@ namespace AZ
|
||||
public:
|
||||
/**
|
||||
* Allocator used by the EBus.
|
||||
* The default setting is AZStd::allocator, which uses AZ::SystemAllocator.
|
||||
* The default setting is Internal EBusEnvironmentAllocator
|
||||
* EBus code stores their Context instances in static memory
|
||||
* Therfore the configured allocator must last as long as the EBus in a module
|
||||
*/
|
||||
using AllocatorType = AZStd::allocator;
|
||||
using AllocatorType = AZ::Internal::EBusEnvironmentAllocator;
|
||||
|
||||
/**
|
||||
* Defines how many handlers can connect to an address on the EBus
|
||||
@@ -236,6 +238,17 @@ namespace AZ
|
||||
* code before or after an event.
|
||||
*/
|
||||
using EventProcessingPolicy = EBusEventProcessingPolicy;
|
||||
|
||||
/**
|
||||
* Template Lock Guard class that wraps around the Mutex
|
||||
* The EBus Context uses the LockGuard when dispatching
|
||||
* (either AZStd::scoped_lock<MutexType> or NullLockGuard<MutexType>)
|
||||
* The IsLocklessDispatch bool is there to defer evaluation of the LocklessDispatch constant
|
||||
* Otherwise the value above in EBusTraits.h is always used and not the value
|
||||
* that the derived trait class sets.
|
||||
*/
|
||||
template <typename DispatchMutex, bool IsLocklessDispatch>
|
||||
using DispatchLockGuard = AZStd::conditional_t<IsLocklessDispatch, AZ::Internal::NullLockGuard<DispatchMutex>, AZStd::scoped_lock<DispatchMutex>>;
|
||||
};
|
||||
|
||||
namespace Internal
|
||||
@@ -259,8 +272,8 @@ namespace AZ
|
||||
*
|
||||
* EBuses are configurable and support many different use cases.
|
||||
* For more information about EBuses, see
|
||||
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
|
||||
* and [Components and EBuses: Best Practices ](http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-components-ebuses-best-practices.html)
|
||||
* [Event Bus](https://o3de.org/docs/user-guide/engine/ebus/)
|
||||
* and [Components and EBuses: Best Practices ](https://o3de.org/docs/user-guide/components/development/entity-system-pg-components-ebuses-best-practices/)
|
||||
* in the *Open 3D Engine Developer Guide*.
|
||||
*
|
||||
* ## How Components Use EBuses
|
||||
@@ -496,6 +509,14 @@ namespace AZ
|
||||
*/
|
||||
static const bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single;
|
||||
|
||||
/**
|
||||
* Template Lock Guard class that wraps around the Mutex
|
||||
* The EBus uses for Dispatching Events.
|
||||
* This is not EBus Context Mutex when LocklessDispatch is set
|
||||
*/
|
||||
template <typename DispatchMutex>
|
||||
using DispatchLockGuard = typename ImplTraits::template DispatchLockGuard<DispatchMutex>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Check to help identify common mistakes
|
||||
/// @cond EXCLUDE_DOCS
|
||||
@@ -620,11 +641,11 @@ namespace AZ
|
||||
using ContextMutexType = AZStd::conditional_t<BusTraits::LocklessDispatch && AZStd::is_same_v<MutexType, AZ::NullMutex>, AZStd::shared_mutex, MutexType>;
|
||||
|
||||
/**
|
||||
* The scoped lock guard to use (either AZStd::scoped_lock<MutexType> or NullLockGuard<MutexType>
|
||||
* The scoped lock guard to use
|
||||
* during broadcast/event dispatch.
|
||||
* @see EBusTraits::LocklessDispatch
|
||||
*/
|
||||
using DispatchLockGuard = AZStd::conditional_t<BusTraits::LocklessDispatch, AZ::Internal::NullLockGuard<ContextMutexType>, AZStd::scoped_lock<ContextMutexType>>;
|
||||
using DispatchLockGuard = DispatchLockGuard<ContextMutexType>;
|
||||
|
||||
/**
|
||||
* The scoped lock guard to use during connection. Some specialized policies execute handler methods which
|
||||
@@ -704,6 +725,11 @@ namespace AZ
|
||||
static Context& GetOrCreateContext(bool trackCallstack=true);
|
||||
|
||||
static bool IsInDispatch(Context* context = GetContext(false));
|
||||
|
||||
/**
|
||||
* Returns whether the EBus context is in the middle of a dispatch on the current thread
|
||||
*/
|
||||
static bool IsInDispatchThisThread(Context* context = GetContext(false));
|
||||
/// @cond EXCLUDE_DOCS
|
||||
struct RouterCallstackEntry
|
||||
: public CallstackEntry
|
||||
@@ -1208,6 +1234,13 @@ AZ_POP_DISABLE_WARNING
|
||||
return context != nullptr && context->m_dispatches > 0;
|
||||
}
|
||||
|
||||
template<class Interface, class Traits>
|
||||
bool EBus<Interface, Traits>::IsInDispatchThisThread(Context* context)
|
||||
{
|
||||
return context != nullptr && context->s_callstack != nullptr
|
||||
&& context->s_callstack->m_prev != nullptr;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
template<class Interface, class Traits>
|
||||
EBus<Interface, Traits>::RouterCallstackEntry::RouterCallstackEntry(Iterator it, const BusIdType* busId, bool isQueued, bool isReverse)
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace AZ
|
||||
virtual AZ::u64 ModificationTime(HandleType fileHandle) = 0;
|
||||
virtual AZ::u64 ModificationTime(const char* filePath) = 0;
|
||||
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
virtual Result Size(const char* filePath, AZ::u64& size) = 0;
|
||||
virtual Result Size(HandleType fileHandle, AZ::u64& size) = 0;
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace AZ
|
||||
/// note: the callback will contain the full concatenated path (filePath + slash + fileName)
|
||||
/// not just the individual file name found.
|
||||
/// note: if the file path of the found file corresponds to a registered ALIAS, the longest matching alias will be returned
|
||||
/// so expect return values like @assets@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// so expect return values like @products@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// note: if rootPath is specified the implementation has the option of substituting it for the current directory
|
||||
/// as would be the case on a file server.
|
||||
typedef AZStd::function<bool(const char*)> FindFilesCallbackType;
|
||||
@@ -206,13 +206,18 @@ namespace AZ
|
||||
|
||||
// Alias system
|
||||
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @root@, etc.
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @products@, etc.
|
||||
virtual void SetAlias(const char* alias, const char* path) = 0;
|
||||
/// ClearAlias - Removes an alias from the path resolution system
|
||||
virtual void ClearAlias(const char* alias) = 0;
|
||||
/// GetAlias - Returns the destination path for a given alias, or nullptr if the alias does not exist
|
||||
virtual const char* GetAlias(const char* alias) const = 0;
|
||||
|
||||
/// SetDeprecateAlias - Adds a deprecated alias with path resolution which points to a new alias
|
||||
/// When the DeprecatedAlias is used an Error is logged and the alias is resolved to the path
|
||||
/// specified by the new alais
|
||||
virtual void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) = 0;
|
||||
|
||||
/// Shorten the given path if it contains an alias. it will always pick the longest alias match.
|
||||
/// note that it re-uses the buffer, since the data can only get smaller and we don't want to internally allocate memory if we
|
||||
/// can avoid it.
|
||||
@@ -230,8 +235,8 @@ namespace AZ
|
||||
|
||||
//! ResolvePath - Replaces any aliases in path with their values and stores the result in resolvedPath,
|
||||
//! also ensures that the path is absolute
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @assets@ is used
|
||||
//! which has the effect of making the path relative to the @assets@/ folder
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @products@ is used
|
||||
//! which has the effect of making the path relative to the @products@/ folder
|
||||
//! returns true if path was resolved, false otherwise
|
||||
//! note that all of the above file-finding and opening functions automatically resolve the path before operating
|
||||
//! so you should not need to call this except in very exceptional circumstances where you absolutely need to
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace AZ::IO
|
||||
// These functions can't be called after a request has been queued.
|
||||
//
|
||||
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -62,9 +62,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -84,8 +84,8 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -106,9 +106,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -138,7 +138,7 @@ namespace AZ::IO
|
||||
//! @result A smart pointer to the newly created request with the cancel command.
|
||||
virtual FileRequestPtr Cancel(FileRequestPtr target) = 0;
|
||||
|
||||
//! Sets a request to the cancel command.
|
||||
//! Sets a request to the cancel command.
|
||||
//! When this request completes it's not guaranteed to have canceled the target request. Not all requests can be canceled and requests
|
||||
//! that already processing may complete. It's recommended to let the target request handle the completion of the request as normal
|
||||
//! and handle cancellation by checking the status on the target request is set to IStreamerTypes::RequestStatus::Canceled.
|
||||
@@ -177,7 +177,7 @@ namespace AZ::IO
|
||||
//! DestroyDedicatedCache is called. Typical use of a dedicated cache is for files that have their own compression
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to create a dedicated cache.
|
||||
virtual FileRequestPtr CreateDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -186,25 +186,25 @@ namespace AZ::IO
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param request The request that will store the command to create a dedicated cache.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& CreateDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to destroy a dedicated cache.
|
||||
virtual FileRequestPtr DestroyDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param request The request that will store the command to destroy a dedicated cache.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& DestroyDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Clears a file from all caches in use by Streamer.
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to flush a file from all caches.
|
||||
virtual FileRequestPtr FlushCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace AZ::IO
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param request The request that will store the command to flush a file from all caches.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& FlushCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -334,7 +334,7 @@ namespace AZ::IO
|
||||
//
|
||||
|
||||
//! Collect statistics from all the components that make up Streamer.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! Data is collected lockless from involved threads and might be slightly
|
||||
//! out of date in some cases.
|
||||
//! @param statistics The container where statistics will be added to.
|
||||
|
||||
@@ -98,6 +98,11 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const noexcept;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// decomposition
|
||||
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
|
||||
//! "/O3DE/foo/bar/name.txt"
|
||||
@@ -178,7 +183,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -238,7 +243,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
@@ -253,24 +258,23 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
friend class BasicPath;
|
||||
friend struct AZStd::hash<PathView>;
|
||||
|
||||
template <typename PathResultType>
|
||||
static constexpr void MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base);
|
||||
|
||||
struct PathIterable;
|
||||
|
||||
static constexpr void MakeRelativeTo(PathIterable& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept;
|
||||
|
||||
//! Returns a structure that provides a view of the path parts which can be used for iteration
|
||||
//! Only the path parts that correspond to creating an normalized path is returned
|
||||
//! This function is useful for returning a "view" into a normalized path without the need
|
||||
//! to allocate memory for the heap
|
||||
static constexpr PathIterable GetNormalPathParts(const AZ::IO::PathView& path) noexcept;
|
||||
// joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
// If the input path is absolute it will replace the current PathIterable otherwise
|
||||
// the input path will be appended to the Path Iterable structure
|
||||
// For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
// If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
// If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
// If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
// If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
//! joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
//! If the input path is absolute it will replace the current PathIterable otherwise
|
||||
//! the input path will be appended to the Path Iterable structure
|
||||
//! For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
//! If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
//! If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
//! If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
//! If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept;
|
||||
|
||||
constexpr int ComparePathView(const PathView& other) const;
|
||||
@@ -325,32 +329,32 @@ namespace AZ::IO
|
||||
constexpr BasicPath(BasicPath&& other) = default;
|
||||
|
||||
// Conversion constructor for other types of BasicPath instantiations
|
||||
constexpr BasicPath(const PathView& other);
|
||||
constexpr BasicPath(const PathView& other) noexcept;
|
||||
|
||||
// String constructors
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const string_type& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const string_type& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by moving the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(string_type&& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(string_type&& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(AZStd::string_view src) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separators it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(AZStd::string_view src, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const value_type* pathString) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const value_type* pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a empty Path with the preferred separator set to the parameter
|
||||
explicit constexpr BasicPath(const char preferredSeparator) noexcept;
|
||||
@@ -371,7 +375,7 @@ namespace AZ::IO
|
||||
constexpr BasicPath& operator=(BasicPath&& other) = default;
|
||||
|
||||
// conversion assignment operator
|
||||
constexpr BasicPath& operator=(const PathView& pathView);
|
||||
constexpr BasicPath& operator=(const PathView& pathView) noexcept;
|
||||
constexpr BasicPath& operator=(const string_type& str) noexcept;
|
||||
constexpr BasicPath& operator=(string_type&& str) noexcept;
|
||||
constexpr BasicPath& operator=(AZStd::string_view str) noexcept;
|
||||
@@ -477,6 +481,12 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
AZStd::string StringAsPosix() const;
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// compare
|
||||
//! Performs a compare of each of the path parts for equivalence
|
||||
//! Each part of the path is compare using string comparison
|
||||
@@ -574,7 +584,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -616,7 +626,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
|
||||
@@ -240,6 +240,14 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
constexpr AZStd::fixed_string<MaxPathLength> PathView::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), AZ::IO::WindowsPathSeparator, AZ::IO::PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
// decomposition
|
||||
constexpr auto PathView::RootName() const -> PathView
|
||||
{
|
||||
@@ -473,8 +481,7 @@ namespace AZ::IO
|
||||
return lhs.Compare(rhs) >= 0;
|
||||
}
|
||||
|
||||
template <typename PathResultType>
|
||||
constexpr void PathView::MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base)
|
||||
constexpr void PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept
|
||||
{
|
||||
const bool exactCaseCompare = path.m_preferred_separator == PosixPathSeparator
|
||||
|| base.m_preferred_separator == PosixPathSeparator;
|
||||
@@ -492,13 +499,11 @@ namespace AZ::IO
|
||||
if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare);
|
||||
res != 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -512,7 +517,6 @@ namespace AZ::IO
|
||||
}
|
||||
if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -530,7 +534,7 @@ namespace AZ::IO
|
||||
// If there is no mismatch, return ".".
|
||||
if (!pathParser && !pathParserBase)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -539,27 +543,25 @@ namespace AZ::IO
|
||||
int elemCount = parser::DetermineLexicalElementCount(pathParserBase);
|
||||
if (elemCount < 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
// if elemCount == 0 and (pathParser == end() || pathParser->empty()), returns path("."); otherwise
|
||||
if (elemCount == 0 && (pathParser.AtEnd() || *pathParser == ""))
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
// return a path constructed with 'n' dot-dot elements, followed by the
|
||||
// elements of '*this' after the mismatch.
|
||||
pathResult = PathResultType(path.m_preferred_separator);
|
||||
while (elemCount--)
|
||||
{
|
||||
pathResult /= "..";
|
||||
pathIterable.emplace_back("..", parser::PathPartKind::PK_DotDot);
|
||||
}
|
||||
for (; pathParser; ++pathParser)
|
||||
{
|
||||
pathResult /= *pathParser;
|
||||
pathIterable.emplace_back(*pathParser, parser::ClassifyPathPart(pathParser));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,7 +675,7 @@ namespace AZ::IO
|
||||
// Basic Path implementation
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other)
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other) noexcept
|
||||
: m_path(other.m_path)
|
||||
, m_preferred_separator(other.m_preferred_separator) {}
|
||||
|
||||
@@ -726,6 +728,7 @@ namespace AZ::IO
|
||||
: m_path(first, last)
|
||||
, m_preferred_separator(preferredSeparator) {}
|
||||
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::operator PathView() const noexcept
|
||||
{
|
||||
@@ -733,7 +736,7 @@ namespace AZ::IO
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) -> BasicPath&
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) noexcept -> BasicPath&
|
||||
{
|
||||
m_path = other.m_path;
|
||||
m_preferred_separator = other.m_preferred_separator;
|
||||
@@ -974,13 +977,13 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::MakePreferred() -> BasicPath&
|
||||
{
|
||||
if (m_preferred_separator != '/')
|
||||
if (m_preferred_separator != PosixPathSeparator)
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '/', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), PosixPathSeparator, m_preferred_separator);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '\\', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), WindowsPathSeparator, m_preferred_separator);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1033,6 +1036,24 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
// Returns a copy of the path with the path separators converted to PosixPathSeparator
|
||||
template <typename StringType>
|
||||
AZStd::string BasicPath<StringType>::StringAsPosix() const
|
||||
{
|
||||
AZStd::string resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr AZStd::fixed_string<MaxPathLength> BasicPath<StringType>::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr void BasicPath<StringType>::swap(BasicPath& rhs) noexcept
|
||||
{
|
||||
@@ -1234,6 +1255,7 @@ namespace AZ::IO
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1241,7 +1263,13 @@ namespace AZ::IO
|
||||
constexpr auto BasicPath<StringType>::LexicallyRelative(const PathView& base) const -> BasicPath
|
||||
{
|
||||
BasicPath pathResult(m_preferred_separator);
|
||||
static_cast<PathView>(*this).MakeRelativeTo(pathResult, *this, base);
|
||||
PathView::PathIterable pathIterable;
|
||||
PathView::MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1355,7 +1383,7 @@ namespace AZ::IO
|
||||
return !basePathParts.empty() || !thisPathParts.IsAbsolute();
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyNormal() const
|
||||
constexpr auto PathView::LexicallyNormal() const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
PathIterable pathIterable = GetNormalPathParts(*this);
|
||||
@@ -1367,21 +1395,28 @@ namespace AZ::IO
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyRelative(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyRelative(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
MakeRelativeTo(pathResult, *this, base);
|
||||
PathIterable pathIterable;
|
||||
MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyProximate(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyProximate(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath result = LexicallyRelative(base);
|
||||
if (result.empty())
|
||||
FixedMaxPath pathResult = LexicallyRelative(base);
|
||||
if (pathResult.empty())
|
||||
{
|
||||
return FixedMaxPath(*this);
|
||||
}
|
||||
return result;
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ namespace AZ::IO
|
||||
|
||||
constexpr void clear() noexcept;
|
||||
|
||||
friend constexpr auto PathView::GetNormalPathParts(const AZ::IO::PathView&) noexcept -> PathIterable;
|
||||
friend constexpr auto PathView::AppendNormalPathParts(PathIterable& pathIterable, const AZ::IO::PathView&) noexcept -> void;
|
||||
friend constexpr auto PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView&, const AZ::IO::PathView&) noexcept -> void;
|
||||
PartKindArray m_parts{};
|
||||
size_t m_size{};
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Platform
|
||||
SystemFile::SizeType Length(FileHandleType handle, const SystemFile* systemFile);
|
||||
|
||||
bool Exists(const char* fileName);
|
||||
bool IsDirectory(const char* filePath);
|
||||
void FindFiles(const char* filter, SystemFile::FindFileCB cb);
|
||||
AZ::u64 ModificationTime(const char* fileName);
|
||||
SystemFile::SizeType Length(const char* fileName);
|
||||
@@ -235,6 +236,11 @@ bool SystemFile::Exists(const char* fileName)
|
||||
return Platform::Exists(fileName);
|
||||
}
|
||||
|
||||
bool SystemFile::IsDirectory(const char* filePath)
|
||||
{
|
||||
return Platform::IsDirectory(filePath);
|
||||
}
|
||||
|
||||
void SystemFile::FindFiles(const char* filter, FindFileCB cb)
|
||||
{
|
||||
Platform::FindFiles(filter, cb);
|
||||
|
||||
@@ -99,6 +99,8 @@ namespace AZ
|
||||
// Utility functions
|
||||
/// Check if a file or directory exists.
|
||||
static bool Exists(const char* path);
|
||||
/// Check if path is a directory
|
||||
static bool IsDirectory(const char* path);
|
||||
/// FindFiles
|
||||
typedef AZStd::function<bool /* true to continue to enumerate otherwise false */ (const char* /* fileName*/, bool /* true if file, false if folder*/)> FindFileCB;
|
||||
static void FindFiles(const char* filter, FindFileCB cb);
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
|
||||
AZ_CVAR(float, cl_jobThreadsConcurrencyRatio, 0.6f, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine creates at initialization");
|
||||
AZ_CVAR(uint32_t, cl_jobThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system number of hardware threads that are reserved for O3DE system threads");
|
||||
AZ_CVAR(uint32_t, cl_jobThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system minimum number of worker threads to create after scaling the number of hw threads");
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//=========================================================================
|
||||
@@ -46,9 +54,10 @@ namespace AZ
|
||||
JobManagerThreadDesc threadDesc;
|
||||
|
||||
int numberOfWorkerThreads = m_numberOfWorkerThreads;
|
||||
if (numberOfWorkerThreads <= 0)
|
||||
if (numberOfWorkerThreads <= 0) // spawn default number of threads
|
||||
{
|
||||
numberOfWorkerThreads = AZ::GetMin(static_cast<unsigned int>(desc.m_workerThreads.capacity()), AZStd::thread::hardware_concurrency());
|
||||
uint32_t scaledHardwareThreads = Threading::CalcNumWorkerThreads(cl_jobThreadsConcurrencyRatio, cl_jobThreadsMinNumber, cl_jobThreadsNumReserved);
|
||||
numberOfWorkerThreads = AZ::GetMin(static_cast<unsigned int>(desc.m_workerThreads.capacity()), scaledHardwareThreads);
|
||||
#if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
|
||||
numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS);
|
||||
#endif // (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS)
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AZ
|
||||
*/
|
||||
int m_stackSize;
|
||||
|
||||
JobManagerThreadDesc(int cpuId = -1, int priority = -100000, int stackSize = -1)
|
||||
JobManagerThreadDesc(int cpuId = -1, int priority = 0, int stackSize = -1)
|
||||
: m_cpuId(cpuId)
|
||||
, m_priority(priority)
|
||||
, m_stackSize(stackSize)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
@@ -135,18 +135,12 @@ namespace AZ
|
||||
{
|
||||
stringLength = strlen(uuidString);
|
||||
}
|
||||
if (stringLength > MaxPermissiveStringSize)
|
||||
{
|
||||
if (!skipWarnings)
|
||||
{
|
||||
AZ_Warning("Math", false, "Can't create UUID from string length %zu over maximum %zu", stringLength, MaxPermissiveStringSize);
|
||||
}
|
||||
return Uuid::CreateNull();
|
||||
}
|
||||
|
||||
size_t newLength{ 0 };
|
||||
char createString[MaxPermissiveStringSize];
|
||||
|
||||
for (size_t curPos = 0; curPos < stringLength; ++curPos)
|
||||
// Loop until we get to the end of the string OR stop once we've accumulated a full UUID string worth of data
|
||||
for (size_t curPos = 0; curPos < stringLength && newLength < ValidUuidStringLength; ++curPos)
|
||||
{
|
||||
char curChar = uuidString[curPos];
|
||||
switch (curChar)
|
||||
|
||||
@@ -42,8 +42,9 @@ namespace AZ
|
||||
//VER_AZ_RANDOM_CRC32 = 6, // 0 1 1 0
|
||||
};
|
||||
|
||||
static constexpr int ValidUuidStringLength = 32; /// Number of characters (data only, no extra formatting) in a valid UUID string
|
||||
static const size_t MaxStringBuffer = 39; /// 32 Uuid + 4 dashes + 2 brackets + 1 terminate
|
||||
|
||||
|
||||
Uuid() {}
|
||||
Uuid(const char* string, size_t stringLength = 0) { *this = CreateString(string, stringLength); }
|
||||
|
||||
|
||||
@@ -180,6 +180,13 @@ namespace AZ
|
||||
bool IsGreaterEqualThan(const Vector2& v) const;
|
||||
//! @}
|
||||
|
||||
//! Floor/Ceil/Round functions, operate on each component individually, result will be a new Vector2.
|
||||
//! @{
|
||||
Vector2 GetFloor() const;
|
||||
Vector2 GetCeil() const;
|
||||
Vector2 GetRound() const; // Ties to even (banker's rounding)
|
||||
//! @}
|
||||
|
||||
//! Min/Max functions, operate on each component individually, result will be a new Vector2.
|
||||
//! @{
|
||||
Vector2 GetMin(const Vector2& v) const;
|
||||
|
||||
@@ -398,6 +398,24 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetFloor() const
|
||||
{
|
||||
return Vector2(Simd::Vec2::Floor(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetCeil() const
|
||||
{
|
||||
return Vector2(Simd::Vec2::Ceil(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetRound() const
|
||||
{
|
||||
return Vector2(Simd::Vec2::Round(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2 Vector2::GetMin(const Vector2& v) const
|
||||
{
|
||||
#if AZ_TRAIT_USE_PLATFORM_SIMD_SCALAR
|
||||
|
||||
@@ -211,6 +211,13 @@ namespace AZ
|
||||
bool IsGreaterEqualThan(const Vector3& rhs) const;
|
||||
//! @}
|
||||
|
||||
//! Floor/Ceil/Round functions, operate on each component individually, result will be a new Vector3.
|
||||
//! @{
|
||||
Vector3 GetFloor() const;
|
||||
Vector3 GetCeil() const;
|
||||
Vector3 GetRound() const; // Ties to even (banker's rounding)
|
||||
//! @}
|
||||
|
||||
//! Min/Max functions, operate on each component individually, result will be a new Vector3.
|
||||
//! @{
|
||||
Vector3 GetMin(const Vector3& v) const;
|
||||
|
||||
@@ -481,6 +481,24 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetFloor() const
|
||||
{
|
||||
return Vector3(Simd::Vec3::Floor(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetCeil() const
|
||||
{
|
||||
return Vector3(Simd::Vec3::Ceil(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetRound() const
|
||||
{
|
||||
return Vector3(Simd::Vec3::Round(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Vector3::GetMin(const Vector3& v) const
|
||||
{
|
||||
#if AZ_TRAIT_USE_PLATFORM_SIMD_SCALAR
|
||||
|
||||
@@ -189,6 +189,13 @@ namespace AZ
|
||||
bool IsGreaterEqualThan(const Vector4& rhs) const;
|
||||
//! @}
|
||||
|
||||
//! Floor/Ceil/Round functions, operate on each component individually, result will be a new Vector4.
|
||||
//! @{
|
||||
Vector4 GetFloor() const;
|
||||
Vector4 GetCeil() const;
|
||||
Vector4 GetRound() const; // Ties to even (banker's rounding)
|
||||
//! @}
|
||||
|
||||
//! Min/Max functions, operate on each component individually, result will be a new Vector4.
|
||||
//! @{
|
||||
Vector4 GetMin(const Vector4& v) const;
|
||||
|
||||
@@ -464,6 +464,24 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetFloor() const
|
||||
{
|
||||
return Vector4(Simd::Vec4::Floor(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetCeil() const
|
||||
{
|
||||
return Vector4(Simd::Vec4::Ceil(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetRound() const
|
||||
{
|
||||
return Vector4(Simd::Vec4::Round(m_value));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector4 Vector4::GetMin(const Vector4& v) const
|
||||
{
|
||||
#if AZ_TRAIT_USE_PLATFORM_SIMD_SCALAR
|
||||
|
||||
@@ -34,7 +34,9 @@ namespace AZ
|
||||
friend IAllocator;
|
||||
friend class AllocatorBase;
|
||||
friend class Debug::AllocationRecords;
|
||||
friend class AZ::Internal::EnvironmentVariableHolder<AllocatorManager>;
|
||||
template<typename T, typename... Args> friend constexpr auto AZStd::construct_at(T*, Args&&... args)
|
||||
->AZStd::enable_if_t<AZStd::is_void_v<AZStd::void_t<decltype(new (AZStd::declval<void*>()) T(AZStd::forward<Args>(args)...))>>, T*>;
|
||||
template<typename T> constexpr friend void AZStd::destroy_at(T*);
|
||||
|
||||
public:
|
||||
typedef AZStd::function<void (IAllocator* allocator, size_t /*byteSize*/, size_t /*alignment*/, int/* flags*/, const char* /*name*/, const char* /*fileName*/, int lineNum /*=0*/)> OutOfMemoryCBType;
|
||||
|
||||
@@ -251,16 +251,15 @@ namespace AZ
|
||||
class EnvironmentVariableHolder
|
||||
: public EnvironmentVariableHolderBase
|
||||
{
|
||||
void ConstructImpl(const AZStd::true_type& /* AZStd::has_trivial_constructor<T> */)
|
||||
{
|
||||
memset(&m_value, 0, sizeof(T));
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void ConstructImpl(const AZStd::false_type& /* AZStd::has_trivial_constructor<T> */, Args&&... args)
|
||||
void ConstructImpl(Args&&... args)
|
||||
{
|
||||
// Construction of non-trivial types is left up to the type's constructor.
|
||||
new(&m_value) T(AZStd::forward<Args>(args)...);
|
||||
// Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object
|
||||
#if __cpp_lib_launder
|
||||
AZStd::construct_at(std::launder(reinterpret_cast<T*>(&m_value)), AZStd::forward<Args>(args)...);
|
||||
#else
|
||||
AZStd::construct_at(reinterpret_cast<T*>(&m_value), AZStd::forward<Args>(args)...);
|
||||
#endif
|
||||
}
|
||||
static void DestructDispatchNoLock(EnvironmentVariableHolderBase *base, DestroyTarget selfDestruct)
|
||||
{
|
||||
@@ -274,10 +273,12 @@ namespace AZ
|
||||
AZ_Assert(self->m_isConstructed, "Variable is not constructed. Please check your logic and guard if needed!");
|
||||
self->m_isConstructed = false;
|
||||
self->m_moduleOwner = nullptr;
|
||||
if constexpr(!AZStd::is_trivially_destructible_v<T>)
|
||||
{
|
||||
reinterpret_cast<T*>(&self->m_value)->~T();
|
||||
}
|
||||
// Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object
|
||||
#if __cpp_lib_launder
|
||||
AZStd::destroy_at(std::launder(reinterpret_cast<T*>(&self->m_value)));
|
||||
#else
|
||||
AZStd::destroy_at(reinterpret_cast<T*>(&self->m_value));
|
||||
#endif
|
||||
}
|
||||
public:
|
||||
EnvironmentVariableHolder(u32 guid, bool isOwnershipTransfer, Environment::AllocatorInterface* allocator)
|
||||
@@ -303,24 +304,13 @@ namespace AZ
|
||||
UnregisterAndDestroy(DestructDispatchNoLock, moduleRelease);
|
||||
}
|
||||
|
||||
void Construct()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::spin_mutex> lock(m_mutex);
|
||||
if (!m_isConstructed)
|
||||
{
|
||||
ConstructImpl(AZStd::is_trivially_constructible<T>{});
|
||||
m_isConstructed = true;
|
||||
m_moduleOwner = Environment::GetModuleId();
|
||||
}
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
void Construct(Args&&... args)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::spin_mutex> lock(m_mutex);
|
||||
if (!m_isConstructed)
|
||||
{
|
||||
ConstructImpl(typename AZStd::false_type(), AZStd::forward<Args>(args)...);
|
||||
ConstructImpl(AZStd::forward<Args>(args)...);
|
||||
m_isConstructed = true;
|
||||
m_moduleOwner = Environment::GetModuleId();
|
||||
}
|
||||
@@ -333,7 +323,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// variable storage
|
||||
typename AZStd::aligned_storage<sizeof(T), AZStd::alignment_of<T>::value>::type m_value;
|
||||
AZStd::aligned_storage_for_t<T> m_value;
|
||||
static int s_moduleUseCount;
|
||||
};
|
||||
|
||||
@@ -468,6 +458,11 @@ namespace AZ
|
||||
Get() = value;
|
||||
}
|
||||
|
||||
void Set(T&& value)
|
||||
{
|
||||
Get() = AZStd::move(value);
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return IsValid();
|
||||
|
||||
@@ -42,7 +42,10 @@ namespace AZ
|
||||
AZ_Assert(m_useCount > 0, "m_useCount is already 0!");
|
||||
if (m_useCount.fetch_sub(1) == 1)
|
||||
{
|
||||
AZ::NameDictionary::Instance().TryReleaseName(hash);
|
||||
if (AZ::NameDictionary::IsReady())
|
||||
{
|
||||
AZ::NameDictionary::Instance().TryReleaseName(hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,23 +21,18 @@ namespace AZ
|
||||
|
||||
namespace NameDictionaryInternal
|
||||
{
|
||||
static AZ::EnvironmentVariable<NameDictionary*> s_instance = nullptr;
|
||||
static AZ::EnvironmentVariable<NameDictionary> s_instance = nullptr;
|
||||
}
|
||||
|
||||
void NameDictionary::Create()
|
||||
{
|
||||
using namespace NameDictionaryInternal;
|
||||
|
||||
AZ_Assert(!s_instance || !s_instance.Get(), "NameDictionary already created!");
|
||||
AZ_Assert(!s_instance, "NameDictionary already created!");
|
||||
|
||||
if (!s_instance)
|
||||
{
|
||||
s_instance = AZ::Environment::CreateVariable<NameDictionary*>(NameDictionaryInstanceName);
|
||||
}
|
||||
|
||||
if (!s_instance.Get())
|
||||
{
|
||||
s_instance.Set(aznew NameDictionary());
|
||||
s_instance = AZ::Environment::CreateVariable<NameDictionary>(NameDictionaryInstanceName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +41,7 @@ namespace AZ
|
||||
using namespace NameDictionaryInternal;
|
||||
|
||||
AZ_Assert(s_instance, "NameDictionary not created!");
|
||||
delete (*s_instance);
|
||||
*s_instance = nullptr;
|
||||
s_instance.Reset();
|
||||
}
|
||||
|
||||
bool NameDictionary::IsReady()
|
||||
@@ -56,10 +50,10 @@ namespace AZ
|
||||
|
||||
if (!s_instance)
|
||||
{
|
||||
s_instance = Environment::FindVariable<NameDictionary*>(NameDictionaryInstanceName);
|
||||
s_instance = Environment::FindVariable<NameDictionary>(NameDictionaryInstanceName);
|
||||
}
|
||||
|
||||
return s_instance && *s_instance;
|
||||
return s_instance.IsConstructed();
|
||||
}
|
||||
|
||||
NameDictionary& NameDictionary::Instance()
|
||||
@@ -68,12 +62,12 @@ namespace AZ
|
||||
|
||||
if (!s_instance)
|
||||
{
|
||||
s_instance = Environment::FindVariable<NameDictionary*>(NameDictionaryInstanceName);
|
||||
s_instance = Environment::FindVariable<NameDictionary>(NameDictionaryInstanceName);
|
||||
}
|
||||
|
||||
AZ_Assert(s_instance && *s_instance, "NameDictionary has not been initialized yet.");
|
||||
AZ_Assert(s_instance.IsConstructed(), "NameDictionary has not been initialized yet.");
|
||||
|
||||
return *(*s_instance);
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
NameDictionary::NameDictionary()
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
|
||||
namespace MaterialEditor
|
||||
namespace MaterialEditor
|
||||
{
|
||||
class MaterialEditorCoreComponent;
|
||||
}
|
||||
@@ -34,14 +34,14 @@ namespace AZ
|
||||
{
|
||||
class NameData;
|
||||
};
|
||||
|
||||
|
||||
//! Maintains a list of unique strings for Name objects.
|
||||
//! The main benefit of the Name system is very fast string equality comparison, because every
|
||||
//! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not
|
||||
//! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not
|
||||
//! collide. It also saves memory by removing duplicate strings.
|
||||
//!
|
||||
//! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't
|
||||
//! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names
|
||||
//! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't
|
||||
//! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names
|
||||
//! that already exist.
|
||||
class NameDictionary final
|
||||
{
|
||||
@@ -51,7 +51,10 @@ namespace AZ
|
||||
friend Name;
|
||||
friend Internal::NameData;
|
||||
friend UnitTest::NameDictionaryTester;
|
||||
|
||||
template<typename T, typename... Args> friend constexpr auto AZStd::construct_at(T*, Args&&... args)
|
||||
-> AZStd::enable_if_t<AZStd::is_void_v<AZStd::void_t<decltype(new (AZStd::declval<void*>()) T(AZStd::forward<Args>(args)...))>>, T*>;
|
||||
template<typename T> constexpr friend void AZStd::destroy_at(T*);
|
||||
|
||||
public:
|
||||
|
||||
static void Create();
|
||||
@@ -62,7 +65,7 @@ namespace AZ
|
||||
|
||||
//! Makes a Name from the provided raw string. If an entry already exists in the dictionary, it is shared.
|
||||
//! Otherwise, it is added to the internal dictionary.
|
||||
//!
|
||||
//!
|
||||
//! @param name The name to resolve against the dictionary.
|
||||
//! @return A Name instance holding a dictionary entry associated with the provided raw string.
|
||||
Name MakeName(AZStd::string_view name);
|
||||
@@ -84,13 +87,13 @@ namespace AZ
|
||||
// Attempts to release the name from the dictionary, but checks to make sure
|
||||
// a reference wasn't taken by another thread.
|
||||
void TryReleaseName(Name::Hash hash);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Calculates a hash for the provided name string.
|
||||
// Does not attempt to resolve hash collisions; that is handled elsewhere.
|
||||
Name::Hash CalcHash(AZStd::string_view name);
|
||||
|
||||
|
||||
AZStd::unordered_map<Name::Hash, Internal::NameData*> m_dictionary;
|
||||
mutable AZStd::shared_mutex m_sharedMutex;
|
||||
};
|
||||
|
||||
@@ -204,14 +204,14 @@ namespace AZ
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0;
|
||||
//! Register a function that will be called before a file is merged.
|
||||
//! @callback The function to call before a file is merged.
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0;
|
||||
[[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) = 0;
|
||||
|
||||
//! Register a function that will be called after a file is merged.
|
||||
//! @callback The function to call after a file is merged.
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0;
|
||||
//! Register a function that will be called after a file is merged.
|
||||
//! @callback The function to call after a file is merged.
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0;
|
||||
[[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) = 0;
|
||||
|
||||
//! Gets the boolean value at the provided path.
|
||||
//! @param result The target to write the result to.
|
||||
|
||||
@@ -276,7 +276,9 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return engineRoot;
|
||||
}
|
||||
|
||||
return {};
|
||||
// Fall back to using the project root as the engine root if the engine path could not be reconciled
|
||||
// by checking the project.json "engine" string within o3de_manifest.json "engine_paths" object
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry)
|
||||
@@ -309,7 +311,13 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
return {};
|
||||
// Step 3 Check for a "Cache" directory by scanning upwards from the executable directory
|
||||
if (auto candidateRoot = Internal::ScanUpRootLocator("Cache");
|
||||
!candidateRoot.empty() && AZ::IO::SystemFile::IsDirectory(candidateRoot.c_str()))
|
||||
{
|
||||
projectRoot = AZStd::move(candidateRoot);
|
||||
}
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
AZStd::string_view ConfigParserSettings::DefaultCommentPrefixFilter(AZStd::string_view line)
|
||||
@@ -538,7 +546,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetExecutableDirectory();
|
||||
registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
|
||||
|
||||
// Engine root folder - corresponds to the @engroot@ and @devroot@ aliases
|
||||
// Engine root folder - corresponds to the @engroot@ and @engroot@ aliases
|
||||
AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry);
|
||||
registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native());
|
||||
|
||||
@@ -562,7 +570,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
}
|
||||
|
||||
// Project path - corresponds to the @devassets@ alias
|
||||
// Project path - corresponds to the @projectroot@ alias
|
||||
// NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded.
|
||||
path = engineRoot / projectPathValue;
|
||||
|
||||
@@ -654,7 +662,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache: root - same as the @root@ alias, this is the starting path for cache files.
|
||||
// Cache: root - same as the @products@ alias, this is the starting path for cache files.
|
||||
path = normalizedProjectPath / "Cache";
|
||||
registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native());
|
||||
path /= assetPlatform;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistryVisitorUtils.h>
|
||||
|
||||
|
||||
namespace AZ::SettingsRegistryVisitorUtils
|
||||
{
|
||||
// Field Visitor implementation
|
||||
FieldVisitor::FieldVisitor() = default;
|
||||
FieldVisitor::FieldVisitor(VisitFieldType visitFieldType)
|
||||
: m_visitFieldType{ visitFieldType }
|
||||
{
|
||||
}
|
||||
|
||||
auto FieldVisitor::Traverse(AZStd::string_view path, AZStd::string_view valueName,
|
||||
VisitAction action, Type type) -> VisitResponse
|
||||
{
|
||||
// A default response skip prevents visiting grand children(depth 2 or lower)
|
||||
VisitResponse visitResponse = VisitResponse::Skip;
|
||||
if (action == VisitAction::Begin)
|
||||
{
|
||||
// Invoke FieldVisitor override if the root path has been set
|
||||
if (m_rootPath.has_value())
|
||||
{
|
||||
Visit(path, valueName, type);
|
||||
}
|
||||
// To make sure only the direct children are visited(depth 1)
|
||||
// set the root path once and set the VisitReponsoe
|
||||
// to Continue to recurse into is fields
|
||||
if (!m_rootPath.has_value())
|
||||
{
|
||||
bool visitableFieldType{};
|
||||
switch (m_visitFieldType)
|
||||
{
|
||||
case VisitFieldType::Array:
|
||||
visitableFieldType = type == Type::Array;
|
||||
break;
|
||||
case VisitFieldType::Object:
|
||||
visitableFieldType = type == Type::Object;
|
||||
break;
|
||||
case VisitFieldType::ArrayOrObject:
|
||||
visitableFieldType = type == Type::Array || type ==Type::Object;
|
||||
break;
|
||||
default:
|
||||
AZ_Error("FieldVisitor", false, "The field visitation type value is invalid");
|
||||
break;
|
||||
}
|
||||
|
||||
if (visitableFieldType)
|
||||
{
|
||||
m_rootPath = path;
|
||||
visitResponse = VisitResponse::Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (action == VisitAction::Value)
|
||||
{
|
||||
// Invoke FieldVisitor override if the root path has been set
|
||||
if (m_rootPath.has_value())
|
||||
{
|
||||
Visit(path, valueName, type);
|
||||
}
|
||||
}
|
||||
else if (action == VisitAction::End)
|
||||
{
|
||||
// Reset m_rootPath back to null when the root path has finished being visited
|
||||
if (m_rootPath.has_value() && *m_rootPath == path)
|
||||
{
|
||||
m_rootPath = AZStd::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return visitResponse;
|
||||
}
|
||||
|
||||
// Array Visitor implementation
|
||||
ArrayVisitor::ArrayVisitor()
|
||||
: FieldVisitor(VisitFieldType::Array)
|
||||
{
|
||||
}
|
||||
|
||||
// Object Visitor implementation
|
||||
ObjectVisitor::ObjectVisitor()
|
||||
: FieldVisitor(VisitFieldType::Object)
|
||||
{
|
||||
}
|
||||
|
||||
// Generic VisitField Callback implemention
|
||||
template <typename BaseVisitor>
|
||||
bool VisitFieldCallback(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
struct VisitFieldVisitor
|
||||
: BaseVisitor
|
||||
{
|
||||
using BaseVisitor::Visit;
|
||||
VisitFieldVisitor(const VisitorCallback& visitCallback)
|
||||
: m_visitCallback{ visitCallback }
|
||||
{}
|
||||
|
||||
void Visit(AZStd::string_view path, AZStd::string_view fieldIndex, typename BaseVisitor::Type type) override
|
||||
{
|
||||
m_visitCallback(path, fieldIndex, type);
|
||||
}
|
||||
|
||||
const VisitorCallback& m_visitCallback;
|
||||
};
|
||||
|
||||
VisitFieldVisitor visitor{ visitCallback };
|
||||
return settingsRegistry.Visit(visitor, path);
|
||||
}
|
||||
|
||||
// VisitField implementation
|
||||
bool VisitField(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
return VisitFieldCallback<FieldVisitor>(settingsRegistry, visitCallback, path);
|
||||
}
|
||||
|
||||
// VisitArray implementation
|
||||
bool VisitArray(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
return VisitFieldCallback<ArrayVisitor>(settingsRegistry, visitCallback, path);
|
||||
}
|
||||
|
||||
// VisitObject implementation
|
||||
bool VisitObject(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path)
|
||||
{
|
||||
return VisitFieldCallback<ObjectVisitor>(settingsRegistry, visitCallback, path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
|
||||
|
||||
namespace AZ::SettingsRegistryVisitorUtils
|
||||
{
|
||||
//! Interface for visiting the fields of an array or object
|
||||
//! To access the values, use the SettingsRegistryInterface Get/GetObject methods
|
||||
struct FieldVisitor
|
||||
: public AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse;
|
||||
using VisitAction = AZ::SettingsRegistryInterface::VisitAction;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
|
||||
FieldVisitor();
|
||||
|
||||
// Bring the base class visitor functions into scope
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
virtual void Visit(AZStd::string_view path, AZStd::string_view arrayIndex, Type type) = 0;
|
||||
|
||||
protected:
|
||||
// VisitFieldType is used for filtering the type of referenced by the root path
|
||||
enum class VisitFieldType
|
||||
{
|
||||
Array,
|
||||
Object,
|
||||
ArrayOrObject
|
||||
};
|
||||
FieldVisitor(const VisitFieldType visitFieldType);
|
||||
private:
|
||||
VisitResponse Traverse(AZStd::string_view path, AZStd::string_view valueName,
|
||||
VisitAction action, Type type) override;
|
||||
|
||||
VisitFieldType m_visitFieldType{ VisitFieldType::ArrayOrObject };
|
||||
AZStd::optional<AZ::SettingsRegistryInterface::FixedValueString> m_rootPath;
|
||||
};
|
||||
|
||||
//! Interface for visiting the fields of an array
|
||||
//! To access the values, use the SettingsRegistryInterface Get/GetObject methods
|
||||
struct ArrayVisitor
|
||||
: public FieldVisitor
|
||||
{
|
||||
ArrayVisitor();
|
||||
};
|
||||
|
||||
//! Interface for visiting the fields of an object
|
||||
//! To access the values, use the SettingsRegistryInterface Get/GetObject methods
|
||||
struct ObjectVisitor
|
||||
: public FieldVisitor
|
||||
{
|
||||
ObjectVisitor();
|
||||
};
|
||||
|
||||
//! Signature of callback funcition invoked when visiting an element of an array or object
|
||||
using VisitorCallback = AZStd::function<void(AZStd::string_view path, AZStd::string_view fieldName,
|
||||
AZ::SettingsRegistryInterface::Type)>;
|
||||
|
||||
//! Invokes the visitor callback for each element of either the array or object at @path
|
||||
//! If @path is not an array or object, then no elements are visited
|
||||
//! This function will not recurse into children of elements
|
||||
//! @visitCallback functor that is invoked for each array or object element found
|
||||
bool VisitField(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path);
|
||||
//! Invokes the visitor callback for each element of the array at @path
|
||||
//! If @path is not an array, then no elements are visited
|
||||
//! This function will not recurse into children of elements
|
||||
//! @visitCallback functor that is invoked for each array element found
|
||||
bool VisitArray(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path);
|
||||
//! Invokes the visitor callback for each element of the object at @path
|
||||
//! If @path is not an object, then no elements are visited
|
||||
//! This function will not recurse into children of elements
|
||||
//! @visitCallback functor that is invoked for each object element found
|
||||
bool VisitObject(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path);
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "RunningStatisticsManager.h"
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
namespace Statistics
|
||||
{
|
||||
bool RunningStatisticsManager::ContainsStatistic(const AZStd::string& name)
|
||||
{
|
||||
auto iterator = m_statisticsNamesToIndexMap.find(name);
|
||||
return iterator != m_statisticsNamesToIndexMap.end();
|
||||
}
|
||||
|
||||
bool RunningStatisticsManager::AddStatistic(const AZStd::string& name, const AZStd::string& units)
|
||||
{
|
||||
if (ContainsStatistic(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AddStatisticValidated(name, units);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::RemoveStatistic(const AZStd::string& name)
|
||||
{
|
||||
auto iterator = m_statisticsNamesToIndexMap.find(name);
|
||||
if (iterator == m_statisticsNamesToIndexMap.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
AZ::u32 itemIndex = iterator->second;
|
||||
m_statistics.erase(m_statistics.begin() + itemIndex);
|
||||
m_statisticsNamesToIndexMap.erase(iterator);
|
||||
//Update the indices in m_statisticsNamesToIndexMap.
|
||||
while (itemIndex < m_statistics.size())
|
||||
{
|
||||
const AZStd::string& statName = m_statistics[itemIndex].GetName();
|
||||
m_statisticsNamesToIndexMap[statName] = itemIndex;
|
||||
++itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::ResetStatistic(const AZStd::string& name)
|
||||
{
|
||||
NamedRunningStatistic* stat = GetStatistic(name);
|
||||
if (!stat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
stat->Reset();
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::ResetAllStatistics()
|
||||
{
|
||||
for (NamedRunningStatistic& stat : m_statistics)
|
||||
{
|
||||
stat.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::PushSampleForStatistic(const AZStd::string& name, double value)
|
||||
{
|
||||
NamedRunningStatistic* stat = GetStatistic(name);
|
||||
if (!stat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
stat->PushSample(value);
|
||||
}
|
||||
|
||||
NamedRunningStatistic* RunningStatisticsManager::GetStatistic(const AZStd::string& name, AZ::u32* indexOut)
|
||||
{
|
||||
auto iterator = m_statisticsNamesToIndexMap.find(name);
|
||||
if (iterator == m_statisticsNamesToIndexMap.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const AZ::u32 index = iterator->second;
|
||||
if (indexOut)
|
||||
{
|
||||
*indexOut = index;
|
||||
}
|
||||
return &m_statistics[index];
|
||||
}
|
||||
|
||||
const AZStd::vector<NamedRunningStatistic>& RunningStatisticsManager::GetAllStatistics() const
|
||||
{
|
||||
return m_statistics;
|
||||
}
|
||||
|
||||
void RunningStatisticsManager::AddStatisticValidated(const AZStd::string& name, const AZStd::string& units)
|
||||
{
|
||||
m_statistics.emplace_back(NamedRunningStatistic(name, units));
|
||||
const AZ::u32 itemIndex = static_cast<AZ::u32>(m_statistics.size() - 1);
|
||||
m_statisticsNamesToIndexMap[name] = itemIndex;
|
||||
}
|
||||
|
||||
}//namespace Statistics
|
||||
}//namespace AzFramework
|
||||
@@ -8,7 +8,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/BusImpl.h> //Just to get AZ::NullMutex
|
||||
#include <AzCore/std/chrono/types.h>
|
||||
#include <AzCore/Statistics/StatisticsManager.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
@@ -37,8 +36,7 @@ namespace AZ
|
||||
//! are some things to consider when working with the StatisticalProfilerProxy:
|
||||
//! The StatisticalProfilerProxy OWNS an array of StatisticalProfiler<AZStd::string, AZStd::shared_spin_mutex>.
|
||||
//! You can "manage" one of those StatisticalProfiler by getting a reference to it and
|
||||
//! add Running statistics etc. See The TerrainProfilers mentioned above to see concrete use
|
||||
//! cases on how to work with the StatisticalProfilerProxy.
|
||||
//! add Running statistics etc.
|
||||
template <class StatIdType = AZStd::string, class MutexType = AZ::NullMutex>
|
||||
class StatisticalProfiler
|
||||
{
|
||||
|
||||
@@ -7,28 +7,12 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/chrono/types.h>
|
||||
#include <AzCore/std/parallel/shared_spin_mutex.h>
|
||||
#include <AzCore/std/parallel/scoped_lock.h>
|
||||
#include <AzCore/std/containers/bitset.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Statistics/StatisticalProfiler.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/parallel/shared_spin_mutex.h>
|
||||
|
||||
|
||||
#if defined(AZ_STATISTICAL_PROFILING_ENABLED)
|
||||
|
||||
#if defined(AZ_PROFILE_SCOPE)
|
||||
#undef AZ_PROFILE_SCOPE
|
||||
#endif // #if defined(AZ_PROFILE_SCOPE)
|
||||
|
||||
#define AZ_PROFILE_SCOPE(profiler, scopeNameId) \
|
||||
static const AZStd::string AZ_JOIN(blockName, __LINE__)(scopeNameId); \
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope AZ_JOIN(scope, __LINE__)(profiler, AZ_JOIN(blockName, __LINE__));
|
||||
|
||||
#endif //#if defined(AZ_STATISTICAL_PROFILING_ENABLED)
|
||||
|
||||
namespace AZ::Statistics
|
||||
{
|
||||
using StatisticalProfilerId = uint32_t;
|
||||
@@ -65,7 +49,7 @@ namespace AZ::Statistics
|
||||
public:
|
||||
AZ_TYPE_INFO(StatisticalProfilerProxy, "{1103D0EB-1C32-4854-B9D9-40A2D65BDBD2}");
|
||||
|
||||
using StatIdType = AZStd::string;
|
||||
using StatIdType = AZ::Crc32;
|
||||
using StatisticalProfilerType = StatisticalProfiler<StatIdType, AZStd::shared_spin_mutex>;
|
||||
|
||||
//! A Convenience class used to measure time performance of scopes of code
|
||||
@@ -94,6 +78,7 @@ namespace AZ::Statistics
|
||||
}
|
||||
m_startTime = AZStd::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
~TimedScope()
|
||||
{
|
||||
if (!m_profilerProxy)
|
||||
@@ -122,7 +107,6 @@ namespace AZ::Statistics
|
||||
|
||||
StatisticalProfilerProxy()
|
||||
{
|
||||
// TODO:BUDGETS Query available budgets at registration time and create an associated profiler per type
|
||||
AZ::Interface<StatisticalProfilerProxy>::Register(this);
|
||||
}
|
||||
|
||||
@@ -135,30 +119,54 @@ namespace AZ::Statistics
|
||||
StatisticalProfilerProxy(StatisticalProfilerProxy&&) = delete;
|
||||
StatisticalProfilerProxy& operator=(StatisticalProfilerProxy&&) = delete;
|
||||
|
||||
void RegisterProfilerId(StatisticalProfilerId id)
|
||||
{
|
||||
m_profilers.try_emplace(id, ProfilerInfo());
|
||||
}
|
||||
|
||||
bool IsProfilerActive(StatisticalProfilerId id) const
|
||||
{
|
||||
return m_activeProfilersFlag[static_cast<AZStd::size_t>(id)];
|
||||
auto iter = m_profilers.find(id);
|
||||
return (iter != m_profilers.end()) ? iter->second.m_enabled : false;
|
||||
}
|
||||
|
||||
StatisticalProfilerType& GetProfiler(StatisticalProfilerId id)
|
||||
{
|
||||
return m_profilers[static_cast<AZStd::size_t>(id)];
|
||||
auto iter = m_profilers.try_emplace(id, ProfilerInfo()).first;
|
||||
return iter->second.m_profiler;
|
||||
}
|
||||
|
||||
void ActivateProfiler(StatisticalProfilerId id, bool activate)
|
||||
void ActivateProfiler(StatisticalProfilerId id, bool activate, bool autoCreate = true)
|
||||
{
|
||||
m_activeProfilersFlag[static_cast<AZStd::size_t>(id)] = activate;
|
||||
if (autoCreate)
|
||||
{
|
||||
auto iter = m_profilers.try_emplace(id, ProfilerInfo()).first;
|
||||
iter->second.m_enabled = activate;
|
||||
}
|
||||
else if (auto iter = m_profilers.find(id); iter != m_profilers.end())
|
||||
{
|
||||
iter->second.m_enabled = activate;
|
||||
}
|
||||
}
|
||||
|
||||
void PushSample(StatisticalProfilerId id, const StatIdType& statId, double value)
|
||||
{
|
||||
m_profilers[static_cast<AZStd::size_t>(id)].PushSample(statId, value);
|
||||
if (auto iter = m_profilers.find(id); iter != m_profilers.end())
|
||||
{
|
||||
iter->second.m_profiler.PushSample(statId, value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// TODO:BUDGETS the number of bits allocated here must be based on the number of budgets available at profiler registration time
|
||||
AZStd::bitset<128> m_activeProfilersFlag;
|
||||
AZStd::vector<StatisticalProfilerType> m_profilers;
|
||||
struct ProfilerInfo
|
||||
{
|
||||
StatisticalProfilerType m_profiler;
|
||||
bool m_enabled{ false };
|
||||
};
|
||||
|
||||
using ProfilerMap = AZStd::unordered_map<StatisticalProfilerId, ProfilerInfo>;
|
||||
|
||||
ProfilerMap m_profilers;
|
||||
}; // class StatisticalProfilerProxy
|
||||
|
||||
}; // namespace AZ::Statistics
|
||||
|
||||
@@ -308,11 +308,11 @@ namespace AZ
|
||||
|
||||
void TaskExecutor::SetInstance(TaskExecutor* executor)
|
||||
{
|
||||
if (!executor)
|
||||
if (!executor) // allow unsetting the executor
|
||||
{
|
||||
s_executor.Reset();
|
||||
}
|
||||
else if (!s_executor) // ignore any calls to set after the first (this happens in unit tests that create new system entities)
|
||||
else if (!s_executor) // ignore any extra executors after the first (this happens during unit tests)
|
||||
{
|
||||
s_executor = AZ::Environment::CreateVariable<TaskExecutor*>(s_executorName, executor);
|
||||
}
|
||||
|
||||
@@ -11,9 +11,15 @@
|
||||
#include <AzCore/Task/TaskGraphSystemComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
|
||||
// Create a cvar as a central location for experimentation with switching from the Job system to TaskGraph system.
|
||||
AZ_CVAR(bool, cl_activateTaskGraph, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Flag clients of TaskGraph to switch between jobs/taskgraph (Note does not disable task graph system)");
|
||||
AZ_CVAR(float, cl_taskGraphThreadsConcurrencyRatio, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph calculate the number of worker threads to spawn by scaling the number of hw threads, value is clamped between 0.0f and 1.0f");
|
||||
AZ_CVAR(uint32_t, cl_taskGraphThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph number of hardware threads that are reserved for O3DE system threads. Value is clamped between 0 and the number of logical cores in the system");
|
||||
AZ_CVAR(uint32_t, cl_taskGraphThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph minimum number of worker threads to create after scaling the number of hw threads");
|
||||
|
||||
static constexpr uint32_t TaskExecutorServiceCrc = AZ_CRC_CE("TaskExecutorService");
|
||||
|
||||
namespace AZ
|
||||
@@ -24,8 +30,8 @@ namespace AZ
|
||||
|
||||
if (Interface<TaskGraphActiveInterface>::Get() == nullptr)
|
||||
{
|
||||
Interface<TaskGraphActiveInterface>::Register(this);
|
||||
m_taskExecutor = aznew TaskExecutor();
|
||||
Interface<TaskGraphActiveInterface>::Register(this); // small window that another thread can try to use taskgraph between this line and the set instance.
|
||||
m_taskExecutor = aznew TaskExecutor(Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved));
|
||||
TaskExecutor::SetInstance(m_taskExecutor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Threading/ThreadUtils.h>
|
||||
#include <AzCore/std/parallel/thread.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
namespace AZ::Threading
|
||||
{
|
||||
uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads)
|
||||
{
|
||||
const uint32_t maxHardwareThreads = AZStd::thread::hardware_concurrency();
|
||||
const uint32_t numReservedThreads = AZ::GetMin<uint32_t>(reservedNumThreads, maxHardwareThreads); // protect against num reserved being bigger than the number of hw threads
|
||||
const uint32_t maxWorkerThreads = maxHardwareThreads - numReservedThreads;
|
||||
const float requestedWorkerThreads = AZ::GetClamp<float>(workerThreadsRatio, 0.0f, 1.0f) * static_cast<float>(maxWorkerThreads);
|
||||
const uint32_t requestedWorkerThreadsRounded = AZStd::lround(requestedWorkerThreads);
|
||||
const uint32_t numWorkerThreads = AZ::GetMax<uint32_t>(minNumWorkerThreads, requestedWorkerThreadsRounded);
|
||||
return numWorkerThreads;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
|
||||
namespace AZ::Threading
|
||||
{
|
||||
//! Calculates the number of worker threads a system should use based on the number of hardware threads a device has.
|
||||
//! result = max (minNumWorkerThreads, workerThreadsRatio * (num_hardware_threads - reservedNumThreads))
|
||||
//! @param workerThreadsRatio scale applied to the calculated maximum number of threads available after reserved threads have been accounted for. Clamped between 0 and 1.
|
||||
//! @param minNumWorkerThreads minimum value that will be returned. Value is unclamped and can be more than num_hardware_threads.
|
||||
//! @param reservedNumThreads number of hardware threads to reserve for O3DE system threads. Value clamped to num_hardware_threads.
|
||||
//! @return number of worker threads for the calling system to allocate
|
||||
uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads);
|
||||
};
|
||||
@@ -13,14 +13,26 @@
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/std/time.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
//! This is a strong typedef for representing a millisecond value since application start.
|
||||
AZ_TYPE_SAFE_INTEGRAL(TimeMs, int64_t);
|
||||
|
||||
//! This is a strong typedef for representing a microsecond value since application start.
|
||||
//! Using int64_t as the underlying type, this is good to represent approximately 292,471 years
|
||||
AZ_TYPE_SAFE_INTEGRAL(TimeUs, int64_t);
|
||||
|
||||
//! @class ITime
|
||||
//! @brief This is an AZ::Interface<> for managing time related operations.
|
||||
//! AZ::ITime and associated types may not operate in realtime. These abstractions are to allow our application
|
||||
//! simulation to operate both slower and faster than realtime in a well defined and user controllable manner
|
||||
//! The rate at which time passes for AZ::ITime is controlled by the cvar t_scale
|
||||
//! t_scale == 0 means simulation time should halt
|
||||
//! 0 < t_scale < 1 will cause time to pass slower than realtime, with t_scale 0.1 being roughly 1/10th realtime
|
||||
//! t_scale == 1 will cause time to pass at roughly realtime
|
||||
//! t_scale > 1 will cause time to pass faster than normal, with t_scale 10 being roughly 10x realtime
|
||||
class ITime
|
||||
{
|
||||
public:
|
||||
@@ -33,6 +45,10 @@ namespace AZ
|
||||
//! @return the number of milliseconds that have elapsed since application start
|
||||
virtual TimeMs GetElapsedTimeMs() const = 0;
|
||||
|
||||
//! Returns the number of microseconds since application start.
|
||||
//! @return the number of microseconds that have elapsed since application start
|
||||
virtual TimeUs GetElapsedTimeUs() const = 0;
|
||||
|
||||
AZ_DISABLE_COPY_MOVE(ITime);
|
||||
};
|
||||
|
||||
@@ -51,6 +67,53 @@ namespace AZ
|
||||
{
|
||||
return AZ::Interface<ITime>::Get()->GetElapsedTimeMs();
|
||||
}
|
||||
}
|
||||
|
||||
//! This is a simple convenience wrapper
|
||||
inline TimeUs GetElapsedTimeUs()
|
||||
{
|
||||
return AZ::Interface<ITime>::Get()->GetElapsedTimeUs();
|
||||
}
|
||||
|
||||
//! Converts from milliseconds to microseconds
|
||||
inline TimeUs TimeMsToUs(TimeMs value)
|
||||
{
|
||||
return static_cast<TimeUs>(value * static_cast<TimeMs>(1000));
|
||||
}
|
||||
|
||||
//! Converts from microseconds to milliseconds
|
||||
inline TimeMs TimeUsToMs(TimeUs value)
|
||||
{
|
||||
return static_cast<TimeMs>(value / static_cast<TimeUs>(1000));
|
||||
}
|
||||
|
||||
//! Converts from milliseconds to seconds
|
||||
inline float TimeMsToSeconds(TimeMs value)
|
||||
{
|
||||
return static_cast<float>(value) / 1000.0f;
|
||||
}
|
||||
|
||||
//! Converts from microseconds to seconds
|
||||
inline float TimeUsToSeconds(TimeUs value)
|
||||
{
|
||||
return static_cast<float>(value) / 1000000.0f;
|
||||
}
|
||||
|
||||
//! Converts from milliseconds to AZStd::chrono::time_point
|
||||
inline auto TimeMsToChrono(TimeMs value)
|
||||
{
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoValue = AZStd::chrono::milliseconds(aznumeric_cast<int64_t>(value));
|
||||
return epoch + chronoValue;
|
||||
}
|
||||
|
||||
//! Converts from microseconds to AZStd::chrono::time_point
|
||||
inline auto TimeUsToChrono(TimeUs value)
|
||||
{
|
||||
auto epoch = AZStd::chrono::time_point<AZStd::chrono::high_resolution_clock>();
|
||||
auto chronoValue = AZStd::chrono::microseconds(aznumeric_cast<int64_t>(value));
|
||||
return epoch + chronoValue;
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(AZ::TimeMs);
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(AZ::TimeUs);
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace AZ
|
||||
|
||||
TimeSystemComponent::TimeSystemComponent()
|
||||
{
|
||||
m_lastInvokedTimeMs = static_cast<TimeMs>(AZStd::GetTimeNowMicroSecond() / 1000);
|
||||
m_lastInvokedTimeUs = static_cast<TimeUs>(AZStd::GetTimeNowMicroSecond());
|
||||
AZ::Interface<ITime>::Register(this);
|
||||
ITimeRequestBus::Handler::BusConnect();
|
||||
}
|
||||
@@ -58,18 +58,23 @@ namespace AZ
|
||||
|
||||
TimeMs TimeSystemComponent::GetElapsedTimeMs() const
|
||||
{
|
||||
TimeMs currentTime = static_cast<TimeMs>(AZStd::GetTimeNowMicroSecond() / 1000);
|
||||
TimeMs deltaTime = currentTime - m_lastInvokedTimeMs;
|
||||
return TimeUsToMs(GetElapsedTimeUs());
|
||||
}
|
||||
|
||||
TimeUs TimeSystemComponent::GetElapsedTimeUs() const
|
||||
{
|
||||
TimeUs currentTime = static_cast<TimeUs>(AZStd::GetTimeNowMicroSecond());
|
||||
TimeUs deltaTime = currentTime - m_lastInvokedTimeUs;
|
||||
|
||||
if (t_scale != 1.0f)
|
||||
{
|
||||
float floatDelta = static_cast<float>(deltaTime) * t_scale;
|
||||
deltaTime = static_cast<TimeMs>(static_cast<int64_t>(floatDelta));
|
||||
deltaTime = static_cast<TimeUs>(static_cast<int64_t>(floatDelta));
|
||||
}
|
||||
|
||||
m_accumulatedTimeMs += deltaTime;
|
||||
m_lastInvokedTimeMs = currentTime;
|
||||
m_accumulatedTimeUs += deltaTime;
|
||||
m_lastInvokedTimeUs = currentTime;
|
||||
|
||||
return m_accumulatedTimeMs;
|
||||
return m_accumulatedTimeUs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,11 +39,12 @@ namespace AZ
|
||||
//! ITime overrides.
|
||||
//! @{
|
||||
TimeMs GetElapsedTimeMs() const override;
|
||||
TimeUs GetElapsedTimeUs() const override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
|
||||
mutable TimeMs m_lastInvokedTimeMs = TimeMs{0};
|
||||
mutable TimeMs m_accumulatedTimeMs = TimeMs{0};
|
||||
mutable TimeUs m_lastInvokedTimeUs = TimeUs{0};
|
||||
mutable TimeUs m_accumulatedTimeUs = TimeUs{0};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
MOCK_METHOD2(SetAlias, void(const char* alias, const char* path));
|
||||
MOCK_METHOD1(ClearAlias, void(const char* alias));
|
||||
MOCK_CONST_METHOD1(GetAlias, const char*(const char* alias));
|
||||
MOCK_METHOD2(SetDeprecatedAlias, void(AZStd::string_view, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, AZStd::optional<AZ::u64>(char* inOutBuffer, AZ::u64 bufferLength));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, bool(AZ::IO::FixedMaxPath& aliasPath, const AZ::IO::PathView& path));
|
||||
MOCK_CONST_METHOD3(ResolvePath, bool(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize));
|
||||
|
||||
@@ -51,6 +51,20 @@ namespace AZ::Utils
|
||||
return executableDirectory;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
if (ConvertToAbsolutePath(srcPath.c_str(), absolutePath.data(), absolutePath.capacity()))
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
{
|
||||
AZ::IO::FixedMaxPath o3deManifestPath = GetO3deManifestDirectory();
|
||||
|
||||
@@ -104,6 +104,7 @@ namespace AZ
|
||||
// Attempts the supplied path to an absolute path.
|
||||
//! Returns nullopt if path cannot be converted to an absolute path
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path);
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 absolutePathMaxSize);
|
||||
|
||||
//! Save a string to a file. Otherwise returns a failure with error message.
|
||||
AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath);
|
||||
|
||||
@@ -566,6 +566,8 @@ set(FILES
|
||||
Settings/SettingsRegistryMergeUtils.h
|
||||
Settings/SettingsRegistryScriptUtils.cpp
|
||||
Settings/SettingsRegistryScriptUtils.h
|
||||
Settings/SettingsRegistryVisitorUtils.cpp
|
||||
Settings/SettingsRegistryVisitorUtils.h
|
||||
State/HSM.cpp
|
||||
State/HSM.h
|
||||
Statistics/NamedRunningStatistic.h
|
||||
@@ -639,6 +641,8 @@ set(FILES
|
||||
Threading/ThreadSafeDeque.inl
|
||||
Threading/ThreadSafeObject.h
|
||||
Threading/ThreadSafeObject.inl
|
||||
Threading/ThreadUtils.h
|
||||
Threading/ThreadUtils.cpp
|
||||
Time/ITime.h
|
||||
Time/TimeSystemComponent.cpp
|
||||
Time/TimeSystemComponent.h
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/std/allocator_stateless.h>
|
||||
#include <AzCore/Memory/OSAllocator.h>
|
||||
|
||||
namespace AZStd
|
||||
{
|
||||
stateless_allocator::stateless_allocator(const char* name)
|
||||
: m_name(name) {}
|
||||
|
||||
const char* stateless_allocator::get_name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void stateless_allocator::set_name(const char* name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
auto stateless_allocator::allocate(size_type byteSize) -> pointer_type
|
||||
{
|
||||
return allocate(byteSize, AZ_DEFAULT_ALIGNMENT, 0);
|
||||
}
|
||||
|
||||
auto stateless_allocator::allocate(size_type byteSize, size_type alignment, int) -> pointer_type
|
||||
{
|
||||
pointer_type address = AZ_OS_MALLOC(byteSize, alignment);
|
||||
|
||||
if (address == nullptr)
|
||||
{
|
||||
AZ_Error("Memory", false, "stateless_allocator ran out of system memory!\n");
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void stateless_allocator::deallocate(pointer_type ptr, size_type)
|
||||
{
|
||||
AZ_OS_FREE(ptr);
|
||||
}
|
||||
|
||||
void stateless_allocator::deallocate(pointer_type ptr, size_type, size_type)
|
||||
{
|
||||
AZ_OS_FREE(ptr);
|
||||
}
|
||||
|
||||
auto stateless_allocator::max_size() const -> size_type
|
||||
{
|
||||
return AZ_CORE_MAX_ALLOCATOR_SIZE;
|
||||
}
|
||||
|
||||
stateless_allocator stateless_allocator::select_on_container_copy_construction() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto stateless_allocator::resize(pointer_type, size_type) -> size_type
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool stateless_allocator::is_lock_free()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool stateless_allocator::is_stale_read_allowed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool stateless_allocator::is_delayed_recycling()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// comparison operators
|
||||
bool operator==(const stateless_allocator&, const stateless_allocator&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!=(const stateless_allocator&, const stateless_allocator&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/base.h>
|
||||
#include <AzCore/std/typetraits/integral_constant.h>
|
||||
#include <AzCore/RTTI/TypeInfoSimple.h>
|
||||
|
||||
namespace AZStd
|
||||
{
|
||||
class stateless_allocator
|
||||
{
|
||||
public:
|
||||
|
||||
AZ_TYPE_INFO(stateless_allocator, "{E4976C53-0B20-4F39-8D41-0A76F59A7D68}");
|
||||
|
||||
using value_type = uint8_t;
|
||||
using pointer_type = void*;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using allow_memory_leaks = AZStd::true_type;
|
||||
|
||||
stateless_allocator(const char* name = "AZStd::stateless_allocator");
|
||||
stateless_allocator(const stateless_allocator& rhs) = default;
|
||||
|
||||
stateless_allocator& operator=(const stateless_allocator& rhs) = default;
|
||||
|
||||
const char* get_name() const;
|
||||
void set_name(const char* name);
|
||||
|
||||
pointer_type allocate(size_type byteSize);
|
||||
pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0);
|
||||
void deallocate(pointer_type ptr, size_type alignment);
|
||||
void deallocate(pointer_type ptr, size_type byteSize, size_type alignment);
|
||||
|
||||
// max_size actually returns the true maximum size of a single allocation
|
||||
size_type max_size() const;
|
||||
|
||||
// Returns a copy of the allocator
|
||||
stateless_allocator select_on_container_copy_construction() const;
|
||||
|
||||
//! extensions
|
||||
size_type resize(pointer_type ptr, size_type newSize);
|
||||
|
||||
bool is_lock_free();
|
||||
bool is_stale_read_allowed();
|
||||
bool is_delayed_recycling();
|
||||
|
||||
private:
|
||||
const char* m_name;
|
||||
};
|
||||
|
||||
bool operator==(const stateless_allocator& left, const stateless_allocator& right);
|
||||
bool operator!=(const stateless_allocator& left, const stateless_allocator& right);
|
||||
}
|
||||
@@ -12,6 +12,8 @@ set(FILES
|
||||
allocator.h
|
||||
allocator_ref.h
|
||||
allocator_stack.h
|
||||
allocator_stateless.cpp
|
||||
allocator_stateless.h
|
||||
allocator_static.h
|
||||
allocator_traits.h
|
||||
any.h
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace AZStd
|
||||
{
|
||||
// alias std::pointer_traits into the AZStd::namespace
|
||||
// alias std::pointer_traits into the AZStd::namespace
|
||||
using std::pointer_traits;
|
||||
|
||||
//! Bring the names of uninitialized_default_construct and
|
||||
@@ -229,7 +229,7 @@ namespace AZStd
|
||||
//! `new (declval<void*>()) T(declval<Args>()...)` is well-formed
|
||||
template <typename T, typename... Args>
|
||||
constexpr auto construct_at(T* ptr, Args&&... args)
|
||||
-> enable_if_t<is_void_v<void_t<decltype(new (declval<void*>()) T(AZStd::forward<Args>(args)...))>>, T*>
|
||||
-> enable_if_t<AZStd::is_void_v<AZStd::void_t<decltype(new (AZStd::declval<void*>()) T(AZStd::forward<Args>(args)...))>>, T*>
|
||||
{
|
||||
return ::new (ptr) T(AZStd::forward<Args>(args)...);
|
||||
}
|
||||
@@ -487,7 +487,7 @@ namespace AZStd
|
||||
{
|
||||
//! Implements the C++17 uninitialized_move function
|
||||
//! The functions accepts two input iterators and an output iterator
|
||||
//! It performs an AZStd::move on each in in the range of the input iterator
|
||||
//! It performs an AZStd::move on each in in the range of the input iterator
|
||||
//! and stores the result in location pointed by the output iterator
|
||||
template <typename InputIt, typename ForwardIt>
|
||||
ForwardIt uninitialized_move(InputIt first, InputIt last, ForwardIt result)
|
||||
|
||||
@@ -30,4 +30,49 @@ namespace AZStd
|
||||
using std::sqrt;
|
||||
using std::tan;
|
||||
using std::trunc;
|
||||
|
||||
} // namespace AZStd
|
||||
|
||||
// from c++20 standard
|
||||
namespace AZStd::Internal
|
||||
{
|
||||
template<typename T>
|
||||
constexpr T lerp(T a, T b, T t) noexcept
|
||||
{
|
||||
if ((a <= 0 && b >= 0) || (a >= 0 && b <= 0))
|
||||
{
|
||||
return t * b + (1 - t) * a;
|
||||
}
|
||||
if (t == 1)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
const T x = a + t * (b - a);
|
||||
if ((t > 1) == (b > a))
|
||||
{
|
||||
return b < x ? x : b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return x < b ? x : b;
|
||||
}
|
||||
}
|
||||
} // namespace AZStd::Internal
|
||||
|
||||
namespace AZStd
|
||||
{
|
||||
constexpr float lerp(float a, float b, float t) noexcept
|
||||
{
|
||||
return Internal::lerp(a, b, t);
|
||||
}
|
||||
|
||||
constexpr double lerp(double a, double b, double t) noexcept
|
||||
{
|
||||
return Internal::lerp(a, b, t);
|
||||
}
|
||||
|
||||
constexpr long double lerp(long double a, long double b, long double t) noexcept
|
||||
{
|
||||
return Internal::lerp(a, b, t);
|
||||
}
|
||||
} // namespace AZStd
|
||||
|
||||
@@ -39,7 +39,7 @@ ly_add_target(
|
||||
3rdParty::Lua
|
||||
3rdParty::RapidJSON
|
||||
3rdParty::RapidXML
|
||||
3rdParty::zlib
|
||||
3rdParty::ZLIB
|
||||
3rdParty::zstd
|
||||
3rdParty::cityhash
|
||||
${AZ_CORE_PIX_BUILD_DEPENDENCIES}
|
||||
|
||||
@@ -368,6 +368,21 @@ namespace Platform
|
||||
return access(fileName, F_OK) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsDirectory(const char* filePath)
|
||||
{
|
||||
if (AZ::Android::Utils::IsApkPath(filePath))
|
||||
{
|
||||
return AZ::Android::APKFileHandler::IsDirectory(AZ::Android::Utils::StripApkPrefix(filePath).c_str());
|
||||
}
|
||||
|
||||
struct stat result;
|
||||
if (stat(filePath, &result) == 0)
|
||||
{
|
||||
return S_ISDIR(result.st_mode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace AZ::IO::Platform
|
||||
|
||||
} // namespace AZ::IO
|
||||
|
||||
@@ -60,23 +60,34 @@ namespace AZ
|
||||
return writeStorage ? AZStd::make_optional<AZ::IO::FixedMaxPathString>(writeStorage) : AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
if (AZ::Android::Utils::IsApkPath(srcPath.c_str()))
|
||||
if (AZ::Android::Utils::IsApkPath(path))
|
||||
{
|
||||
return srcPath;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
|
||||
#ifdef PATH_MAX
|
||||
static constexpr size_t UnixMaxPathLength = PATH_MAX;
|
||||
#else
|
||||
// Fallback to 4096 if the PATH_MAX macro isn't defined on the Unix System
|
||||
static constexpr size_t UnixMaxPathLength = 4096;
|
||||
#endif
|
||||
if (!AZ::IO::PathView(path).IsAbsolute())
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return absolutePath;
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
char absolutePathBuffer[UnixMaxPathLength];
|
||||
if (const char* result = realpath(path, absolutePathBuffer); result != nullptr)
|
||||
{
|
||||
azstrcpy(absolutePath, maxLength, absolutePathBuffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return AZ::IO::PathView(absolutePath).IsAbsolute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace AZ
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (size_t i = tracerPidOffset; i < numRead; ++i)
|
||||
for (size_t i = tracerPidOffset + tracerPidString.length(); i < numRead; ++i)
|
||||
{
|
||||
if (!::isspace(processStatusView[i]))
|
||||
{
|
||||
|
||||
@@ -47,23 +47,32 @@ namespace AZ
|
||||
AZ::IO::FixedMaxPath path{pass->pw_dir};
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
|
||||
if (char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
|
||||
#ifdef PATH_MAX
|
||||
static constexpr size_t UnixMaxPathLength = PATH_MAX;
|
||||
#else
|
||||
// Fallback to 4096 if the PATH_MAX macro isn't defined on the Unix System
|
||||
static constexpr size_t UnixMaxPathLength = 4096;
|
||||
#endif
|
||||
if (!AZ::IO::PathView(path).IsAbsolute())
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return absolutePath;
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
char absolutePathBuffer[UnixMaxPathLength];
|
||||
if (const char* result = realpath(path, absolutePathBuffer); result != nullptr)
|
||||
{
|
||||
azstrcpy(absolutePath, maxLength, absolutePathBuffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return AZ::IO::PathView(absolutePath).IsAbsolute();
|
||||
}
|
||||
} // namespace Utils
|
||||
} // namespace AZ
|
||||
|
||||
+4
@@ -59,6 +59,10 @@ namespace AZStd
|
||||
{
|
||||
priority = desc->m_priority;
|
||||
}
|
||||
else
|
||||
{
|
||||
priority = SCHED_OTHER;
|
||||
}
|
||||
if (desc->m_name)
|
||||
{
|
||||
name = desc->m_name;
|
||||
|
||||
+10
@@ -249,6 +249,16 @@ namespace Platform
|
||||
{
|
||||
return access(fileName, F_OK) == 0;
|
||||
}
|
||||
|
||||
bool IsDirectory(const char* filePath)
|
||||
{
|
||||
struct stat result;
|
||||
if (stat(filePath, &result) == 0)
|
||||
{
|
||||
return S_ISDIR(result.st_mode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AZ::IO
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/FileIOEventBus.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
@@ -18,7 +19,7 @@
|
||||
|
||||
namespace AZ::IO
|
||||
{
|
||||
|
||||
using FixedMaxPathWString = AZStd::fixed_wstring<MaxPathLength>;
|
||||
namespace
|
||||
{
|
||||
//=========================================================================
|
||||
@@ -28,16 +29,9 @@ namespace
|
||||
//=========================================================================
|
||||
DWORD GetAttributes(const char* fileName)
|
||||
{
|
||||
wchar_t fileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
{
|
||||
return GetFileAttributesW(fileNameW);
|
||||
}
|
||||
else
|
||||
{
|
||||
return INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
FixedMaxPathWString fileNameW;
|
||||
AZStd::to_wstring(fileNameW, fileName);
|
||||
return GetFileAttributesW(fileNameW.c_str());
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -47,16 +41,9 @@ namespace
|
||||
//=========================================================================
|
||||
BOOL SetAttributes(const char* fileName, DWORD fileAttributes)
|
||||
{
|
||||
wchar_t fileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
{
|
||||
return SetFileAttributesW(fileNameW, fileAttributes);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
FixedMaxPathWString fileNameW;
|
||||
AZStd::to_wstring(fileNameW, fileName);
|
||||
return SetFileAttributesW(fileNameW.c_str(), fileAttributes);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -68,9 +55,9 @@ namespace
|
||||
// * GetLastError() on Windows-like platforms
|
||||
// * errno on Unix platforms
|
||||
//=========================================================================
|
||||
bool CreateDirRecursive(wchar_t* dirPath)
|
||||
bool CreateDirRecursive(AZ::IO::FixedMaxPathWString& dirPath)
|
||||
{
|
||||
if (CreateDirectoryW(dirPath, nullptr))
|
||||
if (CreateDirectoryW(dirPath.c_str(), nullptr))
|
||||
{
|
||||
return true; // Created without error
|
||||
}
|
||||
@@ -78,28 +65,24 @@ namespace
|
||||
if (error == ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
// try to create our parent hierarchy
|
||||
for (size_t i = wcslen(dirPath); i > 0; --i)
|
||||
if (size_t i = dirPath.find_last_of(LR"(/\)"); i != FixedMaxPathWString::npos)
|
||||
{
|
||||
if (dirPath[i] == L'/' || dirPath[i] == L'\\')
|
||||
wchar_t delimiter = dirPath[i];
|
||||
dirPath[i] = 0; // null-terminate at the previous slash
|
||||
const bool ret = CreateDirRecursive(dirPath);
|
||||
dirPath[i] = delimiter; // restore slash
|
||||
if (ret)
|
||||
{
|
||||
wchar_t delimiter = dirPath[i];
|
||||
dirPath[i] = 0; // null-terminate at the previous slash
|
||||
bool ret = CreateDirRecursive(dirPath);
|
||||
dirPath[i] = delimiter; // restore slash
|
||||
if (ret)
|
||||
{
|
||||
// now that our parent is created, try to create again
|
||||
return CreateDirectoryW(dirPath, nullptr) != 0;
|
||||
}
|
||||
return false;
|
||||
// now that our parent is created, try to create again
|
||||
return CreateDirectoryW(dirPath.c_str(), nullptr) != 0;
|
||||
}
|
||||
}
|
||||
// if we reach here then there was no parent folder to create, so we failed for other reasons
|
||||
}
|
||||
else if (error == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW(dirPath);
|
||||
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
DWORD attributes = GetFileAttributesW(dirPath.c_str());
|
||||
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -152,13 +135,10 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
|
||||
CreatePath(m_fileName.c_str());
|
||||
}
|
||||
|
||||
wchar_t fileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
AZ::IO::FixedMaxPathWString fileNameW;
|
||||
AZStd::to_wstring(fileNameW, m_fileName);
|
||||
m_handle = INVALID_HANDLE_VALUE;
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, m_fileName.c_str(), AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
{
|
||||
m_handle = CreateFileW(fileNameW, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
|
||||
}
|
||||
m_handle = CreateFileW(fileNameW.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
|
||||
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@@ -350,6 +330,12 @@ namespace Platform
|
||||
return GetAttributes(fileName) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
bool IsDirectory(const char* filePath)
|
||||
{
|
||||
DWORD attributes = GetAttributes(filePath);
|
||||
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
}
|
||||
|
||||
|
||||
void FindFiles(const char* filter, SystemFile::FindFileCB cb)
|
||||
{
|
||||
@@ -357,35 +343,26 @@ namespace Platform
|
||||
HANDLE hFile;
|
||||
int lastError;
|
||||
|
||||
wchar_t filterW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
AZ::IO::FixedMaxPathWString filterW;
|
||||
AZStd::to_wstring(filterW, filter);
|
||||
hFile = INVALID_HANDLE_VALUE;
|
||||
if (mbstowcs_s(&numCharsConverted, filterW, filter, AZ_ARRAY_SIZE(filterW) - 1) == 0)
|
||||
{
|
||||
hFile = FindFirstFile(filterW, &fd);
|
||||
}
|
||||
hFile = FindFirstFileW(filterW.c_str(), &fd);
|
||||
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
const char* fileName;
|
||||
|
||||
char fileNameA[AZ_MAX_PATH_LEN];
|
||||
fileName = NULL;
|
||||
if (wcstombs_s(&numCharsConverted, fileNameA, fd.cFileName, AZ_ARRAY_SIZE(fileNameA) - 1) == 0)
|
||||
{
|
||||
fileName = fileNameA;
|
||||
}
|
||||
AZ::IO::FixedMaxPathString fileNameUtf8;
|
||||
AZStd::to_string(fileNameUtf8, fd.cFileName);
|
||||
fileName = fileNameUtf8.c_str();
|
||||
|
||||
cb(fileName, (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
|
||||
|
||||
// List all the other files in the directory.
|
||||
while (FindNextFileW(hFile, &fd) != 0)
|
||||
{
|
||||
fileName = NULL;
|
||||
if (wcstombs_s(&numCharsConverted, fileNameA, fd.cFileName, AZ_ARRAY_SIZE(fileNameA) - 1) == 0)
|
||||
{
|
||||
fileName = fileNameA;
|
||||
}
|
||||
AZStd::to_string(fileNameUtf8, fd.cFileName);
|
||||
fileName = fileNameUtf8.c_str();
|
||||
|
||||
cb(fileName, (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0);
|
||||
}
|
||||
@@ -411,12 +388,9 @@ namespace Platform
|
||||
{
|
||||
HANDLE handle = nullptr;
|
||||
|
||||
wchar_t fileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
{
|
||||
handle = CreateFileW(fileNameW, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
}
|
||||
AZ::IO::FixedMaxPathWString fileNameW;
|
||||
AZStd::to_wstring(fileNameW, fileName);
|
||||
handle = CreateFileW(fileNameW.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
@@ -448,12 +422,9 @@ namespace Platform
|
||||
WIN32_FILE_ATTRIBUTE_DATA data = { 0 };
|
||||
BOOL result = FALSE;
|
||||
|
||||
wchar_t fileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
{
|
||||
result = GetFileAttributesExW(fileNameW, GetFileExInfoStandard, &data);
|
||||
}
|
||||
AZ::IO::FixedMaxPathWString fileNameW;
|
||||
AZStd::to_wstring(fileNameW, fileName);
|
||||
result = GetFileAttributesExW(fileNameW.c_str(), GetFileExInfoStandard, &data);
|
||||
|
||||
if (result)
|
||||
{
|
||||
@@ -473,18 +444,11 @@ namespace Platform
|
||||
|
||||
bool Delete(const char* fileName)
|
||||
{
|
||||
wchar_t fileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
{
|
||||
if (DeleteFileW(fileNameW) == 0)
|
||||
{
|
||||
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
AZ::IO::FixedMaxPathWString fileNameW;
|
||||
AZStd::to_wstring(fileNameW, fileName);
|
||||
if (DeleteFileW(fileNameW.c_str()) == 0)
|
||||
{
|
||||
EBUS_EVENT(FileIOEventBus, OnError, nullptr, fileName, (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -493,20 +457,13 @@ namespace Platform
|
||||
|
||||
bool Rename(const char* sourceFileName, const char* targetFileName, bool overwrite)
|
||||
{
|
||||
wchar_t sourceFileNameW[AZ_MAX_PATH_LEN];
|
||||
wchar_t targetFileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, sourceFileNameW, sourceFileName, AZ_ARRAY_SIZE(sourceFileNameW) - 1) == 0 &&
|
||||
mbstowcs_s(&numCharsConverted, targetFileNameW, targetFileName, AZ_ARRAY_SIZE(targetFileNameW) - 1) == 0)
|
||||
{
|
||||
if (MoveFileExW(sourceFileNameW, targetFileNameW, overwrite ? MOVEFILE_REPLACE_EXISTING : 0) == 0)
|
||||
{
|
||||
EBUS_EVENT(FileIOEventBus, OnError, nullptr, sourceFileName, (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
AZ::IO::FixedMaxPathWString sourceFileNameW;
|
||||
AZStd::to_wstring(sourceFileNameW, sourceFileName);
|
||||
AZ::IO::FixedMaxPathWString targetFileNameW;
|
||||
AZStd::to_wstring(targetFileNameW, targetFileName);
|
||||
if (MoveFileExW(sourceFileNameW.c_str(), targetFileNameW.c_str(), overwrite ? MOVEFILE_REPLACE_EXISTING : 0) == 0)
|
||||
{
|
||||
EBUS_EVENT(FileIOEventBus, OnError, nullptr, sourceFileName, (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -543,17 +500,14 @@ namespace Platform
|
||||
{
|
||||
if (dirName)
|
||||
{
|
||||
wchar_t dirPath[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, dirPath, dirName, AZ_ARRAY_SIZE(dirPath) - 1) == 0)
|
||||
AZ::IO::FixedMaxPathWString dirNameW;
|
||||
AZStd::to_wstring(dirNameW, dirName);
|
||||
bool success = CreateDirRecursive(dirNameW);
|
||||
if (!success)
|
||||
{
|
||||
bool success = CreateDirRecursive(dirPath);
|
||||
if (!success)
|
||||
{
|
||||
EBUS_EVENT(FileIOEventBus, OnError, nullptr, dirName, (int)GetLastError());
|
||||
}
|
||||
return success;
|
||||
EBUS_EVENT(FileIOEventBus, OnError, nullptr, dirName, (int)GetLastError());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -562,12 +516,9 @@ namespace Platform
|
||||
{
|
||||
if (dirName)
|
||||
{
|
||||
wchar_t dirNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
if (mbstowcs_s(&numCharsConverted, dirNameW, dirName, AZ_ARRAY_SIZE(dirNameW) - 1) == 0)
|
||||
{
|
||||
return RemoveDirectory(dirNameW) != 0;
|
||||
}
|
||||
AZ::IO::FixedMaxPathWString dirNameW;
|
||||
AZStd::to_wstring(dirNameW, dirName);
|
||||
return RemoveDirectory(dirNameW.c_str()) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -67,19 +67,12 @@ namespace AZ
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
char* result = _fullpath(absolutePath.data(), srcPath.c_str(), absolutePath.capacity());
|
||||
// Force update of the fixed_string size() value
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
if (result)
|
||||
{
|
||||
return absolutePath;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
char* result = _fullpath(absolutePath, path, maxLength);
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/std/math.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
template<typename T>
|
||||
class StdMathTest : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
using MathTestConfigs = ::testing::Types<float, double, long double>;
|
||||
TYPED_TEST_CASE(StdMathTest, MathTestConfigs);
|
||||
|
||||
TYPED_TEST(StdMathTest, LerpOperations)
|
||||
{
|
||||
using AZStd::lerp;
|
||||
using ::testing::Eq;
|
||||
using T = TypeParam;
|
||||
|
||||
constexpr T maxNumber = AZStd::numeric_limits<T>::max();
|
||||
constexpr T eps = AZStd::numeric_limits<T>::epsilon();
|
||||
constexpr T a{ 42 };
|
||||
|
||||
// exactness: lerp(a,b,0)==a && lerp(a,b,1)==b
|
||||
EXPECT_THAT(lerp(eps, maxNumber, T(0)), Eq(eps));
|
||||
EXPECT_THAT(lerp(eps, maxNumber, T(1)), Eq(maxNumber));
|
||||
|
||||
// consistency: lerp(a,a,t)==a
|
||||
EXPECT_THAT(lerp(a, a, T(0.5)), Eq(a));
|
||||
EXPECT_THAT(lerp(eps, eps, T(0.5)), Eq(eps));
|
||||
|
||||
// a few generic tests taken from MathUtilTests.cpp
|
||||
EXPECT_EQ(T(2.5), lerp(T(2), T(4), T(0.25)));
|
||||
EXPECT_EQ(T(6.0), lerp(T(2), T(4), T(2.0)));
|
||||
EXPECT_EQ(T(3.5), lerp(T(2), T(4), T(0.75)));
|
||||
EXPECT_EQ(T(0.0), lerp(T(2), T(4), T(-1.0)));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
@@ -64,6 +64,91 @@ namespace JsonSerializationTests
|
||||
|
||||
};
|
||||
|
||||
class TestSerializedAssetTracker
|
||||
: public BaseJsonSerializerFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
BaseJsonSerializerFixture::SetUp();
|
||||
|
||||
AZ::AllocatorInstance<AZ::PoolAllocator>::Create();
|
||||
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Create();
|
||||
|
||||
// Set up the Job Manager with 1 thread so that the Asset Manager is able to load assets.
|
||||
AZ::JobManagerDesc jobDesc;
|
||||
AZ::JobManagerThreadDesc threadDesc;
|
||||
jobDesc.m_workerThreads.push_back(threadDesc);
|
||||
m_jobManager = aznew AZ::JobManager(jobDesc);
|
||||
m_jobContext = aznew AZ::JobContext(*m_jobManager);
|
||||
AZ::JobContext::SetGlobalContext(m_jobContext);
|
||||
|
||||
AZ::Data::AssetManager::Descriptor descriptor;
|
||||
AZ::Data::AssetManager::Create(descriptor);
|
||||
AZ::Data::AssetManager::Instance().RegisterHandler(&m_assetHandler, azrtti_typeid<TestAssetData>());
|
||||
|
||||
m_serializeContext->RegisterGenericType<AZ::Data::Asset<TestAssetData>>();
|
||||
m_jsonRegistrationContext->Serializer<AZ::Data::AssetJsonSerializer>()->HandlesType<AZ::Data::Asset>();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_jsonRegistrationContext->EnableRemoveReflection();
|
||||
m_jsonRegistrationContext->Serializer<AZ::Data::AssetJsonSerializer>()->HandlesType<AZ::Data::Asset>();
|
||||
m_jsonRegistrationContext->DisableRemoveReflection();
|
||||
|
||||
AZ::Data::AssetManager::Instance().UnregisterHandler(&m_assetHandler);
|
||||
AZ::Data::AssetManager::Destroy();
|
||||
|
||||
AZ::JobContext::SetGlobalContext(nullptr);
|
||||
delete m_jobContext;
|
||||
delete m_jobManager;
|
||||
|
||||
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();
|
||||
AZ::AllocatorInstance<AZ::PoolAllocator>::Destroy();
|
||||
|
||||
BaseJsonSerializerFixture::TearDown();
|
||||
}
|
||||
|
||||
private:
|
||||
TestAssetHandler m_assetHandler;
|
||||
AZ::JobManager* m_jobManager{ nullptr };
|
||||
AZ::JobContext* m_jobContext{ nullptr };
|
||||
};
|
||||
|
||||
TEST_F(TestSerializedAssetTracker, AssetTracker_Callback_Works)
|
||||
{
|
||||
auto assetCallback = [](AZ::Data::Asset<AZ::Data::AssetData>& asset)
|
||||
{
|
||||
if (!asset.GetId().IsValid() && !asset.GetHint().empty())
|
||||
{
|
||||
if (asset.GetHint() == "test/path/foo.asset")
|
||||
{
|
||||
asset.SetHint("passed");
|
||||
}
|
||||
}
|
||||
};
|
||||
auto tracker = AZ::Data::SerializedAssetTracker{};
|
||||
tracker.SetAssetFixUp(assetCallback);
|
||||
|
||||
AZ::JsonDeserializerSettings settings;
|
||||
settings.m_metadata.Add(tracker);
|
||||
settings.m_registrationContext = this->m_jsonRegistrationContext.get();
|
||||
settings.m_serializeContext = this->m_serializeContext.get();
|
||||
|
||||
AZStd::string_view assetHintOnlyTestAsset = R"(
|
||||
{
|
||||
"assetHint" : "test/path/foo.asset"
|
||||
})";
|
||||
rapidjson::Document jsonDom;
|
||||
jsonDom.Parse(assetHintOnlyTestAsset.data());
|
||||
|
||||
AZ::Data::Asset<TestAssetData> instance;
|
||||
auto result = AZ::JsonSerialization::Load(instance, jsonDom, settings);
|
||||
EXPECT_NE(result.GetProcessing(), AZ::JsonSerializationResult::Processing::Halted);
|
||||
EXPECT_STREQ(instance.GetHint().c_str(), "passed");
|
||||
}
|
||||
|
||||
class AssetSerializerTestDescription final
|
||||
: public JsonSerializerConformityTestDescriptor<AZ::Data::Asset<TestAssetData>>
|
||||
{
|
||||
|
||||
@@ -2088,7 +2088,7 @@ namespace UnitTest
|
||||
DisconnectNextHandlerByIdImpl multiHandler2;
|
||||
multiHandler2.BusConnect(DisconnectNextHandlerByIdImpl::firstBusAddress);
|
||||
multiHandler2.BusConnect(DisconnectNextHandlerByIdImpl::secondBusAddress);
|
||||
|
||||
|
||||
// Set the first handler m_nextHandler field to point to the second handler
|
||||
multiHandler1.m_nextHandler = &multiHandler2;
|
||||
|
||||
@@ -2807,7 +2807,7 @@ namespace UnitTest
|
||||
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(m_val % m_maxSleep));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DoConnect() override
|
||||
{
|
||||
MyEventGroupBus::Handler::BusConnect(m_id);
|
||||
@@ -2854,7 +2854,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
MyEventGroupBus::Event(id, &MyEventGroupBus::Events::Calculate, i, i * 2, i << 4);
|
||||
|
||||
|
||||
LocklessConnectorBus::Event(id, &LocklessConnectorBus::Events::DoDisconnect);
|
||||
|
||||
bool failed = (AZStd::find_if(&sentinel[0], end, [](char s) { return s != 0; }) != end);
|
||||
@@ -2891,7 +2891,7 @@ namespace UnitTest
|
||||
{
|
||||
MyEventGroupImpl()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
~MyEventGroupImpl() override
|
||||
@@ -3614,7 +3614,7 @@ namespace UnitTest
|
||||
{
|
||||
AZStd::this_thread::yield();
|
||||
}
|
||||
|
||||
|
||||
EXPECT_GE(AZStd::chrono::system_clock::now(), endTime);
|
||||
};
|
||||
AZStd::thread connectThread([&connectHandler, &waitHandler]()
|
||||
@@ -3813,7 +3813,7 @@ namespace UnitTest
|
||||
struct LastHandlerDisconnectHandler
|
||||
: public LastHandlerDisconnectBus::Handler
|
||||
{
|
||||
void OnEvent() override
|
||||
void OnEvent() override
|
||||
{
|
||||
++m_numOnEvents;
|
||||
BusDisconnect();
|
||||
@@ -3854,7 +3854,7 @@ namespace UnitTest
|
||||
struct DisconnectAssertHandler
|
||||
: public DisconnectAssertBus::Handler
|
||||
{
|
||||
|
||||
|
||||
};
|
||||
|
||||
TEST_F(EBus, HandlerDestroyedWithoutDisconnect_Asserts)
|
||||
@@ -3995,6 +3995,191 @@ namespace UnitTest
|
||||
|
||||
idTestRequest.Disconnect();
|
||||
}
|
||||
|
||||
// IsInDispatchThisThread
|
||||
struct IsInThreadDispatchRequests
|
||||
: AZ::EBusTraits
|
||||
{
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
};
|
||||
|
||||
using IsInThreadDispatchBus = AZ::EBus<IsInThreadDispatchRequests>;
|
||||
|
||||
class IsInThreadDispatchHandler
|
||||
: public IsInThreadDispatchBus::Handler
|
||||
{};
|
||||
|
||||
TEST_F(EBus, InvokingIsInThisThread_ReturnsSuccess_OnlyIfThreadIsInDispatch)
|
||||
{
|
||||
IsInThreadDispatchHandler handler;
|
||||
handler.BusConnect();
|
||||
|
||||
auto ThreadDispatcher = [](IsInThreadDispatchRequests*)
|
||||
{
|
||||
EXPECT_TRUE(IsInThreadDispatchBus::IsInDispatchThisThread());
|
||||
auto PerThreadBusDispatch = []()
|
||||
{
|
||||
EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread());
|
||||
};
|
||||
AZStd::array threads{ AZStd::thread(PerThreadBusDispatch), AZStd::thread(PerThreadBusDispatch) };
|
||||
for (AZStd::thread& thread : threads)
|
||||
{
|
||||
thread.join();
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr size_t ThreadDispatcherIterations = 4;
|
||||
for (size_t iteration = 0; iteration < ThreadDispatcherIterations; ++iteration)
|
||||
{
|
||||
EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread());
|
||||
IsInThreadDispatchBus::Broadcast(ThreadDispatcher);
|
||||
EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread());
|
||||
}
|
||||
}
|
||||
|
||||
// Thread Dispatch Policy
|
||||
struct ThreadDispatchTestBusTraits
|
||||
: AZ::EBusTraits
|
||||
{
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
struct PostThreadDispatchTestInvoker
|
||||
{
|
||||
~PostThreadDispatchTestInvoker();
|
||||
};
|
||||
|
||||
template <typename DispatchMutex>
|
||||
struct ThreadDispatchTestLockGuard
|
||||
{
|
||||
ThreadDispatchTestLockGuard(DispatchMutex& contextMutex)
|
||||
: m_lock{ contextMutex }
|
||||
{}
|
||||
ThreadDispatchTestLockGuard(DispatchMutex& contextMutex, AZStd::adopt_lock_t adopt_lock)
|
||||
: m_lock{ contextMutex, adopt_lock }
|
||||
{}
|
||||
ThreadDispatchTestLockGuard(const ThreadDispatchTestLockGuard&) = delete;
|
||||
ThreadDispatchTestLockGuard& operator=(const ThreadDispatchTestLockGuard&) = delete;
|
||||
private:
|
||||
PostThreadDispatchTestInvoker m_threadPolicyInvoker;
|
||||
using LockType = AZStd::conditional_t<LocklessDispatch, AZ::Internal::NullLockGuard<DispatchMutex>, AZStd::scoped_lock<DispatchMutex>>;
|
||||
LockType m_lock;
|
||||
};
|
||||
|
||||
template <typename DispatchMutex, bool IsLocklessDispatch>
|
||||
using DispatchLockGuard = ThreadDispatchTestLockGuard<DispatchMutex>;
|
||||
|
||||
static inline AZStd::atomic<int32_t> s_threadPostDispatchCalls;
|
||||
};
|
||||
|
||||
class ThreadDispatchTestRequests
|
||||
{
|
||||
public:
|
||||
virtual void FirstCall() = 0;
|
||||
virtual void SecondCall() = 0;
|
||||
virtual void ThirdCall() = 0;
|
||||
};
|
||||
|
||||
using ThreadDispatchTestBus = AZ::EBus<ThreadDispatchTestRequests, ThreadDispatchTestBusTraits>;
|
||||
|
||||
ThreadDispatchTestBusTraits::PostThreadDispatchTestInvoker::~PostThreadDispatchTestInvoker()
|
||||
{
|
||||
if (!ThreadDispatchTestBus::IsInDispatchThisThread())
|
||||
{
|
||||
++s_threadPostDispatchCalls;
|
||||
}
|
||||
}
|
||||
|
||||
class ThreadDispatchTestHandler
|
||||
: public ThreadDispatchTestBus::Handler
|
||||
{
|
||||
public:
|
||||
void Connect()
|
||||
{
|
||||
ThreadDispatchTestBus::Handler::BusConnect();
|
||||
}
|
||||
void Disconnect()
|
||||
{
|
||||
ThreadDispatchTestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void FirstCall() override
|
||||
{
|
||||
ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::SecondCall);
|
||||
}
|
||||
void SecondCall() override
|
||||
{
|
||||
ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::ThirdCall);
|
||||
}
|
||||
void ThirdCall() override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ParamType>
|
||||
class EBusParamFixture
|
||||
: public ScopedAllocatorSetupFixture
|
||||
, public ::testing::WithParamInterface<ParamType>
|
||||
{};
|
||||
|
||||
struct ThreadDispatchParams
|
||||
{
|
||||
size_t m_threadCount{};
|
||||
size_t m_handlerCount{};
|
||||
};
|
||||
|
||||
using ThreadDispatchParamFixture = EBusParamFixture<ThreadDispatchParams>;
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ThreadDispatch,
|
||||
ThreadDispatchParamFixture,
|
||||
::testing::Values(
|
||||
ThreadDispatchParams{ 1, 1 },
|
||||
ThreadDispatchParams{ 2, 1 },
|
||||
ThreadDispatchParams{ 1, 2 },
|
||||
ThreadDispatchParams{ 2, 2 },
|
||||
ThreadDispatchParams{ 16, 8 }
|
||||
)
|
||||
);
|
||||
|
||||
TEST_P(ThreadDispatchParamFixture, CustomDispatchLockGuard_InvokesPostDispatchFunction_AfterThreadHasFinishedDispatch)
|
||||
{
|
||||
ThreadDispatchTestBusTraits::s_threadPostDispatchCalls = 0;
|
||||
ThreadDispatchParams threadDispatchParams = GetParam();
|
||||
AZStd::vector<AZStd::thread> testThreads;
|
||||
AZStd::vector<ThreadDispatchTestHandler> testHandlers(threadDispatchParams.m_handlerCount);
|
||||
for (ThreadDispatchTestHandler& testHandler : testHandlers)
|
||||
{
|
||||
testHandler.Connect();
|
||||
}
|
||||
|
||||
static constexpr size_t DispatchThreadCalls = 3;
|
||||
const size_t totalThreadDispatchCalls = threadDispatchParams.m_threadCount * DispatchThreadCalls;
|
||||
|
||||
auto DispatchThreadWorker = []()
|
||||
{
|
||||
ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::FirstCall);
|
||||
ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::SecondCall);
|
||||
ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::ThirdCall);
|
||||
};
|
||||
|
||||
for (size_t threadIndex = 0; threadIndex < threadDispatchParams.m_threadCount; ++threadIndex)
|
||||
{
|
||||
testThreads.emplace_back(DispatchThreadWorker);
|
||||
}
|
||||
|
||||
for (AZStd::thread& thread : testThreads)
|
||||
{
|
||||
thread.join();
|
||||
}
|
||||
|
||||
for (ThreadDispatchTestHandler& testHandler : testHandlers)
|
||||
{
|
||||
testHandler.Disconnect();
|
||||
}
|
||||
|
||||
EXPECT_EQ(totalThreadDispatchCalls, ThreadDispatchTestBusTraits::s_threadPostDispatchCalls);
|
||||
ThreadDispatchTestBusTraits::s_threadPostDispatchCalls = 0;
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
#if defined(HAVE_BENCHMARK)
|
||||
@@ -4370,7 +4555,7 @@ namespace Benchmark
|
||||
Bus::ExecuteQueuedEvents();
|
||||
}
|
||||
s_benchmarkEBusEnv<Bus>.Disconnect(state);
|
||||
|
||||
|
||||
}
|
||||
BUS_BENCHMARK_REGISTER_ALL(BM_EBus_ExecuteBroadcast);
|
||||
|
||||
|
||||
@@ -426,6 +426,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SetDeprecatedAlias(AZStd::string_view, AZStd::string_view) override
|
||||
{
|
||||
}
|
||||
|
||||
void ClearAlias(const char* ) override { }
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64) const override
|
||||
|
||||
@@ -698,7 +698,7 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
using PathViewLexicallyProximateFixture = PathLexicallyFixture<PathViewLexicallyProximateParams>;
|
||||
|
||||
TEST_P(PathViewLexicallyProximateFixture, LexicallyProximate_ReturnsRelativePathIfNotEmptyOrTestPathIfNot)
|
||||
TEST_P(PathViewLexicallyProximateFixture, LexicallyProximate_ReturnsRelativePathIfNotEmptyOrTestPath)
|
||||
{
|
||||
const auto& testParams = GetParam();
|
||||
AZ::IO::PathView testPath(testParams.m_testPathString, testParams.m_preferredSeparator);
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
||||
#include <AzCore/Settings/SettingsRegistryVisitorUtils.h>
|
||||
#include <AzCore/std/containers/fixed_vector.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
|
||||
namespace SettingsRegistryVisitorUtilsTests
|
||||
{
|
||||
struct VisitCallbackParams
|
||||
{
|
||||
AZStd::string_view m_inputJsonDocument;
|
||||
using VisitFieldFunction = bool(*)(AZ::SettingsRegistryInterface&,
|
||||
const AZ::SettingsRegistryVisitorUtils::VisitorCallback&,
|
||||
AZStd::string_view);
|
||||
|
||||
static inline constexpr size_t MaxFieldCount = 10;
|
||||
using ObjectFields = AZStd::fixed_vector<AZStd::pair<AZStd::string_view, AZStd::string_view>, MaxFieldCount>;
|
||||
using ArrayFields = AZStd::fixed_vector<AZStd::string_view, MaxFieldCount>;
|
||||
ObjectFields m_objectFields;
|
||||
ArrayFields m_arrayFields;
|
||||
};
|
||||
|
||||
template <typename VisitorParams>
|
||||
class SettingsRegistryVisitorUtilsParamFixture
|
||||
: public UnitTest::ScopedAllocatorSetupFixture
|
||||
, public ::testing::WithParamInterface<VisitorParams>
|
||||
{
|
||||
public:
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
m_registry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_registry.reset();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::SettingsRegistryImpl> m_registry;
|
||||
};
|
||||
|
||||
using SettingsRegistryVisitCallbackFixture = SettingsRegistryVisitorUtilsParamFixture<VisitCallbackParams>;
|
||||
|
||||
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitFieldsOfArrayType_ReturnsFields)
|
||||
{
|
||||
const VisitCallbackParams& visitParams = GetParam();
|
||||
|
||||
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
|
||||
|
||||
AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> testArrayFields;
|
||||
auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
AZStd::string fieldValue;
|
||||
EXPECT_TRUE(m_registry->Get(fieldValue, path));
|
||||
testArrayFields.emplace_back(AZStd::move(fieldValue));
|
||||
};
|
||||
|
||||
AZ::SettingsRegistryVisitorUtils::VisitField(*m_registry, visitorCallback, "/Test/Array");
|
||||
|
||||
const AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> expectedFields{
|
||||
visitParams.m_arrayFields.begin(), visitParams.m_arrayFields.end() };
|
||||
EXPECT_THAT(testArrayFields, ::testing::ContainerEq(expectedFields));
|
||||
}
|
||||
|
||||
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitFieldsOfObjectType_ReturnsFields)
|
||||
{
|
||||
const VisitCallbackParams& visitParams = GetParam();
|
||||
|
||||
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
|
||||
|
||||
AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> testObjectFields;
|
||||
auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
AZStd::string fieldValue;
|
||||
EXPECT_TRUE(m_registry->Get(fieldValue, path));
|
||||
testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue));
|
||||
};
|
||||
|
||||
AZ::SettingsRegistryVisitorUtils::VisitField(*m_registry, visitorCallback, "/Test/Object");
|
||||
|
||||
const AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> expectedFields{
|
||||
visitParams.m_objectFields.begin(), visitParams.m_objectFields.end() };
|
||||
EXPECT_THAT(testObjectFields, ::testing::ContainerEq(expectedFields));
|
||||
}
|
||||
|
||||
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitArrayOfArrayType_ReturnsFields)
|
||||
{
|
||||
const VisitCallbackParams& visitParams = GetParam();
|
||||
|
||||
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
|
||||
|
||||
AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> testArrayFields;
|
||||
auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
AZStd::string fieldValue;
|
||||
EXPECT_TRUE(m_registry->Get(fieldValue, path));
|
||||
testArrayFields.emplace_back(AZStd::move(fieldValue));
|
||||
};
|
||||
|
||||
AZ::SettingsRegistryVisitorUtils::VisitArray(*m_registry, visitorCallback, "/Test/Array");
|
||||
|
||||
const AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> expectedArrayFields{
|
||||
visitParams.m_arrayFields.begin(), visitParams.m_arrayFields.end() };
|
||||
EXPECT_THAT(testArrayFields, ::testing::ContainerEq(expectedArrayFields));
|
||||
}
|
||||
|
||||
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitArrayOfObjectType_ReturnsEmpty)
|
||||
{
|
||||
const VisitCallbackParams& visitParams = GetParam();
|
||||
|
||||
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
|
||||
|
||||
AZStd::fixed_vector<AZStd::string, VisitCallbackParams::MaxFieldCount> testArrayFields;
|
||||
auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
AZStd::string fieldValue;
|
||||
EXPECT_TRUE(m_registry->Get(fieldValue, path));
|
||||
testArrayFields.emplace_back(AZStd::move(fieldValue));
|
||||
};
|
||||
|
||||
AZ::SettingsRegistryVisitorUtils::VisitArray(*m_registry, visitorCallback, "/Test/Object");
|
||||
|
||||
EXPECT_TRUE(testArrayFields.empty());
|
||||
}
|
||||
|
||||
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitObjectOfArrayType_ReturnsEmpty)
|
||||
{
|
||||
const VisitCallbackParams& visitParams = GetParam();
|
||||
|
||||
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
|
||||
|
||||
AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> testObjectFields;
|
||||
auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
AZStd::string fieldValue;
|
||||
EXPECT_TRUE(m_registry->Get(fieldValue, path));
|
||||
testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue));
|
||||
};
|
||||
|
||||
AZ::SettingsRegistryVisitorUtils::VisitObject(*m_registry, visitorCallback, "/Test/Array");
|
||||
|
||||
EXPECT_TRUE(testObjectFields.empty());
|
||||
}
|
||||
|
||||
TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitObjectOfObjectType_ReturnsFields)
|
||||
{
|
||||
const VisitCallbackParams& visitParams = GetParam();
|
||||
|
||||
ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch));
|
||||
|
||||
AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> testObjectFields;
|
||||
auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
AZStd::string fieldValue;
|
||||
EXPECT_TRUE(m_registry->Get(fieldValue, path));
|
||||
testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue));
|
||||
};
|
||||
|
||||
AZ::SettingsRegistryVisitorUtils::VisitObject(*m_registry, visitorCallback, "/Test/Object");
|
||||
|
||||
const AZStd::fixed_vector<AZStd::pair<AZStd::string, AZStd::string>, VisitCallbackParams::MaxFieldCount> expectedObjectFields{
|
||||
visitParams.m_objectFields.begin(), visitParams.m_objectFields.end() };
|
||||
EXPECT_THAT(testObjectFields, ::testing::ContainerEq(expectedObjectFields));
|
||||
}
|
||||
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
VisitField,
|
||||
SettingsRegistryVisitCallbackFixture,
|
||||
::testing::Values(
|
||||
VisitCallbackParams
|
||||
{
|
||||
R"({)" "\n"
|
||||
R"( "Test":)" "\n"
|
||||
R"( {)" "\n"
|
||||
R"( "Array": [ "Hello", "World" ],)" "\n"
|
||||
R"( "Object": { "Foo": "Hello", "Bar": "World"})" "\n"
|
||||
R"( })" "\n"
|
||||
R"(})" "\n",
|
||||
VisitCallbackParams::ObjectFields{{"Foo", "Hello"}, {"Bar", "World"}},
|
||||
VisitCallbackParams::ArrayFields{"Hello", "World"}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
constexpr AZ::u32 ProfilerProxyGroup = AZ_CRC_CE("StatisticalProfilerProxyTests");
|
||||
|
||||
class StatisticalProfilerTest
|
||||
: public AllocatorsFixture
|
||||
{
|
||||
@@ -98,10 +100,10 @@ namespace UnitTest
|
||||
|
||||
AZ::Statistics::StatisticalProfiler<AZ::Crc32> profiler;
|
||||
|
||||
const AZ::Crc32 statIdPerformance = AZ_CRC("PerformanceResult", 0xc1f29a10);
|
||||
constexpr AZ::Crc32 statIdPerformance = AZ_CRC_CE("PerformanceResult");
|
||||
const AZStd::string statNamePerformance("PerformanceResult");
|
||||
|
||||
const AZ::Crc32 statIdBlock = AZ_CRC("Block", 0x831b9722);
|
||||
constexpr AZ::Crc32 statIdBlock = AZ_CRC_CE("Block");
|
||||
const AZStd::string statNameBlock("Block");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdPerformance, statNamePerformance, "us") != nullptr);
|
||||
@@ -175,10 +177,10 @@ namespace UnitTest
|
||||
|
||||
AZ::Statistics::StatisticalProfiler<AZ::Crc32, AZStd::shared_spin_mutex> profiler;
|
||||
|
||||
const AZ::Crc32 statIdPerformance = AZ_CRC("PerformanceResult", 0xc1f29a10);
|
||||
constexpr AZ::Crc32 statIdPerformance = AZ_CRC_CE("PerformanceResult");
|
||||
const AZStd::string statNamePerformance("PerformanceResult");
|
||||
|
||||
const AZ::Crc32 statIdBlock = AZ_CRC("Block", 0x831b9722);
|
||||
constexpr AZ::Crc32 statIdBlock = AZ_CRC_CE("Block");
|
||||
const AZStd::string statNameBlock("Block");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdPerformance, statNamePerformance, "us") != nullptr);
|
||||
@@ -317,26 +319,26 @@ namespace UnitTest
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope::ClearCachedProxy();
|
||||
AZ::Statistics::StatisticalProfilerProxy profilerProxy;
|
||||
AZ::Statistics::StatisticalProfilerProxy* proxy = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get();
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(AZ::Debug::ProfileCategory::Terrain);
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(ProfilerProxyGroup);
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdPerformance = "PerformanceResult";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdPerformance("PerformanceResult");
|
||||
const AZStd::string statNamePerformance("PerformanceResult");
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdBlock = "Block";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdBlock("Block");
|
||||
const AZStd::string statNameBlock("Block");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdPerformance, statNamePerformance, "us") != nullptr);
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdBlock, statNameBlock, "us") != nullptr);
|
||||
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, true);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, true);
|
||||
|
||||
const int iter_count = 10;
|
||||
{
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, statIdPerformance)
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, statIdPerformance)
|
||||
int counter = 0;
|
||||
for (int i = 0; i < iter_count; i++)
|
||||
{
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, statIdBlock)
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, statIdBlock)
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
@@ -348,7 +350,7 @@ namespace UnitTest
|
||||
EXPECT_EQ(profiler.GetStatistic(statIdBlock)->GetNumSamples(), iter_count);
|
||||
|
||||
//Clean Up
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, false);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, false);
|
||||
|
||||
#undef CODE_PROFILER_PROXY_PUSH_TIME
|
||||
|
||||
@@ -362,12 +364,12 @@ namespace UnitTest
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType simple_thread1("simple_thread1");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType simple_thread1_loop("simple_thread1_loop");
|
||||
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, simple_thread1);
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, simple_thread1);
|
||||
|
||||
static int counter = 0;
|
||||
for (int i = 0; i < loop_cnt; i++)
|
||||
{
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, simple_thread1_loop);
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, simple_thread1_loop);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
@@ -377,12 +379,12 @@ namespace UnitTest
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType simple_thread2("simple_thread2");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType simple_thread2_loop("simple_thread2_loop");
|
||||
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, simple_thread2);
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, simple_thread2);
|
||||
|
||||
static int counter = 0;
|
||||
for (int i = 0; i < loop_cnt; i++)
|
||||
{
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, simple_thread2_loop);
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, simple_thread2_loop);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
@@ -392,12 +394,13 @@ namespace UnitTest
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType simple_thread3("simple_thread3");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType simple_thread3_loop("simple_thread3_loop");
|
||||
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, simple_thread3);
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, simple_thread3);
|
||||
|
||||
static int counter = 0;
|
||||
for (int i = 0; i < loop_cnt; i++)
|
||||
{
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, simple_thread3_loop);
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, simple_thread3_loop);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,21 +411,21 @@ namespace UnitTest
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope::ClearCachedProxy();
|
||||
AZ::Statistics::StatisticalProfilerProxy profilerProxy;
|
||||
AZ::Statistics::StatisticalProfilerProxy* proxy = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get();
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(AZ::Debug::ProfileCategory::Terrain);
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(ProfilerProxyGroup);
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1 = "simple_thread1";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1("simple_thread1");
|
||||
const AZStd::string statNameThread1("simple_thread1");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1Loop = "simple_thread1_loop";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1Loop("simple_thread1_loop");
|
||||
const AZStd::string statNameThread1Loop("simple_thread1_loop");
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2 = "simple_thread2";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2("simple_thread2");
|
||||
const AZStd::string statNameThread2("simple_thread2");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2Loop = "simple_thread2_loop";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2Loop("simple_thread2_loop");
|
||||
const AZStd::string statNameThread2Loop("simple_thread2_loop");
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3 = "simple_thread3";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3("simple_thread3");
|
||||
const AZStd::string statNameThread3("simple_thread3");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3Loop = "simple_thread3_loop";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3Loop("simple_thread3_loop");
|
||||
const AZStd::string statNameThread3Loop("simple_thread3_loop");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdThread1, statNameThread1, "us"));
|
||||
@@ -432,7 +435,7 @@ namespace UnitTest
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdThread3, statNameThread3, "us"));
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdThread3Loop, statNameThread3Loop, "us"));
|
||||
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, true);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, true);
|
||||
|
||||
//Let's kickoff the threads to see how much contention affects the profiler's performance.
|
||||
const int iter_count = 10;
|
||||
@@ -459,7 +462,7 @@ namespace UnitTest
|
||||
EXPECT_EQ(profiler.GetStatistic(statIdThread3Loop)->GetNumSamples(), iter_count);
|
||||
|
||||
//Clean Up
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, false);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, false);
|
||||
}
|
||||
|
||||
/** Trace message handler to track messages during tests
|
||||
@@ -566,10 +569,10 @@ namespace UnitTest
|
||||
|
||||
AZ::Statistics::StatisticalProfiler<AZ::Crc32> profiler;
|
||||
|
||||
const AZ::Crc32 statIdPerformance = AZ_CRC("PerformanceResult", 0xc1f29a10);
|
||||
constexpr AZ::Crc32 statIdPerformance = AZ_CRC_CE("PerformanceResult");
|
||||
const AZStd::string statNamePerformance("PerformanceResult");
|
||||
|
||||
const AZ::Crc32 statIdBlock = AZ_CRC("Block", 0x831b9722);
|
||||
constexpr AZ::Crc32 statIdBlock = AZ_CRC_CE("Block");
|
||||
const AZStd::string statNameBlock("Block");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdPerformance, statNamePerformance, "us") != nullptr);
|
||||
@@ -647,10 +650,10 @@ namespace UnitTest
|
||||
|
||||
AZ::Statistics::StatisticalProfiler<AZ::Crc32, AZStd::shared_spin_mutex> profiler;
|
||||
|
||||
const AZ::Crc32 statIdPerformance = AZ_CRC("PerformanceResult", 0xc1f29a10);
|
||||
constexpr AZ::Crc32 statIdPerformance = AZ_CRC_CE("PerformanceResult");
|
||||
const AZStd::string statNamePerformance("PerformanceResult");
|
||||
|
||||
const AZ::Crc32 statIdBlock = AZ_CRC("Block", 0x831b9722);
|
||||
constexpr AZ::Crc32 statIdBlock = AZ_CRC_CE("Block");
|
||||
const AZStd::string statNameBlock("Block");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdPerformance, statNamePerformance, "us") != nullptr);
|
||||
@@ -745,26 +748,26 @@ namespace UnitTest
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope::ClearCachedProxy();
|
||||
AZ::Statistics::StatisticalProfilerProxy profilerProxy;
|
||||
AZ::Statistics::StatisticalProfilerProxy* proxy = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get();
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(AZ::Debug::ProfileCategory::Terrain);
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(ProfilerProxyGroup);
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdPerformance = "PerformanceResult";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdPerformance("PerformanceResult");
|
||||
const AZStd::string statNamePerformance("PerformanceResult");
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdBlock = "Block";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdBlock("Block");
|
||||
const AZStd::string statNameBlock("Block");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdPerformance, statNamePerformance, "us") != nullptr);
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdBlock, statNameBlock, "us") != nullptr);
|
||||
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, true);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, true);
|
||||
|
||||
const int iter_count = 1000000;
|
||||
{
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, statIdPerformance)
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, statIdPerformance)
|
||||
int counter = 0;
|
||||
for (int i = 0; i < iter_count; i++)
|
||||
{
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(AZ::Debug::ProfileCategory::Terrain, statIdBlock)
|
||||
CODE_PROFILER_PROXY_PUSH_TIME(ProfilerProxyGroup, statIdBlock)
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
@@ -778,7 +781,7 @@ namespace UnitTest
|
||||
profiler.LogAndResetStats("StatisticalProfilerProxy");
|
||||
|
||||
//Clean Up
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, false);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, false);
|
||||
}
|
||||
|
||||
#undef CODE_PROFILER_PROXY_PUSH_TIME
|
||||
@@ -788,21 +791,21 @@ namespace UnitTest
|
||||
AZ::Statistics::StatisticalProfilerProxy::TimedScope::ClearCachedProxy();
|
||||
AZ::Statistics::StatisticalProfilerProxy profilerProxy;
|
||||
AZ::Statistics::StatisticalProfilerProxy* proxy = AZ::Interface<AZ::Statistics::StatisticalProfilerProxy>::Get();
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(AZ::Debug::ProfileCategory::Terrain);
|
||||
AZ::Statistics::StatisticalProfilerProxy::StatisticalProfilerType& profiler = proxy->GetProfiler(ProfilerProxyGroup);
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1 = "simple_thread1";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1("simple_thread1");
|
||||
const AZStd::string statNameThread1("simple_thread1");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1Loop = "simple_thread1_loop";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread1Loop("simple_thread1_loop");
|
||||
const AZStd::string statNameThread1Loop("simple_thread1_loop");
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2 = "simple_thread2";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2("simple_thread2");
|
||||
const AZStd::string statNameThread2("simple_thread2");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2Loop = "simple_thread2_loop";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread2Loop("simple_thread2_loop");
|
||||
const AZStd::string statNameThread2Loop("simple_thread2_loop");
|
||||
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3 = "simple_thread3";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3("simple_thread3");
|
||||
const AZStd::string statNameThread3("simple_thread3");
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3Loop = "simple_thread3_loop";
|
||||
const AZ::Statistics::StatisticalProfilerProxy::StatIdType statIdThread3Loop("simple_thread3_loop");
|
||||
const AZStd::string statNameThread3Loop("simple_thread3_loop");
|
||||
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdThread1, statNameThread1, "us"));
|
||||
@@ -812,7 +815,7 @@ namespace UnitTest
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdThread3, statNameThread3, "us"));
|
||||
ASSERT_TRUE(profiler.GetStatsManager().AddStatistic(statIdThread3Loop, statNameThread3Loop, "us"));
|
||||
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, true);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, true);
|
||||
|
||||
//Let's kickoff the threads to see how much contention affects the profiler's performance.
|
||||
const int iter_count = 1000000;
|
||||
@@ -841,7 +844,7 @@ namespace UnitTest
|
||||
profiler.LogAndResetStats("3_Threads_StatisticalProfilerProxy");
|
||||
|
||||
//Clean Up
|
||||
proxy->ActivateProfiler(AZ::Debug::ProfileCategory::Terrain, false);
|
||||
proxy->ActivateProfiler(ProfilerProxyGroup, false);
|
||||
}
|
||||
|
||||
}//namespace UnitTest
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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/Time/TimeSystemComponent.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class TimeTests
|
||||
: public AllocatorsFixture
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
SetupAllocator();
|
||||
m_timeComponent = new AZ::TimeSystemComponent;
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
delete m_timeComponent;
|
||||
TeardownAllocator();
|
||||
}
|
||||
|
||||
AZ::TimeSystemComponent* m_timeComponent = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(TimeTests, TestConversionUsToMs)
|
||||
{
|
||||
AZ::TimeUs timeUs = AZ::TimeUs{ 1000 };
|
||||
AZ::TimeMs timeMs = AZ::TimeUsToMs(timeUs);
|
||||
EXPECT_EQ(timeMs, AZ::TimeMs{ 1 });
|
||||
}
|
||||
|
||||
TEST_F(TimeTests, TestConversionMsToUs)
|
||||
{
|
||||
AZ::TimeMs timeMs = AZ::TimeMs{ 1000 };
|
||||
AZ::TimeUs timeUs = AZ::TimeMsToUs(timeMs);
|
||||
EXPECT_EQ(timeUs, AZ::TimeUs{ 1000000 });
|
||||
}
|
||||
|
||||
TEST_F(TimeTests, TestClocks)
|
||||
{
|
||||
AZ::TimeUs timeUs = AZ::GetElapsedTimeUs();
|
||||
AZ::TimeMs timeMs = AZ::GetElapsedTimeMs();
|
||||
|
||||
AZ::TimeMs timeUsToMs = AZ::TimeUsToMs(timeUs);
|
||||
int64_t delta = static_cast<int64_t>(timeMs) - static_cast<int64_t>(timeUsToMs);
|
||||
EXPECT_LT(abs(delta), 1);
|
||||
}
|
||||
}
|
||||
@@ -247,4 +247,27 @@ namespace UnitTest
|
||||
Uuid right = Uuid::CreateStringPermissive(permissiveStr1);
|
||||
EXPECT_EQ(left, right);
|
||||
}
|
||||
|
||||
TEST_F(UuidTests, CreateStringPermissive_StringWithExtraData_Succeeds)
|
||||
{
|
||||
const char uuidStr[] = "{34D44249-E599-4B30-811F-4215C2DEA269}";
|
||||
Uuid left = Uuid::CreateString(uuidStr);
|
||||
|
||||
const char permissiveStr[] = "0x34D44249-0xE5994B30-0x811F4215-0xC2DEA269 Hello World";
|
||||
Uuid right = Uuid::CreateStringPermissive(permissiveStr);
|
||||
EXPECT_EQ(left, right);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(UuidTests, CreateStringPermissive_StringWithLotsOfExtraData_Succeeds)
|
||||
{
|
||||
const char uuidStr[] = "{34D44249-E599-4B30-811F-4215C2DEA269}";
|
||||
Uuid left = Uuid::CreateString(uuidStr);
|
||||
|
||||
const char permissiveStr[] = "0x34D44249-0xE5994B30-0x811F4215-0xC2DEA269 Hello World this is a really long string "
|
||||
"with lots of extra data to make sure we can parse a long string without failing as long as the uuid is in "
|
||||
"the beginning of the string then we should succeed";
|
||||
Uuid right = Uuid::CreateStringPermissive(permissiveStr);
|
||||
EXPECT_EQ(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ set(FILES
|
||||
Slice.cpp
|
||||
State.cpp
|
||||
Statistics.cpp
|
||||
StatisticalProfiler.cpp
|
||||
StreamerTests.cpp
|
||||
StringFunc.cpp
|
||||
SystemFile.cpp
|
||||
@@ -74,11 +75,12 @@ set(FILES
|
||||
Name/NameJsonSerializerTests.cpp
|
||||
Name/NameTests.cpp
|
||||
RTTI/TypeSafeIntegralTests.cpp
|
||||
SettingsRegistryTests.cpp
|
||||
SettingsRegistryMergeUtilsTests.cpp
|
||||
Settings/CommandLineTests.cpp
|
||||
Settings/SettingsRegistryTests.cpp
|
||||
Settings/SettingsRegistryConsoleUtilsTests.cpp
|
||||
Settings/SettingsRegistryMergeUtilsTests.cpp
|
||||
Settings/SettingsRegistryScriptUtilsTests.cpp
|
||||
Settings/SettingsRegistryVisitorUtilsTests.cpp
|
||||
Streamer/BlockCacheTests.cpp
|
||||
Streamer/DedicatedCacheTests.cpp
|
||||
Streamer/FullDecompressorTests.cpp
|
||||
@@ -127,6 +129,7 @@ set(FILES
|
||||
Serialization/Json/UnorderedSetSerializerTests.cpp
|
||||
Serialization/Json/UnsupportedTypesSerializerTests.cpp
|
||||
Serialization/Json/UuidSerializerTests.cpp
|
||||
Time/TimeTests.cpp
|
||||
Math/AabbTests.cpp
|
||||
Math/ColorTests.cpp
|
||||
Math/CrcTests.cpp
|
||||
@@ -192,6 +195,7 @@ set(FILES
|
||||
AZStd/LockFreeQueues.cpp
|
||||
AZStd/LockFreeStacks.cpp
|
||||
AZStd/LockTests.cpp
|
||||
AZStd/Math.cpp
|
||||
AZStd/Numeric.cpp
|
||||
AZStd/Ordered.cpp
|
||||
AZStd/Optional.cpp
|
||||
|
||||
@@ -77,11 +77,15 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
namespace ApplicationInternal
|
||||
{
|
||||
static constexpr const char s_prefabSystemKey[] = "/Amazon/Preferences/EnablePrefabSystem";
|
||||
static constexpr const char s_prefabWipSystemKey[] = "/Amazon/Preferences/EnablePrefabSystemWipFeatures";
|
||||
static constexpr const char s_legacySlicesAssertKey[] = "/Amazon/Preferences/ShouldAssertForLegacySlicesUsage";
|
||||
static constexpr const char* DeprecatedFileIOAliasesRoot = "/O3DE/AzCore/FileIO/DeprecatedAliases";
|
||||
static constexpr const char* DeprecatedFileIOAliasesOldAliasKey = "OldAlias";
|
||||
static constexpr const char* DeprecatedFileIOAliasesNewAliasKey = "NewAlias";
|
||||
}
|
||||
|
||||
Application::Application()
|
||||
@@ -563,6 +567,68 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
struct DeprecatedAliasesKeyVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse;
|
||||
using VisitAction = AZ::SettingsRegistryInterface::VisitAction;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
|
||||
VisitResponse Traverse(AZStd::string_view path, AZStd::string_view,
|
||||
VisitAction action, Type type) override
|
||||
{
|
||||
if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = path;
|
||||
}
|
||||
|
||||
// Strip off last path segment from json path and check if is a child element of the array
|
||||
if (AZ::StringFunc::TokenizeLast(path, '/');
|
||||
m_parentArrayPath == path)
|
||||
{
|
||||
m_aliases.emplace_back();
|
||||
}
|
||||
}
|
||||
else if (action == AZ::SettingsRegistryInterface::VisitAction::End)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = AZStd::string{};
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::SettingsRegistryInterface::VisitResponse::Continue;
|
||||
}
|
||||
|
||||
void Visit(AZStd::string_view, AZStd::string_view valueName, Type, AZStd::string_view value) override
|
||||
{
|
||||
if (!m_aliases.empty())
|
||||
{
|
||||
if (valueName == ApplicationInternal::DeprecatedFileIOAliasesOldAliasKey)
|
||||
{
|
||||
m_aliases.back().m_oldAlias = value;
|
||||
}
|
||||
else if (valueName == ApplicationInternal::DeprecatedFileIOAliasesNewAliasKey)
|
||||
{
|
||||
m_aliases.back().m_newAlias = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AliasPair
|
||||
{
|
||||
AZStd::string m_oldAlias;
|
||||
AZStd::string m_newAlias;
|
||||
};
|
||||
AZStd::vector<AliasPair> m_aliases;
|
||||
|
||||
private:
|
||||
AZStd::string m_parentArrayPath;
|
||||
};
|
||||
|
||||
static void CreateUserCache(const AZ::IO::FixedMaxPath& cacheUserPath, AZ::IO::FileIOBase& fileIoBase)
|
||||
{
|
||||
@@ -610,9 +676,8 @@ namespace AzFramework
|
||||
|
||||
void Application::SetFileIOAliases()
|
||||
{
|
||||
if (m_archiveFileIO)
|
||||
if (auto fileIoBase = m_archiveFileIO.get(); fileIoBase)
|
||||
{
|
||||
auto fileIoBase = m_archiveFileIO.get();
|
||||
// Set up the default file aliases based on the settings registry
|
||||
fileIoBase->SetAlias("@engroot@", GetEngineRoot());
|
||||
fileIoBase->SetAlias("@projectroot@", GetEngineRoot());
|
||||
@@ -620,29 +685,20 @@ namespace AzFramework
|
||||
|
||||
{
|
||||
AZ::IO::FixedMaxPath pathAliases;
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@projectcache@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@assets@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectplatformcache@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@root@", pathAliases.c_str()); // Deprecated Use @projectplatformcache@
|
||||
fileIoBase->SetAlias("@products@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@engroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@devroot@", pathAliases.c_str()); // Deprecated - Use @engroot@
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
|
||||
{
|
||||
fileIoBase->SetAlias("@devassets@", pathAliases.c_str()); // Deprecated - Use @projectsourceassets@
|
||||
fileIoBase->SetAlias("@projectroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectsourceassets@", (pathAliases / "Assets").c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,6 +719,15 @@ namespace AzFramework
|
||||
}
|
||||
fileIoBase->SetAlias("@log@", projectLogPath.c_str());
|
||||
fileIoBase->CreatePath(projectLogPath.c_str());
|
||||
|
||||
DeprecatedAliasesKeyVisitor visitor;
|
||||
if (m_settingsRegistry->Visit(visitor, ApplicationInternal::DeprecatedFileIOAliasesRoot))
|
||||
{
|
||||
for (const auto& [oldAlias, newAlias] : visitor.m_aliases)
|
||||
{
|
||||
fileIoBase->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1121,7 +1121,7 @@ namespace AZ::IO
|
||||
|
||||
if (AZ::IO::FixedMaxPath pathBindRoot; !AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, szBindRoot))
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@assets@");
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@products@");
|
||||
desc.m_pathBindRoot = pathBindRoot.LexicallyNormal().String();
|
||||
}
|
||||
else
|
||||
@@ -1807,9 +1807,9 @@ namespace AZ::IO
|
||||
if (m_eRecordFileOpenList != IArchive::RFOM_Disabled)
|
||||
{
|
||||
// we only want to record ASSET access
|
||||
// assets are identified as files that are relative to the resolved @assets@ alias path
|
||||
// assets are identified as files that are relative to the resolved @products@ alias path
|
||||
auto fileIoBase = AZ::IO::FileIOBase::GetInstance();
|
||||
const char* aliasValue = fileIoBase->GetAlias("@assets@");
|
||||
const char* aliasValue = fileIoBase->GetAlias("@products@");
|
||||
|
||||
if (AZ::IO::FixedMaxPath resolvedFilePath;
|
||||
fileIoBase->ResolvePath(resolvedFilePath, szFilename)
|
||||
|
||||
@@ -546,6 +546,16 @@ namespace AZ::IO
|
||||
realUnderlyingFileIO->GetAlias(alias);
|
||||
}
|
||||
|
||||
void ArchiveFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
FileIOBase* realUnderlyingFileIO = FileIOBase::GetDirectInstance();
|
||||
if (!realUnderlyingFileIO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
realUnderlyingFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> ArchiveFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
if ((!inOutBuffer) || (bufferLength == 0))
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace AZ::IO
|
||||
IO::Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
@@ -186,8 +186,8 @@ namespace AZ::IO
|
||||
{
|
||||
// filter out the stuff which does not match.
|
||||
|
||||
// the problem here is that szDir might be something like "@assets@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@assets@" or "@assets@/levels/mylevel"
|
||||
// the problem here is that szDir might be something like "@products@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@products@" or "@products@/levels/mylevel"
|
||||
// so there's really no way to filter out opening the pack and looking at the files inside.
|
||||
// however, the bind root is not part of the inner zip entry name either
|
||||
// and the ZipDir::FindFile actually expects just the chopped off piece.
|
||||
@@ -202,22 +202,22 @@ namespace AZ::IO
|
||||
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\" <--- mount point
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\" <--- mount point
|
||||
// ~~~~~~~~~~~ Common part
|
||||
// "levels\\*" <---- remainder that is not in common
|
||||
// "" <--- mount point remainder. In this case, we should scan the contents of the pak for the remainder
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// ~~~~~~~~~~~~~~~~~~ common part
|
||||
// "*" <---- remainder that is not in common
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
// example:
|
||||
// "@assets@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "otherlevel\\*" <---- remainder
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace AZ::IO
|
||||
// which means we may search inside the pack.
|
||||
ScanInZip(it->pZip.get(), sourcePathRemainder.Native());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace AZ::IO::Internal
|
||||
}
|
||||
|
||||
AZStd::smatch matches;
|
||||
const AZStd::regex lodRegex("@assets@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
const AZStd::regex lodRegex("@products@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
if (!AZStd::regex_match(szPath, matches, lodRegex) || matches.size() != 3)
|
||||
{
|
||||
// The current file is not a valid LOD file
|
||||
|
||||
@@ -725,7 +725,7 @@ namespace AzFramework
|
||||
|
||||
if (!info.m_relativePath.empty())
|
||||
{
|
||||
const char* devAssetRoot = fileIO->GetAlias("@devassets@");
|
||||
const char* devAssetRoot = fileIO->GetAlias("@projectroot@");
|
||||
if (devAssetRoot)
|
||||
{
|
||||
AZ::Data::AssetStreamInfo streamInfo;
|
||||
|
||||
@@ -133,6 +133,8 @@ namespace AzFramework
|
||||
behaviorContext->Class<BehaviorEntity>("Entity")
|
||||
->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)
|
||||
->Attribute(AZ::Script::Attributes::ConstructorOverride, &Internal::BehaviorEntityScriptConstructor)
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Module, "entity")
|
||||
->Constructor()
|
||||
->Constructor<AZ::EntityId>()
|
||||
->Constructor<AZ::Entity*>()
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace AzFramework
|
||||
|
||||
AZ::IO::Path& gemAbsPath = gemInfo.m_absoluteSourcePaths.emplace_back(value);
|
||||
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
|
||||
// any relative path is underneath the @assets@ alias
|
||||
// any relative path is underneath the @products@ alias
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
AZ::IO::FixedMaxPath replacedAliasPath;
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzCore/std/containers/fixed_unordered_set.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <cctype>
|
||||
|
||||
namespace AZ
|
||||
@@ -281,10 +283,18 @@ namespace AZ
|
||||
return SystemFile::Exists(resolvedPath);
|
||||
}
|
||||
|
||||
bool LocalFileIO::IsDirectory(const char* filePath)
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
|
||||
return SystemFile::IsDirectory(resolvedPath);
|
||||
}
|
||||
|
||||
void LocalFileIO::CheckInvalidWrite([[maybe_unused]] const char* path)
|
||||
{
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* assetAliasPath = GetAlias("@products@");
|
||||
if (path && assetAliasPath)
|
||||
{
|
||||
const AZ::IO::PathView pathView(path);
|
||||
@@ -470,17 +480,15 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsAbsolutePath(path))
|
||||
if (AZ::IO::PathView(path).HasRootPath())
|
||||
{
|
||||
size_t pathLen = strlen(path);
|
||||
if (pathLen + 1 < resolvedPathSize)
|
||||
{
|
||||
azstrncpy(resolvedPath, resolvedPathSize, path, pathLen + 1);
|
||||
|
||||
//see if the absolute path uses @assets@ or @root@, if it does lowercase the relative part
|
||||
[[maybe_unused]] bool lowercasePath = LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@assets@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@root@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@projectplatformcache@"));
|
||||
//see if the absolute path matches the resolved value of @products@, if it does lowercase the relative part
|
||||
LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@products@"));
|
||||
|
||||
ToUnixSlashes(resolvedPath, resolvedPathSize);
|
||||
return true;
|
||||
@@ -491,34 +499,39 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
char rootedPathBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
constexpr AZStd::string_view productAssetAlias = "@products@";
|
||||
// Add plus one for the path separator: <alias>/<path>
|
||||
constexpr size_t MaxPathSizeWithProductAssetAlias = AZ::IO::MaxPathLength + productAssetAlias.size() + 1;
|
||||
using RootedPathString = AZStd::fixed_string<MaxPathSizeWithProductAssetAlias>;
|
||||
RootedPathString rootedPathBuffer;
|
||||
const char* rootedPath = path;
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @assets@
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @products@
|
||||
if (path[0] != '@')
|
||||
{
|
||||
if (GetAlias("@assets@"))
|
||||
if (GetAlias("@products@"))
|
||||
{
|
||||
const int rootLength = 9;// strlen("@assets@/")
|
||||
azstrncpy(rootedPathBuffer, AZ_MAX_PATH_LEN, "@assets@/", rootLength);
|
||||
size_t pathLen = strlen(path);
|
||||
size_t rootedPathBufferlength = rootLength + pathLen + 1;// +1 for null terminator
|
||||
if (rootedPathBufferlength > resolvedPathSize)
|
||||
|
||||
if (const size_t requiredSize = productAssetAlias.size() + strlen(path) + 1;
|
||||
requiredSize > rootedPathBuffer.capacity())
|
||||
{
|
||||
AZ_Assert(rootedPathBufferlength < resolvedPathSize, "Constructed path length is wrong:%s", rootedPathBuffer);//path constructed is wrong
|
||||
size_t remainingSize = resolvedPathSize - rootLength - 1;// - 1 for null terminator
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN, path, remainingSize);
|
||||
rootedPathBuffer[resolvedPathSize - 1] = '\0';
|
||||
AZ_Error("FileIO", false, "Prepending the %.*s alias to the input path results in a path longer than the"
|
||||
" AZ::IO::MaxPathLength + the alias size of %zu. The size of the potential failed path is %zu",
|
||||
AZ_STRING_ARG(productAssetAlias), rootedPathBuffer.capacity(), requiredSize)
|
||||
}
|
||||
else
|
||||
{
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN - rootLength, path, pathLen + 1);
|
||||
rootedPathBuffer = RootedPathString::format("%.*s/%s", AZ_STRING_ARG(productAssetAlias), path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertToAbsolutePath(path, rootedPathBuffer, AZ_MAX_PATH_LEN);
|
||||
if (ConvertToAbsolutePath(path, rootedPathBuffer.data(), rootedPathBuffer.capacity()))
|
||||
{
|
||||
// Recalculate the internal string length
|
||||
rootedPathBuffer.resize_no_construct(AZStd::char_traits<char>::length(rootedPathBuffer.data()));
|
||||
}
|
||||
}
|
||||
rootedPath = rootedPathBuffer;
|
||||
rootedPath = rootedPathBuffer.c_str();
|
||||
}
|
||||
|
||||
if (ResolveAliases(rootedPath, resolvedPath, resolvedPathSize))
|
||||
@@ -553,11 +566,57 @@ namespace AZ
|
||||
|
||||
const char* LocalFileIO::GetAlias(const char* key) const
|
||||
{
|
||||
const auto it = m_aliases.find(key);
|
||||
if (it != m_aliases.end())
|
||||
if (const auto it = m_aliases.find(key); it != m_aliases.end())
|
||||
{
|
||||
return it->second.c_str();
|
||||
}
|
||||
else if (const auto deprecatedIt = m_deprecatedAliases.find(key);
|
||||
deprecatedIt != m_deprecatedAliases.end())
|
||||
{
|
||||
AZ_Error("FileIO", false, R"(Alias "%s" is deprecated. Please use alias "%s" instead)",
|
||||
key, deprecatedIt->second.c_str());
|
||||
AZStd::string_view aliasValue = deprecatedIt->second;
|
||||
// Contains the list of aliases resolved so far
|
||||
// If max_size is hit, than an error is logged and nullptr is returned
|
||||
using VisitedAliasSet = AZStd::fixed_unordered_set<AZStd::string_view, 8, 8>;
|
||||
VisitedAliasSet visitedAliasSet;
|
||||
while (aliasValue.starts_with("@"))
|
||||
{
|
||||
if (visitedAliasSet.contains(aliasValue))
|
||||
{
|
||||
AZ_Error("FileIO", false, "Cycle found with for alias %.*s when trying to resolve deprecated alias %s",
|
||||
AZ_STRING_ARG(aliasValue), key);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(visitedAliasSet.size() == visitedAliasSet.max_size())
|
||||
{
|
||||
AZ_Error("FileIO", false, "Unable to resolve path to deprecated alias %s within %zu steps",
|
||||
key, visitedAliasSet.max_size());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Add the current alias value to the visited set
|
||||
visitedAliasSet.emplace(aliasValue);
|
||||
|
||||
// Check if the alias value corresponds to another alias
|
||||
if (auto resolvedIter = m_aliases.find(aliasValue); resolvedIter != m_aliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else if (resolvedIter = m_deprecatedAliases.find(aliasValue);
|
||||
resolvedIter != m_deprecatedAliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return aliasValue.data();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -566,6 +625,11 @@ namespace AZ
|
||||
m_aliases.erase(key);
|
||||
}
|
||||
|
||||
void LocalFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
m_deprecatedAliases[oldAlias] = newAlias;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> LocalFileIO::ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const
|
||||
{
|
||||
size_t longestMatch = 0;
|
||||
@@ -667,7 +731,9 @@ namespace AZ
|
||||
: string_view_pair{};
|
||||
|
||||
size_t requiredResolvedPathSize = pathView.size() - aliasKey.size() + aliasValue.size() + 1;
|
||||
AZ_Assert(path != resolvedPath && resolvedPathSize >= requiredResolvedPathSize, "Resolved path is incorrect");
|
||||
AZ_Assert(path != resolvedPath, "ResolveAliases does not support inplace update of the path");
|
||||
AZ_Assert(resolvedPathSize >= requiredResolvedPathSize, "Resolved path size %llu not large enough. It needs to be %zu",
|
||||
resolvedPathSize, requiredResolvedPathSize);
|
||||
// we assert above, but we also need to properly handle the case when the resolvedPath buffer size
|
||||
// is too small to copy the source into.
|
||||
if (path == resolvedPath || (resolvedPathSize < requiredResolvedPathSize))
|
||||
@@ -691,13 +757,9 @@ namespace AZ
|
||||
resolvedPath[resolvedPathLen] = '\0';
|
||||
|
||||
// If the path started with one of the "asset cache" path aliases, lowercase the path
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* rootAliasPath = GetAlias("@root@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@projectplatformcache@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@products@");
|
||||
|
||||
const bool lowercasePath = (assetAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, assetAliasPath)) ||
|
||||
(rootAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, rootAliasPath)) ||
|
||||
(projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath));
|
||||
const bool lowercasePath = projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath);
|
||||
|
||||
if (lowercasePath)
|
||||
{
|
||||
@@ -814,5 +876,10 @@ namespace AZ
|
||||
|
||||
return pathStr + "/";
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
return AZ::Utils::ConvertToAbsolutePath(path, absolutePath, maxLength);
|
||||
}
|
||||
} // namespace IO
|
||||
} // namespace AZ
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -71,7 +73,7 @@ namespace AZ
|
||||
|
||||
bool GetFilename(HandleType fileHandle, char* filename, AZ::u64 filenameSize) const override;
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const;
|
||||
|
||||
|
||||
private:
|
||||
SystemFile* GetFilePointerFromHandle(HandleType fileHandle);
|
||||
|
||||
@@ -79,7 +81,6 @@ namespace AZ
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const;
|
||||
bool ResolveAliases(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const;
|
||||
bool IsAbsolutePath(const char* path) const;
|
||||
|
||||
bool LowerIfBeginsWith(char* inOutBuffer, AZ::u64 bufferLen, const char* alias) const;
|
||||
|
||||
@@ -91,6 +92,7 @@ namespace AZ
|
||||
AZStd::atomic<HandleType> m_nextHandle;
|
||||
AZStd::unordered_map<HandleType, SystemFile> m_openFiles;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_aliases;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_deprecatedAliases;
|
||||
|
||||
void CheckInvalidWrite(const char* path);
|
||||
};
|
||||
|
||||
@@ -49,14 +49,14 @@ namespace AZ
|
||||
s_IOLog.append(m_name);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
void Append(const char* line)
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u ", m_fileOperation));
|
||||
s_IOLog.append(line);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
~LogCall()
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u End ", m_fileOperation));
|
||||
@@ -251,7 +251,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size request failed. return Error", filePath).c_str());
|
||||
return ResultCode::Error;
|
||||
}
|
||||
|
||||
|
||||
size = response.m_size;
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size=%u. return Success", filePath, size).c_str());
|
||||
return ResultCode::Success;
|
||||
@@ -793,6 +793,12 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ClearAlias(alias=%s)", alias?alias:"nullptr").c_str());
|
||||
}
|
||||
|
||||
void NetworkFileIO::SetDeprecatedAlias([[maybe_unused]] AZStd::string_view oldAlias, [[maybe_unused]] AZStd::string_view newAlias)
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::SetDeprecatedAlias(oldAlias=%.*s, newAlias=%.*s)",
|
||||
AZ_STRING_ARG(oldAlias), AZ_STRING_ARG(newAlias)).c_str());
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> NetworkFileIO::ConvertToAlias(char* inOutBuffer, [[maybe_unused]] AZ::u64 bufferLength) const
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ConvertToAlias(inOutBuffer=%s, bufferLength=%u)", inOutBuffer?inOutBuffer:"nullptr", bufferLength).c_str());
|
||||
@@ -927,7 +933,7 @@ namespace AZ
|
||||
{
|
||||
m_cacheLookaheadPos = filePosition - CacheStartFilePosition();
|
||||
}
|
||||
|
||||
|
||||
void RemoteFileCache::SyncCheck()
|
||||
{
|
||||
#ifdef REMOTEFILEIO_SYNC_CHECK
|
||||
@@ -955,7 +961,7 @@ namespace AZ
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle);
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle).c_str());
|
||||
}
|
||||
|
||||
|
||||
if (responce.m_offset != m_filePosition)
|
||||
{
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) failed!!! m_filePosition=%u tell=%u", m_fileHandle, m_filePosition, responce.m_offset);
|
||||
@@ -1028,7 +1034,7 @@ namespace AZ
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Close(fileHandle=%u)", fileHandle).c_str());
|
||||
Result returnValue = NetworkFileIO::Close(fileHandle);
|
||||
|
||||
|
||||
if (returnValue == ResultCode::Success)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
@@ -1160,7 +1166,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Read(fileHandle=%u, buffer=OUT, size=%u, failOnFewerThanSizeBytesRead=%s, bytesRead=OUT)", fileHandle, size, failOnFewerThanSizeBytesRead ? "True" : "False").c_str());
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
|
||||
|
||||
AZ::u64 remainingBytesToRead = size;
|
||||
AZ::u64 bytesReadFromCache = 0;
|
||||
AZ::u64 remainingBytesInCache = cache.RemainingBytes();
|
||||
@@ -1263,7 +1269,7 @@ namespace AZ
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
if (cache.m_cacheLookaheadBuffer.size() && cache.RemainingBytes())
|
||||
{
|
||||
// find out where we are
|
||||
// find out where we are
|
||||
AZ::u64 seekPosition = cache.CacheFilePosition();
|
||||
|
||||
// note, seeks are predicted, and do not ask for a response.
|
||||
@@ -1361,6 +1367,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
if (m_excludedFileIO)
|
||||
{
|
||||
m_excludedFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> RemoteFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
return m_excludedFileIO ? m_excludedFileIO->ConvertToAlias(inOutBuffer, bufferLength) : strlen(inOutBuffer);
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace AZ
|
||||
Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -194,6 +195,7 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace AzFramework
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingAnd::Config::GetNameLabelOverride)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names",
|
||||
"The source input channel names that will be mapped to the output input channel name.")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace AzFramework
|
||||
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &InputMappingOr::Config::GetNameLabelOverride)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &Config::m_sourceInputChannelNames, "Source Input Channel Names",
|
||||
"The source input channel names that will be mapped to the output input channel name.")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Matchmaking/MatchmakingRequests.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! IMatchmakingRequests
|
||||
//! Pure virtual session interface class to abstract the details of session handling from application code.
|
||||
class IMatchmakingRequests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(IMatchmakingRequests, "{BC0B74DA-A448-4F40-9B50-9D73142829D5}");
|
||||
|
||||
IMatchmakingRequests() = default;
|
||||
virtual ~IMatchmakingRequests() = default;
|
||||
|
||||
// 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
|
||||
virtual AZStd::string StartMatchmaking(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
|
||||
|
||||
// Cancels a matchmaking ticket that is currently being processed.
|
||||
// @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
virtual void StopMatchmaking(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
|
||||
};
|
||||
|
||||
//! IMatchmakingAsyncRequests
|
||||
//! Async version of IMatchmakingRequests
|
||||
class IMatchmakingAsyncRequests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ISessionAsyncRequests, "{53513480-2D02-493C-B44E-96AA27F42429}");
|
||||
|
||||
IMatchmakingAsyncRequests() = default;
|
||||
virtual ~IMatchmakingAsyncRequests() = default;
|
||||
|
||||
// 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
|
||||
virtual void StartMatchmakingAsync(const StartMatchmakingRequest& startMatchmakingRequest) = 0;
|
||||
|
||||
// StopMatchmaking Async
|
||||
// @param stopMatchmakingRequest The request of StopMatchmaking operation
|
||||
virtual void StopMatchmakingAsync(const StopMatchmakingRequest& stopMatchmakingRequest) = 0;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! MatchmakingAsyncRequestNotifications
|
||||
//! The notifications correspond to matchmaking async requests
|
||||
class MatchmakingAsyncRequestNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// Safeguard handler for multi-threaded use case
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 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
|
||||
virtual void OnStartMatchmakingAsyncComplete(const AZStd::string& matchmakingTicketId) = 0;
|
||||
|
||||
// OnStopMatchmakingAsyncComplete is fired once StopMatchmakingAsync completes
|
||||
virtual void OnStopMatchmakingAsyncComplete() = 0;
|
||||
};
|
||||
using MatchmakingAsyncRequestNotificationBus = AZ::EBus<MatchmakingAsyncRequestNotifications>;
|
||||
|
||||
//! MatchmakingNotifications
|
||||
//! The matchmaking notifications to listen for performing required operations
|
||||
class MatchAcceptanceNotifications
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// Safeguard handler for multi-threaded use case
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OnMatchAcceptance is fired when DescribeMatchmaking ticket status is REQUIRES_ACCEPTANCE
|
||||
virtual void OnMatchAcceptance() = 0;
|
||||
};
|
||||
using MatchAcceptanceNotificationBus = AZ::EBus<MatchAcceptanceNotifications>;
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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/RTTI/ReflectContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzFramework/Matchmaking/MatchmakingRequests.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
void AcceptMatchRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AcceptMatchRequest>()
|
||||
->Version(0)
|
||||
->Field("acceptMatch", &AcceptMatchRequest::m_acceptMatch)
|
||||
->Field("playerIds", &AcceptMatchRequest::m_playerIds)
|
||||
->Field("ticketId", &AcceptMatchRequest::m_ticketId);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<AcceptMatchRequest>("AcceptMatchRequest", "The container for AcceptMatch request parameters")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AcceptMatchRequest::m_acceptMatch, "AcceptMatch",
|
||||
"Player response to accept or reject match")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AcceptMatchRequest::m_playerIds, "PlayerIds",
|
||||
"A list of unique identifiers for players delivering the response")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &AcceptMatchRequest::m_ticketId, "TicketId",
|
||||
"A unique identifier for a matchmaking ticket");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartMatchmakingRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<StartMatchmakingRequest>()
|
||||
->Version(0)
|
||||
->Field("ticketId", &StartMatchmakingRequest::m_ticketId);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<StartMatchmakingRequest>("StartMatchmakingRequest", "The container for StartMatchmaking request parameters")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &StartMatchmakingRequest::m_ticketId, "TicketId",
|
||||
"A unique identifier for a matchmaking ticket");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StopMatchmakingRequest::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<StopMatchmakingRequest>()
|
||||
->Version(0)
|
||||
->Field("ticketId", &StopMatchmakingRequest::m_ticketId);
|
||||
|
||||
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
|
||||
{
|
||||
editContext->Class<StopMatchmakingRequest>("StopMatchmakingRequest", "The container for StopMatchmaking request parameters")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &StopMatchmakingRequest::m_ticketId, "TicketId",
|
||||
"A unique identifier for a matchmaking ticket");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace AzFramework
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
}
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//! AcceptMatchRequest
|
||||
//! The container for AcceptMatch request parameters.
|
||||
struct AcceptMatchRequest
|
||||
{
|
||||
AZ_RTTI(AcceptMatchRequest, "{AD289D76-CEE2-424F-847E-E62AA83B7D79}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AcceptMatchRequest() = default;
|
||||
virtual ~AcceptMatchRequest() = default;
|
||||
|
||||
// Player response to accept or reject match
|
||||
bool m_acceptMatch;
|
||||
// A list of unique identifiers for players delivering the response
|
||||
AZStd::vector<AZStd::string> m_playerIds;
|
||||
// A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
|
||||
//! StartMatchmakingRequest
|
||||
//! The container for StartMatchmaking request parameters.
|
||||
struct StartMatchmakingRequest
|
||||
{
|
||||
AZ_RTTI(StartMatchmakingRequest, "{70B47776-E8E7-4993-BEC3-5CAEC3D48E47}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
StartMatchmakingRequest() = default;
|
||||
virtual ~StartMatchmakingRequest() = default;
|
||||
|
||||
// A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
|
||||
//! StopMatchmakingRequest
|
||||
//! The container for StopMatchmaking request parameters.
|
||||
struct StopMatchmakingRequest
|
||||
{
|
||||
AZ_RTTI(StopMatchmakingRequest, "{6132E293-65EF-4DC2-A8A0-00269697229D}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
StopMatchmakingRequest() = default;
|
||||
virtual ~StopMatchmakingRequest() = default;
|
||||
|
||||
// A unique identifier for a matchmaking ticket
|
||||
AZStd::string m_ticketId;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
@@ -10,98 +10,11 @@
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/RTTI/ReflectContext.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzFramework/Session/SessionRequests.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
struct SessionConfig;
|
||||
|
||||
//! CreateSessionRequest
|
||||
//! The container for CreateSession request parameters.
|
||||
struct CreateSessionRequest
|
||||
{
|
||||
AZ_RTTI(CreateSessionRequest, "{E39C2A45-89C9-4CFB-B337-9734DC798930}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
CreateSessionRequest() = default;
|
||||
virtual ~CreateSessionRequest() = default;
|
||||
|
||||
// A unique identifier for a player or entity creating the session.
|
||||
AZStd::string m_creatorId;
|
||||
|
||||
// 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.
|
||||
AZStd::string m_sessionName;
|
||||
|
||||
// The maximum number of players that can be connected simultaneously to the session.
|
||||
uint64_t m_maxPlayer = 0;
|
||||
};
|
||||
|
||||
//! SearchSessionsRequest
|
||||
//! The container for SearchSessions request parameters.
|
||||
struct SearchSessionsRequest
|
||||
{
|
||||
AZ_RTTI(SearchSessionsRequest, "{B49207A8-8549-4ADB-B7D9-D7A4932F9B4B}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
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.
|
||||
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.
|
||||
AZStd::string m_sortExpression;
|
||||
|
||||
// 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.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
//! SearchSessionsResponse
|
||||
//! The container for SearchSession request results.
|
||||
struct SearchSessionsResponse
|
||||
{
|
||||
AZ_RTTI(SearchSessionsResponse, "{F93DE7DC-D381-4E08-8A3B-0B08F7C38714}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SearchSessionsResponse() = default;
|
||||
virtual ~SearchSessionsResponse() = default;
|
||||
|
||||
// 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.
|
||||
AZStd::string m_nextToken;
|
||||
};
|
||||
|
||||
//! JoinSessionRequest
|
||||
//! The container for JoinSession request parameters.
|
||||
struct JoinSessionRequest
|
||||
{
|
||||
AZ_RTTI(JoinSessionRequest, "{519769E8-3CDE-4385-A0D7-24DBB3685657}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
JoinSessionRequest() = default;
|
||||
virtual ~JoinSessionRequest() = default;
|
||||
|
||||
// A unique identifier for the session.
|
||||
AZStd::string m_sessionId;
|
||||
|
||||
// A unique identifier for a player. Player IDs are developer-defined.
|
||||
AZStd::string m_playerId;
|
||||
|
||||
// Developer-defined information related to a player.
|
||||
AZStd::string m_playerData;
|
||||
};
|
||||
|
||||
//! ISessionRequests
|
||||
//! Pure virtual session interface class to abstract the details of session handling from application code.
|
||||
class ISessionRequests
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user