Merge branch 'main' into hasareej_LYN-2475_viewportui_switcher

This commit is contained in:
hasareej
2021-04-26 17:30:51 +01:00
7171 changed files with 112119 additions and 619305 deletions
@@ -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
)
)
+1 -1
View File
@@ -169,4 +169,4 @@ namespace UnitTest
intintptr_cache.clear();
EXPECT_EQ(p->use_count(), 1);
}
}
}
+1 -1
View File
@@ -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;
}
}
@@ -320,4 +320,4 @@ public class ObbDownloaderActivity extends Activity implements IDownloaderClient
private int m_buttonPauseTextId;
private int m_kbPerSecondTextId;
private int m_timeRemainingTextId;
}
}
@@ -37,4 +37,4 @@ public class ObbDownloaderAlarmReceiver extends BroadcastReceiver
e.printStackTrace();
}
}
}
}
@@ -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";
}
}
+5 -6
View File
@@ -302,10 +302,10 @@ def ProcessExpansionRule(sourceFiles, templateFiles, templateCache, outputDir, p
# Due to the lack of wildcards in the output file, we've determined we'll glob all matching input files into the template conversion
for filename in fnmatch.filter(sourceFiles, inputFiles):
dataInputFiles = [os.path.abspath(file) for file in fnmatch.filter(sourceFiles, inputFiles)]
outputFileAbsolute = outputFile.replace("$path", ComputeOutputPath(dataInputFiles, projectDir, outputDir))
outputFileAbsolute = SanitizePath(outputFileAbsolute)
ProcessTemplateConversion(dataInputSet, dataInputFiles, templateFile, outputFileAbsolute, templateCache, dryrun, verbose)
outputFiles.append(outputFileAbsolute)
outputFileAbsolute = outputFile.replace("$path", ComputeOutputPath(dataInputFiles, projectDir, outputDir))
outputFileAbsolute = SanitizePath(outputFileAbsolute)
ProcessTemplateConversion(dataInputSet, dataInputFiles, templateFile, outputFileAbsolute, templateCache, dryrun, verbose)
outputFiles.append(outputFileAbsolute)
except IOError as e:
PrintError('%s : error I/O(%s) accessing %s : %s' % (expansionRule, e.errno, e.filename, e.strerror))
except:
@@ -357,8 +357,7 @@ if __name__ == '__main__':
parser.add_argument("expansionRules", help="set of azcg expansion rules for matching data files to template files")
parser.add_argument("-n", "--dryrun", action='store_true', help="does not execute autogen, only outputs the set of files that autogen would generate")
parser.add_argument("-v", "--verbose", action='store_true', help="output only the set of files that would be generated by an expansion run")
parser.add_argument("-p", "--pythonPaths", action='append', nargs='+', default=[""],
help="set of additional python paths to use for module imports")
parser.add_argument("-p", "--pythonPaths", action='append', nargs='+', default=[""], help="set of additional python paths to use for module imports")
args = parser.parse_args()
pythonPaths = args.pythonPaths
@@ -11,4 +11,4 @@
set(FILES
AzAutoGen.py
)
)
@@ -111,7 +111,7 @@ namespace AZ
bool loadFileToMemory = Get().ShouldLoadFileToMemory(filename);
int assetMode = loadFileToMemory ? AASSET_MODE_BUFFER : AASSET_MODE_UNKNOWN;
asset = AAssetManager_open(Utils::GetAssetManager(), Utils::StripApkPrefix(filename), assetMode);
asset = AAssetManager_open(Utils::GetAssetManager(), Utils::StripApkPrefix(filename).c_str(), assetMode);
if (asset != nullptr)
{
@@ -192,7 +192,7 @@ namespace AZ
{
buf->m_offset = buf->m_totalSize - offset;
}
if (buf->m_offset > buf->m_totalSize)
{
buf->m_offset = buf->m_totalSize;
@@ -320,12 +320,19 @@ namespace AZ
bool APKFileHandler::DirectoryOrFileExists(const char* path)
{
ANDROID_IO_PROFILE_SECTION_ARGS("APK DirOrFileexists");
ANDROID_IO_PROFILE_SECTION_ARGS("APK DirOrFileExists");
AZ::IO::PathView insideApkPathView(Utils::StripApkPrefix(path));
AZ::IO::FixedMaxPath insideApkPath(Utils::StripApkPrefix(path));
AZ::IO::FixedMaxPathString filename{ insideApkPathView.Filename().Native() };
AZ::IO::FixedMaxPathString pathToFile{ insideApkPathView.ParentPath().Native() };
// Check for the case where the input path is equal to the APK Assets Prefix of /APK
// In that case the directory is the "root" of APK assets in which case the directory exist
if (insideApkPath.empty() && Utils::IsApkPath(path))
{
return true;
}
AZ::IO::FixedMaxPathString filename{ insideApkPath.Filename().Native() };
AZ::IO::FixedMaxPathString pathToFile{ insideApkPath.ParentPath().Native() };
bool foundFile = false;
ParseDirectory(pathToFile.c_str(), [&](const char* name)
@@ -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>
+9 -14
View File
@@ -17,7 +17,7 @@
#include <AzCore/Debug/Trace.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/IO/Path/Path.h>
namespace AZ
{
@@ -28,9 +28,9 @@ namespace AZ
namespace
{
////////////////////////////////////////////////////////////////
const char* GetApkAssetsPrefix()
constexpr const char* GetApkAssetsPrefix()
{
return "/APK/";
return "/APK";
}
}
@@ -104,19 +104,14 @@ namespace AZ
////////////////////////////////////////////////////////////////
bool IsApkPath(const char* filePath)
{
return (strncmp(filePath, GetApkAssetsPrefix(), 4) == 0); // +3 for "APK", +1 for '/' starting slash
return AZ::IO::PathView(filePath).IsRelativeTo(AZ::IO::PathView(GetApkAssetsPrefix()));
}
////////////////////////////////////////////////////////////////
const char* StripApkPrefix(const char* filePath)
AZ::IO::FixedMaxPath StripApkPrefix(const char* filePath)
{
const int prefixLength = 5; // +3 for "APK", +2 for '/' on either end
if (!IsApkPath(filePath))
{
return filePath;
}
return filePath + prefixLength;
constexpr AZ::IO::PathView apkPrefixView = GetApkAssetsPrefix();
return AZ::IO::PathView(filePath).LexicallyProximate(apkPrefixView);
}
////////////////////////////////////////////////////////////////
@@ -130,7 +125,7 @@ namespace AZ
// first check to see if they are in public storage (application specific)
const char* publicAppStorage = GetAppPublicStoragePath();
OSString path = OSString::format("%s/bootstrap.cfg", publicAppStorage);
OSString path = OSString::format("%s/engine.json", publicAppStorage);
AZ_TracePrintf("Android::Utils", "Searching for %s\n", path.c_str());
FILE* f = fopen(path.c_str(), "r");
@@ -145,7 +140,7 @@ namespace AZ
AAssetManager* mgr = GetAssetManager();
if (mgr)
{
AAsset* asset = AAssetManager_open(mgr, "bootstrap.cfg", AASSET_MODE_UNKNOWN);
AAsset* asset = AAssetManager_open(mgr, "engine.json", AASSET_MODE_UNKNOWN);
if (asset)
{
AAsset_close(asset);
+3 -2
View File
@@ -11,6 +11,7 @@
*/
#pragma once
#include <AzCore/IO/Path/Path_fwd.h>
#include <AzCore/std/string/string.h>
#include <jni.h>
@@ -55,7 +56,7 @@ namespace AZ
const char* GetObbStoragePath();
//! Get the dot separated package name for the current application.
//! e.g. com.lumberyard.samples for SamplesProject
//! e.g. com.o3de.samples for SamplesProject
const char* GetPackageName();
//! Get the app version code (android:versionCode in the manifest).
@@ -70,7 +71,7 @@ namespace AZ
//! Will first check to verify the argument is an apk asset path and if so
//! will strip the prefix from the path.
//! \return The pointer position of the relative asset path
const char* StripApkPrefix(const char* filePath);
AZ::IO::FixedMaxPath StripApkPrefix(const char* filePath);
//! Searches application storage and the APK for bootstrap.cfg. Will return nullptr
//! if bootstrap.cfg is not found.
@@ -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))
@@ -418,16 +422,19 @@ namespace AZ
void AssetContainer::ListWaitingAssets() const
{
#if defined(AZ_ENABLE_TRACING)
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_readyMutex);
AZ_TracePrintf("AssetContainer", "Waiting on assets:\n");
for (auto& thisAsset : m_waitingAssets)
{
AZ_TracePrintf("AssetContainer", " %s\n",thisAsset.ToString<AZStd::string>().c_str());
}
#endif
}
void AssetContainer::ListWaitingPreloads(const AssetId& assetId) const
void AssetContainer::ListWaitingPreloads([[maybe_unused]] const AssetId& assetId) const
{
#if defined(AZ_ENABLE_TRACING)
AZStd::lock_guard<AZStd::recursive_mutex> preloadGuard(m_preloadMutex);
auto preloadEntry = m_preloadList.find(assetId);
if (preloadEntry != m_preloadList.end())
@@ -442,6 +449,7 @@ namespace AZ
{
AZ_TracePrintf("AssetContainer", "%s isn't waiting on any preloads:\n", assetId.ToString<AZStd::string>().c_str());
}
#endif
}
void AssetContainer::AddWaitingAssets(const AZStd::vector<AssetId>& assetList)
@@ -606,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());
}
}
}
}
@@ -90,8 +90,8 @@ namespace AZ::Data
// Get the results
auto streamer = AZ::Interface<AZ::IO::IStreamer>::Get();
AZ::u64 bytesRead = 0;
bool result = streamer->GetReadRequestResult(fileHandle, m_buffer, bytesRead,
AZ::IO::IStreamerTypes::ClaimMemory::Yes);
streamer->GetReadRequestResult(fileHandle, m_buffer, bytesRead,
AZ::IO::IStreamerTypes::ClaimMemory::Yes);
auto status = streamer->GetRequestStatus(fileHandle);
m_loadedSize = aznumeric_cast<size_t>(bytesRead);
@@ -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;
@@ -10,7 +10,7 @@
*
*/
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/StackedString.h>
@@ -107,7 +107,8 @@ namespace AZ
result = ContinueLoading(&id, azrtti_typeid<AssetId>(), it->value, context);
if (!id.m_guid.IsNull())
{
*instance = Asset<AssetData>(id, instance->GetType());
*instance = AssetManager::Instance().FindOrCreateAsset(id, instance->GetType(), AssetLoadBehavior::NoLoad);
result.Combine(context.Report(result, "Successfully created Asset<T> with id."));
}
@@ -1117,7 +1117,7 @@ namespace AZ
return asset;
}
void AssetManager::UpdateDebugStatus(AZ::Data::Asset<AZ::Data::AssetData> asset)
void AssetManager::UpdateDebugStatus(const AZ::Data::Asset<AZ::Data::AssetData>& asset)
{
if(!m_debugAssetEvents)
{
@@ -1750,7 +1750,6 @@ namespace AZ
{
AssetData* data = asset.Get();
{
const AZ::Data::AssetId& assetId = asset.GetId();
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
if (data)
@@ -2145,7 +2144,7 @@ namespace AZ
if (curIter != m_assetContainers.end())
{
auto newRef = curIter->second.lock();
if (newRef)
if (newRef && newRef->IsValid())
{
return newRef;
}
@@ -358,7 +358,7 @@ namespace AZ
Asset<AssetData> GetAssetInternal(const AssetId& assetId, const AssetType& assetType, AssetLoadBehavior assetReferenceLoadBehavior, const AssetLoadParameters& loadParams = AssetLoadParameters{}, AssetInfo assetInfo = AssetInfo(), bool signalLoaded = false);
void UpdateDebugStatus(AZ::Data::Asset<AZ::Data::AssetData> asset);
void UpdateDebugStatus(const AZ::Data::Asset<AZ::Data::AssetData>& asset);
/**
* Gets a root asset and dependencies as individual async loads if necessary.
@@ -12,7 +12,7 @@
/** @file
* Header file for the Component base class.
* In Lumberyard's component entity system, each component defines a discrete
* In Open 3D Engine's component entity system, each component defines a discrete
* feature that can be attached to an entity.
*/
@@ -76,7 +76,7 @@ namespace AZ
* practice to access other components through EBuses instead of accessing them directly.
* For more information, see the
* <a href="http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-intro.html">Programmer's Guide to Entities and Components</a>
* in the Lumberyard Developer Guide.
* in the Open 3D Engine Developer Guide.
* @return A pointer to the entity. If the component is not attached to any entity,
* the return value is a null pointer.
*/
@@ -426,7 +426,7 @@ namespace AZ
/**
* Describes the properties of the component descriptor event bus.
* This bus uses AzTypeInfo::Uuid as the ID for the specific descriptor. Lumberyard allows only one
* This bus uses AzTypeInfo::Uuid as the ID for the specific descriptor. Open 3D Engine allows only one
* descriptor for each component type. When you call functions on the bus for a specific component
* type, you can safely pass only one result variable because aggregating or overwriting results
* is impossible.
@@ -27,7 +27,6 @@
#include <AzCore/Memory/OverrunDetectionAllocator.h>
#include <AzCore/Memory/AllocatorManager.h>
#include <AzCore/Memory/MallocSchema.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/ObjectStream.h>
@@ -174,78 +173,85 @@ namespace AZ
return true;
};
//! SettingsRegistry notifier handler which updates relevant registry settings based
//! 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)
{
UpdateProjectSpecializationInRegistry(path);
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)
&& m_registry.Get(newProjectPath.Native(), projectPathKey) && newProjectPath != m_oldProjectPath)
{
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)
&& m_registry.Get(newProjectName, projectNameKey) && newProjectName != m_oldProjectName)
{
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
//! and remove the current project name specialization if one exists.
void UpdateProjectSpecializationInRegistry(AZStd::string_view path)
void UpdateProjectSpecializationFromProjectName(AZStd::string_view newProjectName)
{
auto projectPathKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey)
+ "/project_path";
if (path == projectPathKey)
{
AZ::SettingsRegistryInterface::FixedValueString newProjectPath;
if (m_registry.Get(newProjectPath, path) && !newProjectPath.empty())
{
// Make the path absolute by appending to app root, in case project path is relative.
// If the project path is already absolute it will remain the same.
// If we turn it from a relative path to an absolute path, write-back the absolute path to the registry.
AZ::IO::FixedMaxPath projectPath = AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath;
if (projectPath.Compare(newProjectPath.c_str()))
{
m_registry.Set(path, projectPath.Native());
}
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
// Add the project_name as a specialization for loading the build system dependency .setreg files
auto newProjectNameSpecialization = FixedValueString::format("%s/%.*s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey,
aznumeric_cast<int>(newProjectName.size()), newProjectName.data());
auto oldProjectNameSpecialization = FixedValueString::format("%s/%s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey,
m_oldProjectName.c_str());
m_registry.Remove(oldProjectNameSpecialization);
m_oldProjectName = newProjectName;
m_registry.Set(newProjectNameSpecialization, true);
}
// Merge the project.json file into settings registry under ProjectSettingsRootKey path.
AZ::IO::FixedMaxPath projectMetadataFile{ projectPath };
projectMetadataFile /= "project.json";
m_registry.MergeSettingsFile(projectMetadataFile.Native(),
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
void UpdateProjectSettingsFromProjectPath(AZ::IO::PathView newProjectPath)
{
// Update old Project path before attempting to merge in new Settings Registry values in order to prevent recursive calls
m_oldProjectPath = newProjectPath;
// Get the 'project_name' value from what was in the 'project.json' file...
auto projectNameKey =
AZ::SettingsRegistryInterface::FixedValueString(AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey)
+ "/project_name";
// Merge the project.json file into settings registry under ProjectSettingsRootKey path.
AZ::IO::FixedMaxPath projectMetadataFile{ AZ::SettingsRegistryMergeUtils::FindEngineRoot(m_registry) / newProjectPath };
projectMetadataFile /= "project.json";
m_registry.MergeSettingsFile(projectMetadataFile.Native(),
AZ::SettingsRegistryInterface::Format::JsonMergePatch, AZ::SettingsRegistryMergeUtils::ProjectSettingsRootKey);
AZ::SettingsRegistryInterface::FixedValueString projectSpecialization;
if (m_registry.Get(projectSpecialization, projectNameKey))
{
auto specializationKey = AZ::SettingsRegistryInterface::FixedValueString::format(
"%s/%s", AZ::SettingsRegistryMergeUtils::SpecializationsRootKey, projectSpecialization.c_str());
if (m_currentSpecialization != specializationKey)
{
m_registry.Set(specializationKey, true);
if (!m_currentSpecialization.empty())
{
// Remove the previous Project Name from the specialization path if it was set.
m_registry.Remove(m_currentSpecialization);
}
m_currentSpecialization = specializationKey;
// Update all the runtime file paths based on the new "project_path" value.
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
}
// Update all the runtime file paths based on the new "project_path" value.
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(m_registry);
}
}
}
}
void UpdateCommandLine()
{
AZ::SettingsRegistryMergeUtils::GetCommandLineFromRegistry(m_registry, m_commandLine);
}
private:
AZ::SettingsRegistryInterface::FixedValueString m_currentSpecialization;
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)
@@ -335,6 +341,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);
}
}
//=========================================================================
@@ -362,11 +378,20 @@ namespace AZ
ComponentApplication::ComponentApplication()
: ComponentApplication(0, nullptr)
{
if (Interface<ComponentApplicationRequests>::Get() == nullptr)
{
Interface<ComponentApplicationRequests>::Register(this);
}
}
ComponentApplication::ComponentApplication(int argC, char** argV)
: m_eventLogger{}
{
if (Interface<ComponentApplicationRequests>::Get() == nullptr)
{
Interface<ComponentApplicationRequests>::Register(this);
}
if (argV)
{
m_argC = argC;
@@ -415,7 +440,13 @@ namespace AZ
// Add the Command Line arguments into the SettingsRegistry
SettingsRegistryMergeUtils::StoreCommandLineToRegistry(*m_settingsRegistry, m_commandLine);
// Merge Command Line arguments
// 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 +460,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, {});
@@ -462,6 +489,11 @@ namespace AZ
//=========================================================================
ComponentApplication::~ComponentApplication()
{
if (Interface<ComponentApplicationRequests>::Get() == this)
{
Interface<ComponentApplicationRequests>::Unregister(this);
}
if (m_isStarted)
{
Destroy();
@@ -495,8 +527,7 @@ namespace AZ
DestroyAllocator();
}
Entity* ComponentApplication::Create(const Descriptor& descriptor,
const StartupParameters& startupParameters)
Entity* ComponentApplication::Create(const Descriptor& descriptor, const StartupParameters& startupParameters)
{
AZ_Assert(!m_isStarted, "Component application already started!");
@@ -905,6 +936,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)
@@ -943,6 +976,16 @@ namespace AZ
}
}
void ComponentApplication::RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler)
{
handler.Connect(m_entityAddedEvent);
}
void ComponentApplication::RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler)
{
handler.Connect(m_entityRemovedEvent);
}
//=========================================================================
// AddEntity
// [5/30/2012]
@@ -954,7 +997,7 @@ namespace AZ
{
return false;
}
m_entityAddedEvent.Signal(entity);
return m_entities.insert(AZStd::make_pair(entity->GetId(), entity)).second;
}
@@ -969,7 +1012,7 @@ namespace AZ
{
return false;
}
m_entityRemovedEvent.Signal(entity);
return (m_entities.erase(entity->GetId()) == 1);
}
@@ -982,6 +1025,7 @@ namespace AZ
Entity* entity = FindEntity(id);
if (entity)
{
m_entityRemovedEvent.Signal(entity);
delete entity;
return true;
}
@@ -1016,6 +1060,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
//=========================================================================
@@ -1371,10 +1429,7 @@ namespace AZ
//=========================================================================
void ComponentApplication::CalculateExecutablePath()
{
Utils::GetExecutableDirectory(m_exeDirectory.data(), m_exeDirectory.capacity());
// Update the size value of the executable directory fixed string to correctly be the length of the null-terminated string stored within it
m_exeDirectory.resize_no_construct(AZStd::char_traits<char>::length(m_exeDirectory.data()));
m_exeDirectory.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
m_exeDirectory = Utils::GetExecutableDirectory();
}
void ComponentApplication::CalculateAppRoot()
@@ -1382,19 +1437,12 @@ namespace AZ
if (AZStd::optional<AZ::StringFunc::Path::FixedString> appRootPath = Utils::GetDefaultAppRootPath(); appRootPath)
{
m_appRoot = AZStd::move(*appRootPath);
if (!m_appRoot.empty() && !m_appRoot.ends_with(AZ_CORRECT_FILESYSTEM_SEPARATOR))
{
m_appRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
}
}
}
void ComponentApplication::CalculateEngineRoot()
{
if (m_engineRoot = AZ::SettingsRegistryMergeUtils::FindEngineRoot(*m_settingsRegistry).Native(); !m_engineRoot.empty())
{
m_engineRoot.push_back(AZ_CORRECT_FILESYSTEM_SEPARATOR);
}
m_engineRoot = AZ::SettingsRegistryMergeUtils::FindEngineRoot(*m_settingsRegistry).Native();
}
void ComponentApplication::ResolveModulePath([[maybe_unused]] AZ::OSString& modulePath)
@@ -21,6 +21,7 @@
#include <AzCore/Module/DynamicModuleHandle.h>
#include <AzCore/Module/ModuleManager.h>
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/RTTI/ReflectionManager.h>
@@ -193,8 +194,7 @@ namespace AZ
* You will need to setup all system components manually.
* \returns pointer to the system entity.
*/
virtual Entity* Create(const Descriptor& descriptor,
const StartupParameters& startupParameters = StartupParameters());
virtual Entity* Create(const Descriptor& descriptor, const StartupParameters& startupParameters = StartupParameters());
virtual void Destroy();
virtual void DestroyAllocator(); // Called at the end of Destroy(). Applications can override to do tear down work right before allocator is destroyed.
@@ -202,11 +202,14 @@ namespace AZ
// ComponentApplicationRequests
void RegisterComponentDescriptor(const ComponentDescriptor* descriptor) override final;
void UnregisterComponentDescriptor(const ComponentDescriptor* descriptor) override final;
void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler) override final;
void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) override final;
bool AddEntity(Entity* entity) override;
bool RemoveEntity(Entity* entity) override;
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.
@@ -380,6 +383,8 @@ namespace AZ
float m_deltaTime{ 0.0f };
AZStd::unique_ptr<ModuleManager> m_moduleManager;
AZStd::unique_ptr<SettingsRegistryInterface> m_settingsRegistry;
EntityAddedEvent m_entityAddedEvent;
EntityRemovedEvent m_entityRemovedEvent;
AZ::IConsole* m_console{};
Descriptor m_descriptor;
bool m_isStarted{ false };
@@ -389,9 +394,9 @@ namespace AZ
void* m_fixedMemoryBlock{ nullptr }; //!< Pointer to the memory block allocator, so we can free it OnDestroy.
IAllocatorAllocate* m_osAllocator{ nullptr };
EntitySetType m_entities;
AZ::IO::FixedMaxPathString m_exeDirectory;
AZ::IO::FixedMaxPathString m_engineRoot;
AZ::IO::FixedMaxPathString m_appRoot;
AZ::IO::FixedMaxPath m_exeDirectory;
AZ::IO::FixedMaxPath m_engineRoot;
AZ::IO::FixedMaxPath m_appRoot;
AZ::SettingsRegistryInterface::NotifyEventHandler m_projectChangedHandler;
@@ -13,6 +13,7 @@
#pragma once
#include <AzCore/EBus/EBus.h>
#include <AzCore/EBus/Event.h>
#include <AzCore/Component/EntityId.h>
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/string/osstring.h>
@@ -69,160 +70,144 @@ namespace AZ
inline bool ApplicationTypeQuery::IsGame() const { return (m_maskValue & Masks::Game) == Masks::Game; }
inline bool ApplicationTypeQuery::IsValid() const { return m_maskValue != Masks::Invalid; }
/**
* Event bus that components use to make requests of the main application.
* Only one application can exist at a time, which is why this bus
* supports only one listener.
*/
using EntityAddedEvent = AZ::Event<AZ::Entity*>;
using EntityRemovedEvent = AZ::Event<AZ::Entity*>;
//! Interface that components can use to make requests of the main application.
class ComponentApplicationRequests
: public AZ::EBusTraits
{
public:
AZ_RTTI(ComponentApplicationRequests, "{E8BE41B7-615F-4FE8-B611-8A9E441290A8}");
/**
* Destroys the event bus that components use to make requests of the main application.
*/
virtual ~ComponentApplicationRequests() {}
//! Destroys the event bus that components use to make requests of the main application.
virtual ~ComponentApplicationRequests() = default;
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides - application is a singleton
/**
* Overrides the default AZ::EBusTraits handler policy to allow one
* listener only, because only one application can exist at a time.
*/
static const AZ::EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single; // We sort components on m_initOrder.
/**
* Overrides the default AZ::EBusTraits mutex type to the AZStd implementation of
* a recursive mutex with exclusive ownership semantics. A mutex prevents multiple
* threads from accessing shared data simultaneously.
*/
typedef AZStd::recursive_mutex MutexType;
//////////////////////////////////////////////////////////////////////////
/**
* Registers a component descriptor with the application.
* @param descriptor A component descriptor.
*/
//! Registers a component descriptor with the application.
//! @param descriptor A component descriptor.
virtual void RegisterComponentDescriptor(const ComponentDescriptor* descriptor) = 0;
/**
* Unregisters a component descriptor with the application.
* @param descriptor A component descriptor.
*/
//! Unregisters a component descriptor with the application.
//! @param descriptor A component descriptor.
virtual void UnregisterComponentDescriptor(const ComponentDescriptor* descriptor) = 0;
/**
* Gets a pointer to the application.
* @return A pointer to the application.
*/
virtual ComponentApplication* GetApplication() = 0;
/**
* Adds an entity to the application's registry.
* Calling Init() on an entity automatically performs this operation.
* @param entity A pointer to the entity to add to the application's registry.
* @return True if the operation succeeded. False if the operation failed.
*/
virtual bool AddEntity(Entity* entity) = 0;
/**
* Removes the specified entity from the application's registry.
* Deleting an entity automatically performs this operation.
* @param entity A pointer to the entity that will be removed from the application's registry.
* @return True if the operation succeeded. False if the operation failed.
*/
virtual bool RemoveEntity(Entity* entity) = 0;
/**
* Unregisters and deletes the specified entity.
* @param entity A reference to the entity that will be unregistered and deleted.
* @return True if the operation succeeded. False if the operation failed.
*/
virtual bool DeleteEntity(const EntityId& id) = 0;
/**
* Returns the entity with the matching ID, if the entity is registered with the application.
* @param entity A reference to the entity that you are searching for.
* @return A pointer to the entity with the specified entity ID.
*/
virtual Entity* FindEntity(const EntityId& id) = 0;
/**
* Returns the name of the entity that has the specified entity ID.
* Entity names are not unique.
* This method exists to facilitate better debugging messages.
* @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(); };
//! Gets a pointer to the application.
//! @return A pointer to the application.
virtual ComponentApplication* GetApplication() = 0;
/**
* The type that AZ::ComponentApplicationRequests::EnumerateEntities uses to
* pass entity callbacks to the application for enumeration.
*/
//! Registers an event handler that will be signalled whenever an entity is added.
//! @param handler the event handler to signal.
virtual void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler& handler) = 0;
//! Registers an event handler that will be signalled whenever an entity is removed.
//! @param handler the event handler to signal.
virtual void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler& handler) = 0;
//! Adds an entity to the application's registry.
//! Calling Init() on an entity automatically performs this operation.
//! @param entity A pointer to the entity to add to the application's registry.
//! @return True if the operation succeeded. False if the operation failed.
virtual bool AddEntity(Entity* entity) = 0;
//! Removes the specified entity from the application's registry.
//! Deleting an entity automatically performs this operation.
//! @param entity A pointer to the entity that will be removed from the application's registry.
//! @return True if the operation succeeded. False if the operation failed.
virtual bool RemoveEntity(Entity* entity) = 0;
//! Unregisters and deletes the specified entity.
//! @param entity A reference to the entity that will be unregistered and deleted.
//! @return True if the operation succeeded. False if the operation failed.
virtual bool DeleteEntity(const EntityId& id) = 0;
//! Returns the entity with the matching ID, if the entity is registered with the application.
//! @param entity A reference to the entity that you are searching for.
//! @return A pointer to the entity with the specified entity ID.
virtual Entity* FindEntity(const EntityId& id) = 0;
//! Returns the name of the entity that has the specified entity ID.
//! Entity names are not unique.
//! This method exists to facilitate better debugging messages.
//! @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(); }
//! 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.
using EntityCallback = AZStd::function<void(Entity*)>;
/**
* Enumerates all registered entities and invokes the specified callback for each entity.
* @param callback A reference to the callback that is invoked for each entity.
*/
virtual void EnumerateEntities(const EntityCallback& callback) = 0;
/**
* Returns the serialize context that was registered with the app.
* @return The serialize context, if there is one. SerializeContext is a class that contains reflection data
* for serialization and construction of objects.
*/
//! Enumerates all registered entities and invokes the specified callback for each entity.
//! @param callback A reference to the callback that is invoked for each entity.
virtual void EnumerateEntities(const EntityCallback& callback) = 0;
//! Returns the serialize context that was registered with the app.
//! @return The serialize context, if there is one. SerializeContext is a class that contains reflection data
//! for serialization and construction of objects.
virtual class SerializeContext* GetSerializeContext() = 0;
/**
* Returns the behavior context that was registered with the app.
* @return The behavior context, if there is one. BehaviorContext is a class that reflects classes, methods,
* and EBuses for runtime interaction.
*/
//! Returns the behavior context that was registered with the app.
//! @return The behavior context, if there is one. BehaviorContext is a class that reflects classes, methods,
//! and EBuses for runtime interaction.
virtual class BehaviorContext* GetBehaviorContext() = 0;
/**
* Returns the Json Registration context that was registered with the app.
* @return The Json Registration context, if there is one. JsonRegistrationContext is a class that contains
* the serializers used by the best-effort json serialization.
*/
//! Returns the Json Registration context that was registered with the app.
//! @return The Json Registration context, if there is one. JsonRegistrationContext is a class that contains
//! the serializers used by the best-effort json serialization.
virtual class JsonRegistrationContext* GetJsonRegistrationContext() = 0;
/**
* Gets the name of the working root folder that was registered with the app.
* @return A pointer to the name of the app's root folder, if a root folder was registered.
*/
virtual const char* GetAppRoot() const = 0;
/**
* Gets the path of the working engine folder that the app is a part of.
* @return A pointer to the engine path.
*/
virtual const char* GetEngineRoot() const = 0;
/**
* Gets the path to the directory that contains the application's executable.
* @return A pointer to the name of the path that contains the application's executable.
*/
virtual const char* GetExecutableFolder() const = 0;
/**
* Returns a pointer to the driller manager, if driller is enabled.
* The driller manager manages all active driller sessions and driller factories.
* @return A pointer to the driller manager. If driller is not enabled,
* this function returns null.
*/
virtual Debug::DrillerManager* GetDrillerManager() = 0;
//! Gets the name of the working root folder that was registered with the app.
//! @return a pointer to the name of the app's root folder, if a root folder was registered.
virtual const char* GetAppRoot() const = 0;
/**
* ResolveModulePath is called whenever LoadDynamicModule wants to resolve a module in order to actually load it.
* You can override this if you need to load modules from a different path or hijack module loading in some other way.
* If you do, ensure that you use platform-specific conventions to do so, as this is called by multiple platforms.
* The default implantation prepends the path to the executable to the module path, but you can override this behavior
* (Call the base class if you want this behavior to persist in overrides)
*/
virtual void ResolveModulePath(AZ::OSString& /*modulePath*/) { }
//! Gets the path of the working engine folder that the app is a part of.
//! @return a pointer to the engine path.
virtual const char* GetEngineRoot() const = 0;
/**
* Returns AZ parsed command line structure.
* Command Line structure can be queried for switches (-<switch> /<switch>) or positional parameter (<value>)
*/
//! Gets the path to the directory that contains the application's executable.
//! @return a pointer to the name of the path that contains the application's executable.
virtual const char* GetExecutableFolder() const = 0;
//! Returns a pointer to the driller manager, if driller is enabled.
//! The driller manager manages all active driller sessions and driller factories.
//! @return A pointer to the driller manager. If driller is not enabled, this function returns null.
virtual Debug::DrillerManager* GetDrillerManager() = 0;
//! ResolveModulePath is called whenever LoadDynamicModule wants to resolve a module in order to actually load it.
//! You can override this if you need to load modules from a different path or hijack module loading in some other way.
//! If you do, ensure that you use platform-specific conventions to do so, as this is called by multiple platforms.
//! The default implantation prepends the path to the executable to the module path, but you can override this behavior
//! (Call the base class if you want this behavior to persist in overrides)
virtual void ResolveModulePath([[maybe_unused]] AZ::OSString& modulePath) { }
//! Returns AZ parsed command line structure.
//! Command Line structure can be queried for switches (-<switch> /<switch>) or positional parameter (<value>)
virtual AZ::CommandLine* GetAzCommandLine() { return{}; }
//! Returns all the flags that are true for the current application.
virtual void QueryApplicationType(ApplicationTypeQuery& appType) const = 0;
};
/**
* Used by components to make requests of the component application.
*/
typedef AZ::EBus<ComponentApplicationRequests> ComponentApplicationBus;
class ComponentApplicationRequestsEBusTraits
: public AZ::EBusTraits
{
public:
//! EBusTraits overrides - application is a singleton
//! Overrides the default AZ::EBusTraits handler policy to allow one
//! listener only, because only one application can exist at a time.
static const AZ::EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single; // We sort components on m_initOrder.
//! Overrides the default AZ::EBusTraits mutex type to the AZStd implementation of
//! a recursive mutex with exclusive ownership semantics. A mutex prevents multiple
//! threads from accessing shared data simultaneously.
using MutexType = AZStd::recursive_mutex;
};
//! Used by components to make requests of the component application.
using ComponentApplicationBus = AZ::EBus<ComponentApplicationRequests, ComponentApplicationRequestsEBusTraits>;
}
@@ -18,7 +18,7 @@
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Component/NamedEntityId.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Casting/lossy_cast.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
@@ -159,10 +159,11 @@ namespace AZ
AZ_Assert(m_state == State::Constructed, "Component should be in Constructed state to be Initialized!");
SetState(State::Initializing);
bool result = true;
EBUS_EVENT_RESULT(result, ComponentApplicationBus, AddEntity, this);
(void)result;
AZ_Assert(result, "Failed to add entity '%s' [0x%llx]! Did you already register an entity with this ID?", m_name.c_str(), m_id);
if (AZ::Interface<ComponentApplicationRequests>::Get() != nullptr)
{
[[maybe_unused]] const bool result = AZ::Interface<ComponentApplicationRequests>::Get()->AddEntity(this);
AZ_Assert(result, "Failed to add entity '%s' [0x%llx]! Did you already register an entity with this ID?", m_name.c_str(), m_id);
}
for (ComponentArrayType::iterator it = m_components.begin(); it != m_components.end();)
{
@@ -12,7 +12,7 @@
/** @file
* Header file for the Entity class.
* In Lumberyard's component entity system, an entity is an addressable container for
* In Open 3D Engine's component entity system, an entity is an addressable container for
* a group of components. The entity represents the functionality and properties of an
* object within your game.
*/
@@ -40,10 +40,26 @@ namespace AZ
(*idMapper)->SetIsEntityReference(false);
}
JSR::ResultCode idLoadResult =
ContinueLoadingFromJsonObjectField(&entityInstance->m_id,
azrtti_typeid<decltype(entityInstance->m_id)>(),
inputValue, "Id", context);
JSR::ResultCode idLoadResult = ContinueLoadingFromJsonObjectField(
&entityInstance->m_id, azrtti_typeid<decltype(entityInstance->m_id)>(), inputValue, "Id", context);
// If the entity has an invalid ID, there's no point in deserializing, the entity will be unusable.
// It's also dangerous to generate new IDs here:
// - They need to be globally unique
// - We don't know *why* it's invalid (maybe just a typo on the name "Id" for example), so we don't know the ramifications
// of changing it. There might be many other entities that have references to this one that would become invalid as well
// if we try to silently fix it up.
// - Unless we save the ID immediately, it will change every time we serialize the data in, which can happen multiple times
// during the serialization pipeline. So it either needs to be saved back immediately, or we need a deterministic way
// to generate a globally unique ID for the entity.
if (!entityInstance->GetId().IsValid())
{
// Since we're going to halt processing anyways, we just return the error here immediately.
return context.Report(
JSR::ResultCode(JSR::Tasks::ReadField, JSR::Outcomes::Invalid),
"Invalid or missing entity ID - please add an 'Id' field to this entity with a globally unique id. \n"
"Failed to load entity information.");
}
if (hasValidIdMapper)
{
@@ -93,9 +109,10 @@ namespace AZ
inputValue, "IsRuntimeActive", context);
}
return context.Report(result,
result.GetProcessing() == JSR::Processing::Halted ? "Succesfully loaded entity information." :
"Failed to load entity information.");
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded entity information."
: "Failed to load entity information.");
}
JsonSerializationResult::Result JsonEntitySerializer::Store(rapidjson::Value& outputValue,
@@ -199,7 +216,7 @@ namespace AZ
}
return context.Report(result,
result.GetProcessing() == JSR::Processing::Halted ? "Successfully stored Entity information." :
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored Entity information." :
"Failed to store Entity information.");
}
@@ -19,9 +19,6 @@ namespace AZ
{
class Vector3;
//! Do not allow the scale to be zero to avoid problems with inverting scale.
static constexpr float MinNonUniformScale = 1e-3f;
using NonUniformScaleChangedEvent = AZ::Event<const AZ::Vector3&>;
//! Requests for working with non-uniform scale.
@@ -26,7 +26,7 @@ namespace AZ
{
class Transform;
using TransformChangedEvent = Event<Transform, Transform>;
using TransformChangedEvent = Event<const Transform&, const Transform&>;
using ParentChangedEvent = Event<EntityId, EntityId>;
@@ -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;
@@ -42,9 +42,8 @@ namespace AZ
}
}
#define AZ_TRACE_METHOD_NAME_CATEGORY(name, category) AZ::Debug::EventTrace::ScopedSlice AZ_JOIN(ScopedSlice__, __LINE__)(name, category);
#ifdef AZ_PROFILE_TELEMETRY
# define AZ_TRACE_METHOD_NAME_CATEGORY(name, category) AZ::Debug::EventTrace::ScopedSlice AZ_JOIN(ScopedSlice__, __LINE__)(name, category);
# define AZ_TRACE_METHOD_NAME(name) \
AZ_TRACE_METHOD_NAME_CATEGORY(name, "") \
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzTrace, name)
@@ -53,6 +52,7 @@ namespace AZ
AZ_TRACE_METHOD_NAME_CATEGORY(AZ_FUNCTION_SIGNATURE, "") \
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzTrace)
#else
# define AZ_TRACE_METHOD_NAME_CATEGORY(name, category)
# define AZ_TRACE_METHOD_NAME(name) AZ_TRACE_METHOD_NAME_CATEGORY(name, "")
# define AZ_TRACE_METHOD() AZ_TRACE_METHOD_NAME(AZ_FUNCTION_SIGNATURE)
#endif
@@ -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
+9 -2
View File
@@ -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;
}
+1 -1
View File
@@ -15,7 +15,7 @@
* Header file for internal EBus classes.
* For more information about EBuses, see AZ::EBus and AZ::EBusTraits in this guide and
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
* in the *Lumberyard Developer Guide*.
* in the *Open 3D Engine Developer Guide*.
*/
#pragma once
+5 -5
View File
@@ -13,11 +13,11 @@
/**
* @file
* Header file for event bus (EBus), a general-purpose communication system
* that Lumberyard uses to dispatch notifications and receive requests.
* that Open 3D Engine uses to dispatch notifications and receive requests.
* EBuses are configurable and support many different use cases.
* For more information about %EBuses, see AZ::EBus in this guide and
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
* in the *Lumberyard Developer Guide*.
* in the *Open 3D Engine Developer Guide*.
*/
#pragma once
@@ -70,7 +70,7 @@ namespace AZ
*
* For more information about %EBuses, see EBus in this guide and
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
* in the *Lumberyard Developer Guide*.
* in the *Open 3D Engine Developer Guide*.
*/
struct EBusTraits
{
@@ -256,7 +256,7 @@ namespace AZ
/**
* Event buses (EBuses) are a general-purpose communication system
* that Lumberyard uses to dispatch notifications and receive requests.
* that Open 3D Engine uses to dispatch notifications and receive requests.
*
* @tparam Interface A class whose virtual functions define the events
* dispatched or received by the %EBus.
@@ -268,7 +268,7 @@ namespace AZ
* For more information about EBuses, see
* [Event Bus](http://docs.aws.amazon.com/lumberyard/latest/developerguide/asset-pipeline-ebus.html)
* and [Components and EBuses: Best Practices ](http://docs.aws.amazon.com/lumberyard/latest/developerguide/component-entity-system-pg-components-ebuses-best-practices.html)
* in the *Lumberyard Developer Guide*.
* in the *Open 3D Engine Developer Guide*.
*
* ## How Components Use EBuses
* Components commonly use EBuses in two ways: to dispatch events or to handle requests.
@@ -11,7 +11,6 @@
*/
#include <AzCore/EBus/EventSchedulerSystemComponent.h>
#include <AzCore/EBus/ScheduledEvent.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Console/ILogger.h>
#include <AzCore/Serialization/SerializeContext.h>
@@ -111,8 +110,10 @@ namespace AZ
TimeMs currentMilliseconds = GetElapsedTimeMs();
if (timedEvent->m_handle == nullptr)
{
timedEvent->m_handle = AllocateHandle(TimeMs(currentMilliseconds + durationMs), durationMs, timedEvent);
timedEvent->m_handle = AllocateHandle();
}
const bool ownsScheduledEvent = false;
*(timedEvent->m_handle) = ScheduledEventHandle(TimeMs(currentMilliseconds + durationMs), durationMs, timedEvent, ownsScheduledEvent);
timedEvent->m_timeInserted = currentMilliseconds;
m_queue.push(timedEvent->m_handle);
return timedEvent->m_handle;
@@ -126,7 +127,9 @@ namespace AZ
}
TimeMs currentMilliseconds = GetElapsedTimeMs();
ScheduledEvent* timedEvent = AllocateManagedEvent(TimeMs(currentMilliseconds + durationMs), durationMs, callback, eventName);
ScheduledEvent* timedEvent = AllocateManagedEvent(callback, eventName);
const bool ownsScheduledEvent = true;
*(timedEvent->m_handle) = ScheduledEventHandle(TimeMs(currentMilliseconds + durationMs), durationMs, timedEvent, ownsScheduledEvent);
timedEvent->m_timeInserted = currentMilliseconds;
m_queue.push(timedEvent->m_handle);
}
@@ -150,10 +153,12 @@ namespace AZ
{
AZLOG_INFO("EventSchedulerSystemComponent::HandleCount = %u", aznumeric_cast<uint32_t>(GetHandleCount()));
AZLOG_INFO("EventSchedulerSystemComponent::FreeHandleCount = %u", aznumeric_cast<uint32_t>(GetFreeHandleCount()));
AZLOG_INFO("EventSchedulerSystemComponent::OwnedEventCount = %u", aznumeric_cast<uint32_t>(m_ownedEvents.size()));
AZLOG_INFO("EventSchedulerSystemComponent::FreeEventCount = %u", aznumeric_cast<uint32_t>(m_freeEvents.size()));
AZLOG_INFO("EventSchedulerSystemComponent::QueueSize = %u", aznumeric_cast<uint32_t>(GetQueueSize()));
}
ScheduledEventHandle* EventSchedulerSystemComponent::AllocateHandle(TimeMs executeTimeMs, TimeMs durationTimeMs, ScheduledEvent* scheduledEvent)
ScheduledEventHandle* EventSchedulerSystemComponent::AllocateHandle()
{
ScheduledEventHandle* result = nullptr;
if (!m_freeHandles.empty())
@@ -166,31 +171,34 @@ namespace AZ
m_handles.resize(m_handles.size() + 1);
result = &(m_handles.back());
}
*result = ScheduledEventHandle(executeTimeMs, durationTimeMs, scheduledEvent, false);
return result;
}
ScheduledEvent* EventSchedulerSystemComponent::AllocateManagedEvent(TimeMs executeTimeMs, TimeMs durationTimeMs, const AZStd::function<void()>& callback, const Name& eventName)
ScheduledEvent* EventSchedulerSystemComponent::AllocateManagedEvent(const AZStd::function<void()>& callback, const Name& eventName)
{
ScheduledEvent* result = new ScheduledEvent(callback, eventName);
ScheduledEventHandle* handle = nullptr;
if (!m_freeHandles.empty())
ScheduledEvent* scheduledEvent = nullptr;
if (!m_freeEvents.empty())
{
handle = m_freeHandles.back();
m_freeHandles.pop_back();
scheduledEvent = m_freeEvents.back();
m_freeEvents.pop_back();
}
else
{
m_handles.resize(m_handles.size() + 1);
handle = &(m_handles.back());
m_ownedEvents.resize(m_ownedEvents.size() + 1);
scheduledEvent = &(m_ownedEvents.back());
}
*handle = ScheduledEventHandle(executeTimeMs, durationTimeMs, result, true);
result->m_handle = handle;
return result;
scheduledEvent->m_eventName = eventName;
scheduledEvent->m_callback = callback;
scheduledEvent->m_handle = AllocateHandle();
return scheduledEvent;
}
void EventSchedulerSystemComponent::FreeHandle(ScheduledEventHandle* handle)
{
if (handle->GetOwnsScheduledEvent())
{
m_freeEvents.push_back(handle->GetScheduledEvent());
}
m_freeHandles.push_back(handle);
}
}
@@ -16,6 +16,7 @@
#include <AzCore/Console/IConsole.h>
#include <AzCore/Component/Component.h>
#include <AzCore/EBus/ScheduledEventHandle.h>
#include <AzCore/EBus/ScheduledEvent.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/queue.h>
@@ -89,9 +90,11 @@ namespace AZ
//! @}
private:
ScheduledEventHandle* AllocateHandle(TimeMs executeTimeMs, TimeMs durationTimeMs, ScheduledEvent* scheduledEvent);
// Allocates a single use event to capture the passed in callback. Event is cleaned up on completion.
ScheduledEvent* AllocateManagedEvent(TimeMs executeTimeMs, TimeMs durationTimeMs, const AZStd::function<void()>& callback, const Name& eventName);
ScheduledEventHandle* AllocateHandle();
//! Allocates a single use event to capture the passed in callback. Event is cleaned up on completion.
ScheduledEvent* AllocateManagedEvent(const AZStd::function<void()>& callback, const Name& eventName);
void FreeHandle(ScheduledEventHandle* handle);
// Bind the DumpStats member function to the console as 'EventSchedulerSystemComponent.DumpStats'
@@ -100,6 +103,8 @@ namespace AZ
// Priority queues of scheduled events sorted by execution time
AZStd::priority_queue<ScheduledEventHandle*, AZStd::vector<ScheduledEventHandle*>, CompareScheduledEventPtrs> m_queue;
AZStd::priority_queue<ScheduledEventHandle*, AZStd::vector<ScheduledEventHandle*>, PrioritizeScheduledEventPtrs> m_pendingQueue;
AZStd::deque<ScheduledEvent> m_ownedEvents;
AZStd::vector<ScheduledEvent*> m_freeEvents;
AZStd::deque<ScheduledEventHandle> m_handles;
AZStd::vector<ScheduledEventHandle*> m_freeHandles;
};
@@ -194,4 +194,4 @@ namespace AZ
}
};
}
}
}
@@ -359,7 +359,7 @@ namespace AZ
//insert the new handler
handler.m_index = aznumeric_cast<int32_t>(AZStd::distance(m_handlers.begin(), insertLocation));
auto insertedItr = m_handlers.insert(insertLocation, &handler);
m_handlers.insert(insertLocation, &handler);
return handler.m_index;
}
@@ -55,7 +55,6 @@ namespace AZ
void ScheduledEvent::Requeue(TimeMs durationMs)
{
m_durationMs = durationMs;
ClearHandle();
IEventScheduler* eventScheduler = Interface<IEventScheduler>::Get();
if (eventScheduler)
{
@@ -120,10 +119,6 @@ namespace AZ
void ScheduledEvent::ClearHandle()
{
if (m_handle)
{
m_handle->Clear();
m_handle = nullptr;
}
m_handle = nullptr;
}
}
@@ -29,6 +29,9 @@ namespace AZ
class ScheduledEvent
{
public:
//! Default constructor only for AZStd::deque compatibility.
ScheduledEvent() = default;
//! Constructor of ScheduledEvent class.
//! @param callback a call back function to be executed when the event triggers
//! @param eventName name of the scheduled event for easier debugging
@@ -82,8 +85,6 @@ namespace AZ
//! Clears any currently set handle pointer.
void ClearHandle();
AZ_DISABLE_COPY_MOVE(ScheduledEvent);
Name m_eventName; //< Scheduled event name
AZStd::function<void()> m_callback; //< A callback function to run when the scheduled event triggers
ScheduledEventHandle* m_handle = nullptr; //< Handle pointer to protect running a deleted event callback function
@@ -16,11 +16,11 @@
namespace AZ
{
ScheduledEventHandle::ScheduledEventHandle(TimeMs executeTimeMs, TimeMs durationTimeMs, ScheduledEvent* scheduledEvent, bool isAutoDelete)
ScheduledEventHandle::ScheduledEventHandle(TimeMs executeTimeMs, TimeMs durationTimeMs, ScheduledEvent* scheduledEvent, bool ownsScheduledEvent)
: m_executeTimeMs(executeTimeMs)
, m_durationMs(durationTimeMs)
, m_event(scheduledEvent)
, m_autoDelete(isAutoDelete)
, m_ownsScheduledEvent(ownsScheduledEvent)
{
;
}
@@ -49,11 +49,6 @@ namespace AZ
else // Not configured to auto-requeue, so remove the handle
{
m_event->ClearHandle();
if (m_autoDelete)
{
delete m_event;
}
m_event = nullptr;
}
}
}
@@ -65,11 +60,6 @@ namespace AZ
return false; // Event has been deleted, so the handle class must be deleted after this function.
}
void ScheduledEventHandle::Clear()
{
m_event = nullptr;
}
TimeMs ScheduledEventHandle::GetExecuteTimeMs() const
{
return m_executeTimeMs;
@@ -79,4 +69,14 @@ namespace AZ
{
return m_durationMs;
}
bool ScheduledEventHandle::GetOwnsScheduledEvent() const
{
return m_ownsScheduledEvent;
}
ScheduledEvent* ScheduledEventHandle::GetScheduledEvent() const
{
return m_event;
}
}
@@ -31,8 +31,8 @@ namespace AZ
//! @param executeTimeMs an absolute time in ms at which point the scheduled event should trigger
//! @param durationTimeMs the interval time in ms used for prioritization as well as re-queueing
//! @param scheduledEvent a scheduled event to run
//! @param autoDelete if the event handle will be automatically deleted after execution completes
ScheduledEventHandle(TimeMs executeTimeMs, TimeMs durationTimeMs, ScheduledEvent* scheduledEvent, bool isAutoDelete);
//! @param ownsScheduledEvent true if the event handle owns its own scheduled event instance
ScheduledEventHandle(TimeMs executeTimeMs, TimeMs durationTimeMs, ScheduledEvent* scheduledEvent, bool ownsScheduledEvent = false);
//! operator of comparing a scheduled event by execute time.
//! @param a_Rhs a scheduled event handle to compare
@@ -42,9 +42,6 @@ namespace AZ
//! @return true for re-queuing a scheduled event or false for deleting this class.
bool Notify();
//! Set nullptr for a scheduled event pointer.
void Clear();
//! Get the execution time in ms for this scheduled event.
//! @return the execution time in ms for this scheduled event
TimeMs GetExecuteTimeMs() const;
@@ -54,12 +51,20 @@ namespace AZ
//! @return the duration time in ms for this scheduled event
TimeMs GetDurationTimeMs() const;
//! Gets whether or not the event handle owns its own scheduled event.
//! @return true if the event handle owns
bool GetOwnsScheduledEvent() const;
//! Gets the scheduled event instance bound to this event handle.
//! @return the scheduled event instance bound to this event handle
ScheduledEvent* GetScheduledEvent() const;
private:
TimeMs m_executeTimeMs = TimeMs{ 0 }; //< execution time of the scheduled event
TimeMs m_durationMs = TimeMs{ 0 }; //< interval time of the scheduled event
ScheduledEvent* m_event = nullptr; //< pointer to the scheduled event
bool m_autoDelete = false; //< if the handle manages the memory of its own event
bool m_ownsScheduledEvent = false; //< if the handle manages the memory of its own event
};
}
+11 -11
View File
@@ -96,8 +96,8 @@ namespace AZ::IO
constexpr int Compare(const value_type* pathString) const noexcept;
// decomposition
//! Given a windows path of "C:\lumberyard\foo\bar\name.txt" and a posix path of
//! "/lumberyard/foo/bar/name.txt"
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
//! "/O3DE/foo/bar/name.txt"
//! The following functions return the following
//! Returns the root name part of the path. if it has one.
@@ -114,10 +114,10 @@ namespace AZ::IO
constexpr PathView RootPath() const;
//! Returns the relative path portion of the path.
//! This contains the path parts after the root path
//! windows = "lumberyard\foo\bar\name.txt", posix = "lumberyard/foo/bar/name.txt"
//! windows = "O3DE\foo\bar\name.txt", posix = "O3DE/foo/bar/name.txt"
constexpr PathView RelativePath() const;
//! Returns the parent directory of filename contained within the path
//! windows = "C:\lumberyard\foo\bar", posix = "/lumberyard/foo/bar"
//! windows = "C:\O3DE\foo\bar", posix = "/O3DE/foo/bar"
//! NOTE: If the path ends with a trailing separator "test/foo/" it is treated as being a path of
//! "test/foo" as if the filename of the path is "foo" and the parent directory is "test"
constexpr PathView ParentPath() const;
@@ -150,7 +150,7 @@ namespace AZ::IO
//! The root portion of the path is made up of root_name() / root_directory()
[[nodiscard]] constexpr bool HasRootPath() const;
//! checks whether the relative part of path is empty
//! (C:\\ lumberyard\dev\)
//! (C:\\ O3DE\dev\)
//! ^ ^
//! root part relative part
[[nodiscard]] constexpr bool HasRelativePath() const;
@@ -485,10 +485,10 @@ namespace AZ::IO
constexpr PathView RootPath() const;
//! Returns the relative path portion of the path.
//! This contains the path parts after the root path
//! windows = "lumberyard\foo\bar\name.txt", posix = "lumberyard/foo/bar/name.txt"
//! windows = "O3DE\foo\bar\name.txt", posix = "O3DE/foo/bar/name.txt"
constexpr PathView RelativePath() const;
//! Returns the parent directory of filename contained within the path
//! windows = "C:\lumberyard\foo\bar", posix = "/lumberyard/foo/bar"
//! windows = "C:\O3DE\foo\bar", posix = "/O3DE/foo/bar"
//! NOTE: If the path ends with a trailing separator "test/foo/" it is treated as being a path of
//! "test/foo" as if the filename of the path is "foo" and the parent directory is "test"
constexpr PathView ParentPath() const;
@@ -521,8 +521,8 @@ namespace AZ::IO
//! The root portion of the path is made up of root_name() / root_directory()
[[nodiscard]] constexpr bool HasRootPath() const;
//! checks whether the relative part of path is empty
//! (C:\\ lumberyard\dev\)
//! ^ ^
//! (C:\\ O3DE\dev\)
//! ^ ^
//! root part relative part
[[nodiscard]] constexpr bool HasRelativePath() const;
//! checks whether the path has a parent path that empty
@@ -544,8 +544,8 @@ namespace AZ::IO
[[nodiscard]] constexpr bool IsRelativeTo(const PathView& base) const;
// decomposition
//! Given a windows path of "C:\lumberyard\foo\bar\name.txt" and a posix path of
//! "/lumberyard/foo/bar/name.txt"
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
//! "/O3DE/foo/bar/name.txt"
//! The following functions return the following
// query
+34 -6
View File
@@ -214,6 +214,20 @@ namespace AZ::IO::Internal
// logic
return IsAbsolute(pathView.begin(), pathView.end(), preferredSeparator);
}
// Compares path segments using either Posix or Windows path rules based on the path separator in use
// Posix paths perform a case-sensitive comparison, while Windows paths perform a case-insensitive comparison
static int ComparePathSegment(AZStd::string_view left, AZStd::string_view right, char pathSeparator)
{
const size_t maxCharsToCompare = (AZStd::min)(left.size(), right.size());
int charCompareResult = pathSeparator == PosixPathSeparator
? strncmp(left.data(), right.data(), maxCharsToCompare)
: azstrnicmp(left.data(), right.data(), maxCharsToCompare);
return charCompareResult == 0
? aznumeric_cast<ptrdiff_t>(left.size()) - aznumeric_cast<ptrdiff_t>(right.size())
: charCompareResult;
}
}
//! PathParser implementation
@@ -351,7 +365,6 @@ namespace AZ::IO::parser
constexpr void Decrement() noexcept
{
auto pathStart = m_path_view.begin();
auto pathEnd = m_path_view.end();
auto currentPathEntry = getCurrentTokenStartPos();
if (currentPathEntry == pathStart)
@@ -613,7 +626,7 @@ namespace AZ::IO::parser
{
return pathParser->InRootName() ? **pathParser : "";
};
int res = GetRootName(lhsPathParser).compare(GetRootName(rhsPathParser));
int res = Internal::ComparePathSegment(GetRootName(lhsPathParser), GetRootName(rhsPathParser), lhsPathParser->m_preferred_separator);
ConsumeRootName(lhsPathParser);
ConsumeRootName(rhsPathParser);
return res;
@@ -642,7 +655,8 @@ namespace AZ::IO::parser
while (lhsPathParser && rhsPathParser)
{
if (int res = (*lhsPathParser).compare(*rhsPathParser); res != 0)
if (int res = Internal::ComparePathSegment(*lhsPathParser, *rhsPathParser, lhsPathParser.m_preferred_separator);
res != 0)
{
return res;
}
@@ -1033,11 +1047,25 @@ namespace AZ::IO
parser::PathParser patternParserEnd(pathPatternView.relative_path_view(), parser::ParserState::PS_AtEnd, pathPatternView.m_preferred_separator);
// move the parser from the end to a valid filename by decrementing
for(--pathParserEnd, --patternParserEnd; pathParserEnd && patternParserEnd; --pathParserEnd, --patternParserEnd)
// Windows Paths are case-insensitive, while Posix paths are case-sensitive
if (m_preferred_separator == PosixPathSeparator)
{
if (!AZStd::wildcard_match_case(*patternParserEnd, *pathParserEnd))
for (--pathParserEnd, --patternParserEnd; pathParserEnd && patternParserEnd; --pathParserEnd, --patternParserEnd)
{
return false;
if (!AZStd::wildcard_match_case(*patternParserEnd, *pathParserEnd))
{
return false;
}
}
}
else
{
for (--pathParserEnd, --patternParserEnd; pathParserEnd && patternParserEnd; --pathParserEnd, --patternParserEnd)
{
if (!AZStd::wildcard_match(*patternParserEnd, *pathParserEnd))
{
return false;
}
}
}
@@ -147,15 +147,18 @@ namespace AZ
ReadFile(request, args);
return;
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
else
{
FlushCache(args.m_path);
if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
{
FlushCache(args.m_path);
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
{
FlushEntireCache();
}
StreamStackEntry::QueueRequest(request);
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
{
FlushEntireCache();
}
StreamStackEntry::QueueRequest(request);
}, request->GetCommand());
}
@@ -146,15 +146,18 @@ namespace AZ
DestroyDedicatedCache(request, args);
return;
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
else
{
FlushCache(args.m_path);
if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
{
FlushCache(args.m_path);
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
{
FlushEntireCache();
}
StreamStackEntry::QueueRequest(request);
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
{
FlushEntireCache();
}
StreamStackEntry::QueueRequest(request);
}, request->GetCommand());
}
@@ -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
@@ -97,19 +97,22 @@ namespace AZ
CancelRequest(request, args.m_target);
return;
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
else
{
FlushCache(args.m_path);
if constexpr (AZStd::is_same_v<Command, FileRequest::FlushData>)
{
FlushCache(args.m_path);
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
{
FlushEntireCache();
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::ReportData>)
{
Report(args);
}
StreamStackEntry::QueueRequest(request);
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::FlushAllData>)
{
FlushEntireCache();
}
else if constexpr (AZStd::is_same_v<Command, FileRequest::ReportData>)
{
Report(args);
}
StreamStackEntry::QueueRequest(request);
}, request->GetCommand());
}
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+29 -2
View File
@@ -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;
}
}
+12 -2
View File
@@ -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();
}
};
}
}
@@ -300,7 +300,6 @@ namespace AZ
context.Class<Uuid>("Uuid")->
Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)->
Attribute(AZ::Script::Attributes::Module, "math")->
Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)->
Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)->
Attribute(AZ::Script::Attributes::ConstructorOverride, &Internal::ScriptUuidConstructor)->
Attribute(AZ::Script::Attributes::GenericConstructorOverride, &Internal::UuidDefaultConstructor)->
@@ -18,11 +18,8 @@ namespace AZ
{
Quaternion CreateRandomQuaternion(SimpleLcgRandom& rng)
{
float u1 = rng.GetRandomFloat();
float u2 = rng.GetRandomFloat();
float u3 = rng.GetRandomFloat();
float c1 = Sqrt(1.0f - u1);
float c2 = Sqrt(u1);
float x, y, z, w;
SinCos(Constants::TwoPi * u2, x, y);
SinCos(Constants::TwoPi * u3, z, w);
@@ -374,7 +374,7 @@ namespace AZ
targetForward.Normalize();
// Lumberyard is Z-up and is right-handed.
// Open 3D Engine is Z-up and is right-handed.
Vector3 up = Vector3::CreateAxisZ();
// We have a degenerate case if target forward is parallel to the up axis,
@@ -391,7 +391,7 @@ namespace AZ
up.Normalize();
// Passing in forwardAxis allows you to force a particular local-space axis to look
// at the target point. In Lumberyard, the default is forward is along Y+.
// at the target point. In Open 3D Engine, the default is forward is along Y+.
switch (forwardAxis)
{
case Axis::XPositive:
@@ -426,7 +426,7 @@ namespace AZ
Matrix4x4 Matrix4x4::CreateProjection(float fovY, float aspectRatio, float nearDist, float farDist)
{
// This section contains some notes about camera matrices and field of view, because there are some subtle differences
// between the convention Lumberyard uses and what you might be used to from other software packages.
// between the convention Open 3D Engine uses and what you might be used to from other software packages.
// Our camera space has the camera looking down the *positive* z-axis, the x-axis points towards the left of the screen,
// and the y-axis points towards the top of the screen.
//
@@ -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
+1 -2
View File
@@ -74,7 +74,6 @@ namespace AZ
{
behaviorContext->Class<Obb>()->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::All)->
Attribute(Script::Attributes::ExcludeFrom, Script::Attributes::ExcludeFlags::Preview)->
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
Attribute(Script::Attributes::GenericConstructorOverride, &Internal::ObbDefaultConstructor)->
Property("position", &Obb::GetPosition, &Obb::SetPosition)->
@@ -155,7 +154,7 @@ namespace AZ
return Obb::CreateFromPositionRotationAndHalfLengths(
transform.TransformPoint(obb.GetPosition()),
transform.GetRotation() * obb.GetRotation(),
obb.GetHalfLengths()
transform.GetScale() * obb.GetHalfLengths()
);
}
}
+2 -3
View File
@@ -104,9 +104,9 @@ namespace AZ
// As one return value (hit point) is based on the other (hit time), for simplicity, the Lua implementation
// just returns all three values: does the ray hit? When does it hit? Where does it hit?
if (!dc.IsClass<Vector3>(0) || !dc.IsClass<Vector3>(0))
if (!dc.IsClass<Vector3>(0) || !dc.IsClass<Vector3>(1))
{
AZ_Error("Script", false, "ScriptPlane CastRay requires two ScriptVector3s as arguments.");
AZ_Error("Script", false, "ScriptPlane IntersectSegment requires two ScriptVector3s as arguments.");
return;
}
@@ -147,7 +147,6 @@ namespace AZ
{
behaviorContext->Class<Plane>()->
Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)->
Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)->
Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value)->
Attribute(AZ::Script::Attributes::GenericConstructorOverride, &Internal::PlaneDefaultConstructor)->
Method("ToString", &Internal::PlaneToString)->
@@ -53,7 +53,6 @@ namespace AZ
if (auto behaviorContext = azrtti_cast<BehaviorContext*>(context))
{
behaviorContext->Class<PolygonPrism>()
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)
->Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::RuntimeOwn)
->Property("height", BehaviorValueGetter(&PolygonPrism::m_height), nullptr)
->Property("vertexContainer", BehaviorValueGetter(&PolygonPrism::m_vertexContainer), nullptr)
@@ -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)
;
}
}
@@ -111,13 +111,11 @@ namespace AZ
Property("segmentFraction", BehaviorValueProperty(&SplineAddress::m_segmentFraction));
behaviorContext->Class<PositionSplineQueryResult>()->
Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)->
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
Property("splineAddress", [](PositionSplineQueryResult* thisPtr) { return thisPtr->m_splineAddress; }, nullptr)->
Property("distanceSq", [](PositionSplineQueryResult* thisPtr) { return thisPtr->m_distanceSq; }, nullptr);
behaviorContext->Class<RaySplineQueryResult>()->
Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::Preview)->
Attribute(Script::Attributes::Storage, Script::Attributes::StorageType::Value)->
Property("splineAddress", [](RaySplineQueryResult* thisPtr) { return thisPtr->m_splineAddress; }, nullptr)->
Property("distanceSq", [](RaySplineQueryResult* thisPtr) { return thisPtr->m_distanceSq; }, nullptr)->
@@ -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)->
@@ -354,7 +355,7 @@ namespace AZ
targetForward.Normalize();
// Lumberyard is Z-up and is right-handed.
// Open 3D Engine is Z-up and is right-handed.
Vector3 up = Vector3::CreateAxisZ();
// We have a degenerate case if target forward is parallel to the up axis,
@@ -371,7 +372,7 @@ namespace AZ
up.Normalize();
// Passing in forwardAxis allows you to force a particular local-space axis to look
// at the target point. In Lumberyard, the default is forward is along Y+.
// at the target point. In Open 3D Engine, the default is forward is along Y+.
switch (forwardAxis)
{
case Axis::XPositive:
@@ -38,6 +38,13 @@ namespace AZ
bool CompareValueData(const void* lhs, const void* rhs) override;
};
//! Limits for transform scale values.
//! The scale should not be zero to avoid problems with inverting.
//! @{
static constexpr float MinTransformScale = 1e-2f;
static constexpr float MaxTransformScale = 1e9f;
//! @}
//! The basic transformation class, represented using a quaternion rotation, vector scale and vector translation.
//! By design, cannot represent skew transformations.
class Transform
@@ -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
+2 -2
View File
@@ -720,9 +720,9 @@ namespace AZ
StoragePolicyBase<Allocator>::Destroy(Base::GetModuleAllocatorInstance());
}
AZ_FORCE_INLINE static bool IsReady()
static bool IsReady()
{
return true;
return Base::GetModuleAllocatorInstance().IsReady();
}
};
}
@@ -707,7 +707,7 @@ PoolSchema::GarbageCollect()
// occur exclusively in the destruction of the allocator.
//
// TODO: A better solution needs to be found for integrating back into mainline
// Lumberyard.
// Open 3D Engine.
//m_impl->GarbageCollect();
}
@@ -31,4 +31,4 @@ namespace AZ
return modulePath;
}
} // namespace Internal
} // namespace AZ
} // namespace AZ
@@ -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

Some files were not shown because too many files have changed in this diff Show More