merge main
This commit is contained in:
@@ -26,4 +26,4 @@ namespace AZ
|
||||
template <typename T>
|
||||
using Instance = AZStd::intrusive_ptr<T>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +60,4 @@ namespace AZ
|
||||
return m_guid != rhs.m_guid || m_subId != rhs.m_subId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,4 @@ namespace AZStd
|
||||
base_type::assign(list.begin(), list.end());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,4 +158,4 @@ namespace AZStd
|
||||
/// Old elements will be evicted if the capacity is exceeded.
|
||||
size_t m_capacity = 0;
|
||||
};
|
||||
} // namespace AZStd
|
||||
} // namespace AZStd
|
||||
|
||||
@@ -76,4 +76,4 @@ namespace AZStd
|
||||
base_type::m_container.set_allocator(allocator);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,4 +231,4 @@ namespace AZStd
|
||||
protected:
|
||||
RandomAccessContainer m_container;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,4 @@ set(FILES
|
||||
lru_cache.cpp
|
||||
Main.cpp
|
||||
vector_set.cpp
|
||||
)
|
||||
)
|
||||
|
||||
@@ -169,4 +169,4 @@ namespace UnitTest
|
||||
intintptr_cache.clear();
|
||||
EXPECT_EQ(p->use_count(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,4 +282,4 @@ namespace UnitTest
|
||||
VectorSetTester<AZStd::fixed_vector_set<int32_t, 64>> tester;
|
||||
tester.TestIteratorsConst();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,4 +193,4 @@ public class KeyboardHandler
|
||||
private Activity m_activity;
|
||||
private InputMethodManager m_inputManager;
|
||||
private DummyTextView m_textView;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,4 +88,4 @@ public class APKHandler
|
||||
|
||||
private static AssetManager s_assetManager = null;
|
||||
private static boolean s_debug = false;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -320,4 +320,4 @@ public class ObbDownloaderActivity extends Activity implements IDownloaderClient
|
||||
private int m_buttonPauseTextId;
|
||||
private int m_kbPerSecondTextId;
|
||||
private int m_timeRemainingTextId;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,4 +37,4 @@ public class ObbDownloaderAlarmReceiver extends BroadcastReceiver
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -75,4 +75,4 @@ public class ObbDownloaderService extends DownloaderService
|
||||
private byte[] m_salt = new byte[] { 23, 12, 4, -12, -34, 23,
|
||||
-120, 122, -23, -104, -2, -4, 12, 3, -21, 123, -11, 4, -11, 32
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,4 +84,4 @@ public class SimpleObject
|
||||
// ----
|
||||
|
||||
private static final String TAG = "SimpleObject";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,4 +11,4 @@
|
||||
|
||||
set(FILES
|
||||
AzAutoGen.py
|
||||
)
|
||||
)
|
||||
|
||||
@@ -417,4 +417,4 @@ namespace AZ
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,4 +219,4 @@ namespace AZ
|
||||
bool m_isRunning; //!< Internal flag indicating if the application is running, mainly used to determine if we shoudl be blocking on the event pump while paused
|
||||
};
|
||||
} // namespace Android
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
@@ -485,4 +485,4 @@ namespace AZ { namespace Android
|
||||
} // namespace AZ
|
||||
|
||||
|
||||
#include <AzCore/Android/JNI/Internal/Object_impl.h>
|
||||
#include <AzCore/Android/JNI/Internal/Object_impl.h>
|
||||
|
||||
@@ -1104,8 +1104,11 @@ namespace AZ
|
||||
// If we either already had valid asset data, or just created it via FindOrCreateAsset, try to queue the load.
|
||||
if (m_assetData && m_assetData->GetId().IsValid())
|
||||
{
|
||||
// Only try to queue if the asset isn't already loading or loaded.
|
||||
if (m_assetData->GetStatus() == AZ::Data::AssetData::AssetStatus::NotLoaded)
|
||||
// Try to queue if the asset isn't already loading or loaded.
|
||||
// Also try to queue if the asset *is* already loading or loaded, but we're the only one with a strong reference
|
||||
// (i.e. use count == 1), because that means it was in the process of being garbage-collected.
|
||||
if ((m_assetData->GetStatus() == AZ::Data::AssetData::AssetStatus::NotLoaded) ||
|
||||
(m_assetData->GetUseCount() == 1))
|
||||
{
|
||||
*this = AssetInternal::GetAsset(m_assetData->GetId(), m_assetData->GetType(), loadBehavior, loadParams);
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ namespace AZ
|
||||
|
||||
bool AssetContainer::IsValid() const
|
||||
{
|
||||
return (m_containerAssetId.IsValid() && m_initComplete);
|
||||
return (m_containerAssetId.IsValid() && m_initComplete && m_rootAsset);
|
||||
}
|
||||
|
||||
void AssetContainer::CheckReady()
|
||||
@@ -341,6 +341,7 @@ namespace AZ
|
||||
|
||||
void AssetContainer::OnAssetError(Asset<AssetData> asset)
|
||||
{
|
||||
AZ_Warning("AssetContainer", false, "Error loading asset %s", asset->GetId().ToString<AZStd::string>().c_str());
|
||||
HandleReadyAsset(asset);
|
||||
}
|
||||
|
||||
@@ -366,7 +367,10 @@ namespace AZ
|
||||
auto remainingPreloadIter = m_preloadList.find(waiterId);
|
||||
if (remainingPreloadIter == m_preloadList.end())
|
||||
{
|
||||
AZ_Warning("AssetContainer", !m_initComplete, "Couldn't find waiting list for %s", waiterId.ToString<AZStd::string>().c_str());
|
||||
// If we got here without an entry on the preload list, it probably means this asset was triggered to load multiple
|
||||
// times, some with dependencies and some without. To ensure that we don't disturb the loads that expect the
|
||||
// dependencies, just silently return and don't treat the asset as finished loading. We'll rely on the other load
|
||||
// to send an OnAssetReady() whenever its expected dependencies are met.
|
||||
return;
|
||||
}
|
||||
if (!remainingPreloadIter->second.erase(preloadID))
|
||||
@@ -610,7 +614,12 @@ namespace AZ
|
||||
}
|
||||
for(auto& thisList : preloadList)
|
||||
{
|
||||
m_preloadList[thisList.first].insert(thisList.second.begin(), thisList.second.end());
|
||||
// Only save the entry to the final preload list if it has at least one dependent asset still remaining after
|
||||
// the checks above.
|
||||
if (!thisList.second.empty())
|
||||
{
|
||||
m_preloadList[thisList.first].insert(thisList.second.begin(), thisList.second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +208,7 @@ namespace AZ::Data
|
||||
void AssetDataStream::Close()
|
||||
{
|
||||
AZ_Assert(m_isOpen, "Attempting to close a stream that hasn't been opened.");
|
||||
AZ_Assert(m_curReadRequest == nullptr, "Attempting to close a stream with a read request in flight.");
|
||||
|
||||
// Destroy the asset buffer and unlock the allocator, so the allocator itself knows that it is no longer needed.
|
||||
if (m_buffer != m_preloadedData.data())
|
||||
@@ -222,6 +223,16 @@ namespace AZ::Data
|
||||
AZ_PROFILE_INTERVAL_END(AZ::Debug::ProfileCategory::AzCore, this);
|
||||
}
|
||||
|
||||
void AssetDataStream::RequestCancel()
|
||||
{
|
||||
AZStd::scoped_lock<AZStd::mutex> lock(m_readRequestMutex);
|
||||
if (m_curReadRequest)
|
||||
{
|
||||
auto streamer = Interface<IO::IStreamer>::Get();
|
||||
m_curReadRequest = streamer->Cancel(m_curReadRequest);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetDataStream::Seek(AZ::IO::OffsetType bytes, AZ::IO::GenericStream::SeekMode mode)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzCore);
|
||||
|
||||
@@ -82,6 +82,10 @@ namespace AZ::Data
|
||||
//! Gets the size of data loaded (so far).
|
||||
size_t GetLoadedSize() const { return m_loadedSize; }
|
||||
|
||||
//! Request a cancellation of any current IO streamer requests.
|
||||
//! Note: This is asynchronous and not guaranteed to cancel if the request is already in-process.
|
||||
void RequestCancel();
|
||||
|
||||
private:
|
||||
//! Perform any operations needed by all variants of Open()
|
||||
void OpenInternal(size_t assetSize, const char* streamName);
|
||||
|
||||
@@ -28,6 +28,8 @@ namespace AZ::Data::AssetInternal
|
||||
class WeakAsset
|
||||
{
|
||||
public:
|
||||
static constexpr bool EnableAssetCancellation = false;
|
||||
|
||||
WeakAsset() = default;
|
||||
|
||||
WeakAsset(AssetData* assetData, AssetLoadBehavior assetReferenceLoadBehavior);
|
||||
@@ -111,7 +113,14 @@ namespace AZ::Data::AssetInternal
|
||||
// - If the left and right sides are the same, clearing the right side's reference means one less reference will exist
|
||||
if (m_assetData)
|
||||
{
|
||||
m_assetData->ReleaseWeak();
|
||||
if constexpr (EnableAssetCancellation)
|
||||
{
|
||||
m_assetData->ReleaseWeak();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_assetData->Release();
|
||||
}
|
||||
}
|
||||
m_assetData = AZStd::move(rhs.m_assetData);
|
||||
rhs.m_assetData = nullptr;
|
||||
@@ -141,13 +150,27 @@ namespace AZ::Data::AssetInternal
|
||||
|
||||
if (assetData)
|
||||
{
|
||||
assetData->AcquireWeak();
|
||||
if constexpr (EnableAssetCancellation)
|
||||
{
|
||||
assetData->AcquireWeak();
|
||||
}
|
||||
else
|
||||
{
|
||||
assetData->Acquire();
|
||||
}
|
||||
m_assetId = assetData->GetId();
|
||||
}
|
||||
|
||||
if (m_assetData)
|
||||
{
|
||||
m_assetData->ReleaseWeak();
|
||||
if constexpr (EnableAssetCancellation)
|
||||
{
|
||||
m_assetData->ReleaseWeak();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_assetData->Release();
|
||||
}
|
||||
}
|
||||
|
||||
m_assetData = assetData;
|
||||
|
||||
@@ -1454,32 +1454,48 @@ namespace AZ
|
||||
//=========================================================================
|
||||
void AssetManager::ReloadAssetFromData(const Asset<AssetData>& asset)
|
||||
{
|
||||
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
|
||||
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
|
||||
AZ_Assert(m_assets.find(asset.GetId()) != m_assets.end(), "Unable to reload asset %s because its not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(m_assets.find(asset.GetId()) == m_assets.end() || asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
|
||||
"New and old data types are mismatched!");
|
||||
bool shouldAssignAssetData = false;
|
||||
|
||||
auto found = m_assets.find(asset.GetId());
|
||||
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
|
||||
{
|
||||
return; // this will just lead to crashes down the line and the above asserts cover this.
|
||||
}
|
||||
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
|
||||
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
|
||||
AZ_Assert(
|
||||
m_assets.find(asset.GetId()) != m_assets.end(),
|
||||
"Unable to reload asset %s because it's not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(
|
||||
m_assets.find(asset.GetId()) == m_assets.end() ||
|
||||
asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
|
||||
"New and old data types are mismatched!");
|
||||
|
||||
AssetData* newData = asset.Get();
|
||||
|
||||
if (found->second != newData)
|
||||
{
|
||||
// Notify users that we are about to change asset
|
||||
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
|
||||
|
||||
// Resolve the asset handler and account for the new asset instance.
|
||||
auto found = m_assets.find(asset.GetId());
|
||||
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
|
||||
{
|
||||
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
|
||||
AZ_Assert(handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
|
||||
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
|
||||
return; // this will just lead to crashes down the line and the above asserts cover this.
|
||||
}
|
||||
|
||||
AssetData* newData = asset.Get();
|
||||
|
||||
if (found->second != newData)
|
||||
{
|
||||
// Notify users that we are about to change asset
|
||||
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
|
||||
|
||||
// Resolve the asset handler and account for the new asset instance.
|
||||
{
|
||||
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
|
||||
AZ_Assert(
|
||||
handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
|
||||
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
|
||||
}
|
||||
|
||||
shouldAssignAssetData = true;
|
||||
}
|
||||
}
|
||||
|
||||
// We specifically perform this outside of the m_assetMutex lock so that the lock isn't held at the point that
|
||||
// OnAssetReload is triggered inside of AssignAssetData. Otherwise, we open up a high potential for deadlocks.
|
||||
if (shouldAssignAssetData)
|
||||
{
|
||||
AssignAssetData(asset);
|
||||
}
|
||||
}
|
||||
@@ -2144,7 +2160,7 @@ namespace AZ
|
||||
if (curIter != m_assetContainers.end())
|
||||
{
|
||||
auto newRef = curIter->second.lock();
|
||||
if (newRef)
|
||||
if (newRef && newRef->IsValid())
|
||||
{
|
||||
return newRef;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <AzCore/Jobs/JobManagerComponent.h>
|
||||
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
|
||||
#include <AzCore/Memory/MemoryComponent.h>
|
||||
#include <AzCore/NativeUI/NativeUISystemComponent.h>
|
||||
#include <AzCore/Script/ScriptSystemComponent.h>
|
||||
#include <AzCore/Slice/SliceComponent.h>
|
||||
#include <AzCore/Slice/SliceSystemComponent.h>
|
||||
@@ -43,7 +42,6 @@ namespace AZ
|
||||
AssetManagerComponent::CreateDescriptor(),
|
||||
UserSettingsComponent::CreateDescriptor(),
|
||||
Debug::FrameProfilerComponent::CreateDescriptor(),
|
||||
NativeUI::NativeUISystemComponent::CreateDescriptor(),
|
||||
SliceComponent::CreateDescriptor(),
|
||||
SliceSystemComponent::CreateDescriptor(),
|
||||
SliceMetadataInfoComponent::CreateDescriptor(),
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <AzCore/Memory/AllocatorManager.h>
|
||||
#include <AzCore/Memory/MallocSchema.h>
|
||||
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
#include <AzCore/Serialization/Utils.h>
|
||||
@@ -178,14 +180,16 @@ namespace AZ
|
||||
//! on an update to '/Amazon/AzCore/Bootstrap/project_path' key.
|
||||
struct UpdateProjectSettingsEventHandler
|
||||
{
|
||||
UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry)
|
||||
UpdateProjectSettingsEventHandler(AZ::SettingsRegistryInterface& registry, AZ::CommandLine& commandLine)
|
||||
: m_registry{ registry }
|
||||
, m_commandLine{ commandLine }
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
// #1 Update the project settings when the project path is set
|
||||
const auto projectPathKey = FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) + "/project_path";
|
||||
AZ::IO::FixedMaxPath newProjectPath;
|
||||
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectPathKey, path)
|
||||
@@ -194,6 +198,7 @@ namespace AZ
|
||||
UpdateProjectSettingsFromProjectPath(AZ::IO::PathView(newProjectPath));
|
||||
}
|
||||
|
||||
// #2 Update the project specialization when the project name is set
|
||||
const auto projectNameKey = FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey) + "/project_name";
|
||||
FixedValueString newProjectName;
|
||||
if (SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual(projectNameKey, path)
|
||||
@@ -201,6 +206,12 @@ namespace AZ
|
||||
{
|
||||
UpdateProjectSpecializationFromProjectName(newProjectName);
|
||||
}
|
||||
|
||||
// #3 Update the ComponentApplication CommandLine instance when the command line settings are merged into the Settings Registry
|
||||
if (path == AZ::SettingsRegistryMergeUtils::CommandLineValueChangedKey)
|
||||
{
|
||||
UpdateCommandLine();
|
||||
}
|
||||
}
|
||||
|
||||
//! Add the project name as a specialization underneath the /Amazon/AzCore/Settings/Specializations path
|
||||
@@ -233,10 +244,16 @@ namespace AZ
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
|
||||
}
|
||||
|
||||
void UpdateCommandLine()
|
||||
{
|
||||
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(m_registry, m_commandLine);
|
||||
}
|
||||
|
||||
private:
|
||||
AZ::IO::FixedMaxPath m_oldProjectPath;
|
||||
AZ::SettingsRegistryInterface::FixedValueString m_oldProjectName;
|
||||
AZ::SettingsRegistryInterface& m_registry;
|
||||
AZ::CommandLine& m_commandLine;
|
||||
};
|
||||
|
||||
void ComponentApplication::Descriptor::AllocatorRemapping::Reflect(ReflectContext* context, ComponentApplication* app)
|
||||
@@ -326,6 +343,16 @@ namespace AZ
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<ComponentApplicationBus>("ComponentApplicationBus")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Category, "Components")
|
||||
|
||||
->Event("GetEntityName", &ComponentApplicationBus::Events::GetEntityName)
|
||||
->Event("SetEntityName", &ComponentApplicationBus::Events::SetEntityName);
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -399,7 +426,7 @@ namespace AZ
|
||||
|
||||
// Now that the Allocators are initialized, the Command Line parameters can be parsed
|
||||
m_commandLine.Parse(m_argC, m_argV);
|
||||
ParseCommandLine(m_commandLine);
|
||||
SettingsRegistryMergeUtils::ParseCommandLine(m_commandLine);
|
||||
|
||||
// Create the settings registry and register it with the AZ interface system
|
||||
// This is done after the AppRoot has been calculated so that the Bootstrap.cfg
|
||||
@@ -415,6 +442,12 @@ namespace AZ
|
||||
// Add the Command Line arguments into the SettingsRegistry
|
||||
SettingsRegistryMergeUtils::StoreCommandLineToRegistry(*m_settingsRegistry, m_commandLine);
|
||||
|
||||
// Add a notifier to update the project_settings when
|
||||
// 1. The 'project_path' key changes
|
||||
// 2. The project specialization when the 'project-name' key changes
|
||||
// 3. The ComponentApplication command line when the command line is stored to the registry
|
||||
m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry, m_commandLine });
|
||||
|
||||
// Merge Command Line arguments
|
||||
constexpr bool executeRegDumpCommands = false;
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
|
||||
@@ -429,10 +462,6 @@ namespace AZ
|
||||
// for the application root.
|
||||
CalculateAppRoot();
|
||||
|
||||
// Add a notifier to update the /Amazon/AzCore/Settings/Specializations
|
||||
// when the 'project_path' property changes within the SettingsRegistry
|
||||
m_projectChangedHandler = m_settingsRegistry->RegisterNotifier(UpdateProjectSettingsEventHandler{ *m_settingsRegistry });
|
||||
|
||||
// Merge the bootstrap.cfg file into the Settings Registry as soon as the OSAllocator has been created.
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_Bootstrap(*m_settingsRegistry);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(*m_settingsRegistry, AZ_TRAIT_OS_PLATFORM_CODENAME, {});
|
||||
@@ -500,10 +529,42 @@ namespace AZ
|
||||
DestroyAllocator();
|
||||
}
|
||||
|
||||
|
||||
void ReportBadEngineRoot()
|
||||
{
|
||||
AZStd::string errorMessage = {"Unable to determine a valid path to the engine.\n"
|
||||
"Check parameters such as --project-path and --engine-path and make sure they are valid.\n"};
|
||||
if (auto registry = AZ::SettingsRegistry::Get(); registry != nullptr)
|
||||
{
|
||||
AZ::SettingsRegistryInterface::FixedValueString filePathErrorStr;
|
||||
if (registry->Get(filePathErrorStr, AZ::SettingsRegistryMergeUtils::FilePathKey_ErrorText); !filePathErrorStr.empty())
|
||||
{
|
||||
errorMessage += "Additional Info:\n";
|
||||
errorMessage += filePathErrorStr.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (auto nativeUI = AZ::Interface<AZ::NativeUI::NativeUIRequests>::Get(); nativeUI != nullptr)
|
||||
{
|
||||
nativeUI->DisplayOkDialog("O3DE Fatal Error", errorMessage.c_str(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("ComponentApplication", false, "O3DE Fatal Error: %s\n", errorMessage.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Entity* ComponentApplication::Create(const Descriptor& descriptor, const StartupParameters& startupParameters)
|
||||
{
|
||||
AZ_Assert(!m_isStarted, "Component application already started!");
|
||||
|
||||
if (m_engineRoot.empty())
|
||||
{
|
||||
ReportBadEngineRoot();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_startupParameters = startupParameters;
|
||||
|
||||
m_descriptor = descriptor;
|
||||
@@ -844,46 +905,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentApplication::ParseCommandLine(const AZ::CommandLine& commandLine)
|
||||
{
|
||||
struct OptionKeyToRegsetKey
|
||||
{
|
||||
AZStd::string_view m_optionKey;
|
||||
AZStd::string m_regsetKey;
|
||||
};
|
||||
|
||||
// Provide overrides for the engine root, the project root and the project cache root
|
||||
AZStd::array commandOptions = {
|
||||
OptionKeyToRegsetKey{ "engine-path", AZStd::string::format("%s/engine_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) },
|
||||
OptionKeyToRegsetKey{ "project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) },
|
||||
OptionKeyToRegsetKey{ "project-cache-path", AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey) }
|
||||
};
|
||||
|
||||
AZStd::fixed_vector<AZStd::string, commandOptions.size()> overrideArgs;
|
||||
|
||||
for (auto&& [optionKey, regsetKey] : commandOptions)
|
||||
{
|
||||
if (size_t optionCount = commandLine.GetNumSwitchValues(optionKey); optionCount > 0)
|
||||
{
|
||||
// Use the last supplied command option value to override previous values
|
||||
auto overrideArg = AZStd::string::format(R"(--regset="%s=%s")", regsetKey.c_str(),
|
||||
commandLine.GetSwitchValue(optionKey, optionCount - 1).c_str());
|
||||
overrideArgs.emplace_back(AZStd::move(overrideArg));
|
||||
}
|
||||
}
|
||||
|
||||
if (!overrideArgs.empty())
|
||||
{
|
||||
// Dump the input command line, add the additional option overrides
|
||||
// and Parse the new command line into the Component Application command line
|
||||
AZ::CommandLine::ParamContainer commandLineArgs;
|
||||
commandLine.Dump(commandLineArgs);
|
||||
commandLineArgs.insert(commandLineArgs.end(), AZStd::make_move_iterator(overrideArgs.begin()),
|
||||
AZStd::make_move_iterator(overrideArgs.end()));
|
||||
m_commandLine.Parse(commandLineArgs);
|
||||
}
|
||||
}
|
||||
|
||||
void ComponentApplication::MergeSettingsToRegistry(SettingsRegistryInterface& registry)
|
||||
{
|
||||
SettingsRegistryInterface::Specializations specializations;
|
||||
@@ -909,6 +930,8 @@ namespace AZ
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer);
|
||||
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true);
|
||||
#endif
|
||||
// Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry
|
||||
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry);
|
||||
}
|
||||
|
||||
void ComponentApplication::SetSettingsRegistrySpecializations(SettingsRegistryInterface::Specializations& specializations)
|
||||
@@ -1031,6 +1054,20 @@ namespace AZ
|
||||
return AZStd::string();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// SetEntityName
|
||||
//=========================================================================
|
||||
bool ComponentApplication::SetEntityName(const EntityId& id, const AZStd::string_view name)
|
||||
{
|
||||
Entity* entity = FindEntity(id);
|
||||
if (entity)
|
||||
{
|
||||
entity->SetName(name);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// EnumerateEntities
|
||||
//=========================================================================
|
||||
|
||||
@@ -209,6 +209,7 @@ namespace AZ
|
||||
bool DeleteEntity(const EntityId& id) override;
|
||||
Entity* FindEntity(const EntityId& id) override;
|
||||
AZStd::string GetEntityName(const EntityId& id) override;
|
||||
bool SetEntityName(const EntityId& id, const AZStd::string_view name) override;
|
||||
void EnumerateEntities(const ComponentApplicationRequests::EntityCallback& callback) override;
|
||||
ComponentApplication* GetApplication() override { return this; }
|
||||
/// Returns the serialize context that has been registered with the app, if there is one.
|
||||
@@ -327,9 +328,6 @@ namespace AZ
|
||||
/// Create the drillers
|
||||
void CreateDrillers();
|
||||
|
||||
/// Parse ComponentApplication specific command line arguments
|
||||
void ParseCommandLine(const AZ::CommandLine& commandLine);
|
||||
|
||||
virtual void MergeSettingsToRegistry(SettingsRegistryInterface& registry);
|
||||
|
||||
//! Sets the specializations that will be used when loading the Settings Registry. Extend this in derived
|
||||
|
||||
@@ -130,7 +130,13 @@ namespace AZ
|
||||
//! @param entity A reference to the entity whose name you are seeking.
|
||||
//! @return The name of the entity with the specified entity ID.
|
||||
//! If no entity is found for the specified ID, it returns an empty string.
|
||||
virtual AZStd::string GetEntityName(const EntityId& id) { (void)id; return AZStd::string(); };
|
||||
virtual AZStd::string GetEntityName(const EntityId& id) { (void)id; return AZStd::string(); }
|
||||
|
||||
//! Sets the name of the entity that has the specified entity ID.
|
||||
//! Entity names are not enforced to be unique.
|
||||
//! @param entityId A reference to the entity whose name you want to change.
|
||||
//! @return True if the name was changed successfully, false if it wasn't.
|
||||
virtual bool SetEntityName([[maybe_unused]] const EntityId& id, [[maybe_unused]] const AZStd::string_view name) { return false; }
|
||||
|
||||
//! The type that AZ::ComponentApplicationRequests::EnumerateEntities uses to
|
||||
//! pass entity callbacks to the application for enumeration.
|
||||
|
||||
@@ -87,4 +87,4 @@ namespace AZ
|
||||
size_t m_nextBlockSize;
|
||||
unsigned int m_compressedBufferIndex;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -63,13 +63,13 @@ namespace AZ
|
||||
static AssetTrackingImpl* GetSharedInstance();
|
||||
static ThreadData& GetSharedThreadData();
|
||||
|
||||
using MasterAssets = AZStd::unordered_map<AssetTrackingId, AssetMasterInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>;
|
||||
using PrimaryAssets = AZStd::unordered_map<AssetTrackingId, AssetPrimaryInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>;
|
||||
using ThreadData = ThreadData;
|
||||
using mutex_type = AZStd::mutex;
|
||||
using lock_type = AZStd::lock_guard<mutex_type>;
|
||||
|
||||
mutex_type m_mutex;
|
||||
MasterAssets m_masterAssets;
|
||||
PrimaryAssets m_primaryAssets;
|
||||
AssetTreeNodeBase* m_assetRoot = nullptr;
|
||||
AssetAllocationTableBase* m_allocationTable = nullptr;
|
||||
bool m_performingAnalysis = false;
|
||||
@@ -118,7 +118,7 @@ namespace AZ
|
||||
auto& threadData = GetSharedThreadData();
|
||||
AssetTreeNodeBase* parentAsset = threadData.m_currentAssetStack.empty() ? nullptr : threadData.m_currentAssetStack.back();
|
||||
AssetTreeNodeBase* childAsset;
|
||||
AssetMasterInfo* assetMasterInfo;
|
||||
AssetPrimaryInfo* assetPrimaryInfo;
|
||||
|
||||
if (!parentAsset)
|
||||
{
|
||||
@@ -128,22 +128,22 @@ namespace AZ
|
||||
{
|
||||
lock_type lock(m_mutex);
|
||||
|
||||
// Locate or create the master record for this asset
|
||||
auto masterItr = m_masterAssets.find(assetId);
|
||||
// Locate or create the primary record for this asset
|
||||
auto primaryItr = m_primaryAssets.find(assetId);
|
||||
|
||||
if (masterItr != m_masterAssets.end())
|
||||
if (primaryItr != m_primaryAssets.end())
|
||||
{
|
||||
assetMasterInfo = &masterItr->second;
|
||||
assetPrimaryInfo = &primaryItr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto insertResult = m_masterAssets.emplace(assetId, AssetMasterInfo());
|
||||
assetMasterInfo = &insertResult.first->second;
|
||||
assetMasterInfo->m_id = &insertResult.first->first;
|
||||
auto insertResult = m_primaryAssets.emplace(assetId, AssetPrimaryInfo());
|
||||
assetPrimaryInfo = &insertResult.first->second;
|
||||
assetPrimaryInfo->m_id = &insertResult.first->first;
|
||||
}
|
||||
|
||||
// Add this asset to the stack for this thread's context
|
||||
childAsset = parentAsset->FindOrAddChild(assetId, assetMasterInfo);
|
||||
childAsset = parentAsset->FindOrAddChild(assetId, assetPrimaryInfo);
|
||||
}
|
||||
|
||||
threadData.m_currentAssetStack.push_back(childAsset);
|
||||
@@ -304,7 +304,7 @@ namespace AZ
|
||||
char* pos = buffer;
|
||||
for (auto itr = assetStack.rbegin(); itr != assetStack.rend(); ++itr)
|
||||
{
|
||||
pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetMasterInfo()->m_id->m_id.c_str());
|
||||
pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetPrimaryInfo()->m_id->m_id.c_str());
|
||||
|
||||
if (pos >= buffer + BUFFER_SIZE)
|
||||
{
|
||||
|
||||
@@ -79,9 +79,9 @@ namespace AZ
|
||||
AssetTrackingString m_id;
|
||||
};
|
||||
|
||||
// Master information about an asset.
|
||||
// Primary information about an asset.
|
||||
// Currently just contains the ID of the asset, but in the future may carry additional information about that asset (such as where in code it was initialized).
|
||||
struct AssetMasterInfo
|
||||
struct AssetPrimaryInfo
|
||||
{
|
||||
const AssetTrackingId* m_id;
|
||||
};
|
||||
@@ -90,8 +90,8 @@ namespace AZ
|
||||
class AssetTreeNodeBase
|
||||
{
|
||||
public:
|
||||
virtual const AssetMasterInfo* GetAssetMasterInfo() const = 0;
|
||||
virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) = 0;
|
||||
virtual const AssetPrimaryInfo* GetAssetPrimaryInfo() const = 0;
|
||||
virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) = 0;
|
||||
};
|
||||
|
||||
// Base class for an asset tree. Implemented by the template AssetTree<>.
|
||||
|
||||
@@ -29,18 +29,18 @@ namespace AZ
|
||||
class AssetTreeNode : public AssetTreeNodeBase
|
||||
{
|
||||
public:
|
||||
AssetTreeNode(const AssetMasterInfo* masterInfo = nullptr, AssetTreeNode* parent = nullptr) :
|
||||
m_masterInfo(masterInfo),
|
||||
AssetTreeNode(const AssetPrimaryInfo* primaryInfo = nullptr, AssetTreeNode* parent = nullptr) :
|
||||
m_primaryinfo(primaryInfo),
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
const AssetMasterInfo* GetAssetMasterInfo() const override
|
||||
const AssetPrimaryInfo* GetAssetPrimaryInfo() const override
|
||||
{
|
||||
return m_masterInfo;
|
||||
return m_primaryinfo;
|
||||
}
|
||||
|
||||
AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) override
|
||||
AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) override
|
||||
{
|
||||
AssetTreeNodeBase* result = nullptr;
|
||||
auto childItr = m_children.find(id);
|
||||
@@ -61,7 +61,7 @@ namespace AZ
|
||||
|
||||
using AssetMap = AssetTrackingMap<AssetTrackingId, AssetTreeNode>;
|
||||
|
||||
const AssetMasterInfo* m_masterInfo;
|
||||
const AssetPrimaryInfo* m_primaryinfo;
|
||||
AssetTreeNode* m_parent;
|
||||
AssetMap m_children;
|
||||
AssetDataT m_data;
|
||||
|
||||
@@ -82,4 +82,4 @@ namespace AZ
|
||||
|
||||
#define AZ_TRACE_INSTANT_THREAD_CATEGORY(name, category) \
|
||||
EBUS_QUEUE_EVENT(AZ::Debug::EventTraceDrillerBus, RecordInstantThread, name, category, AZStd::this_thread::get_id(), AZStd::GetTimeNowMicroSecond())
|
||||
#define AZ_TRACE_INSTANT_THREAD(name) AZ_TRACE_INSTANT_THREAD_CATEGORY(name, "")
|
||||
#define AZ_TRACE_INSTANT_THREAD(name) AZ_TRACE_INSTANT_THREAD_CATEGORY(name, "")
|
||||
|
||||
@@ -64,4 +64,4 @@ namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
#endif // AZCORE_FRAME_PROFILER_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -39,4 +39,4 @@ namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
#endif // AZCORE_FRAME_PROFILER_BUS_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -46,4 +46,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif // AZCORE_PROFILER_DRILLER_BUS_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -70,6 +70,7 @@ namespace AZ
|
||||
static const char* logVerbosityUID = "sys_LogLevel";
|
||||
static const int assertLevel_log = 1;
|
||||
static const int assertLevel_nativeUI = 2;
|
||||
static const int assertLevel_crash = 3;
|
||||
static const int logLevel_errorWarning = 1;
|
||||
static const int logLevel_full = 2;
|
||||
static AZ::EnvironmentVariable<AZStd::unordered_set<size_t>> g_ignoredAsserts;
|
||||
@@ -289,8 +290,8 @@ namespace AZ
|
||||
}
|
||||
|
||||
#if AZ_ENABLE_TRACE_ASSERTS
|
||||
//display native UI dialogs at verbosity level 2 or higher
|
||||
if (currentLevel >= assertLevel_nativeUI)
|
||||
//display native UI dialogs at verbosity level 2
|
||||
if (currentLevel == assertLevel_nativeUI)
|
||||
{
|
||||
AZ::NativeUI::AssertAction buttonResult;
|
||||
EBUS_EVENT_RESULT(buttonResult, AZ::NativeUI::NativeUIRequestBus, DisplayAssertDialog, dialogBoxText);
|
||||
@@ -314,7 +315,13 @@ namespace AZ
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif //AZ_ENABLE_TRACE_ASSERTS
|
||||
// Crash the application directly at assert level 3
|
||||
if (currentLevel >= assertLevel_crash)
|
||||
{
|
||||
AZ_Crash();
|
||||
}
|
||||
}
|
||||
g_alreadyHandlingAssertOrFatal = false;
|
||||
}
|
||||
|
||||
@@ -194,4 +194,4 @@ namespace AZ
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,4 +112,4 @@ namespace AZ
|
||||
return m_offsetEnd;
|
||||
}
|
||||
} // namespace IO
|
||||
} // namesapce AZ
|
||||
} // namesapce AZ
|
||||
|
||||
@@ -71,4 +71,4 @@ namespace AZ
|
||||
u64 m_offsetEnd : 63;
|
||||
};
|
||||
} // namespace IO
|
||||
} // namesapce AZ
|
||||
} // namesapce AZ
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
|
||||
#if AZ_TRAIT_JSON_CLANG_IGNORE_UNKNOWN_WARNING && defined(AZ_COMPILER_CLANG)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -46,4 +46,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -68,4 +68,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -70,4 +70,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -36,4 +36,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -96,4 +96,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -135,4 +135,4 @@ namespace AZ
|
||||
}
|
||||
|
||||
#endif
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -146,8 +146,8 @@ namespace AZ
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("GetTranslated", &Aabb::GetTranslated)
|
||||
->Method("GetSurfaceArea", &Aabb::GetSurfaceArea)
|
||||
->Method("GetTransformedObb", &Aabb::GetTransformedObb)
|
||||
->Method("GetTransformedAabb", &Aabb::GetTransformedAabb)
|
||||
->Method("GetTransformedObb", static_cast<Obb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedObb))
|
||||
->Method("GetTransformedAabb", static_cast<Aabb(Aabb::*)(const Transform&) const>(&Aabb::GetTransformedAabb))
|
||||
->Method("ApplyTransform", &Aabb::ApplyTransform)
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Method("Clone", [](const Aabb& rhs) -> Aabb { return rhs; })
|
||||
@@ -195,6 +195,20 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
Obb Aabb::GetTransformedObb(const Matrix3x4& matrix3x4) const
|
||||
{
|
||||
Matrix3x4 matrixNoScale = matrix3x4;
|
||||
const AZ::Vector3 scale = matrixNoScale.ExtractScale();
|
||||
const AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x4(matrixNoScale);
|
||||
|
||||
return Obb::CreateFromPositionRotationAndHalfLengths(
|
||||
matrix3x4 * GetCenter(),
|
||||
rotation,
|
||||
0.5f * scale * GetExtents()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Aabb::ApplyTransform(const Transform& transform)
|
||||
{
|
||||
Vector3 a, b, axisCoeffs;
|
||||
@@ -224,4 +238,17 @@ namespace AZ
|
||||
m_min = newMin;
|
||||
m_max = newMax;
|
||||
}
|
||||
|
||||
|
||||
void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4)
|
||||
{
|
||||
const AZ::Vector3 extents = GetExtents();
|
||||
const AZ::Vector3 center = matrix3x4 * GetCenter();
|
||||
AZ::Vector3 newHalfExtents(
|
||||
0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents),
|
||||
0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents),
|
||||
0.5f * matrix3x4.GetRowAsVector3(2).GetAbs().Dot(extents));
|
||||
m_min = center - newHalfExtents;
|
||||
m_max = center + newHalfExtents;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,11 +129,21 @@ namespace AZ
|
||||
|
||||
void ApplyTransform(const Transform& transform);
|
||||
|
||||
void ApplyMatrix3x4(const Matrix3x4& matrix3x4);
|
||||
|
||||
void MultiplyByScale(const Vector3& scale);
|
||||
|
||||
//! Transforms an Aabb and returns the resulting Obb.
|
||||
class Obb GetTransformedObb(const Transform& transform) const;
|
||||
[[nodiscard]] Obb GetTransformedObb(const Transform& transform) const;
|
||||
|
||||
//! Transforms an Aabb and returns the resulting Obb.
|
||||
[[nodiscard]] Obb GetTransformedObb(const Matrix3x4& matrix3x4) const;
|
||||
|
||||
//! Returns a new AABB containing the transformed AABB.
|
||||
Aabb GetTransformedAabb(const Transform& transform) const;
|
||||
[[nodiscard]] Aabb GetTransformedAabb(const Transform& transform) const;
|
||||
|
||||
//! Returns a new AABB containing the transformed AABB.
|
||||
[[nodiscard]] Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const;
|
||||
|
||||
//! Checks if this aabb is equal to another within a floating point tolerance.
|
||||
bool IsClose(const Aabb& rhs, float tolerance = Constants::Tolerance) const;
|
||||
|
||||
@@ -292,6 +292,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE void Aabb::MultiplyByScale(const Vector3& scale)
|
||||
{
|
||||
m_min *= scale;
|
||||
m_max *= scale;
|
||||
AZ_MATH_ASSERT(IsValid(), "Min must be less than Max");
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Transform& transform) const
|
||||
{
|
||||
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
|
||||
@@ -300,6 +308,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Matrix3x4& matrix3x4) const
|
||||
{
|
||||
Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max);
|
||||
aabb.ApplyMatrix3x4(matrix3x4);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Aabb::IsClose(const Aabb& rhs, float tolerance) const
|
||||
{
|
||||
return m_min.IsClose(rhs.m_min, tolerance) && m_max.IsClose(rhs.m_max, tolerance);
|
||||
|
||||
@@ -296,4 +296,4 @@ namespace AZ
|
||||
m_updateCallback(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,4 +164,4 @@ namespace AZ
|
||||
return GetTargetValue();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,6 +231,18 @@ namespace AZ
|
||||
//! Compound assignment operator for matrix-matrix multiplication.
|
||||
Matrix3x4& operator*=(const Matrix3x4& rhs);
|
||||
|
||||
//! Operator for matrix-matrix addition.
|
||||
[[nodiscard]] Matrix3x4 operator+(const Matrix3x4& rhs) const;
|
||||
|
||||
//! Compound assignment operator for matrix-matrix addition.
|
||||
Matrix3x4& operator+=(const Matrix3x4& rhs);
|
||||
|
||||
//! Operator for multiplying all matrix's elements with a scalar
|
||||
[[nodiscard]] Matrix3x4 operator*(float scalar) const;
|
||||
|
||||
//! Compound assignment operator for multiplying all matrix's elements with a scalar
|
||||
Matrix3x4& operator*=(float scalar);
|
||||
|
||||
//! Operator for transforming a Vector3.
|
||||
[[nodiscard]] Vector3 operator*(const Vector3& rhs) const;
|
||||
|
||||
@@ -274,12 +286,18 @@ namespace AZ
|
||||
//! Gets the scale part of the transformation (the length of the basis vectors).
|
||||
[[nodiscard]] Vector3 RetrieveScale() const;
|
||||
|
||||
//! Gets the squared scale part of the transformation (the squared length of the basis vectors).
|
||||
[[nodiscard]] Vector3 RetrieveScaleSq() const;
|
||||
|
||||
//! Gets the scale part of the transformation as in RetrieveScale, and also removes this scaling from the matrix.
|
||||
Vector3 ExtractScale();
|
||||
|
||||
//! Multiplies the basis vectors of the matrix by the elements of the scale specified.
|
||||
void MultiplyByScale(const Vector3& scale);
|
||||
|
||||
//! Returns a matrix with the reciprocal scale, keeping the same rotation and translation.
|
||||
[[nodiscard]] Matrix3x4 GetReciprocalScaled() const;
|
||||
|
||||
//! Tests if the 3x3 part of the matrix is orthogonal.
|
||||
bool IsOrthogonal(float tolerance = Constants::Tolerance) const;
|
||||
|
||||
|
||||
@@ -487,6 +487,43 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator+(const Matrix3x4& rhs) const
|
||||
{
|
||||
return Matrix3x4
|
||||
(
|
||||
Simd::Vec4::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()),
|
||||
Simd::Vec4::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()),
|
||||
Simd::Vec4::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator+=(const Matrix3x4& rhs)
|
||||
{
|
||||
*this = *this + rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator*(float scalar) const
|
||||
{
|
||||
const Vector4 vector4Scalar(scalar);
|
||||
return Matrix3x4
|
||||
(
|
||||
Simd::Vec4::Mul(m_rows[0].GetSimdValue(), vector4Scalar.GetSimdValue()),
|
||||
Simd::Vec4::Mul(m_rows[1].GetSimdValue(), vector4Scalar.GetSimdValue()),
|
||||
Simd::Vec4::Mul(m_rows[2].GetSimdValue(), vector4Scalar.GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator*=(float scalar)
|
||||
{
|
||||
*this = *this * scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x4::operator*(const Vector3& rhs) const
|
||||
{
|
||||
return Vector3
|
||||
@@ -583,6 +620,12 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x4::RetrieveScaleSq() const
|
||||
{
|
||||
return Vector3(GetColumn(0).GetLengthSq(), GetColumn(1).GetLengthSq(), GetColumn(2).GetLengthSq());
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x4::ExtractScale()
|
||||
{
|
||||
const Vector3 scale = RetrieveScale();
|
||||
@@ -600,6 +643,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::GetReciprocalScaled() const
|
||||
{
|
||||
Matrix3x4 result = *this;
|
||||
result.MultiplyByScale(RetrieveScaleSq().GetReciprocal());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE void Matrix3x4::Orthogonalize()
|
||||
{
|
||||
*this = GetOrthogonalized();
|
||||
|
||||
@@ -67,4 +67,4 @@ namespace AZ
|
||||
//! Transforms a position by a matrix. This function can be used with any generic cases which include projection matrices.
|
||||
Vector3 MatrixTransformPosition(const Matrix4x4& matrix, const Vector3& inPosition);
|
||||
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
@@ -258,7 +258,8 @@ namespace AZ
|
||||
Method("CreateFromMatrix3x3", &Quaternion::CreateFromMatrix3x3)->
|
||||
Method("CreateFromMatrix4x4", &Quaternion::CreateFromMatrix4x4)->
|
||||
Method("CreateFromAxisAngle", &Quaternion::CreateFromAxisAngle)->
|
||||
Method("CreateShortestArc", &Quaternion::CreateShortestArc)
|
||||
Method("CreateShortestArc", &Quaternion::CreateShortestArc)->
|
||||
Method("CreateFromEulerAnglesDegrees", &Quaternion::CreateFromEulerAnglesDegrees)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +250,7 @@ namespace AZ
|
||||
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
|
||||
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
|
||||
Attribute(Script::Attributes::GenericConstructorOverride, &Internal::TransformDefaultConstructor)->
|
||||
Constructor<const Vector3&, const Quaternion&, const Vector3&>()->
|
||||
Method("GetBasis", &Transform::GetBasis)->
|
||||
Method("GetBasisX", &Transform::GetBasisX)->
|
||||
Method("GetBasisY", &Transform::GetBasisY)->
|
||||
|
||||
@@ -167,14 +167,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
AZ_MATH_INLINE Vector2::Vector2(const Vector3& source)
|
||||
Vector2::Vector2(const Vector3& source)
|
||||
: m_x(source.GetX())
|
||||
, m_y(source.GetY())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector2::Vector2(const Vector4& source)
|
||||
Vector2::Vector2(const Vector4& source)
|
||||
: m_x(source.GetX())
|
||||
, m_y(source.GetY())
|
||||
{
|
||||
|
||||
@@ -110,4 +110,4 @@ namespace AZ
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
#include <AzCore/Math/Internal/VertexContainer.inl>
|
||||
#include <AzCore/Math/Internal/VertexContainer.inl>
|
||||
|
||||
@@ -172,4 +172,4 @@ namespace AZ
|
||||
template<>
|
||||
inline AZ::Vector3 AdaptVertexOut<AZ::Vector2>(const AZ::Vector2& vector) { return Vector2ToVector3(vector); }
|
||||
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
@@ -31,4 +31,4 @@ namespace AZ
|
||||
return modulePath;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
@@ -15,45 +15,49 @@
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::NativeUI
|
||||
{
|
||||
namespace NativeUI
|
||||
enum AssertAction
|
||||
{
|
||||
enum AssertAction
|
||||
{
|
||||
IGNORE_ASSERT = 0,
|
||||
IGNORE_ALL_ASSERTS,
|
||||
BREAK,
|
||||
NONE,
|
||||
};
|
||||
IGNORE_ASSERT = 0,
|
||||
IGNORE_ALL_ASSERTS,
|
||||
BREAK,
|
||||
NONE,
|
||||
};
|
||||
|
||||
class NativeUIRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
class NativeUIRequests
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(NativeUIRequests, "{48361EE6-C1E7-4965-A13A-7425B2691817}");
|
||||
virtual ~NativeUIRequests() = default;
|
||||
|
||||
// Waits for user to select an option before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayBlockingDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, const AZStd::vector<AZStd::string>& /*options*/) const { return ""; };
|
||||
// Waits for user to select an option before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayBlockingDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, const AZStd::vector<AZStd::string>& /*options*/) const { return ""; };
|
||||
|
||||
// Waits for user to select an option ('Ok' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayOkDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
// Waits for user to select an option ('Ok' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayOkDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
|
||||
// Waits for user to select an option ('Yes', 'No' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayYesNoDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
// Waits for user to select an option ('Yes', 'No' or optionally 'Cancel') before execution continues
|
||||
// Returns the option string selected by the user
|
||||
virtual AZStd::string DisplayYesNoDialog(const AZStd::string& /*title*/, const AZStd::string& /*message*/, bool /*showCancel*/) const { return ""; };
|
||||
|
||||
// Displays an assert dialog box
|
||||
// Returns the action selected by the user
|
||||
virtual AssertAction DisplayAssertDialog(const AZStd::string& /*message*/) const { return AssertAction::NONE; };
|
||||
};
|
||||
// Displays an assert dialog box
|
||||
// Returns the action selected by the user
|
||||
virtual AssertAction DisplayAssertDialog(const AZStd::string& /*message*/) const { return AssertAction::NONE; };
|
||||
};
|
||||
|
||||
using NativeUIRequestBus = AZ::EBus<NativeUIRequests>;
|
||||
}
|
||||
}
|
||||
class NativeUIEBusTraits
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
};
|
||||
|
||||
using NativeUIRequestBus = AZ::EBus<NativeUIRequests, NativeUIEBusTraits>;
|
||||
} // namespace AZ::NativeUI
|
||||
|
||||
@@ -15,50 +15,19 @@
|
||||
|
||||
#include <AzCore/NativeUI/NativeUISystemComponent.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::NativeUI
|
||||
{
|
||||
using namespace AZ::NativeUI;
|
||||
|
||||
void NativeUISystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
NativeUISystem::NativeUISystem()
|
||||
{
|
||||
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<NativeUISystemComponent, AZ::Component>()
|
||||
->Version(0)
|
||||
;
|
||||
|
||||
if (AZ::EditContext* ec = serialize->GetEditContext())
|
||||
{
|
||||
ec->Class<NativeUISystemComponent>("NativeUI", "Adds basic support for native (platform specific) UI dialog boxes")
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
;
|
||||
}
|
||||
}
|
||||
NativeUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
NativeUISystem::~NativeUISystem()
|
||||
{
|
||||
provided.push_back(AZ_CRC("NativeUIService", 0x8ec25f87));
|
||||
NativeUIRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
incompatible.push_back(AZ_CRC("NativeUIService", 0x8ec25f87));
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
(void)required;
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
(void)dependent;
|
||||
}
|
||||
|
||||
AssertAction NativeUISystemComponent::DisplayAssertDialog(const AZStd::string& message) const
|
||||
AssertAction NativeUISystem::DisplayAssertDialog(const AZStd::string& message) const
|
||||
{
|
||||
static const char* buttonNames[3] = { "Ignore", "Ignore All", "Break" };
|
||||
AZStd::vector<AZStd::string> options;
|
||||
@@ -80,7 +49,7 @@ namespace AZ
|
||||
return AssertAction::NONE;
|
||||
}
|
||||
|
||||
AZStd::string NativeUISystemComponent::DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
AZStd::string NativeUISystem::DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
{
|
||||
AZStd::vector<AZStd::string> options;
|
||||
|
||||
@@ -93,7 +62,7 @@ namespace AZ
|
||||
return DisplayBlockingDialog(title, message, options);
|
||||
}
|
||||
|
||||
AZStd::string NativeUISystemComponent::DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
AZStd::string NativeUISystem::DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const
|
||||
{
|
||||
AZStd::vector<AZStd::string> options;
|
||||
|
||||
@@ -106,18 +75,4 @@ namespace AZ
|
||||
|
||||
return DisplayBlockingDialog(title, message, options);
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::Activate()
|
||||
{
|
||||
NativeUIRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void NativeUISystemComponent::Deactivate()
|
||||
{
|
||||
NativeUIRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
}
|
||||
} // namespace AZ::NativeUI
|
||||
|
||||
@@ -15,40 +15,24 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/NativeUI/NativeUIRequests.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::NativeUI
|
||||
{
|
||||
namespace NativeUI
|
||||
class NativeUISystem
|
||||
: public NativeUIRequestBus::Handler
|
||||
{
|
||||
class NativeUISystemComponent
|
||||
: public AZ::Component
|
||||
, public NativeUIRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(NativeUISystemComponent, "{E996C058-4AFE-4C8C-816F-98D864D8576D}");
|
||||
public:
|
||||
AZ_RTTI(NativeUISystem, "{FF534B2C-11BE-4DEA-A5B7-A4FA96FE1EDE}", NativeUIRequests);
|
||||
AZ_CLASS_ALLOCATOR(NativeUISystem, AZ::OSAllocator, 0);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
NativeUISystem();
|
||||
~NativeUISystem() override;
|
||||
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// NativeUIRequestBus interface implementation
|
||||
AZStd::string DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const override;
|
||||
AZStd::string DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AZStd::string DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AssertAction DisplayAssertDialog(const AZStd::string& message) const override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Component interface implementation
|
||||
void Init() override;
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// NativeUIRequestBus interface implementation
|
||||
AZStd::string DisplayBlockingDialog(const AZStd::string& title, const AZStd::string& message, const AZStd::vector<AZStd::string>& options) const override;
|
||||
AZStd::string DisplayOkDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AZStd::string DisplayYesNoDialog(const AZStd::string& title, const AZStd::string& message, bool showCancel) const override;
|
||||
AssertAction DisplayAssertDialog(const AZStd::string& message) const override;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
};
|
||||
} // namespace AZ::NativeUI
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/PlatformId/PlatformDefaults.h>
|
||||
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
inline namespace PlatformDefaults
|
||||
{
|
||||
static const char* PlatformNames[PlatformId::NumPlatformIds] = { PlatformPC, PlatformES3, PlatformIOS, PlatformOSX, PlatformProvo, PlatformSalem, PlatformJasper, PlatformServer, PlatformAll, PlatformAllClient };
|
||||
|
||||
const char* PlatformIdToPalFolder(AZ::PlatformId platform)
|
||||
{
|
||||
#ifdef IOS
|
||||
#define AZ_REDEFINE_IOS_AT_END IOS
|
||||
#undef IOS
|
||||
#endif
|
||||
switch (platform)
|
||||
{
|
||||
case AZ::PC:
|
||||
return "PC";
|
||||
case AZ::ES3:
|
||||
return "Android";
|
||||
case AZ::IOS:
|
||||
return "iOS";
|
||||
case AZ::OSX:
|
||||
return "Mac";
|
||||
case AZ::PROVO:
|
||||
return "Provo";
|
||||
case AZ::SALEM:
|
||||
return "Salem";
|
||||
case AZ::JASPER:
|
||||
return "Jasper";
|
||||
case AZ::SERVER:
|
||||
return "Server";
|
||||
case AZ::ALL:
|
||||
case AZ::ALL_CLIENT:
|
||||
case AZ::NumPlatformIds:
|
||||
case AZ::Invalid:
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef AZ_REDEFINE_IOS_AT_END
|
||||
#define IOS AZ_REDEFINE_IOS_AT_END
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform)
|
||||
{
|
||||
if (osPlatform == PlatformCodeNameWindows || osPlatform == PlatformCodeNameLinux)
|
||||
{
|
||||
return PlatformPC;
|
||||
}
|
||||
else if (osPlatform == PlatformCodeNameMac)
|
||||
{
|
||||
return PlatformOSX;
|
||||
}
|
||||
else if (osPlatform == PlatformCodeNameAndroid)
|
||||
{
|
||||
return PlatformES3;
|
||||
}
|
||||
else if (osPlatform == PlatformCodeNameiOS)
|
||||
{
|
||||
return PlatformIOS;
|
||||
}
|
||||
else if (osPlatform == PlatformCodeNameProvo)
|
||||
{
|
||||
return PlatformProvo;
|
||||
}
|
||||
else if (osPlatform == PlatformCodeNameSalem)
|
||||
{
|
||||
return PlatformSalem;
|
||||
}
|
||||
else if (osPlatform == PlatformCodeNameJasper)
|
||||
{
|
||||
return PlatformJasper;
|
||||
}
|
||||
|
||||
AZ_Error("PlatformDefault", false, R"(Supplied OS platform "%.*s" does not have a corresponding default asset platform)",
|
||||
aznumeric_cast<int>(osPlatform.size()), osPlatform.data());
|
||||
return "";
|
||||
}
|
||||
|
||||
PlatformFlags PlatformHelper::GetPlatformFlagFromPlatformIndex(PlatformId platformIndex)
|
||||
{
|
||||
if (platformIndex < 0 || platformIndex > PlatformId::NumPlatformIds)
|
||||
{
|
||||
return PlatformFlags::Platform_NONE;
|
||||
}
|
||||
if (platformIndex == PlatformId::ALL)
|
||||
{
|
||||
return PlatformFlags::Platform_ALL;
|
||||
}
|
||||
if (platformIndex == PlatformId::ALL_CLIENT)
|
||||
{
|
||||
return PlatformFlags::Platform_ALL_CLIENT;
|
||||
}
|
||||
return static_cast<PlatformFlags>(1 << platformIndex);
|
||||
}
|
||||
|
||||
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> PlatformHelper::GetPlatforms(PlatformFlags platformFlags)
|
||||
{
|
||||
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> platforms;
|
||||
for (int platformNum = 0; platformNum < PlatformId::NumPlatformIds; ++platformNum)
|
||||
{
|
||||
const bool isAllPlatforms = PlatformId::ALL == static_cast<PlatformId>(platformNum)
|
||||
&& ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE);
|
||||
|
||||
const bool isAllClientPlatforms = PlatformId::ALL_CLIENT == static_cast<PlatformId>(platformNum)
|
||||
&& ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE);
|
||||
|
||||
if (isAllPlatforms || isAllClientPlatforms
|
||||
|| (platformFlags & static_cast<PlatformFlags>(1 << platformNum)) != PlatformFlags::Platform_NONE)
|
||||
{
|
||||
platforms.push_back(PlatformNames[platformNum]);
|
||||
}
|
||||
}
|
||||
|
||||
return platforms;
|
||||
}
|
||||
|
||||
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformsInterpreted(PlatformFlags platformFlags)
|
||||
{
|
||||
return GetPlatforms(GetPlatformFlagsInterpreted(platformFlags));
|
||||
}
|
||||
|
||||
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformIndices(PlatformFlags platformFlags)
|
||||
{
|
||||
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> platformIndices;
|
||||
for (int i = 0; i < PlatformId::NumPlatformIds; i++)
|
||||
{
|
||||
PlatformId index = static_cast<PlatformId>(i);
|
||||
if ((GetPlatformFlagFromPlatformIndex(index) & platformFlags) != PlatformFlags::Platform_NONE)
|
||||
{
|
||||
platformIndices.emplace_back(index);
|
||||
}
|
||||
}
|
||||
return platformIndices;
|
||||
}
|
||||
|
||||
AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> PlatformHelper::GetPlatformIndicesInterpreted(PlatformFlags platformFlags)
|
||||
{
|
||||
return GetPlatformIndices(GetPlatformFlagsInterpreted(platformFlags));
|
||||
}
|
||||
|
||||
PlatformFlags PlatformHelper::GetPlatformFlag(AZStd::string_view platform)
|
||||
{
|
||||
int platformIndex = GetPlatformIndexFromName(platform);
|
||||
if (platformIndex == PlatformId::Invalid)
|
||||
{
|
||||
AZ_Error("PlatformDefault", false, "Invalid Platform ( %.*s ).\n", static_cast<int>(platform.length()), platform.data());
|
||||
return PlatformFlags::Platform_NONE;
|
||||
}
|
||||
|
||||
if (platformIndex == PlatformId::ALL)
|
||||
{
|
||||
return PlatformFlags::Platform_ALL;
|
||||
}
|
||||
|
||||
if (platformIndex == PlatformId::ALL_CLIENT)
|
||||
{
|
||||
return PlatformFlags::Platform_ALL_CLIENT;
|
||||
}
|
||||
|
||||
return static_cast<PlatformFlags>(1 << platformIndex);
|
||||
}
|
||||
|
||||
const char* PlatformHelper::GetPlatformName(PlatformId platform)
|
||||
{
|
||||
if (platform < 0 || platform > PlatformId::NumPlatformIds)
|
||||
{
|
||||
return "invalid";
|
||||
}
|
||||
return PlatformNames[platform];
|
||||
}
|
||||
|
||||
void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, AZStd::string_view platformId)
|
||||
{
|
||||
PlatformId platform = GetPlatformIdFromName(platformId);
|
||||
AZ_Assert(platform != PlatformId::Invalid, "Unsupported Platform ID: %.*s", static_cast<int>(platformId.length()), platformId.data());
|
||||
AppendPlatformCodeNames(platformCodes, platform);
|
||||
}
|
||||
|
||||
void PlatformHelper::AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, PlatformId platformId)
|
||||
{
|
||||
// The IOS SDK has a macro that defines IOS as 1 which causes the enum below to be incorrectly converted to "PlatformId::1".
|
||||
#pragma push_macro("IOS")
|
||||
#undef IOS
|
||||
// To reduce work the Asset Processor groups assets that can be shared between hardware platforms together. For this
|
||||
// reason "PC" can for instance cover both the Windows and Linux platforms and "IOS" can cover AppleTV and iOS.
|
||||
switch (platformId)
|
||||
{
|
||||
case PlatformId::PC:
|
||||
platformCodes.emplace_back(PlatformCodeNameWindows);
|
||||
platformCodes.emplace_back(PlatformCodeNameLinux);
|
||||
break;
|
||||
case PlatformId::ES3:
|
||||
platformCodes.emplace_back(PlatformCodeNameAndroid);
|
||||
break;
|
||||
case PlatformId::IOS:
|
||||
platformCodes.emplace_back(PlatformCodeNameiOS);
|
||||
break;
|
||||
case PlatformId::OSX:
|
||||
platformCodes.emplace_back(PlatformCodeNameMac);
|
||||
break;
|
||||
case PlatformId::PROVO:
|
||||
platformCodes.emplace_back(PlatformCodeNameProvo);
|
||||
break;
|
||||
case PlatformId::SALEM:
|
||||
platformCodes.emplace_back(PlatformCodeNameSalem);
|
||||
break;
|
||||
case PlatformId::JASPER:
|
||||
platformCodes.emplace_back(PlatformCodeNameJasper);
|
||||
break;
|
||||
case PlatformId::SERVER:
|
||||
// Server is not a hardware platform
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "Unsupported Platform ID: %i", platformId);
|
||||
break;
|
||||
}
|
||||
#pragma pop_macro("IOS")
|
||||
}
|
||||
|
||||
int PlatformHelper::GetPlatformIndexFromName(AZStd::string_view platformName)
|
||||
{
|
||||
for (int idx = 0; idx < PlatformId::NumPlatformIds; idx++)
|
||||
{
|
||||
if (platformName == PlatformNames[idx])
|
||||
{
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
return PlatformId::Invalid;
|
||||
}
|
||||
|
||||
PlatformId PlatformHelper::GetPlatformIdFromName(AZStd::string_view platformName)
|
||||
{
|
||||
return aznumeric_caster(GetPlatformIndexFromName(platformName));
|
||||
}
|
||||
|
||||
AssetPlatformCombinedString PlatformHelper::GetCommaSeparatedPlatformList(PlatformFlags platformFlags)
|
||||
{
|
||||
AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> platformNames = GetPlatforms(platformFlags);
|
||||
AssetPlatformCombinedString platformsString;
|
||||
AZ::StringFunc::Join(platformsString, platformNames.begin(), platformNames.end(), ", ");
|
||||
return platformsString;
|
||||
}
|
||||
|
||||
PlatformFlags PlatformHelper::GetPlatformFlagsInterpreted(PlatformFlags platformFlags)
|
||||
{
|
||||
PlatformFlags returnFlags = PlatformFlags::Platform_NONE;
|
||||
|
||||
if ((platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE)
|
||||
{
|
||||
for (int i = 0; i < NumPlatforms; ++i)
|
||||
{
|
||||
auto platformId = static_cast<PlatformId>(i);
|
||||
|
||||
if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT)
|
||||
{
|
||||
returnFlags |= GetPlatformFlagFromPlatformIndex(platformId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE)
|
||||
{
|
||||
for (int i = 0; i < NumPlatforms; ++i)
|
||||
{
|
||||
auto platformId = static_cast<PlatformId>(i);
|
||||
|
||||
if (platformId != PlatformId::ALL && platformId != PlatformId::ALL_CLIENT && platformId != PlatformId::SERVER)
|
||||
{
|
||||
returnFlags |= GetPlatformFlagFromPlatformIndex(platformId);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnFlags = platformFlags;
|
||||
}
|
||||
|
||||
return returnFlags;
|
||||
}
|
||||
|
||||
bool PlatformHelper::IsSpecialPlatform(PlatformFlags platformFlags)
|
||||
{
|
||||
return (platformFlags & PlatformFlags::Platform_ALL) != PlatformFlags::Platform_NONE
|
||||
|| (platformFlags & PlatformFlags::Platform_ALL_CLIENT) != PlatformFlags::Platform_NONE;
|
||||
}
|
||||
|
||||
bool HasFlagHelper(PlatformFlags flags, PlatformFlags checkPlatform)
|
||||
{
|
||||
return (flags & checkPlatform) == checkPlatform;
|
||||
}
|
||||
|
||||
|
||||
bool PlatformHelper::HasPlatformFlag(PlatformFlags flags, PlatformId checkPlatform)
|
||||
{
|
||||
// If checkPlatform contains any kind of invalid id, just exit out here
|
||||
if (checkPlatform == PlatformId::Invalid || checkPlatform == NumPlatforms)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// ALL_CLIENT + SERVER = ALL
|
||||
if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT | PlatformFlags::Platform_SERVER))
|
||||
{
|
||||
flags = PlatformFlags::Platform_ALL;
|
||||
}
|
||||
|
||||
if (HasFlagHelper(flags, PlatformFlags::Platform_ALL))
|
||||
{
|
||||
// It doesn't matter what checkPlatform is set to in this case, just return true
|
||||
return true;
|
||||
}
|
||||
|
||||
if (HasFlagHelper(flags, PlatformFlags::Platform_ALL_CLIENT))
|
||||
{
|
||||
return checkPlatform != PlatformId::SERVER;
|
||||
}
|
||||
|
||||
return HasFlagHelper(flags, GetPlatformFlagFromPlatformIndex(checkPlatform));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Preprocessor/Enum.h>
|
||||
#include <AzCore/std/containers/fixed_vector.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
|
||||
// On IOS builds IOS will be defined and interfere with the below enums
|
||||
#pragma push_macro("IOS")
|
||||
#undef IOS
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
inline namespace PlatformDefaults
|
||||
{
|
||||
constexpr char PlatformPC[] = "pc";
|
||||
constexpr char PlatformES3[] = "es3";
|
||||
constexpr char PlatformIOS[] = "ios";
|
||||
constexpr char PlatformOSX[] = "osx_gl";
|
||||
constexpr char PlatformProvo[] = "provo";
|
||||
constexpr char PlatformSalem[] = "salem";
|
||||
constexpr char PlatformJasper[] = "jasper";
|
||||
constexpr char PlatformServer[] = "server";
|
||||
|
||||
constexpr char PlatformCodeNameWindows[] = "Windows";
|
||||
constexpr char PlatformCodeNameLinux[] = "Linux";
|
||||
constexpr char PlatformCodeNameAndroid[] = "Android";
|
||||
constexpr char PlatformCodeNameiOS[] = "iOS";
|
||||
constexpr char PlatformCodeNameMac[] = "Mac";
|
||||
constexpr char PlatformCodeNameProvo[] = "Provo";
|
||||
constexpr char PlatformCodeNameSalem[] = "Salem";
|
||||
constexpr char PlatformCodeNameJasper[] = "Jasper";
|
||||
constexpr char PlatformAll[] = "all";
|
||||
constexpr char PlatformAllClient[] = "all_client";
|
||||
|
||||
// Used for the capacity of a fixed vector to store the code names of platforms
|
||||
// The value needs to be higher than the number of unique OS platforms that are supported(at this time 8)
|
||||
constexpr size_t MaxPlatformCodeNames = 16;
|
||||
|
||||
//! This platform enum have platform values in sequence and can also be used to get the platform count.
|
||||
AZ_ENUM_WITH_UNDERLYING_TYPE(PlatformId, int,
|
||||
(Invalid, -1),
|
||||
PC,
|
||||
ES3,
|
||||
IOS,
|
||||
OSX,
|
||||
PROVO,
|
||||
SALEM,
|
||||
JASPER,
|
||||
SERVER, // Corresponds to the customer's flavor of "server" which could be windows, ubuntu, etc
|
||||
ALL,
|
||||
ALL_CLIENT,
|
||||
|
||||
// Add new platforms above this
|
||||
NumPlatformIds
|
||||
);
|
||||
constexpr int NumClientPlatforms = 7;
|
||||
constexpr int NumPlatforms = NumClientPlatforms + 1; // 1 "Server" platform currently
|
||||
enum class PlatformFlags : AZ::u32
|
||||
{
|
||||
Platform_NONE = 0x00,
|
||||
Platform_PC = 1 << PlatformId::PC,
|
||||
Platform_ES3 = 1 << PlatformId::ES3,
|
||||
Platform_IOS = 1 << PlatformId::IOS,
|
||||
Platform_OSX = 1 << PlatformId::OSX,
|
||||
Platform_PROVO = 1 << PlatformId::PROVO,
|
||||
Platform_SALEM = 1 << PlatformId::SALEM,
|
||||
Platform_JASPER = 1 << PlatformId::JASPER,
|
||||
Platform_SERVER = 1 << PlatformId::SERVER,
|
||||
|
||||
// A special platform that will always correspond to all platforms, even if new ones are added
|
||||
Platform_ALL = 1ULL << 30,
|
||||
|
||||
// A special platform that will always correspond to all non-server platforms, even if new ones are added
|
||||
Platform_ALL_CLIENT = 1ULL << 31,
|
||||
|
||||
AllNamedPlatforms = Platform_PC | Platform_ES3 | Platform_IOS | Platform_OSX | Platform_PROVO | Platform_SALEM | Platform_JASPER | Platform_SERVER,
|
||||
};
|
||||
|
||||
AZ_DEFINE_ENUM_BITWISE_OPERATORS(PlatformFlags);
|
||||
|
||||
// 32 characters should be more than enough to store a platform name
|
||||
using AssetPlatformFixedString = AZStd::fixed_string<32>;
|
||||
// Fixed string which can store a comma separated list of platforms names
|
||||
// Additional byte is added to take into account the comma
|
||||
using AssetPlatformCombinedString = AZStd::fixed_string < (AssetPlatformFixedString{}.max_size() + 1)* PlatformId::NumPlatformIds > ;
|
||||
|
||||
const char* PlatformIdToPalFolder(PlatformId platform);
|
||||
|
||||
const char* OSPlatformToDefaultAssetPlatform(AZStd::string_view osPlatform);
|
||||
|
||||
//! Platform Helper is an utility class that can be used to retrieve platform related information
|
||||
class PlatformHelper
|
||||
{
|
||||
public:
|
||||
|
||||
//! Given a platformIndex returns the platform name
|
||||
static const char* GetPlatformName(PlatformId platform);
|
||||
|
||||
//! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME.
|
||||
static void AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, AZStd::string_view platformName);
|
||||
|
||||
//! Converts the platform name to the platform code names as defined in AZ_TRAIT_OS_PLATFORM_CODENAME.
|
||||
static void AppendPlatformCodeNames(AZStd::fixed_vector<AZStd::string_view, MaxPlatformCodeNames>& platformCodes, PlatformId platformId);
|
||||
|
||||
//! Given a platform name returns a platform index.
|
||||
//! If the platform is not found, the method returns -1.
|
||||
static int GetPlatformIndexFromName(AZStd::string_view platformName);
|
||||
|
||||
//! Given a platform name returns a platform id.
|
||||
//! If the platform is not found, the method returns -1.
|
||||
static PlatformId GetPlatformIdFromName(AZStd::string_view platformName);
|
||||
|
||||
//! Given a platformIndex returns the platformFlags
|
||||
static PlatformFlags GetPlatformFlagFromPlatformIndex(PlatformId platform);
|
||||
|
||||
//! Given a platformFlags returns all the platform identifiers that are set.
|
||||
static AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> GetPlatforms(PlatformFlags platformFlags);
|
||||
//! Given a platformFlags returns all the platform identifiers that are set, with special flags interpreted. Do not use the result for saving
|
||||
static AZStd::fixed_vector<AZStd::string_view, PlatformId::NumPlatformIds> GetPlatformsInterpreted(PlatformFlags platformFlags);
|
||||
|
||||
//! Given a platformFlags return a list of PlatformId indices
|
||||
static AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> GetPlatformIndices(PlatformFlags platformFlags);
|
||||
//! Given a platformFlags return a list of PlatformId indices, with special flags interpreted. Do not use the result for saving
|
||||
static AZStd::fixed_vector<PlatformId, PlatformId::NumPlatformIds> GetPlatformIndicesInterpreted(PlatformFlags platformFlags);
|
||||
|
||||
//! Given a platform identifier returns its corresponding platform flag.
|
||||
static PlatformFlags GetPlatformFlag(AZStd::string_view platform);
|
||||
|
||||
//! Given any platformFlags returns a string listing the input platforms
|
||||
static AssetPlatformCombinedString GetCommaSeparatedPlatformList(PlatformFlags platformFlags);
|
||||
|
||||
//! If platformFlags contains any special flags, they are removed and replaced with the normal flags they represent
|
||||
static PlatformFlags GetPlatformFlagsInterpreted(PlatformFlags platformFlags);
|
||||
|
||||
//! Returns true if platformFlags contains any special flags
|
||||
static bool IsSpecialPlatform(PlatformFlags platformFlags);
|
||||
|
||||
//! Returns true if platformFlags has checkPlatform flag set.
|
||||
static bool HasPlatformFlag(PlatformFlags platformFlags, PlatformId checkPlatform);
|
||||
};
|
||||
}
|
||||
}
|
||||
#pragma pop_macro("IOS")
|
||||
@@ -113,4 +113,4 @@
|
||||
#define AZCG_Unpack_98(x, ...) AZCG_Unpack_1(x) AZCG_Unpack_97(__VA_ARGS__)
|
||||
#define AZCG_Unpack_99(x, ...) AZCG_Unpack_1(x) AZCG_Unpack_98(__VA_ARGS__)
|
||||
#define AZCG_Unpack(...) AZ_MACRO_SPECIALIZE(AZCG_Unpack_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
|
||||
#define AZCG_Paste(x) x
|
||||
#define AZCG_Paste(x) x
|
||||
|
||||
@@ -816,7 +816,7 @@ namespace AZ
|
||||
template<size_t Index>
|
||||
static void ReflectUnpackMethodFold(BehaviorContext::ClassBuilder<ContainerType>& builder)
|
||||
{
|
||||
AZStd::string methodName = AZStd::string::format("Get%ld", Index);
|
||||
const AZStd::string methodName = AZStd::string::format("Get%zu", Index);
|
||||
builder->Method(methodName.data(), [](ContainerType& value) { return AZStd::get<Index>(value); })
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::TupleGetFunctionIndex, Index)
|
||||
|
||||
@@ -26,4 +26,4 @@ namespace AZ
|
||||
void Activate() override { }
|
||||
void Deactivate() override { }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,4 +79,4 @@ namespace AZ
|
||||
AZ_TYPE_INFO_SPECIALIZE(Script::Attributes::OperatorType, "{26B98C03-7E07-4E3E-9E31-03DA2168E896}");
|
||||
AZ_TYPE_INFO_SPECIALIZE(Script::Attributes::StorageType, "{57FED71F-B590-4002-9599-A48CB50B0F8E}");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,4 @@ namespace AZ
|
||||
};
|
||||
|
||||
typedef AZ::EBus<BehaviorObjectSignalsInterface> BehaviorObjectSignals;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,4 +138,4 @@ namespace AZ
|
||||
m_currentlyProcessingTypeIds.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,4 +208,4 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1411,4 +1411,4 @@ namespace AZ
|
||||
m_value = entityProperty->m_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +38,4 @@ namespace AZ
|
||||
};
|
||||
|
||||
typedef AZ::EBus<ScriptPropertyWatcherInterface> ScriptPropertyWatcherBus;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,6 +699,10 @@ Data::AssetHandler::LoadResult ScriptSystemComponent::LoadAssetData(
|
||||
script->m_scriptBuffer.resize(scriptDataLength);
|
||||
stream->Read(scriptDataLength, script->m_scriptBuffer.data());
|
||||
|
||||
// Clear cached references in the event of a successful load. This function has to be queued on
|
||||
// AssetBus where NotifyAssetReloaded is also queued, to ensure its execution before NotifyAssetReloaded
|
||||
Data::AssetBus::QueueFunction(&ScriptSystemComponent::ClearAssetReferences, this, asset.GetId());
|
||||
|
||||
return Data::AssetHandler::LoadResult::LoadComplete;
|
||||
}
|
||||
|
||||
@@ -853,7 +857,7 @@ const char* ScriptSystemComponent::GetGroup() const
|
||||
|
||||
const char* AZ::ScriptSystemComponent::GetBrowserIcon() const
|
||||
{
|
||||
return "Editor/Icons/Components/LuaScript.svg";
|
||||
return "Icons/Components/LuaScript.svg";
|
||||
}
|
||||
|
||||
AZ::Uuid AZ::ScriptSystemComponent::GetComponentTypeId() const
|
||||
|
||||
@@ -47,4 +47,4 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if !defined(AZCORE_EXCLUDE_LUA)
|
||||
#endif // #if !defined(AZCORE_EXCLUDE_LUA)
|
||||
|
||||
@@ -287,4 +287,4 @@ namespace AZ
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ namespace AZ
|
||||
const static AZ::Crc32 StringLineEditingCompleteNotify = AZ_CRC("StringLineEditingCompleteNotify", 0x139e5fa9);
|
||||
|
||||
const static AZ::Crc32 NameLabelOverride = AZ_CRC("NameLabelOverride", 0x9ff79cab);
|
||||
const static AZ::Crc32 AssetPickerTitle = AZ_CRC_CE("AssetPickerTitle");
|
||||
const static AZ::Crc32 ChildNameLabelOverride = AZ_CRC("ChildNameLabelOverride", 0x73dd2909);
|
||||
//! Container attribute that is used to override labels for its elements given the index of the element
|
||||
const static AZ::Crc32 IndexedChildNameLabelOverride = AZ_CRC("IndexedChildNameLabelOverride", 0x5f313ac2);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Serialization/Json/ByteStreamSerializer.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(JsonByteStreamSerializer, SystemAllocator, 0);
|
||||
|
||||
JsonSerializationResult::Result JsonByteStreamSerializer::Load(
|
||||
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
JsonDeserializerContext& context)
|
||||
{
|
||||
using JsonSerializationResult::Outcomes;
|
||||
using JsonSerializationResult::Tasks;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<JsonByteStream>() == outputValueTypeId,
|
||||
"Unable to deserialize AZStd::vector<AZ::u8>> to json because the provided type is %s",
|
||||
outputValueTypeId.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(outputValue, "Expected a valid pointer to load from json value.");
|
||||
|
||||
switch (inputValue.GetType())
|
||||
{
|
||||
case rapidjson::kStringType: {
|
||||
JsonByteStream buffer;
|
||||
if (AZ::StringFunc::Base64::Decode(buffer, inputValue.GetString(), inputValue.GetStringLength()))
|
||||
{
|
||||
JsonByteStream* valAsByteStream = static_cast<JsonByteStream*>(outputValue);
|
||||
*valAsByteStream = AZStd::move(buffer);
|
||||
return context.Report(Tasks::ReadField, Outcomes::Success, "Successfully read ByteStream.");
|
||||
}
|
||||
return context.Report(Tasks::ReadField, Outcomes::Invalid, "Decode of Base64 encoded ByteStream failed.");
|
||||
}
|
||||
case rapidjson::kArrayType:
|
||||
case rapidjson::kObjectType:
|
||||
case rapidjson::kNullType:
|
||||
case rapidjson::kFalseType:
|
||||
case rapidjson::kTrueType:
|
||||
case rapidjson::kNumberType:
|
||||
return context.Report(
|
||||
Tasks::ReadField, Outcomes::Unsupported,
|
||||
"Unsupported type. ByteStream values cannot be read from arrays, objects, nulls, booleans or numbers.");
|
||||
default:
|
||||
return context.Report(Tasks::ReadField, Outcomes::Unknown, "Unknown json type encountered for ByteStream value.");
|
||||
}
|
||||
}
|
||||
|
||||
JsonSerializationResult::Result JsonByteStreamSerializer::Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
|
||||
JsonSerializerContext& context)
|
||||
{
|
||||
using JsonSerializationResult::Outcomes;
|
||||
using JsonSerializationResult::Tasks;
|
||||
|
||||
AZ_Assert(
|
||||
azrtti_typeid<JsonByteStream>() == valueTypeId,
|
||||
"Unable to serialize AZStd::vector<AZ::u8> to json because the provided type is %s",
|
||||
valueTypeId.ToString<AZStd::string>().c_str());
|
||||
|
||||
const JsonByteStream& valAsByteStream = *static_cast<const JsonByteStream*>(inputValue);
|
||||
if (context.ShouldKeepDefaults() || !defaultValue || (valAsByteStream != *static_cast<const JsonByteStream*>(defaultValue)))
|
||||
{
|
||||
const auto base64ByteStream = AZ::StringFunc::Base64::Encode(valAsByteStream.data(), valAsByteStream.size());
|
||||
outputValue.SetString(base64ByteStream.c_str(), base64ByteStream.size(), context.GetJsonAllocator());
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Success, "ByteStream successfully stored.");
|
||||
}
|
||||
|
||||
return context.Report(Tasks::WriteValue, Outcomes::DefaultsUsed, "Default ByteStream used.");
|
||||
}
|
||||
} // namespace AZ
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
using JsonByteStream = AZStd::vector<AZ::u8>; //!< Alias for AZStd::vector<AZ::u8>.
|
||||
|
||||
//! Serialize a stream of bytes (usually binary data) as a json string value.
|
||||
//! @note Related to GenericClassByteStream (part of SerializeGenericTypeInfo<AZStd::vector<AZ::u8>> - see AZStdContainers.inl for more
|
||||
//! details).
|
||||
class JsonByteStreamSerializer : public BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(JsonByteStreamSerializer, "{30F0EA5A-CD13-4BA7-BAE1-D50D851CAC45}", BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
JsonSerializationResult::Result Load(
|
||||
void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||
JsonDeserializerContext& context) override;
|
||||
JsonSerializationResult::Result Store(
|
||||
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
|
||||
JsonSerializerContext& context) override;
|
||||
};
|
||||
} // namespace AZ
|
||||
@@ -104,13 +104,12 @@ namespace AZ
|
||||
auto serializer = context.GetRegistrationContext()->GetSerializerForType(classData.m_typeId);
|
||||
if (serializer)
|
||||
{
|
||||
if (storeTypeId == StoreTypeId::Yes)
|
||||
ResultCode result = serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
if (storeTypeId == StoreTypeId::Yes && result.GetProcessing() != Processing::Halted)
|
||||
{
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Catastrophic,
|
||||
"Unable to store type information in a JSON Serializer primitive.");
|
||||
result.Combine(InsertTypeId(node, classData, context));
|
||||
}
|
||||
|
||||
return serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (classData.m_azRtti && (classData.m_azRtti->GetTypeTraits() & AZ::TypeTraits::is_enum) == AZ::TypeTraits::is_enum)
|
||||
@@ -128,13 +127,12 @@ namespace AZ
|
||||
serializer = context.GetRegistrationContext()->GetSerializerForType(classData.m_azRtti->GetGenericTypeId());
|
||||
if (serializer)
|
||||
{
|
||||
if (storeTypeId == StoreTypeId::Yes)
|
||||
ResultCode result = serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
if (storeTypeId == StoreTypeId::Yes && result.GetProcessing() != Processing::Halted)
|
||||
{
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Catastrophic,
|
||||
"Unable to store type information in a JSON Serializer primitive.");
|
||||
result.Combine(InsertTypeId(node, classData, context));
|
||||
}
|
||||
|
||||
return serializer->Store(node, object, defaultObject, classData.m_typeId, context);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,6 +147,7 @@ namespace AZ
|
||||
ResultCode result(Tasks::WriteValue);
|
||||
if (storeTypeId == StoreTypeId::Yes)
|
||||
{
|
||||
// Not using InsertTypeId here to avoid needing to create the temporary value and swap it in that call.
|
||||
node.AddMember(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier),
|
||||
StoreTypeName(classData, context), context.GetJsonAllocator());
|
||||
result = ResultCode(Tasks::WriteValue, Outcomes::Success);
|
||||
@@ -569,6 +568,31 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
JsonSerializationResult::ResultCode JsonSerializer::InsertTypeId(
|
||||
rapidjson::Value& output, const SerializeContext::ClassData& classData, JsonSerializerContext& context)
|
||||
{
|
||||
using namespace JsonSerializationResult;
|
||||
|
||||
if (output.IsObject())
|
||||
{
|
||||
rapidjson::Value insertedObject(rapidjson::kObjectType);
|
||||
insertedObject.AddMember(
|
||||
rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), StoreTypeName(classData, context),
|
||||
context.GetJsonAllocator());
|
||||
|
||||
for (auto& element : output.GetObject())
|
||||
{
|
||||
insertedObject.AddMember(AZStd::move(element.name), AZStd::move(element.value), context.GetJsonAllocator());
|
||||
}
|
||||
output = AZStd::move(insertedObject);
|
||||
return ResultCode(Tasks::WriteValue, Outcomes::Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Report(Tasks::WriteValue, Outcomes::Catastrophic, "Only able to store type information in a JSON Object.");
|
||||
}
|
||||
}
|
||||
|
||||
rapidjson::Value JsonSerializer::GetExplicitDefault()
|
||||
{
|
||||
return rapidjson::Value(rapidjson::kObjectType);
|
||||
|
||||
@@ -80,6 +80,9 @@ namespace AZ
|
||||
static JsonSerializationResult::ResultCode StoreTypeName(rapidjson::Value& output,
|
||||
const Uuid& typeId, JsonSerializerContext& context);
|
||||
|
||||
static JsonSerializationResult::ResultCode InsertTypeId(
|
||||
rapidjson::Value& output, const SerializeContext::ClassData& classData, JsonSerializerContext& context);
|
||||
|
||||
static rapidjson::Value GetExplicitDefault();
|
||||
};
|
||||
} // namespace AZ
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Serialization/Json/ArraySerializer.h>
|
||||
#include <AzCore/Serialization/Json/BasicContainerSerializer.h>
|
||||
#include <AzCore/Serialization/Json/BoolSerializer.h>
|
||||
#include <AzCore/Serialization/Json/ByteStreamSerializer.h>
|
||||
#include <AzCore/Serialization/Json/DoubleSerializer.h>
|
||||
#include <AzCore/Serialization/Json/IntSerializer.h>
|
||||
#include <AzCore/Serialization/Json/JsonSystemComponent.h>
|
||||
@@ -68,6 +69,8 @@ namespace AZ
|
||||
jsonContext->Serializer<JsonStringSerializer>()->HandlesType<AZStd::string>();
|
||||
jsonContext->Serializer<JsonOSStringSerializer>()->HandlesType<OSString>();
|
||||
|
||||
jsonContext->Serializer<JsonByteStreamSerializer>()->HandlesType<JsonByteStream>();
|
||||
|
||||
jsonContext->Serializer<JsonBasicContainerSerializer>()
|
||||
->HandlesType<AZStd::fixed_vector>()
|
||||
->HandlesType<AZStd::forward_list>()
|
||||
|
||||
@@ -256,7 +256,7 @@ namespace AZ
|
||||
|
||||
//! Remove the value at the provided path
|
||||
//! @param path The path to a value that should be removed
|
||||
//! @return Whether or not the value was stored at the provided path. An invalid path will return false;
|
||||
//! @return Whether or not the path was found and removed. An invalid path will return false;
|
||||
virtual bool Remove(AZStd::string_view path) = 0;
|
||||
|
||||
//! Structure which contains configuration settings for how to parse a single command line argument
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <AzCore/JSON/pointer.h>
|
||||
#include <AzCore/JSON/prettywriter.h>
|
||||
#include <AzCore/JSON/writer.h>
|
||||
#include <AzCore/PlatformId/PlatformDefaults.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/Settings/CommandLine.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
@@ -31,17 +32,12 @@
|
||||
namespace AZ::Internal
|
||||
{
|
||||
AZ::SettingsRegistryInterface::FixedValueString GetEngineMonikerForProject(
|
||||
SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectPath)
|
||||
SettingsRegistryInterface& settingsRegistry, const AZ::IO::FixedMaxPath& projectJsonPath)
|
||||
{
|
||||
// projectPath needs to be an absolute path here.
|
||||
using namespace AZ::SettingsRegistryMergeUtils;
|
||||
bool projectJsonMerged = false;
|
||||
auto projectJsonPath = projectPath / "project.json";
|
||||
if (AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
|
||||
{
|
||||
projectJsonMerged = settingsRegistry.MergeSettingsFile(
|
||||
projectJsonPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ProjectSettingsRootKey);
|
||||
}
|
||||
bool projectJsonMerged = settingsRegistry.MergeSettingsFile(
|
||||
projectJsonPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ProjectSettingsRootKey);
|
||||
|
||||
AZ::SettingsRegistryInterface::FixedValueString engineMoniker;
|
||||
if (projectJsonMerged)
|
||||
@@ -104,12 +100,12 @@ namespace AZ::Internal
|
||||
|
||||
const auto engineMonikerKey = AZ::SettingsRegistryInterface::FixedValueString::format("%s/engine_name", EngineSettingsRootKey);
|
||||
|
||||
AZStd::set<AZ::IO::FixedMaxPath> projectPathsNotFound;
|
||||
|
||||
for (EngineInfo& engineInfo : pathVisitor.m_enginePaths)
|
||||
{
|
||||
AZ::IO::FixedMaxPath engineSettingsPath{engineInfo.m_path};
|
||||
engineSettingsPath /= "engine.json";
|
||||
|
||||
if (AZ::IO::SystemFile::Exists(engineSettingsPath.c_str()))
|
||||
if (auto engineSettingsPath = AZ::IO::FixedMaxPath{engineInfo.m_path} / "engine.json";
|
||||
AZ::IO::SystemFile::Exists(engineSettingsPath.c_str()))
|
||||
{
|
||||
if (settingsRegistry.MergeSettingsFile(
|
||||
engineSettingsPath.Native(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, EngineSettingsRootKey))
|
||||
@@ -118,12 +114,61 @@ namespace AZ::Internal
|
||||
}
|
||||
}
|
||||
|
||||
auto engineMoniker = Internal::GetEngineMonikerForProject(settingsRegistry, engineInfo.m_path / projectPath);
|
||||
if (!engineMoniker.empty() && engineMoniker == engineInfo.m_moniker)
|
||||
if (auto projectJsonPath = (engineInfo.m_path / projectPath / "project.json").LexicallyNormal();
|
||||
AZ::IO::SystemFile::Exists(projectJsonPath.c_str()))
|
||||
{
|
||||
engineRoot = engineInfo.m_path;
|
||||
break;
|
||||
if (auto engineMoniker = Internal::GetEngineMonikerForProject(settingsRegistry, projectJsonPath);
|
||||
!engineMoniker.empty() && engineMoniker == engineInfo.m_moniker)
|
||||
{
|
||||
engineRoot = engineInfo.m_path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
projectPathsNotFound.insert(projectJsonPath);
|
||||
}
|
||||
|
||||
// Continue looking for candidates, remove the previous engine and project settings that were merged above.
|
||||
settingsRegistry.Remove(ProjectSettingsRootKey);
|
||||
settingsRegistry.Remove(EngineSettingsRootKey);
|
||||
}
|
||||
|
||||
if (engineRoot.empty())
|
||||
{
|
||||
AZStd::string errorStr;
|
||||
if (!projectPathsNotFound.empty())
|
||||
{
|
||||
// This case is usually encountered when a project path is given as a relative path,
|
||||
// which is assumed to be relative to an engine root.
|
||||
// When no project.json files are found this way, dump this error message about
|
||||
// which project paths were checked.
|
||||
AZStd::string projectPathsTested;
|
||||
for (const auto& path : projectPathsNotFound)
|
||||
{
|
||||
projectPathsTested.append(AZStd::string::format(" %s\n", path.c_str()));
|
||||
}
|
||||
errorStr = AZStd::string::format("No valid project was found at these locations:\n%s"
|
||||
"Please supply a valid --project-path to the application.",
|
||||
projectPathsTested.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// The other case is that a project.json was found, but after checking all the registered engines
|
||||
// none of them matched the engine moniker.
|
||||
AZStd::string enginePathsChecked;
|
||||
for (const auto& engineInfo : pathVisitor.m_enginePaths)
|
||||
{
|
||||
enginePathsChecked.append(AZStd::string::format(" %s (%s)\n", engineInfo.m_path.c_str(), engineInfo.m_moniker.c_str()));
|
||||
}
|
||||
errorStr = AZStd::string::format(
|
||||
"No engine was found in o3de_manifest.json with a name that matches the one set in the project.json.\n"
|
||||
"Engines that were checked:\n%s"
|
||||
"Please check that your engine and project have both been registered with scripts/o3de.py.", enginePathsChecked.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
settingsRegistry.Set(FilePathKey_ErrorText, errorStr.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,23 +177,14 @@ namespace AZ::Internal
|
||||
|
||||
AZ::IO::FixedMaxPath ScanUpRootLocator(AZStd::string_view rootFileToLocate)
|
||||
{
|
||||
|
||||
AZStd::fixed_string<AZ::IO::MaxPathLength> executableDir;
|
||||
if (AZ::Utils::GetExecutableDirectory(executableDir.data(), executableDir.capacity()) == Utils::ExecutablePathResult::Success)
|
||||
{
|
||||
// Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string
|
||||
// stored within it
|
||||
executableDir.resize_no_construct(AZStd::char_traits<char>::length(executableDir.data()));
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath engineRootCandidate{ executableDir };
|
||||
AZ::IO::FixedMaxPath rootCandidate{ AZ::Utils::GetExecutableDirectory() };
|
||||
|
||||
bool rootPathVisited = false;
|
||||
do
|
||||
{
|
||||
if (AZ::IO::SystemFile::Exists((engineRootCandidate / rootFileToLocate).c_str()))
|
||||
if (AZ::IO::SystemFile::Exists((rootCandidate / rootFileToLocate).c_str()))
|
||||
{
|
||||
return engineRootCandidate;
|
||||
return rootCandidate;
|
||||
}
|
||||
|
||||
// Note for posix filesystems the parent directory of '/' is '/' and for windows
|
||||
@@ -156,38 +192,69 @@ namespace AZ::Internal
|
||||
|
||||
// Validate that the parent directory isn't itself, that would imply
|
||||
// that it is the filesystem root path
|
||||
AZ::IO::PathView parentPath = engineRootCandidate.ParentPath();
|
||||
rootPathVisited = (engineRootCandidate == parentPath);
|
||||
AZ::IO::PathView parentPath = rootCandidate.ParentPath();
|
||||
rootPathVisited = (rootCandidate == parentPath);
|
||||
// Recurse upwards one directory
|
||||
engineRootCandidate = AZStd::move(parentPath);
|
||||
rootCandidate = AZStd::move(parentPath);
|
||||
|
||||
} while (!rootPathVisited);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void InjectSettingToCommandLineBack(AZ::SettingsRegistryInterface& settingsRegistry,
|
||||
AZStd::string_view path, AZStd::string_view value)
|
||||
{
|
||||
AZ::CommandLine commandLine;
|
||||
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(settingsRegistry, commandLine);
|
||||
AZ::CommandLine::ParamContainer paramContainer;
|
||||
commandLine.Dump(paramContainer);
|
||||
|
||||
auto projectPathOverride = AZStd::string::format(R"(--regset="%.*s=%.*s")",
|
||||
aznumeric_cast<int>(path.size()), path.data(), aznumeric_cast<int>(value.size()), value.data());
|
||||
paramContainer.emplace(paramContainer.end(), AZStd::move(projectPathOverride));
|
||||
commandLine.Parse(paramContainer);
|
||||
AZ::SettingsRegistryMergeUtils::StoreCommandLineToRegistry(settingsRegistry, commandLine);
|
||||
}
|
||||
} // namespace AZ::Internal
|
||||
|
||||
namespace AZ::SettingsRegistryMergeUtils
|
||||
{
|
||||
constexpr AZStd::string_view InternalScanUpEngineRootKey{ "/O3DE/Settings/Internal/engine_root_scan_up_path" };
|
||||
constexpr AZStd::string_view InternalScanUpProjectRootKey{ "/O3DE/Settings/Internal/project_root_scan_up_path" };
|
||||
|
||||
AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry)
|
||||
{
|
||||
AZ::IO::FixedMaxPath engineRoot;
|
||||
|
||||
// This is the 'external' engine root key, as in passed from command-line or .setreg files.
|
||||
auto engineRootKey = SettingsRegistryInterface::FixedValueString::format("%s/engine_path", BootstrapSettingsRootKey);
|
||||
|
||||
// Step 1 Run the scan upwards logic once to find the location of the engine.json if it exist
|
||||
// Once this step is run the {InternalScanUpEngineRootKey} is set in the Settings Registry
|
||||
// to have this scan logic only run once InternalScanUpEngineRootKey the supplied registry
|
||||
if (settingsRegistry.GetType(InternalScanUpEngineRootKey) == SettingsRegistryInterface::Type::NoType)
|
||||
{
|
||||
// We can scan up from exe directory to find engine.json, use that for engine root if it exists.
|
||||
engineRoot = Internal::ScanUpRootLocator("engine.json");
|
||||
// Set the {InternalScanUpEngineRootKey} to make sure this code path isn't called again for this settings registry
|
||||
settingsRegistry.Set(InternalScanUpEngineRootKey, engineRoot.Native());
|
||||
if (!engineRoot.empty())
|
||||
{
|
||||
settingsRegistry.Set(engineRootKey, engineRoot.Native());
|
||||
// Inject the engine root at the end of the command line settings
|
||||
Internal::InjectSettingToCommandLineBack(settingsRegistry, engineRootKey, engineRoot.Native());
|
||||
return engineRoot;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2 check if the engine_path key has been supplied
|
||||
if (settingsRegistry.Get(engineRoot.Native(), engineRootKey); !engineRoot.empty())
|
||||
{
|
||||
return engineRoot;
|
||||
}
|
||||
|
||||
// We can scan up from exe directory to find engine.json, use that for engine root if it exists.
|
||||
if (engineRoot = Internal::ScanUpRootLocator("engine.json"); !engineRoot.empty())
|
||||
{
|
||||
settingsRegistry.Set(engineRootKey, engineRoot.c_str());
|
||||
return engineRoot;
|
||||
}
|
||||
|
||||
// Step 3 locate the project root and attempt to find the engine root using the registered engine
|
||||
// for the project in the project.json file
|
||||
AZ::IO::FixedMaxPath projectRoot = FindProjectRoot(settingsRegistry);
|
||||
if (projectRoot.empty())
|
||||
{
|
||||
@@ -207,16 +274,30 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry)
|
||||
{
|
||||
AZ::IO::FixedMaxPath projectRoot;
|
||||
// This is the 'external' project root key, as in passed from command-line or .setreg files.
|
||||
auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey);
|
||||
if (settingsRegistry.Get(projectRoot.Native(), projectRootKey))
|
||||
const auto projectRootKey = SettingsRegistryInterface::FixedValueString::format("%s/project_path", BootstrapSettingsRootKey);
|
||||
|
||||
// Step 1 Run the scan upwards logic once to find the location of the project.json if it exist
|
||||
// Once this step is run the {InternalScanUpProjectRootKey} is set in the Settings Registry
|
||||
// to have this scan logic only run once for the supplied registry
|
||||
// SettingsRegistryInterface::GetType is used to check if a key is set
|
||||
if (settingsRegistry.GetType(InternalScanUpProjectRootKey) == SettingsRegistryInterface::Type::NoType)
|
||||
{
|
||||
return projectRoot;
|
||||
projectRoot = Internal::ScanUpRootLocator("project.json");
|
||||
// Set the {InternalScanUpProjectRootKey} to make sure this code path isn't called again for this settings registry
|
||||
settingsRegistry.Set(InternalScanUpProjectRootKey, projectRoot.Native());
|
||||
if (!projectRoot.empty())
|
||||
{
|
||||
settingsRegistry.Set(projectRootKey, projectRoot.c_str());
|
||||
// Inject the project root at the end of the command line settings
|
||||
Internal::InjectSettingToCommandLineBack(settingsRegistry, projectRootKey, projectRoot.Native());
|
||||
return projectRoot;
|
||||
}
|
||||
}
|
||||
|
||||
if (projectRoot = Internal::ScanUpRootLocator("project.json"); !projectRoot.empty())
|
||||
// Step 2 Check the project-path key
|
||||
// This is the project path root key, as in passed from command-line or .setreg files.
|
||||
if (settingsRegistry.Get(projectRoot.Native(), projectRootKey))
|
||||
{
|
||||
settingsRegistry.Set(projectRootKey, projectRoot.c_str());
|
||||
return projectRoot;
|
||||
}
|
||||
|
||||
@@ -463,24 +544,13 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
void MergeSettingsToRegistry_Bootstrap(SettingsRegistryInterface& registry)
|
||||
{
|
||||
ConfigParserSettings parserSettings;
|
||||
parserSettings.m_commentPrefixFunc = [](AZStd::string_view line) -> AZStd::string_view
|
||||
{
|
||||
constexpr AZStd::string_view commentPrefixes[]{ "--", ";","#" };
|
||||
for (AZStd::string_view commentPrefix : commentPrefixes)
|
||||
{
|
||||
if (size_t commentOffset = line.find(commentPrefix); commentOffset != AZStd::string_view::npos)
|
||||
{
|
||||
return line.substr(0, commentOffset);
|
||||
}
|
||||
}
|
||||
return line;
|
||||
};
|
||||
parserSettings.m_registryRootPointerPath = BootstrapSettingsRootKey;
|
||||
MergeSettingsToRegistry_ConfigFile(registry, "bootstrap.cfg", parserSettings);
|
||||
}
|
||||
|
||||
void MergeSettingsToRegistry_AddRuntimeFilePaths(SettingsRegistryInterface& registry)
|
||||
{
|
||||
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
||||
// Binary folder
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetExecutableDirectory();
|
||||
registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
|
||||
@@ -489,27 +559,25 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry);
|
||||
registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native());
|
||||
|
||||
constexpr size_t bufferSize = 64;
|
||||
auto buffer = AZStd::fixed_string<bufferSize>::format("%s/project_path", BootstrapSettingsRootKey);
|
||||
|
||||
AZ::SettingsRegistryInterface::FixedValueString projectPathKey(buffer);
|
||||
auto projectPathKey = FixedValueString::format("%s/project_path", BootstrapSettingsRootKey);
|
||||
SettingsRegistryInterface::FixedValueString projectPathValue;
|
||||
if (registry.Get(projectPathValue, projectPathKey))
|
||||
{
|
||||
// Cache folder
|
||||
// Get the name of the asset platform assigned by the bootstrap. First check for platform version such as "windows_assets"
|
||||
// and if that's missing just get "assets".
|
||||
constexpr char platformName[] = AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER;
|
||||
|
||||
SettingsRegistryInterface::FixedValueString assetPlatform;
|
||||
buffer = AZStd::fixed_string<bufferSize>::format("%s/%s_assets", BootstrapSettingsRootKey, platformName);
|
||||
AZStd::string_view assetPlatformKey(buffer);
|
||||
if (!registry.Get(assetPlatform, assetPlatformKey))
|
||||
FixedValueString assetPlatform;
|
||||
if (auto assetPlatformKey = FixedValueString::format("%s/%s_assets", BootstrapSettingsRootKey, AZ_TRAIT_OS_PLATFORM_CODENAME_LOWER);
|
||||
!registry.Get(assetPlatform, assetPlatformKey))
|
||||
{
|
||||
buffer = AZStd::fixed_string<bufferSize>::format("%s/assets", BootstrapSettingsRootKey);
|
||||
assetPlatformKey = AZStd::string_view(buffer);
|
||||
assetPlatformKey = FixedValueString::format("%s/assets", BootstrapSettingsRootKey);
|
||||
registry.Get(assetPlatform, assetPlatformKey);
|
||||
}
|
||||
if (assetPlatform.empty())
|
||||
{
|
||||
// Use the platform codename to retrieve the default asset platform value
|
||||
assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
}
|
||||
|
||||
// Project path - corresponds to the @devassets@ alias
|
||||
// NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded.
|
||||
@@ -549,8 +617,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
{
|
||||
// Cache: project root - no corresponding fileIO alias, but this is where the asset database lives.
|
||||
// A registry override is accepted using the "project_cache_path" key.
|
||||
buffer = AZStd::fixed_string<bufferSize>::format("%s/project_cache_path", BootstrapSettingsRootKey);
|
||||
AZStd::string_view projectCacheRootOverrideKey(buffer);
|
||||
auto projectCacheRootOverrideKey = FixedValueString::format("%s/project_cache_path", BootstrapSettingsRootKey);
|
||||
// Clear path to make sure that the `project_cache_path` value isn't concatenated to the project path
|
||||
path.clear();
|
||||
if (registry.Get(path.Native(), projectCacheRootOverrideKey))
|
||||
@@ -631,7 +698,6 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
if (registry.Get(engineRootPath, FilePathKey_EngineRootFolder))
|
||||
{
|
||||
AZ::IO::FixedMaxPath mergePath{ AZStd::move(engineRootPath) };
|
||||
mergePath /= "Engine";
|
||||
mergePath /= SettingsRegistryInterface::RegistryFolder;
|
||||
registry.MergeSettingsFolder(mergePath.Native(), specializations, platform, "", scratchBuffer);
|
||||
}
|
||||
@@ -807,6 +873,11 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
++argumentIndex;
|
||||
commandLinePath.resize(commandLineRootSize);
|
||||
}
|
||||
|
||||
// This key is used allow Notification Handlers to know when the command line has been updated within the
|
||||
// registry. The value itself is meaningless. The JSON path of {CommandLineValueChangedKey}
|
||||
// being passed to the Notification Event Handler indicates that the command line has be updated
|
||||
registry.Set(CommandLineValueChangedKey, true);
|
||||
}
|
||||
|
||||
bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine)
|
||||
@@ -823,10 +894,16 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
else if (valueName == "Value" && !value.empty())
|
||||
{
|
||||
m_arguments.push_back(value);
|
||||
// Make sure value types are in quotes in case they start with a command option prefix
|
||||
m_arguments.push_back(QuoteArgument(value));
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::string QuoteArgument(AZStd::string_view arg)
|
||||
{
|
||||
return !arg.empty() ? AZStd::string::format(R"("%.*s")", aznumeric_cast<int>(arg.size()), arg.data()) : AZStd::string{ arg };
|
||||
}
|
||||
|
||||
// The first parameter is skipped by the ComamndLine::Parse function so initialize
|
||||
// the container with one empty element
|
||||
AZ::CommandLine::ParamContainer m_arguments{ 1 };
|
||||
@@ -841,6 +918,49 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParseCommandLine(AZ::CommandLine& commandLine)
|
||||
{
|
||||
struct OptionKeyToRegsetKey
|
||||
{
|
||||
AZStd::string_view m_optionKey;
|
||||
AZStd::string m_regsetKey;
|
||||
};
|
||||
|
||||
// Provide overrides for the engine root, the project root and the project cache root
|
||||
AZStd::array commandOptions = {
|
||||
OptionKeyToRegsetKey{
|
||||
"engine-path", AZStd::string::format("%s/engine_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)},
|
||||
OptionKeyToRegsetKey{
|
||||
"project-path", AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)},
|
||||
OptionKeyToRegsetKey{
|
||||
"project-cache-path",
|
||||
AZStd::string::format("%s/project_cache_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)}};
|
||||
|
||||
AZStd::fixed_vector<AZStd::string, commandOptions.size()> overrideArgs;
|
||||
|
||||
for (auto&& [optionKey, regsetKey] : commandOptions)
|
||||
{
|
||||
if (size_t optionCount = commandLine.GetNumSwitchValues(optionKey); optionCount > 0)
|
||||
{
|
||||
// Use the last supplied command option value to override previous values
|
||||
auto overrideArg = AZStd::string::format(
|
||||
R"(--regset="%s=%s")", regsetKey.c_str(), commandLine.GetSwitchValue(optionKey, optionCount - 1).c_str());
|
||||
overrideArgs.emplace_back(AZStd::move(overrideArg));
|
||||
}
|
||||
}
|
||||
|
||||
if (!overrideArgs.empty())
|
||||
{
|
||||
// Dump the input command line, add the additional option overrides
|
||||
// and Parse the new command line args (write back) into the input command line.
|
||||
AZ::CommandLine::ParamContainer commandLineArgs;
|
||||
commandLine.Dump(commandLineArgs);
|
||||
commandLineArgs.insert(
|
||||
commandLineArgs.end(), AZStd::make_move_iterator(overrideArgs.begin()), AZStd::make_move_iterator(overrideArgs.end()));
|
||||
commandLine.Parse(commandLineArgs);
|
||||
}
|
||||
}
|
||||
|
||||
bool DumpSettingsRegistryToStream(SettingsRegistryInterface& registry, AZStd::string_view key,
|
||||
AZ::IO::GenericStream& stream, const DumperSettings& dumperSettings)
|
||||
{
|
||||
|
||||
@@ -55,8 +55,14 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
//! Development write storage path may be considered temporary or cache storage on some platforms
|
||||
inline static constexpr char FilePathKey_DevWriteStorage[] = "/Amazon/AzCore/Runtime/FilePaths/DevWriteStorage";
|
||||
|
||||
//! Stores error text regarding engine boot sequence when engine and project roots cannot be determined
|
||||
inline static constexpr char FilePathKey_ErrorText[] = "/Amazon/AzCore/Runtime/FilePaths/ErrorText";
|
||||
|
||||
//! Root key for where command line are stored at within the settings registry
|
||||
inline static constexpr char CommandLineRootKey[] = "/Amazon/AzCore/Runtime/CommandLine";
|
||||
//! Key set to trigger a notification that the CommandLine has been stored within the settings registry
|
||||
//! The value of the key has no meaning. Notification Handlers only need to check if the key was supplied
|
||||
inline static constexpr char CommandLineValueChangedKey[] = "/Amazon/AzCore/Runtime/CommandLineChanged";
|
||||
|
||||
//! Root key where raw project settings (project.json) file is merged to settings registry
|
||||
inline static constexpr char ProjectSettingsRootKey[] = "/Amazon/Project/Settings";
|
||||
@@ -74,6 +80,20 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
//! If it's still not found, attempt to find the project (by similar means) then reconcile the
|
||||
//! engine root by inspecting project.json and the engine manifest file.
|
||||
AZ::IO::FixedMaxPath FindEngineRoot(SettingsRegistryInterface& settingsRegistry);
|
||||
|
||||
//! The algorithm that is used to find the project root is as follows
|
||||
//! 1. The first time this function is it performs a upward scan for a project.json file from
|
||||
//! the executable directory and if found stores that path to an internal key.
|
||||
//! In the same step it injects the path into the front of list of command line parameters
|
||||
//! using the --regset="{BootstrapSettingsRootKey}/project_path=<path>" value
|
||||
//! 2. Next the "{BootstrapSettingsRootKey}/project_path" is checked to see if it has a project path set
|
||||
//!
|
||||
//! The order in which the project path settings are overridden proceeds in the following order
|
||||
//! 1. project_path set in the <engine-root>/bootstrap.cfg file
|
||||
//! 2. project_path set in a *.setreg/*.setregpatch file
|
||||
//! 3. project_path found by scanning upwards from the executable directory to the project.json path
|
||||
//! 4. project_path set on the Command line via either --regset="{BootstrapSettingsRootKey}/project_path=<path>"
|
||||
//! or --project_path=<path>
|
||||
AZ::IO::FixedMaxPath FindProjectRoot(SettingsRegistryInterface& settingsRegistry);
|
||||
|
||||
//! Query the specializations that will be used when loading the Settings Registry.
|
||||
@@ -202,6 +222,9 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
//! into the AZ::CommandLine instance
|
||||
bool GetCommandLineFromRegistry(SettingsRegistryInterface& registry, AZ::CommandLine& commandLine);
|
||||
|
||||
//! Parse a CommandLine and transform certain options into formal "regset" options
|
||||
void ParseCommandLine(AZ::CommandLine& commandLine);
|
||||
|
||||
//! Structure for configuring how values should be dumped from the Settings Registry
|
||||
struct DumperSettings
|
||||
{
|
||||
|
||||
@@ -139,4 +139,4 @@ namespace AZ
|
||||
|
||||
/// @deprecated Use SliceBus.
|
||||
using PrefabBus = SliceBus;
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
@@ -39,4 +39,4 @@ namespace AZ
|
||||
|
||||
SliceAssetHandler m_assetHandler;
|
||||
};
|
||||
} // namespace AZ
|
||||
} // namespace AZ
|
||||
|
||||
@@ -125,4 +125,4 @@ namespace AZ
|
||||
bool DummyStateHandler(HSM& /*sm*/, const HSM::Event& /*e*/) { return handleEvent; }
|
||||
}
|
||||
#endif // AZCORE_HIERARCHIAL_STATE_MACHINE_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -505,6 +505,8 @@ set(FILES
|
||||
Serialization/Json/BasicContainerSerializer.cpp
|
||||
Serialization/Json/BoolSerializer.h
|
||||
Serialization/Json/BoolSerializer.cpp
|
||||
Serialization/Json/ByteStreamSerializer.h
|
||||
Serialization/Json/ByteStreamSerializer.cpp
|
||||
Serialization/Json/CastingHelpers.h
|
||||
Serialization/Json/DoubleSerializer.h
|
||||
Serialization/Json/DoubleSerializer.cpp
|
||||
@@ -605,6 +607,8 @@ set(FILES
|
||||
Utils/Utils.h
|
||||
Script/lua/lua.h
|
||||
Memory/HeapSchema.cpp
|
||||
PlatformId/PlatformDefaults.h
|
||||
PlatformId/PlatformDefaults.cpp
|
||||
PlatformId/PlatformId.h
|
||||
PlatformId/PlatformId.cpp
|
||||
Socket/AzSocket_fwd.h
|
||||
|
||||
@@ -38,4 +38,4 @@ namespace AZStd
|
||||
using std::is_placeholder;
|
||||
template<class T>
|
||||
constexpr size_t is_placeholder_v = is_placeholder<T>::value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2024,4 +2024,4 @@ namespace AZStd
|
||||
|
||||
|
||||
#endif // AZSTD_DELEGATE_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -228,4 +228,4 @@ namespace AZStd
|
||||
}
|
||||
|
||||
#endif //AZSTD_DELEGATE_BIND_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -23,4 +23,4 @@ namespace AZStd
|
||||
|
||||
|
||||
#endif // AZSTD_DELEGATE_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
+1
-1
@@ -194,4 +194,4 @@ namespace AZStd
|
||||
}
|
||||
|
||||
#endif // AZSTD_PARALLEL_CONTAINERS_CONCURRENT_FIXED_UNORDERED_MAP_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
+1
-1
@@ -162,4 +162,4 @@ namespace AZStd
|
||||
}
|
||||
|
||||
#endif // AZSTD_PARALLEL_CONTAINERS_CONCURRENT_FIXED_UNORDERED_SET_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -266,4 +266,4 @@ namespace AZStd
|
||||
}
|
||||
|
||||
#endif // AZSTD_PARALLEL_CONTAINERS_CONCURRENT_UNORDERED_MAP_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
@@ -228,4 +228,4 @@ namespace AZStd
|
||||
}
|
||||
|
||||
#endif // AZSTD_PARALLEL_CONTAINERS_CONCURRENT_UNORDERED_SET_H
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user