From 029bf038708559c0393d7ad3f7307fe2902cbef3 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Tue, 2 Nov 2021 13:41:55 -0700 Subject: [PATCH 001/108] Changed PassBuilder's job dependencies to be OrderOnce. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a normal job dependency was overkill. As a result, modifying a shader would trigger a pass to rebuild, and that would cause the entire render pipeline to reinitialize. This causes a lot of unnecessary churn that made debugging shader hot reloads difficult. When a builder depends on knowing the UUID of another asset, it does need to have a job dependency on that asset. But when the builder doesn’t actually consume any data from inside the asset, and it just needs the ID, it is best to use JobDependencyType::OrderOnce to simply make sure the AP knows about the asset. Also, the call to GetSourceInfoBySourcePath was an unnecessary check because the AP does not require the file to exist at the time a dependency is reported. GetSourceInfoBySourcePath will only succeed after the AP has scanned the requested source file. We can’t just assume that a false result indicates the file does not exist, it just isn’t known yet. There are a couple additional use cases to be aware of (from @antonmic)... 1. Passes are critical assets, and some passes depend on shaders, so those shaders need to be processed, that's one reason for the dependency (otherwise you can start the engine, load all critical passes, try to load the shader, shader isn't ready, and bad things happen) 2. If a shader is deleted/removed, the pass should try to rebuild and fail. This was a recent issue that I fixed, you could have some odd condition where you delete a shader, but the pass that references that shader doesn't update or throw any errors because it doesn't rebuild, so the user is unaware that they need to change the .pass file and bad things happen OrderOnce is sufficient for both these cases. #1 is related to first time processing which exactly the time when OrderOnce would be applied. I tested #2 as well; deleting a .shader file with OrderOnce dependency did trigger the .pass file to rebuild and fail. Testing: Ran an ASV pass test with both an exiting cache and after deleting the local cache. Started the Editor with a clean cache and didn't encounter any startup issues. Was able to successfully load a level the first time. Deleted SkyBox.shader and saw SkyBox.pass fail in the AP. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Source/RPI.Builders/Pass/PassBuilder.cpp | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp index 6a0b10633e..e2d4bd629a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Pass/PassBuilder.cpp @@ -53,7 +53,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc builder; builder.m_name = PassBuilderJobKey; - builder.m_version = 14; // making .pass files emit product dependencies for the shaders they reference so they are picked up by the asset bundler + builder.m_version = 15; // Changed dependency type to OrderOnce builder.m_busId = azrtti_typeid(); builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2); builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); @@ -97,27 +97,16 @@ namespace AZ // Helper function to get a file reference and create a corresponding job dependency bool AddDependency(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) { - AZStd::string_view& file = params.dependencySourceFile; - AZ::Data::AssetInfo sourceInfo; - AZStd::string watchFolder; - bool fileFound = false; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(fileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.data(), sourceInfo, watchFolder); - - if (fileFound) - { - AssetBuilderSDK::JobDependency jobDependency; - jobDependency.m_jobKey = params.jobKey; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; - jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; - job->m_jobDependencyList.push_back(jobDependency); - AZ_TracePrintf(PassBuilderName, "Creating job dependency on file [%s] \n", file.data()); - return true; - } - else - { - AZ_Error(PassBuilderName, false, "Could not find referenced file [%s]", file.data()); - return false; - } + // We use an OrderOnce job dependency to ensure that the Asset Processor knows about the + // referenced asset, so we can make an AssetId for it later in ProcessJob. OrderOnce is + // enough because we don't need to read any data from the asset, we just needs its ID. + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = params.jobKey; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::OrderOnce; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = params.dependencySourceFile; + job->m_jobDependencyList.push_back(jobDependency); + AZ_TracePrintf(PassBuilderName, "Creating job dependency on file [%.*s] \n", AZ_STRING_ARG(params.dependencySourceFile)); + return true; } bool SetJobKeyForExtension(const AZStd::string& filePath, FindPassReferenceAssetParams& params) From f36255b22ad0115c2cd86b184ff9f8518419857e Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 8 Dec 2021 13:57:24 -0800 Subject: [PATCH 002/108] Initial value implementation Signed-off-by: Nicholas Van Sickle --- .../AzCore/AzCore/DOM/DomDocument.cpp | 0 .../Framework/AzCore/AzCore/DOM/DomDocument.h | 0 Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 747 ++++++++++++++++++ Code/Framework/AzCore/AzCore/DOM/DomValue.h | 289 +++++++ .../AzCore/AzCore/azcore_files.cmake | 4 + 5 files changed, 1040 insertions(+) create mode 100644 Code/Framework/AzCore/AzCore/DOM/DomDocument.cpp create mode 100644 Code/Framework/AzCore/AzCore/DOM/DomDocument.h create mode 100644 Code/Framework/AzCore/AzCore/DOM/DomValue.cpp create mode 100644 Code/Framework/AzCore/AzCore/DOM/DomValue.h diff --git a/Code/Framework/AzCore/AzCore/DOM/DomDocument.cpp b/Code/Framework/AzCore/AzCore/DOM/DomDocument.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Code/Framework/AzCore/AzCore/DOM/DomDocument.h b/Code/Framework/AzCore/AzCore/DOM/DomDocument.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp new file mode 100644 index 0000000000..ad6e648620 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -0,0 +1,747 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +#include + +namespace AZ::Dom +{ + template + AZStd::shared_ptr& CheckCopyOnWrite(AZStd::shared_ptr& refCountedPointer) + { + if (refCountedPointer.use_count() > 1) + { + AZStd::shared_ptr newPointer = AZStd::make_shared(); + *newPointer = *refCountedPointer; + refCountedPointer = AZStd::move(newPointer); + } + return refCountedPointer; + } + + AZ::Name Node::GetName() const + { + return m_name; + } + + void Node::SetName(AZ::Name name) + { + m_name = name; + } + + ObjectPtr Node::GetMutableProperties() + { + CheckCopyOnWrite(m_object); + return m_object; + } + + ConstObjectPtr Node::GetProperties() const + { + return m_object; + } + + ArrayPtr Node::GetMutableChildren() + { + CheckCopyOnWrite(m_array); + return m_array; + } + + ConstArrayPtr Node::GetChildren() const + { + return m_array; + } + + bool Node::operator==(const Node& rhs) const + { + return m_name == rhs.m_name && m_array == rhs.m_array && m_object == rhs.m_object; + } + + Value::Value() + { + } + + Value::Value(const Value& value) + : m_value(value.m_value) + { + } + + Value::Value(Value&& value) noexcept + : m_value(value.m_value) + { + } + + Value::Value(AZStd::string_view string, bool copy) + { + if (copy) + { + CopyFromString(string); + } + else + { + SetString(string); + } + } + + Value::Value(AZStd::any* value) + : m_value(value) + { + } + + Value Value::FromOpaqueValue(AZStd::any& value) + { + return Value(&value); + } + + Value::Value(int64_t value) + : m_value(value) + { + } + + Value::Value(uint64_t value) + : m_value(value) + { + } + + Value::Value(double value) + : m_value(value) + { + } + + Value::Value(bool value) + : m_value(value) + { + } + + Value& Value::operator=(const Value& other) + { + m_value = other.m_value; + return *this; + } + + Value& Value::operator=(Value&& other) noexcept + { + m_value = other.m_value; + return *this; + } + + bool Value::operator==(const Value& rhs) const + { + if (IsString() && rhs.IsString()) + { + return GetString() == rhs.GetString(); + } + else if (IsNumber() && rhs.IsNumber()) + { + if (IsInt()) + { + return GetInt() == rhs.GetInt(); + } + else if (IsUint()) + { + return GetUint() == rhs.GetUint(); + } + else + { + return GetDouble() == rhs.GetDouble(); + } + } + else + { + return m_value == rhs.m_value; + } + } + + bool Value::operator!=(const Value& rhs) const + { + return !operator==(rhs); + } + + void Value::Swap(Value& other) noexcept + { + AZStd::swap(m_value, other.m_value); + } + + Type Dom::Value::GetType() const + { + switch (m_value.index()) + { + case 0: // AZStd::monostate + return Type::NullType; + case 1: // int64_t + case 2: // uint64_t + case 3: // double + return Type::NumberType; + case 4: // bool + return AZStd::get(m_value) ? Type::TrueType : Type::FalseType; + case 5: // AZStd::string_view + case 6: // AZStd::shared_ptr + return Type::StringType; + case 7: // ObjectPtr + return Type::ObjectType; + case 8: // ArrayPtr + return Type::ArrayType; + case 9: // Node + return Type::NodeType; + case 10: // AZStd::any* + return Type::OpaqueType; + } + AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); + return Type::NullType; + } + + bool Value::IsNull() const + { + return GetType() == Type::NullType; + } + + bool Value::IsFalse() const + { + return GetType() == Type::FalseType; + } + + bool Value::IsTrue() const + { + return GetType() == Type::TrueType; + } + + bool Value::IsBool() const + { + return AZStd::holds_alternative(m_value); + } + + bool Value::IsNode() const + { + return GetType() == Type::NodeType; + } + + bool Value::IsObject() const + { + return GetType() == Type::ObjectType; + } + + bool Value::IsArray() const + { + return GetType() == Type::ArrayType; + } + + bool Value::IsOpaqueValue() const + { + return GetType() == Type::OpaqueType; + } + + bool Value::IsNumber() const + { + return GetType() == Type::NumberType; + } + + bool Value::IsInt() const + { + return AZStd::holds_alternative(m_value); + } + + bool Value::IsUint() const + { + return AZStd::holds_alternative(m_value); + } + + bool Value::IsDouble() const + { + return AZStd::holds_alternative(m_value); + } + + bool Value::IsString() const + { + return GetType() == Type::StringType; + } + + Value& Value::SetObject() + { + m_value = AZStd::make_shared(); + return *this; + } + + const Object::ContainerType& Value::GetObjectInternal() const + { + const Type type = GetType(); + AZ_Assert( + type == Type::ObjectType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an object from a non-object value"); + if (type == Type::ObjectType) + { + return AZStd::get(m_value)->m_values; + } + else + { + return AZStd::get(m_value).GetProperties()->m_values; + } + } + + Object::ContainerType& Value::GetObjectInternal() + { + const Type type = GetType(); + AZ_Assert( + type == Type::ObjectType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an object from a non-object value"); + if (type == Type::ObjectType) + { + return CheckCopyOnWrite(AZStd::get(m_value))->m_values; + } + else + { + return AZStd::get(m_value).GetMutableProperties()->m_values; + } + } + + const Array::ContainerType& Value::GetArrayInternal() const + { + const Type type = GetType(); + AZ_Assert( + type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a non-array value"); + if (type == Type::ObjectType) + { + return AZStd::get(m_value)->m_values; + } + else + { + return AZStd::get(m_value).GetChildren()->m_values; + } + } + + Array::ContainerType& Value::GetArrayInternal() + { + const Type type = GetType(); + AZ_Assert( + type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a non-array value"); + if (type == Type::ObjectType) + { + return CheckCopyOnWrite(AZStd::get(m_value))->m_values; + } + else + { + return AZStd::get(m_value).GetMutableChildren()->m_values; + } + } + + size_t Value::MemberCount() const + { + return GetObjectInternal().size(); + } + + size_t Value::MemberCapacity() const + { + return GetObjectInternal().size(); + } + + bool Value::ObjectEmpty() const + { + return GetObjectInternal().empty(); + } + + Value& Value::operator[](KeyType name) + { + return FindMember(name)->second; + } + + const Value& Value::operator[](KeyType name) const + { + return FindMember(name)->second; + } + + Value& Value::operator[](AZStd::string_view name) + { + return operator[](AZ::Name(name)); + } + + const Value& Value::operator[](AZStd::string_view name) const + { + return operator[](AZ::Name(name)); + } + + Object::ConstIterator Value::MemberBegin() const + { + return GetObjectInternal().begin(); + } + + Object::ConstIterator Value::MemberEnd() const + { + return GetObjectInternal().end(); + } + + Object::Iterator Value::MemberBegin() + { + return GetObjectInternal().begin(); + } + + Object::Iterator Value::MemberEnd() + { + return GetObjectInternal().end(); + } + + Object::ConstIterator Value::FindMember(KeyType name) const + { + const Object::ContainerType& object = GetObjectInternal(); + return AZStd::find_if( + object.begin(), object.end(), + [&name](const Object::EntryType& entry) + { + return entry.first == name; + }); + } + + Object::ConstIterator Value::FindMember(AZStd::string_view name) const + { + return FindMember(AZ::Name(name)); + } + + Object::Iterator Value::FindMember(KeyType name) + { + Object::ContainerType& object = GetObjectInternal(); + return AZStd::find_if( + object.begin(), object.end(), + [&name](const Object::EntryType& entry) + { + return entry.first == name; + }); + } + + Object::Iterator Value::FindMember(AZStd::string_view name) + { + return FindMember(AZ::Name(name)); + } + + Value& Value::MemberReserve(size_t newCapacity) + { + GetObjectInternal().reserve(newCapacity); + return *this; + } + + bool Value::HasMember(KeyType name) const + { + return FindMember(name) != GetObjectInternal().end(); + } + + bool Value::HasMember(AZStd::string_view name) const + { + return HasMember(AZ::Name(name)); + } + + Value& Value::AddMember(KeyType name, const Value& value) + { + Object::ContainerType& object = GetObjectInternal(); + if (auto memberIt = FindMember(name); memberIt != object.end()) + { + memberIt->second = value; + } + else + { + object.emplace_back(name, value); + } + return *this; + } + + Value& Value::AddMember(AZStd::string_view name, const Value& value) + { + return AddMember(AZ::Name(name), value); + } + + Value& Value::AddMember(AZ::Name name, Value&& value) + { + Object::ContainerType& object = GetObjectInternal(); + if (auto memberIt = FindMember(name); memberIt != object.end()) + { + memberIt->second = value; + } + else + { + object.emplace_back(name, value); + } + return *this; + } + + Value& Value::AddMember(AZStd::string_view name, Value&& value) + { + return AddMember(AZ::Name(name), value); + } + + void Value::RemoveAllMembers() + { + GetObjectInternal().clear(); + } + + void Value::RemoveMember(KeyType name) + { + Object::ContainerType& object = GetObjectInternal(); + object.erase(AZStd::remove_if( + object.begin(), object.end(), + [&name](const Object::EntryType& entry) + { + return entry.first == name; + })); + } + + void Value::RemoveMember(AZStd::string_view name) + { + RemoveMember(AZ::Name(name)); + } + + Object::Iterator Value::RemoveMember(Object::Iterator pos) + { + Object::ContainerType& object = GetObjectInternal(); + Object::Iterator nextIndex = object.end(); + auto lastEntry = object.end() - 1; + if (pos != lastEntry) + { + AZStd::swap(*pos, *lastEntry); + nextIndex = pos; + } + object.resize(object.size() - 1); + return nextIndex; + } + + Object::Iterator Value::EraseMember(Object::ConstIterator pos) + { + return GetObjectInternal().erase(pos); + } + + Object::Iterator Value::EraseMember(Object::ConstIterator first, Object::ConstIterator last) + { + return GetObjectInternal().erase(first, last); + } + + Object::Iterator Value::EraseMember(KeyType name) + { + return GetObjectInternal().erase(FindMember(name)); + } + + Object::Iterator Value::EraseMember(AZStd::string_view name) + { + return EraseMember(AZ::Name(name)); + } + + Object::ContainerType& Value::GetObject() + { + return GetObjectInternal(); + } + + const Object::ContainerType& Value::GetObject() const + { + return GetObjectInternal(); + } + + Value& Value::SetArray() + { + m_value = AZStd::make_shared(); + return *this; + } + + size_t Value::Size() const + { + return GetArrayInternal().size(); + } + + size_t Value::Capacity() const + { + return GetArrayInternal().capacity(); + } + + bool Value::Empty() const + { + return GetArrayInternal().empty(); + } + + void Value::Clear() + { + GetArrayInternal().clear(); + } + + Value& Value::operator[](size_t index) + { + return GetArrayInternal()[index]; + } + + const Value& Value::operator[](size_t index) const + { + return GetArrayInternal()[index]; + } + + Array::ConstIterator Value::Begin() const + { + return GetArrayInternal().begin(); + } + + Array::ConstIterator Value::End() const + { + return GetArrayInternal().end(); + } + + Array::Iterator Value::Begin() + { + return GetArrayInternal().begin(); + } + + Array::Iterator Value::End() + { + return GetArrayInternal().end(); + } + + Value& Value::Reserve(size_t newCapacity) + { + GetArrayInternal().reserve(newCapacity); + return *this; + } + + Value& Value::PushBack(Value value) + { + GetArrayInternal().push_back(AZStd::move(value)); + return *this; + } + + Value& Value::PopBack() + { + GetArrayInternal().pop_back(); + return *this; + } + + Array::Iterator Value::Erase(Array::ConstIterator pos) + { + return GetArrayInternal().erase(pos); + } + + Array::Iterator Value::Erase(Array::ConstIterator first, Array::ConstIterator last) + { + return GetArrayInternal().erase(first, last); + } + + Array::ContainerType& Value::GetArray() + { + return GetArrayInternal(); + } + + const Array::ContainerType& Value::GetArray() const + { + return GetArrayInternal(); + } + + int64_t Value::GetInt() const + { + switch (m_value.index()) + { + case 1: // int64_t + return AZStd::get(m_value); + case 2: // uint64_t + return aznumeric_cast(AZStd::get(m_value)); + case 3: // double + return aznumeric_cast(AZStd::get(m_value)); + } + AZ_Assert(false, "AZ::Dom::Value: Called GetInt on a non-numeric type"); + return {}; + } + + void Value::SetInt(int64_t value) + { + m_value = value; + } + + uint64_t Value::GetUint() const + { + switch (m_value.index()) + { + case 1: // int64_t + return aznumeric_cast(AZStd::get(m_value)); + case 2: // uint64_t + return AZStd::get(m_value); + case 3: // double + return aznumeric_cast(AZStd::get(m_value)); + } + AZ_Assert(false, "AZ::Dom::Value: Called GetInt on a non-numeric type"); + return {}; + } + + void Value::SetUint(uint64_t value) + { + m_value = value; + } + + bool Value::GetBool() const + { + if (IsBool()) + { + return AZStd::get(m_value); + } + AZ_Assert(false, "AZ::Dom::Value: Called GetBool on a non-bool type"); + return {}; + } + + void Value::SetBool(bool value) + { + m_value = value; + } + + double Value::GetDouble() const + { + switch (m_value.index()) + { + case 1: // int64_t + return aznumeric_cast(AZStd::get(m_value)); + case 2: // uint64_t + return aznumeric_cast(AZStd::get(m_value)); + case 3: // double + return AZStd::get(m_value); + } + AZ_Assert(false, "AZ::Dom::Value: Called GetInt on a non-numeric type"); + return {}; + } + + void Value::SetDouble(double value) + { + m_value = value; + } + + AZStd::string_view Value::GetString() const + { + switch (m_value.index()) + { + case 5: // AZStd::string_view + return AZStd::get(m_value); + case 6: // AZStd::shared_ptr + return *AZStd::get>(m_value); + } + AZ_Assert(false, "AZ::Dom::Value: Called GetString on a non-string type"); + return {}; + } + + size_t Value::GetStringLength() const + { + return GetString().size(); + } + + void Value::SetString(AZStd::string_view value) + { + m_value = value; + } + + void Value::CopyFromString(AZStd::string_view value) + { + m_value = AZStd::make_shared(value); + } + + AZStd::any& Value::GetOpaqueValue() const + { + return *AZStd::get(m_value); + } + + void Value::SetOpaqueValue(AZStd::any& value) + { + m_value = &value; + } + + void Value::SetNull() + { + m_value = AZStd::monostate(); + } +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h new file mode 100644 index 0000000000..f73dbb2549 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -0,0 +1,289 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include + +namespace AZ::Dom +{ + using KeyType = AZ::Name; + + enum class Type + { + NullType = 0, + FalseType = 1, + TrueType = 2, + ObjectType = 3, + ArrayType = 4, + StringType = 5, + NumberType = 6, + NodeType = 7, + OpaqueType = 8, + }; + + class Value; + + class Array + { + public: + using ContainerType = AZStd::vector; + using Iterator = ContainerType::iterator; + using ConstIterator = ContainerType::const_iterator; + + private: + ContainerType m_values; + + friend class Value; + }; + + using ArrayPtr = AZStd::shared_ptr; + using ConstArrayPtr = AZStd::shared_ptr; + + class Object + { + public: + using EntryType = AZStd::pair; + using ContainerType = AZStd::vector; + using Iterator = ContainerType::iterator; + using ConstIterator = ContainerType::const_iterator; + + private: + ContainerType m_values; + + friend class Value; + }; + + using ObjectPtr = AZStd::shared_ptr; + using ConstObjectPtr = AZStd::shared_ptr; + + class Node + { + public: + AZ::Name GetName() const; + void SetName(AZ::Name name); + + ObjectPtr GetMutableProperties(); + ConstObjectPtr GetProperties() const; + + ArrayPtr GetMutableChildren(); + ConstArrayPtr GetChildren() const; + + bool operator==(const Node& rhs) const; + + private: + AZ::Name m_name; + ArrayPtr m_array; + ObjectPtr m_object; + + friend class Value; + }; + + class Value + { + public: + // Constructors... + Value(); + Value(const Value&); + Value(Value&&) noexcept; + Value(AZStd::string_view string, bool copy); + + explicit Value(int64_t value); + explicit Value(uint64_t value); + explicit Value(double value); + explicit Value(bool value); + + static Value FromOpaqueValue(AZStd::any& value); + + // Equality / comparison / swap... + Value& operator=(const Value&); + Value& operator=(Value&&) noexcept; + + bool operator==(const Value& rhs) const; + bool operator!=(const Value& rhs) const; + + void Swap(Value& other) noexcept; + + // Type info... + Type GetType() const; + bool IsNull() const; + bool IsFalse() const; + bool IsTrue() const; + bool IsBool() const; + bool IsNode() const; + bool IsObject() const; + bool IsArray() const; + bool IsOpaqueValue() const; + bool IsNumber() const; + bool IsInt() const; + bool IsUint() const; + bool IsDouble() const; + bool IsString() const; + + // Object API (also used by Node)... + Value& SetObject(); + size_t MemberCount() const; + size_t MemberCapacity() const; + bool ObjectEmpty() const; + + Value& operator[](KeyType name); + const Value& operator[](KeyType name) const; + Value& operator[](AZStd::string_view name); + const Value& operator[](AZStd::string_view name) const; + + Object::ConstIterator MemberBegin() const; + Object::ConstIterator MemberEnd() const; + Object::Iterator MemberBegin(); + Object::Iterator MemberEnd(); + + Object::ConstIterator FindMember(KeyType name) const; + Object::ConstIterator FindMember(AZStd::string_view name) const; + Object::Iterator FindMember(KeyType name); + Object::Iterator FindMember(AZStd::string_view name); + + Value& MemberReserve(size_t newCapacity); + bool HasMember(KeyType name) const; + bool HasMember(AZStd::string_view name) const; + + Value& AddMember(KeyType name, const Value& value); + Value& AddMember(AZStd::string_view name, const Value& value); + Value& AddMember(KeyType name, Value&& value); + Value& AddMember(AZStd::string_view name, Value&& value); + + void RemoveAllMembers(); + void RemoveMember(KeyType name); + void RemoveMember(AZStd::string_view name); + Object::Iterator RemoveMember(Object::Iterator pos); + Object::Iterator EraseMember(Object::ConstIterator pos); + Object::Iterator EraseMember(Object::ConstIterator first, Object::ConstIterator last); + Object::Iterator EraseMember(KeyType name); + Object::Iterator EraseMember(AZStd::string_view name); + + Object::ContainerType& GetObject(); + const Object::ContainerType& GetObject() const; + + // Array API (also used by Node)... + Value& SetArray(); + + size_t Size() const; + size_t Capacity() const; + bool Empty() const; + void Clear(); + + Value& operator[](size_t index); + const Value& operator[](size_t index) const; + + Array::ConstIterator Begin() const; + Array::ConstIterator End() const; + Array::Iterator Begin(); + Array::Iterator End(); + + Value& Reserve(size_t newCapacity); + Value& PushBack(Value value); + Value& PopBack(); + + Array::Iterator Erase(Array::ConstIterator pos); + Array::Iterator Erase(Array::ConstIterator first, Array::ConstIterator last); + + Array::ContainerType& GetArray(); + const Array::ContainerType& GetArray() const; + + // Node API (supports both object + array API, plus a dedicated NodeName)... + // bool CanConvertToNodeFromObject() const; + // Value& ConvertToNodeFromObject(); + // Value& ConvertToObjectFromNode(); + + void SetNode(AZ::Name name); + void SetNode(AZStd::string_view name); + + AZ::Name GetNodeName() const; + void SetNodeName(AZ::Name name); + void SetNodeName(AZStd::string_view name); + //! Convenience method, sets the first non-node element of a Node. + void SetNodeValue(Value value); + //! Convenience method, gets the first non-node element of a Node. + Value GetNodeValue() const; + + // int API... + int64_t GetInt() const; + void SetInt(int64_t); + + // uint API... + uint64_t GetUint() const; + void SetUint(uint64_t); + + // bool API... + bool GetBool() const; + void SetBool(bool); + + // double API... + double GetDouble() const; + void SetDouble(double); + + // string API... + AZStd::string_view GetString() const; + size_t GetStringLength() const; + void SetString(AZStd::string_view); + void CopyFromString(AZStd::string_view); + + // opaque type API... + AZStd::any& GetOpaqueValue() const; + //! This sets this Value to represent a value of an type that the DOM has + //! no formal knowledge of. Where possible, it should be preferred to + //! serialize an opaque type into a DOM value instead, as serializers + //! and other systems will have no means of dealing with fully arbitrary + //! values. + void SetOpaqueValue(AZStd::any&); + + // null API... + void SetNull(); + + private: + const Object::ContainerType& GetObjectInternal() const; + Object::ContainerType& GetObjectInternal(); + const Array::ContainerType& GetArrayInternal() const; + Array::ContainerType& GetArrayInternal(); + + explicit Value(AZStd::any* opaqueValue); + + // If using the the copy on write model, anything stored internally as a shared_ptr will + // detach and copy when doing a mutating operation if use_count() > 1. + + // This internal storage will not have a 1:1 mapping to the public Type, as there may be + // multiple storage options (e.g. strings being stored as non-owning string_view or + // owning shared_ptr) + using ValueType = AZStd::variant< + // NullType + AZStd::monostate, + // NumberType + int64_t, + uint64_t, + double, + // FalseType & TrueType + bool, + // StringType + AZStd::string_view, + AZStd::shared_ptr, + // ObjectType + ObjectPtr, + // ArrayType + ArrayPtr, + // NodeType + Node, + // OpaqueType + AZStd::any*>; + + ValueType m_value; + }; +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index ef6c7434cc..fa9f94505f 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -127,8 +127,12 @@ set(FILES Debug/TraceReflection.h DOM/DomBackend.cpp DOM/DomBackend.h + DOM/DomDocument.cpp + DOM/DomDocument.h DOM/DomUtils.cpp DOM/DomUtils.h + DOM/DomValue.cpp + DOM/DomValue.h DOM/DomVisitor.cpp DOM/DomVisitor.h DOM/Backends/JSON/JsonBackend.h From fada7ace232457b578730be5870df61fb9c7cfa6 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 8 Dec 2021 22:22:18 -0800 Subject: [PATCH 003/108] Add visitor support to Value Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp | 2 +- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 306 ++++++++++++++++++ Code/Framework/AzCore/AzCore/DOM/DomValue.h | 49 ++- 3 files changed, 355 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp index 9751b9cecc..2e78661518 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp @@ -21,4 +21,4 @@ namespace AZ::Dom::Utils { return backend.ReadFromBufferInPlace(string.data(), string.size(), visitor); } -} +} // namespace AZ::Dom::Utils diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index ad6e648620..032e5795da 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -744,4 +744,310 @@ namespace AZ::Dom { m_value = AZStd::monostate(); } + + Visitor::Result Value::Accept(Visitor& visitor, bool copyStrings) const + { + Visitor::Result result = AZ::Success(); + + AZStd::visit( + [&](auto&& arg) + { + using Alternative = AZStd::decay_t; + + if constexpr (AZStd::is_same_v) + { + result = visitor.Null(); + } + else if constexpr (AZStd::is_same_v) + { + result = visitor.Int64(arg); + } + else if constexpr (AZStd::is_same_v) + { + result = visitor.Uint64(arg); + } + else if constexpr (AZStd::is_same_v) + { + result = visitor.Double(arg); + } + else if constexpr (AZStd::is_same_v) + { + result = visitor.String(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); + } + else if constexpr (AZStd::is_same_v>) + { + result = visitor.String(*arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); + } + else if constexpr (AZStd::is_same_v) + { + result = visitor.StartObject(); + if (result.IsSuccess()) + { + const Object::ContainerType& object = GetObjectInternal(); + for (const Object::EntryType& entry : object) + { + result = entry.second.Accept(visitor, copyStrings); + if (!result.IsSuccess()) + { + return; + } + } + result = visitor.EndObject(object.size()); + } + } + else if constexpr (AZStd::is_same_v) + { + result = visitor.StartArray(); + if (result.IsSuccess()) + { + const Array::ContainerType& arrayContainer = GetArrayInternal(); + for (const Value& entry : arrayContainer) + { + result = entry.Accept(visitor, copyStrings); + if (!result.IsSuccess()) + { + return; + } + } + result = visitor.EndArray(arrayContainer.size()); + } + } + else if constexpr (AZStd::is_same_v) + { + const Node& node = AZStd::get(m_value); + result = visitor.StartNode(node.GetName()); + if (result.IsSuccess()) + { + const Object::ContainerType& object = GetObjectInternal(); + for (const Object::EntryType& entry : object) + { + result = entry.second.Accept(visitor, copyStrings); + if (!result.IsSuccess()) + { + return; + } + } + + const Array::ContainerType& arrayContainer = GetArrayInternal(); + for (const Value& entry : arrayContainer) + { + result = entry.Accept(visitor, copyStrings); + if (!result.IsSuccess()) + { + return; + } + } + + result = visitor.EndNode(object.size(), arrayContainer.size()); + } + } + else if constexpr (AZStd::is_same_v) + { + result = visitor.OpaqueValue(*arg); + } + }, + m_value); + return result; + } + + ValueWriter::ValueWriter(Value& outputValue) + : m_result(outputValue) + { + } + + VisitorFlags ValueWriter::GetVisitorFlags() const + { + return VisitorFlags::SupportsRawKeys | VisitorFlags::SupportsArrays | VisitorFlags::SupportsObjects | VisitorFlags::SupportsNodes; + } + + ValueWriter::ValueInfo::ValueInfo(Value& container) + : m_container(container) + { + } + + Visitor::Result ValueWriter::Null() + { + CurrentValue().SetNull(); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Bool(bool value) + { + CurrentValue().SetBool(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Int64(AZ::s64 value) + { + CurrentValue().SetInt(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Uint64(AZ::u64 value) + { + CurrentValue().SetUint(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Double(double value) + { + CurrentValue().SetDouble(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::String(AZStd::string_view value, Lifetime lifetime) + { + if (lifetime == Lifetime::Persistent) + { + CurrentValue().SetString(value); + } + else + { + CurrentValue().CopyFromString(value); + } + return FinishWrite(); + } + + Visitor::Result ValueWriter::StartObject() + { + CurrentValue().SetObject(); + + m_entryStack.emplace(CurrentValue()); + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount) + { + const char* endMethodName; + switch (containerType) + { + case Type::ObjectType: + endMethodName = "EndObject"; + break; + case Type::ArrayType: + endMethodName = "EndArray"; + break; + case Type::NodeType: + endMethodName = "EndNode"; + break; + default: + AZ_Assert(false, "Invalid container type specified"); + return VisitorFailure(VisitorErrorCode::InternalError, "AZ::Dom::ValueWriter: EndContainer called with invalid container type"); + } + + if (m_entryStack.empty()) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format("AZ::Dom::ValueWriter: %s called without a matching call", endMethodName)); + } + + const ValueInfo& topEntry = m_entryStack.top(); + if (topEntry.m_container.GetType() != containerType) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName)); + } + + if (topEntry.m_attributeCount != attributeCount) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format( + "AZ::Dom::ValueWriter: %s expected %llu attributes but received %llu attributes instead", endMethodName, attributeCount, + topEntry.m_attributeCount)); + } + + if (topEntry.m_elementCount != elementCount) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format( + "AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount, + topEntry.m_elementCount)); + } + + m_entryStack.pop(); + return FinishWrite(); + } + + Visitor::Result ValueWriter::EndObject(AZ::u64 attributeCount) + { + return EndContainer(Type::ObjectType, attributeCount, 0); + } + + Visitor::Result ValueWriter::Key(AZ::Name key) + { + AZ_Assert(!m_entryStack.empty(), "Attempmted to push a key with no object"); + AZ_Assert(!m_entryStack.top().m_container.IsArray(), "Attempted to push a key to an array"); + m_entryStack.top().m_key = key; + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::RawKey(AZStd::string_view key, [[maybe_unused]] Lifetime lifetime) + { + return Key(AZ::Name(key)); + } + + Visitor::Result ValueWriter::StartArray() + { + CurrentValue().SetArray(); + + m_entryStack.emplace(CurrentValue()); + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::EndArray(AZ::u64 elementCount) + { + return EndContainer(Type::ArrayType, 0, elementCount); + } + + Visitor::Result ValueWriter::StartNode(AZ::Name name) + { + CurrentValue().SetNode(name); + + m_entryStack.emplace(CurrentValue()); + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) + { + return EndContainer(Type::NodeType, attributeCount, elementCount); + } + + Visitor::Result ValueWriter::FinishWrite() + { + if (m_entryStack.empty()) + { + return VisitorSuccess(); + } + + Value value; + m_entryStack.top().m_value.Swap(value); + ValueInfo& newEntry = m_entryStack.top(); + + if (!newEntry.m_key.IsEmpty()) + { + newEntry.m_container.AddMember(newEntry.m_key, AZStd::move(value)); + newEntry.m_key = AZ::Name(); + ++newEntry.m_attributeCount; + } + else + { + newEntry.m_container.PushBack(AZStd::move(value)); + ++newEntry.m_elementCount; + } + + return VisitorSuccess(); + } + + Value& ValueWriter::CurrentValue() + { + if (m_entryStack.empty()) + { + return m_result; + } + return m_entryStack.top().m_value; + } } // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index f73dbb2549..439971a5a0 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace AZ::Dom @@ -249,6 +250,9 @@ namespace AZ::Dom // null API... void SetNull(); + // Visitor API + Visitor::Result Accept(Visitor& visitor, bool copyStrings) const; + private: const Object::ContainerType& GetObjectInternal() const; Object::ContainerType& GetObjectInternal(); @@ -286,4 +290,47 @@ namespace AZ::Dom ValueType m_value; }; -} // namespace AZ::Dom + + class ValueWriter : public Visitor + { + public: + ValueWriter(Value& outputValue); + + VisitorFlags GetVisitorFlags() const override; + Result Null() override; + Result Bool(bool value) override; + Result Int64(AZ::s64 value) override; + Result Uint64(AZ::u64 value) override; + Result Double(double value) override; + + Result String(AZStd::string_view value, Lifetime lifetime) override; + Result StartObject() override; + Result EndObject(AZ::u64 attributeCount) override; + Result Key(AZ::Name key) override; + Result RawKey(AZStd::string_view key, Lifetime lifetime) override; + Result StartArray() override; + Result EndArray(AZ::u64 elementCount) override; + Result StartNode(AZ::Name name) override; + Result RawStartNode(AZStd::string_view name, Lifetime lifetime) override; + Result EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) override; + + private: + Result FinishWrite(); + Value& CurrentValue(); + Visitor::Result EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount); + + struct ValueInfo + { + ValueInfo(Value& container); + + KeyType m_key; + Value m_value; + Value& m_container; + AZ::u64 m_attributeCount = 0; + AZ::u64 m_elementCount = 0; + }; + + Value& m_result; + AZStd::stack m_entryStack; + }; + } // namespace AZ::Dom From e7c92b5658a0829885a729039356fbad1bf939bb Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 9 Dec 2021 15:25:20 -0800 Subject: [PATCH 004/108] Move ValueWriter out, add DeepCompareIsEqual Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 405 +++++++++--------- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 81 ++-- .../AzCore/AzCore/DOM/DomValueWriter.cpp | 218 ++++++++++ .../AzCore/AzCore/DOM/DomValueWriter.h | 58 +++ .../AzCore/AzCore/azcore_files.cmake | 2 + 5 files changed, 504 insertions(+), 260 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp create mode 100644 Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 032e5795da..68a88ed35a 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -9,7 +9,7 @@ #pragma once #include - +#include #include namespace AZ::Dom @@ -26,6 +26,11 @@ namespace AZ::Dom return refCountedPointer; } + Node::Node(AZ::Name name) + : m_name(name) + { + } + AZ::Name Node::GetName() const { return m_name; @@ -36,31 +41,24 @@ namespace AZ::Dom m_name = name; } - ObjectPtr Node::GetMutableProperties() + Object::ContainerType& Node::GetProperties() { - CheckCopyOnWrite(m_object); - return m_object; + return m_properties; } - ConstObjectPtr Node::GetProperties() const + const Object::ContainerType& Node::GetProperties() const { - return m_object; + return m_properties; } - ArrayPtr Node::GetMutableChildren() + Array::ContainerType& Node::GetChildren() { - CheckCopyOnWrite(m_array); - return m_array; + return m_children; } - ConstArrayPtr Node::GetChildren() const + const Array::ContainerType& Node::GetChildren() const { - return m_array; - } - - bool Node::operator==(const Node& rhs) const - { - return m_name == rhs.m_name && m_array == rhs.m_array && m_object == rhs.m_object; + return m_children; } Value::Value() @@ -187,7 +185,7 @@ namespace AZ::Dom return Type::ObjectType; case 8: // ArrayPtr return Type::ArrayType; - case 9: // Node + case 9: // NodePtr return Type::NodeType; case 10: // AZStd::any* return Type::OpaqueType; @@ -267,18 +265,31 @@ namespace AZ::Dom return *this; } + const Node& Value::GetNodeInternal() const + { + AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: attempted to retrieve a node from a non-node value"); + return *AZStd::get(m_value); + } + + Node& Value::GetNodeInternal() + { + AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: attempted to retrieve a node from a non-node value"); + return *CheckCopyOnWrite(AZStd::get(m_value)); + } + const Object::ContainerType& Value::GetObjectInternal() const { const Type type = GetType(); AZ_Assert( - type == Type::ObjectType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an object from a non-object value"); + type == Type::ObjectType || type == Type::NodeType, + "AZ::Dom::Value: attempted to retrieve an object from a value that isn't an object or a node"); if (type == Type::ObjectType) { return AZStd::get(m_value)->m_values; } else { - return AZStd::get(m_value).GetProperties()->m_values; + return AZStd::get(m_value)->GetProperties(); } } @@ -286,14 +297,15 @@ namespace AZ::Dom { const Type type = GetType(); AZ_Assert( - type == Type::ObjectType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an object from a non-object value"); + type == Type::ObjectType || type == Type::NodeType, + "AZ::Dom::Value: attempted to retrieve an object from a value that isn't an object or a node"); if (type == Type::ObjectType) { return CheckCopyOnWrite(AZStd::get(m_value))->m_values; } else { - return AZStd::get(m_value).GetMutableProperties()->m_values; + return CheckCopyOnWrite(AZStd::get(m_value))->GetProperties(); } } @@ -301,14 +313,15 @@ namespace AZ::Dom { const Type type = GetType(); AZ_Assert( - type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a non-array value"); + type == Type::ArrayType || type == Type::NodeType, + "AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or a node"); if (type == Type::ObjectType) { return AZStd::get(m_value)->m_values; } else { - return AZStd::get(m_value).GetChildren()->m_values; + return AZStd::get(m_value)->GetChildren(); } } @@ -316,14 +329,15 @@ namespace AZ::Dom { const Type type = GetType(); AZ_Assert( - type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a non-array value"); + type == Type::ArrayType || type == Type::NodeType, + "AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or node"); if (type == Type::ObjectType) { return CheckCopyOnWrite(AZStd::get(m_value))->m_values; } else { - return AZStd::get(m_value).GetMutableChildren()->m_values; + return CheckCopyOnWrite(AZStd::get(m_value))->GetChildren(); } } @@ -627,6 +641,67 @@ namespace AZ::Dom return GetArrayInternal(); } + void Value::SetNode(AZ::Name name) + { + m_value = AZStd::make_shared(name); + } + + void Value::SetNode(AZStd::string_view name) + { + SetNode(AZ::Name(name)); + } + + AZ::Name Value::GetNodeName() const + { + return GetNodeInternal().GetName(); + } + + void Value::SetNodeName(AZ::Name name) + { + GetNodeInternal().SetName(name); + } + + void Value::SetNodeName(AZStd::string_view name) + { + SetNodeName(AZ::Name(name)); + } + + void Value::SetNodeValue(Value value) + { + AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: Attempted to set value for non-node type"); + Array::ContainerType& nodeChildren = GetArrayInternal(); + + // Set the first non-node child, if one is found + for (Value& entry : nodeChildren) + { + if (entry.GetType() != Type::NodeType) + { + entry = AZStd::move(value); + return; + } + } + + // Otherwise, append the value entry + nodeChildren.push_back(AZStd::move(value)); + } + + Value Value::GetNodeValue() const + { + AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: Attempted to get value for non-node type"); + const Array::ContainerType& nodeChildren = GetArrayInternal(); + + // Get the first non-node child, if one is found + for (const Value& entry : nodeChildren) + { + if (entry.GetType() != Type::NodeType) + { + return entry; + } + } + + return Value(); + } + int64_t Value::GetInt() const { switch (m_value.index()) @@ -812,9 +887,9 @@ namespace AZ::Dom result = visitor.EndArray(arrayContainer.size()); } } - else if constexpr (AZStd::is_same_v) + else if constexpr (AZStd::is_same_v) { - const Node& node = AZStd::get(m_value); + const Node& node = *AZStd::get(m_value); result = visitor.StartNode(node.GetName()); if (result.IsSuccess()) { @@ -850,204 +925,124 @@ namespace AZ::Dom return result; } - ValueWriter::ValueWriter(Value& outputValue) - : m_result(outputValue) + AZStd::unique_ptr Value::GetWriteHandler() { + return AZStd::make_unique(*this); } - VisitorFlags ValueWriter::GetVisitorFlags() const + bool Value::DeepCompareIsEqual(const Value& other) const { - return VisitorFlags::SupportsRawKeys | VisitorFlags::SupportsArrays | VisitorFlags::SupportsObjects | VisitorFlags::SupportsNodes; - } - - ValueWriter::ValueInfo::ValueInfo(Value& container) - : m_container(container) - { - } - - Visitor::Result ValueWriter::Null() - { - CurrentValue().SetNull(); - return FinishWrite(); - } - - Visitor::Result ValueWriter::Bool(bool value) - { - CurrentValue().SetBool(value); - return FinishWrite(); - } - - Visitor::Result ValueWriter::Int64(AZ::s64 value) - { - CurrentValue().SetInt(value); - return FinishWrite(); - } - - Visitor::Result ValueWriter::Uint64(AZ::u64 value) - { - CurrentValue().SetUint(value); - return FinishWrite(); - } - - Visitor::Result ValueWriter::Double(double value) - { - CurrentValue().SetDouble(value); - return FinishWrite(); - } - - Visitor::Result ValueWriter::String(AZStd::string_view value, Lifetime lifetime) - { - if (lifetime == Lifetime::Persistent) + if (m_value.index() != other.m_value.index()) { - CurrentValue().SetString(value); - } - else - { - CurrentValue().CopyFromString(value); - } - return FinishWrite(); - } - - Visitor::Result ValueWriter::StartObject() - { - CurrentValue().SetObject(); - - m_entryStack.emplace(CurrentValue()); - return VisitorSuccess(); - } - - Visitor::Result ValueWriter::EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount) - { - const char* endMethodName; - switch (containerType) - { - case Type::ObjectType: - endMethodName = "EndObject"; - break; - case Type::ArrayType: - endMethodName = "EndArray"; - break; - case Type::NodeType: - endMethodName = "EndNode"; - break; - default: - AZ_Assert(false, "Invalid container type specified"); - return VisitorFailure(VisitorErrorCode::InternalError, "AZ::Dom::ValueWriter: EndContainer called with invalid container type"); + return false; } - if (m_entryStack.empty()) - { - return VisitorFailure( - VisitorErrorCode::InternalError, - AZStd::string::format("AZ::Dom::ValueWriter: %s called without a matching call", endMethodName)); - } + return AZStd::visit( + [&](auto&& ourValue) -> bool + { + using Alternative = AZStd::decay_t; + auto&& theirValue = AZStd::get>(other.m_value); - const ValueInfo& topEntry = m_entryStack.top(); - if (topEntry.m_container.GetType() != containerType) - { - return VisitorFailure( - VisitorErrorCode::InternalError, - AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName)); - } + if constexpr (AZStd::is_same_v) + { + return true; + } + else if constexpr (AZStd::is_same_v) + { + if (ourValue == theirValue) + { + return true; + } - if (topEntry.m_attributeCount != attributeCount) - { - return VisitorFailure( - VisitorErrorCode::InternalError, - AZStd::string::format( - "AZ::Dom::ValueWriter: %s expected %llu attributes but received %llu attributes instead", endMethodName, attributeCount, - topEntry.m_attributeCount)); - } + if (ourValue->m_values.size() != theirValue->m_values.size()) + { + return false; + } - if (topEntry.m_elementCount != elementCount) - { - return VisitorFailure( - VisitorErrorCode::InternalError, - AZStd::string::format( - "AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount, - topEntry.m_elementCount)); - } + for (size_t i = 0; i < ourValue->m_values.size(); ++i) + { + const Object::EntryType& lhs = ourValue->m_values[i]; + const Object::EntryType& rhs = theirValue->m_values[i]; + if (lhs.first != rhs.first || !lhs.second.DeepCompareIsEqual(rhs.second)) + { + return false; + } + } - m_entryStack.pop(); - return FinishWrite(); - } + return true; + } + else if constexpr (AZStd::is_same_v) + { + if (ourValue == theirValue) + { + return true; + } - Visitor::Result ValueWriter::EndObject(AZ::u64 attributeCount) - { - return EndContainer(Type::ObjectType, attributeCount, 0); - } + if (ourValue->m_values.size() != theirValue->m_values.size()) + { + return false; + } - Visitor::Result ValueWriter::Key(AZ::Name key) - { - AZ_Assert(!m_entryStack.empty(), "Attempmted to push a key with no object"); - AZ_Assert(!m_entryStack.top().m_container.IsArray(), "Attempted to push a key to an array"); - m_entryStack.top().m_key = key; - return VisitorSuccess(); - } + for (size_t i = 0; i < ourValue->m_values.size(); ++i) + { + const Value& lhs = ourValue->m_values[i]; + const Value& rhs = theirValue->m_values[i]; + if (!lhs.DeepCompareIsEqual(rhs)) + { + return false; + } + } - Visitor::Result ValueWriter::RawKey(AZStd::string_view key, [[maybe_unused]] Lifetime lifetime) - { - return Key(AZ::Name(key)); - } + return true; + } + else if constexpr (AZStd::is_same_v) + { + if (ourValue == theirValue) + { + return true; + } - Visitor::Result ValueWriter::StartArray() - { - CurrentValue().SetArray(); + const Node& ourNode = *ourValue; + const Node& theirNode = *theirValue; - m_entryStack.emplace(CurrentValue()); - return VisitorSuccess(); - } + const Object::ContainerType& ourProperties = ourNode.GetProperties(); + const Object::ContainerType& theirProperties = theirNode.GetProperties(); - Visitor::Result ValueWriter::EndArray(AZ::u64 elementCount) - { - return EndContainer(Type::ArrayType, 0, elementCount); - } + if (ourProperties.size() != theirProperties.size()) + { + return false; + } - Visitor::Result ValueWriter::StartNode(AZ::Name name) - { - CurrentValue().SetNode(name); + for (size_t i = 0; i < ourProperties.size(); ++i) + { + const Object::EntryType& lhs = ourProperties[i]; + const Object::EntryType& rhs = theirProperties[i]; + if (lhs.first != rhs.first || !lhs.second.DeepCompareIsEqual(rhs.second)) + { + return false; + } + } - m_entryStack.emplace(CurrentValue()); - return VisitorSuccess(); - } + const Array::ContainerType& ourChildren = ourNode.GetChildren(); + const Array::ContainerType& theirChildren = theirNode.GetChildren(); - Visitor::Result ValueWriter::EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) - { - return EndContainer(Type::NodeType, attributeCount, elementCount); - } + for (size_t i = 0; i < ourChildren.size(); ++i) + { + const Value& lhs = ourChildren[i]; + const Value& rhs = theirChildren[i]; + if (!lhs.DeepCompareIsEqual(rhs)) + { + return false; + } + } - Visitor::Result ValueWriter::FinishWrite() - { - if (m_entryStack.empty()) - { - return VisitorSuccess(); - } - - Value value; - m_entryStack.top().m_value.Swap(value); - ValueInfo& newEntry = m_entryStack.top(); - - if (!newEntry.m_key.IsEmpty()) - { - newEntry.m_container.AddMember(newEntry.m_key, AZStd::move(value)); - newEntry.m_key = AZ::Name(); - ++newEntry.m_attributeCount; - } - else - { - newEntry.m_container.PushBack(AZStd::move(value)); - ++newEntry.m_elementCount; - } - - return VisitorSuccess(); - } - - Value& ValueWriter::CurrentValue() - { - if (m_entryStack.empty()) - { - return m_result; - } - return m_entryStack.top().m_value; + return true; + } + else + { + return ourValue == theirValue; + } + }, + m_value); } } // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 439971a5a0..a460274602 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -8,13 +8,13 @@ #pragma once +#include #include - #include +#include #include #include #include -#include #include namespace AZ::Dom @@ -72,25 +72,34 @@ namespace AZ::Dom class Node { public: + Node() = default; + Node(AZ::Name name); + Node(const Node&) = default; + Node(Node&&) = default; + + Node& operator=(const Node&) = default; + Node& operator=(Node&&) = default; + AZ::Name GetName() const; void SetName(AZ::Name name); - ObjectPtr GetMutableProperties(); - ConstObjectPtr GetProperties() const; + Object::ContainerType& GetProperties(); + const Object::ContainerType& GetProperties() const; - ArrayPtr GetMutableChildren(); - ConstArrayPtr GetChildren() const; - - bool operator==(const Node& rhs) const; + Array::ContainerType& GetChildren(); + const Array::ContainerType& GetChildren() const; private: AZ::Name m_name; - ArrayPtr m_array; - ObjectPtr m_object; + Object::ContainerType m_properties; + Array::ContainerType m_children; friend class Value; }; + using NodePtr = AZStd::shared_ptr; + using ConstNodePtr = AZStd::shared_ptr; + class Value { public: @@ -252,8 +261,13 @@ namespace AZ::Dom // Visitor API Visitor::Result Accept(Visitor& visitor, bool copyStrings) const; + AZStd::unique_ptr GetWriteHandler(); + + bool DeepCompareIsEqual(const Value& other) const; private: + const Node& GetNodeInternal() const; + Node& GetNodeInternal(); const Object::ContainerType& GetObjectInternal() const; Object::ContainerType& GetObjectInternal(); const Array::ContainerType& GetArrayInternal() const; @@ -284,53 +298,10 @@ namespace AZ::Dom // ArrayType ArrayPtr, // NodeType - Node, + NodePtr, // OpaqueType AZStd::any*>; ValueType m_value; }; - - class ValueWriter : public Visitor - { - public: - ValueWriter(Value& outputValue); - - VisitorFlags GetVisitorFlags() const override; - Result Null() override; - Result Bool(bool value) override; - Result Int64(AZ::s64 value) override; - Result Uint64(AZ::u64 value) override; - Result Double(double value) override; - - Result String(AZStd::string_view value, Lifetime lifetime) override; - Result StartObject() override; - Result EndObject(AZ::u64 attributeCount) override; - Result Key(AZ::Name key) override; - Result RawKey(AZStd::string_view key, Lifetime lifetime) override; - Result StartArray() override; - Result EndArray(AZ::u64 elementCount) override; - Result StartNode(AZ::Name name) override; - Result RawStartNode(AZStd::string_view name, Lifetime lifetime) override; - Result EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) override; - - private: - Result FinishWrite(); - Value& CurrentValue(); - Visitor::Result EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount); - - struct ValueInfo - { - ValueInfo(Value& container); - - KeyType m_key; - Value m_value; - Value& m_container; - AZ::u64 m_attributeCount = 0; - AZ::u64 m_elementCount = 0; - }; - - Value& m_result; - AZStd::stack m_entryStack; - }; - } // namespace AZ::Dom +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp new file mode 100644 index 0000000000..71710f543b --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -0,0 +1,218 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +namespace AZ::Dom +{ + ValueWriter::ValueWriter(Value& outputValue) + : m_result(outputValue) + { + } + + VisitorFlags ValueWriter::GetVisitorFlags() const + { + return VisitorFlags::SupportsRawKeys | VisitorFlags::SupportsArrays | VisitorFlags::SupportsObjects | VisitorFlags::SupportsNodes; + } + + ValueWriter::ValueInfo::ValueInfo(Value& container) + : m_container(container) + { + } + + Visitor::Result ValueWriter::Null() + { + CurrentValue().SetNull(); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Bool(bool value) + { + CurrentValue().SetBool(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Int64(AZ::s64 value) + { + CurrentValue().SetInt(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Uint64(AZ::u64 value) + { + CurrentValue().SetUint(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::Double(double value) + { + CurrentValue().SetDouble(value); + return FinishWrite(); + } + + Visitor::Result ValueWriter::String(AZStd::string_view value, Lifetime lifetime) + { + if (lifetime == Lifetime::Persistent) + { + CurrentValue().SetString(value); + } + else + { + CurrentValue().CopyFromString(value); + } + return FinishWrite(); + } + + Visitor::Result ValueWriter::StartObject() + { + CurrentValue().SetObject(); + + m_entryStack.emplace(CurrentValue()); + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount) + { + const char* endMethodName; + switch (containerType) + { + case Type::ObjectType: + endMethodName = "EndObject"; + break; + case Type::ArrayType: + endMethodName = "EndArray"; + break; + case Type::NodeType: + endMethodName = "EndNode"; + break; + default: + AZ_Assert(false, "Invalid container type specified"); + return VisitorFailure(VisitorErrorCode::InternalError, "AZ::Dom::ValueWriter: EndContainer called with invalid container type"); + } + + if (m_entryStack.empty()) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format("AZ::Dom::ValueWriter: %s called without a matching call", endMethodName)); + } + + const ValueInfo& topEntry = m_entryStack.top(); + if (topEntry.m_container.GetType() != containerType) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName)); + } + + if (topEntry.m_attributeCount != attributeCount) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format( + "AZ::Dom::ValueWriter: %s expected %llu attributes but received %llu attributes instead", endMethodName, attributeCount, + topEntry.m_attributeCount)); + } + + if (topEntry.m_elementCount != elementCount) + { + return VisitorFailure( + VisitorErrorCode::InternalError, + AZStd::string::format( + "AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount, + topEntry.m_elementCount)); + } + + m_entryStack.pop(); + return FinishWrite(); + } + + Visitor::Result ValueWriter::EndObject(AZ::u64 attributeCount) + { + return EndContainer(Type::ObjectType, attributeCount, 0); + } + + Visitor::Result ValueWriter::Key(AZ::Name key) + { + AZ_Assert(!m_entryStack.empty(), "Attempmted to push a key with no object"); + AZ_Assert(!m_entryStack.top().m_container.IsArray(), "Attempted to push a key to an array"); + m_entryStack.top().m_key = key; + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::RawKey(AZStd::string_view key, [[maybe_unused]] Lifetime lifetime) + { + return Key(AZ::Name(key)); + } + + Visitor::Result ValueWriter::StartArray() + { + CurrentValue().SetArray(); + + m_entryStack.emplace(CurrentValue()); + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::EndArray(AZ::u64 elementCount) + { + return EndContainer(Type::ArrayType, 0, elementCount); + } + + Visitor::Result ValueWriter::StartNode(AZ::Name name) + { + CurrentValue().SetNode(name); + + m_entryStack.emplace(CurrentValue()); + return VisitorSuccess(); + } + + Visitor::Result ValueWriter::RawStartNode(AZStd::string_view name, [[maybe_unused]] Lifetime lifetime) + { + return StartNode(AZ::Name(name)); + } + + Visitor::Result ValueWriter::EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) + { + return EndContainer(Type::NodeType, attributeCount, elementCount); + } + + Visitor::Result ValueWriter::FinishWrite() + { + if (m_entryStack.empty()) + { + return VisitorSuccess(); + } + + Value value; + m_entryStack.top().m_value.Swap(value); + ValueInfo& newEntry = m_entryStack.top(); + + if (!newEntry.m_key.IsEmpty()) + { + newEntry.m_container.AddMember(newEntry.m_key, AZStd::move(value)); + newEntry.m_key = AZ::Name(); + ++newEntry.m_attributeCount; + } + else + { + newEntry.m_container.PushBack(AZStd::move(value)); + ++newEntry.m_elementCount; + } + + return VisitorSuccess(); + } + + Value& ValueWriter::CurrentValue() + { + if (m_entryStack.empty()) + { + return m_result; + } + return m_entryStack.top().m_value; + } +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h new file mode 100644 index 0000000000..fb5f4324a6 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include + +namespace AZ::Dom +{ + class ValueWriter : public Visitor + { + public: + ValueWriter(Value& outputValue); + + VisitorFlags GetVisitorFlags() const override; + Result Null() override; + Result Bool(bool value) override; + Result Int64(AZ::s64 value) override; + Result Uint64(AZ::u64 value) override; + Result Double(double value) override; + + Result String(AZStd::string_view value, Lifetime lifetime) override; + Result StartObject() override; + Result EndObject(AZ::u64 attributeCount) override; + Result Key(AZ::Name key) override; + Result RawKey(AZStd::string_view key, Lifetime lifetime) override; + Result StartArray() override; + Result EndArray(AZ::u64 elementCount) override; + Result StartNode(AZ::Name name) override; + Result RawStartNode(AZStd::string_view name, Lifetime lifetime) override; + Result EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) override; + + private: + Result FinishWrite(); + Value& CurrentValue(); + Visitor::Result EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount); + + struct ValueInfo + { + ValueInfo(Value& container); + + KeyType m_key; + Value m_value; + Value& m_container; + AZ::u64 m_attributeCount = 0; + AZ::u64 m_elementCount = 0; + }; + + Value& m_result; + AZStd::stack m_entryStack; + }; +} // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index fa9f94505f..e17fb941b8 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -133,6 +133,8 @@ set(FILES DOM/DomUtils.h DOM/DomValue.cpp DOM/DomValue.h + DOM/DomValueWriter.cpp + DOM/DomValueWriter.h DOM/DomVisitor.cpp DOM/DomVisitor.h DOM/Backends/JSON/JsonBackend.h From a2d474cc4f30c17b7354221a1c0e55dfb20c6de4 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 9 Dec 2021 17:47:01 -0800 Subject: [PATCH 005/108] Add some intial tests Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 123 +++++++++- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 28 ++- .../AzCore/AzCore/DOM/DomValueWriter.cpp | 4 +- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 0 .../AzCore/Tests/DOM/DomValueTests.cpp | 211 ++++++++++++++++++ .../AzCore/Tests/azcoretests_files.cmake | 2 + 6 files changed, 350 insertions(+), 18 deletions(-) create mode 100644 Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp create mode 100644 Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 68a88ed35a..2f41835a37 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -97,6 +97,16 @@ namespace AZ::Dom return Value(&value); } + Value::Value(int32_t value) + : m_value(aznumeric_cast(value)) + { + } + + Value::Value(uint32_t value) + : m_value(aznumeric_cast(value)) + { + } + Value::Value(int64_t value) : m_value(value) { @@ -107,6 +117,11 @@ namespace AZ::Dom { } + Value::Value(float value) + : m_value(aznumeric_cast(value)) + { + } + Value::Value(double value) : m_value(value) { @@ -117,6 +132,40 @@ namespace AZ::Dom { } + Value::Value(Type type) + { + switch (type) + { + case Type::NullType: + // Null is the default initialized value + break; + case Type::FalseType: + m_value = false; + break; + case Type::TrueType: + m_value = true; + break; + case Type::ObjectType: + SetObject(); + break; + case Type::ArrayType: + SetArray(); + break; + case Type::StringType: + SetString(""); + break; + case Type::NumberType: + m_value = 0.0; + break; + case Type::NodeType: + SetNode(""); + break; + case Type::OpaqueType: + AZ_Assert(false, "AZ::Dom::Value may not be constructed with an empty opaque type"); + break; + } + } + Value& Value::operator=(const Value& other) { m_value = other.m_value; @@ -139,11 +188,11 @@ namespace AZ::Dom { if (IsInt()) { - return GetInt() == rhs.GetInt(); + return GetInt64() == rhs.GetInt64(); } else if (IsUint()) { - return GetUint() == rhs.GetUint(); + return GetUint64() == rhs.GetUint64(); } else { @@ -315,7 +364,7 @@ namespace AZ::Dom AZ_Assert( type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or a node"); - if (type == Type::ObjectType) + if (type == Type::ArrayType) { return AZStd::get(m_value)->m_values; } @@ -331,7 +380,7 @@ namespace AZ::Dom AZ_Assert( type == Type::ArrayType || type == Type::NodeType, "AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or node"); - if (type == Type::ObjectType) + if (type == Type::ArrayType) { return CheckCopyOnWrite(AZStd::get(m_value))->m_values; } @@ -702,7 +751,7 @@ namespace AZ::Dom return Value(); } - int64_t Value::GetInt() const + int64_t Value::GetInt64() const { switch (m_value.index()) { @@ -717,12 +766,22 @@ namespace AZ::Dom return {}; } - void Value::SetInt(int64_t value) + void Value::SetInt64(int64_t value) { m_value = value; } - uint64_t Value::GetUint() const + int32_t Value::GetInt32() const + { + return aznumeric_cast(GetInt64()); + } + + void Value::SetInt32(int32_t value) + { + m_value = aznumeric_cast(value); + } + + uint64_t Value::GetUint64() const { switch (m_value.index()) { @@ -737,11 +796,21 @@ namespace AZ::Dom return {}; } - void Value::SetUint(uint64_t value) + void Value::SetUint64(uint64_t value) { m_value = value; } + uint32_t Value::GetUint32() const + { + return aznumeric_cast(GetUint64()); + } + + void Value::SetUint32(uint32_t value) + { + m_value = aznumeric_cast(value); + } + bool Value::GetBool() const { if (IsBool()) @@ -777,6 +846,16 @@ namespace AZ::Dom m_value = value; } + float Value::GetFloat() const + { + return aznumeric_cast(GetDouble()); + } + + void Value::SetFloat(float value) + { + m_value = aznumeric_cast(value); + } + AZStd::string_view Value::GetString() const { switch (m_value.index()) @@ -861,6 +940,11 @@ namespace AZ::Dom const Object::ContainerType& object = GetObjectInternal(); for (const Object::EntryType& entry : object) { + result = visitor.Key(entry.first); + if (!result.IsSuccess()) + { + return; + } result = entry.second.Accept(visitor, copyStrings); if (!result.IsSuccess()) { @@ -896,6 +980,11 @@ namespace AZ::Dom const Object::ContainerType& object = GetObjectInternal(); for (const Object::EntryType& entry : object) { + result = visitor.Key(entry.first); + if (!result.IsSuccess()) + { + return; + } result = entry.second.Accept(visitor, copyStrings); if (!result.IsSuccess()) { @@ -932,6 +1021,16 @@ namespace AZ::Dom bool Value::DeepCompareIsEqual(const Value& other) const { + if (IsString() && other.IsString()) + { + // If we both hold the same ref counted string we don't need to do a full comparison + if (AZStd::holds_alternative>(m_value) && m_value == other.m_value) + { + return true; + } + return GetString() == other.GetString(); + } + if (m_value.index() != other.m_value.index()) { return false; @@ -1045,4 +1144,12 @@ namespace AZ::Dom }, m_value); } + + Value Value::DeepCopy(bool copyStrings) const + { + Value newValue; + AZStd::unique_ptr writer = newValue.GetWriteHandler(); + Accept(*writer, copyStrings); + return newValue; + } } // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index a460274602..61c3207ea4 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -109,10 +109,15 @@ namespace AZ::Dom Value(Value&&) noexcept; Value(AZStd::string_view string, bool copy); - explicit Value(int64_t value); - explicit Value(uint64_t value); - explicit Value(double value); - explicit Value(bool value); + Value(int32_t value); + Value(uint32_t value); + Value(int64_t value); + Value(uint64_t value); + Value(float value); + Value(double value); + Value(bool value); + + explicit Value(Type type); static Value FromOpaqueValue(AZStd::any& value); @@ -226,12 +231,16 @@ namespace AZ::Dom Value GetNodeValue() const; // int API... - int64_t GetInt() const; - void SetInt(int64_t); + int64_t GetInt64() const; + void SetInt64(int64_t); + int32_t GetInt32() const; + void SetInt32(int32_t); // uint API... - uint64_t GetUint() const; - void SetUint(uint64_t); + uint64_t GetUint64() const; + void SetUint64(uint64_t); + uint32_t GetUint32() const; + void SetUint32(uint32_t); // bool API... bool GetBool() const; @@ -240,6 +249,8 @@ namespace AZ::Dom // double API... double GetDouble() const; void SetDouble(double); + float GetFloat() const; + void SetFloat(float); // string API... AZStd::string_view GetString() const; @@ -264,6 +275,7 @@ namespace AZ::Dom AZStd::unique_ptr GetWriteHandler(); bool DeepCompareIsEqual(const Value& other) const; + Value DeepCopy(bool copyStrings = true) const; private: const Node& GetNodeInternal() const; diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index 71710f543b..a760cc5b28 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -39,13 +39,13 @@ namespace AZ::Dom Visitor::Result ValueWriter::Int64(AZ::s64 value) { - CurrentValue().SetInt(value); + CurrentValue().SetInt64(value); return FinishWrite(); } Visitor::Result ValueWriter::Uint64(AZ::u64 value) { - CurrentValue().SetUint(value); + CurrentValue().SetUint64(value); return FinishWrite(); } diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp new file mode 100644 index 0000000000..02777bf6dd --- /dev/null +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AZ::Dom::Tests +{ + class DomValueTests : public UnitTest::AllocatorsFixture + { + public: + void SetUp() override + { + UnitTest::AllocatorsFixture::SetUp(); + NameDictionary::Create(); + } + + void TearDown() override + { + m_value = Value(); + + NameDictionary::Destroy(); + UnitTest::AllocatorsFixture::TearDown(); + } + + void PerformValueChecks() + { + Value shallowCopy = m_value; + EXPECT_EQ(m_value, shallowCopy); + EXPECT_TRUE(m_value.DeepCompareIsEqual(shallowCopy)); + + Value deepCopy = m_value.DeepCopy(); + EXPECT_TRUE(m_value.DeepCompareIsEqual(deepCopy)); + } + + Value m_value; + }; + + TEST_F(DomValueTests, EmptyArray) + { + m_value.SetArray(); + + EXPECT_TRUE(m_value.IsArray()); + EXPECT_EQ(m_value.Size(), 0); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, SimpleArray) + { + m_value.SetArray(); + + for (int i = 0; i < 5; ++i) + { + m_value.PushBack(Value(i)); + EXPECT_EQ(m_value.Size(), i + 1); + EXPECT_EQ(m_value[i].GetInt32(), i); + } + + PerformValueChecks(); + } + + TEST_F(DomValueTests, NestedArrays) + { + m_value.SetArray(); + for (int j = 0; j < 5; ++j) + { + Value nestedArray(Type::ArrayType); + for (int i = 0; i < 5; ++i) + { + nestedArray.PushBack(Value(i)); + } + m_value.PushBack(AZStd::move(nestedArray)); + } + + EXPECT_EQ(m_value.Size(), 5); + for (int i = 0; i < 3; ++i) + { + EXPECT_EQ(m_value[i].Size(), 5); + for (int j = 0; j < 5; ++j) + { + EXPECT_EQ(m_value[i][j].GetInt32(), j); + } + } + + PerformValueChecks(); + } + + TEST_F(DomValueTests, EmptyObject) + { + m_value.SetObject(); + EXPECT_EQ(m_value.MemberCount(), 0); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, SimpleObject) + { + m_value.SetObject(); + for (int i = 0; i < 5; ++i) + { + AZStd::string key = AZStd::string::format("Key%i", i); + m_value.AddMember(key, Value(i)); + EXPECT_EQ(m_value.MemberCount(), i + 1); + EXPECT_EQ(m_value[key].GetInt32(), i); + } + + PerformValueChecks(); + } + + TEST_F(DomValueTests, NestedObjects) + { + m_value.SetObject(); + for (int j = 0; j < 3; ++j) + { + Value nestedObject(Type::ObjectType); + for (int i = 0; i < 5; ++i) + { + nestedObject.AddMember(AZStd::string::format("Key%i", i), Value(i)); + } + m_value.AddMember(AZStd::string::format("Obj%i", j), AZStd::move(nestedObject)); + } + + EXPECT_EQ(m_value.MemberCount(), 3); + for (int j = 0; j < 3; ++j) + { + const Value& nestedObject = m_value[AZStd::string::format("Obj%i", j)]; + EXPECT_EQ(nestedObject.MemberCount(), 5); + for (int i = 0; i < 5; ++i) + { + EXPECT_EQ(nestedObject[AZStd::string::format("Key%i", i)].GetInt32(), i); + } + } + + PerformValueChecks(); + } + + TEST_F(DomValueTests, EmptyNode) + { + m_value.SetNode("Test"); + EXPECT_EQ(m_value.GetNodeName(), AZ::Name("Test")); + EXPECT_EQ(m_value.MemberCount(), 0); + EXPECT_EQ(m_value.Size(), 0); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, SimpleNode) + { + m_value.SetNode("Test"); + + for (int i = 0; i < 10; ++i) + { + m_value.PushBack(Value(i)); + EXPECT_EQ(m_value.Size(), i + 1); + EXPECT_EQ(m_value[i].GetInt32(), i); + + if (i < 5) + { + AZ::Name key = AZ::Name(AZStd::string::format("TwoTimes%i", i)); + m_value.AddMember(key, Value(i * 2)); + EXPECT_EQ(m_value.MemberCount(), i + 1); + EXPECT_EQ(m_value[key].GetInt32(), i * 2); + } + } + + PerformValueChecks(); + } + + TEST_F(DomValueTests, NestedNodes) + { + m_value.SetNode("TopLevel"); + + const AZ::Name childNodeName("ChildNode"); + + for (int i = 0; i < 5; ++i) + { + Value childNode(Type::NodeType); + childNode.SetNodeName(childNodeName); + childNode.SetNodeValue(i); + + childNode.AddMember("foo", i); + childNode.AddMember("bar", Value("test", false)); + + m_value.PushBack(childNode); + } + + EXPECT_EQ(m_value.Size(), 5); + for (int i = 0; i < 5; ++i) + { + const Value& childNode = m_value[i]; + EXPECT_EQ(childNode.GetNodeName(), childNodeName); + EXPECT_EQ(childNode.GetNodeValue().GetInt32(), i); + EXPECT_EQ(childNode["foo"].GetInt32(), i); + EXPECT_EQ(childNode["bar"].GetString(), "test"); + } + + PerformValueChecks(); + } +} // namespace AZ::Dom::Tests diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index 0fca75e2a8..14a8bbbac0 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -215,6 +215,8 @@ set(FILES AZStd/VectorAndArray.cpp DOM/DomJsonTests.cpp DOM/DomJsonBenchmarks.cpp + DOM/DomValueTests.cpp + DOM/DomValueBenchmarks.cpp ) # Prevent the following files from being grouped in UNITY builds From 15e0bb16939b38b578cd075e297794a72fee4eac Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 9 Dec 2021 21:37:22 -0800 Subject: [PATCH 006/108] Add tests, fix missing bool in Accept and operator[] insert Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 21 ++++- .../AzCore/Tests/DOM/DomValueTests.cpp | 87 +++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 2f41835a37..675a6931f5 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -407,7 +407,22 @@ namespace AZ::Dom Value& Value::operator[](KeyType name) { - return FindMember(name)->second; + Object::ContainerType& object = GetObjectInternal(); + auto existingEntry = AZStd::find_if( + object.begin(), object.end(), + [&name](const Object::EntryType& entry) + { + return entry.first == name; + }); + if (existingEntry != object.end()) + { + return existingEntry->second; + } + else + { + object.emplace_back(name, Value()); + return object[object.size() - 1].second; + } } const Value& Value::operator[](KeyType name) const @@ -924,6 +939,10 @@ namespace AZ::Dom { result = visitor.Double(arg); } + else if constexpr (AZStd::is_same_v) + { + result = visitor.Bool(arg); + } else if constexpr (AZStd::is_same_v) { result = visitor.String(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index 02777bf6dd..75cb71248f 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace AZ::Dom::Tests { @@ -208,4 +209,90 @@ namespace AZ::Dom::Tests PerformValueChecks(); } + + TEST_F(DomValueTests, Int64) + { + m_value.SetObject(); + m_value["int64_min"] = AZStd::numeric_limits::min(); + m_value["int64_max"] = AZStd::numeric_limits::max(); + + EXPECT_EQ(m_value["int64_min"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["int64_min"].GetInt64(), AZStd::numeric_limits::min()); + EXPECT_EQ(m_value["int64_max"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["int64_max"].GetInt64(), AZStd::numeric_limits::max()); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, Uint64) + { + m_value.SetObject(); + m_value["uint64_min"] = AZStd::numeric_limits::min(); + m_value["uint64_max"] = AZStd::numeric_limits::max(); + + EXPECT_EQ(m_value["uint64_min"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["uint64_min"].GetInt64(), AZStd::numeric_limits::min()); + EXPECT_EQ(m_value["uint64_max"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["uint64_max"].GetInt64(), AZStd::numeric_limits::max()); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, Double) + { + m_value.SetObject(); + m_value["double_min"] = AZStd::numeric_limits::min(); + m_value["double_max"] = AZStd::numeric_limits::max(); + + EXPECT_EQ(m_value["double_min"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["double_min"].GetDouble(), AZStd::numeric_limits::min()); + EXPECT_EQ(m_value["double_max"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["double_max"].GetDouble(), AZStd::numeric_limits::max()); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, Null) + { + m_value.SetObject(); + m_value["null_value"] = Value(Type::NullType); + + EXPECT_EQ(m_value["null_value"].GetType(), Type::NullType); + EXPECT_EQ(m_value["null_type"], Value()); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, Bool) + { + m_value.SetObject(); + m_value["true_value"] = true; + m_value["false_value"] = false; + + EXPECT_EQ(m_value["true_value"].GetType(), Type::TrueType); + EXPECT_EQ(m_value["true_value"].GetBool(), true); + EXPECT_EQ(m_value["false_value"].GetType(), Type::FalseType); + EXPECT_EQ(m_value["false_value"].GetBool(), false); + + PerformValueChecks(); + } + + TEST_F(DomValueTests, String) + { + m_value.SetObject(); + AZStd::string stringToReference = "foo"; + m_value["no_copy"] = Value(stringToReference, false); + AZStd::string stringToCopy = "bar"; + m_value["copy"] = Value(stringToCopy, true); + + EXPECT_EQ(m_value["no_copy"].GetType(), Type::StringType); + EXPECT_EQ(m_value["no_copy"].GetString(), stringToReference); + EXPECT_EQ(m_value["no_copy"].GetString().data(), stringToReference.data()); + + EXPECT_EQ(m_value["copy"].GetType(), Type::StringType); + EXPECT_EQ(m_value["copy"].GetString(), stringToCopy); + EXPECT_NE(m_value["copy"].GetString().data(), stringToCopy.data()); + + PerformValueChecks(); + } } // namespace AZ::Dom::Tests From 947951b6c7473ccd45647e5e5c3938b5122718e7 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 9 Dec 2021 23:43:22 -0800 Subject: [PATCH 007/108] Add copy on write tests Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 34 ++++++-- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 14 ++- .../AzCore/Tests/DOM/DomValueTests.cpp | 86 +++++++++++++++++++ 3 files changed, 123 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 675a6931f5..d9398da116 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -476,7 +476,7 @@ namespace AZ::Dom return FindMember(AZ::Name(name)); } - Object::Iterator Value::FindMember(KeyType name) + Object::Iterator Value::FindMutableMember(KeyType name) { Object::ContainerType& object = GetObjectInternal(); return AZStd::find_if( @@ -487,9 +487,9 @@ namespace AZ::Dom }); } - Object::Iterator Value::FindMember(AZStd::string_view name) + Object::Iterator Value::FindMutableMember(AZStd::string_view name) { - return FindMember(AZ::Name(name)); + return FindMutableMember(AZ::Name(name)); } Value& Value::MemberReserve(size_t newCapacity) @@ -511,7 +511,7 @@ namespace AZ::Dom Value& Value::AddMember(KeyType name, const Value& value) { Object::ContainerType& object = GetObjectInternal(); - if (auto memberIt = FindMember(name); memberIt != object.end()) + if (auto memberIt = FindMutableMember(name); memberIt != object.end()) { memberIt->second = value; } @@ -530,7 +530,7 @@ namespace AZ::Dom Value& Value::AddMember(AZ::Name name, Value&& value) { Object::ContainerType& object = GetObjectInternal(); - if (auto memberIt = FindMember(name); memberIt != object.end()) + if (auto memberIt = FindMutableMember(name); memberIt != object.end()) { memberIt->second = value; } @@ -601,7 +601,7 @@ namespace AZ::Dom return EraseMember(AZ::Name(name)); } - Object::ContainerType& Value::GetObject() + Object::ContainerType& Value::GetMutableObject() { return GetObjectInternal(); } @@ -647,6 +647,16 @@ namespace AZ::Dom return GetArrayInternal()[index]; } + Value& Value::MutableAt(size_t index) + { + return operator[](index); + } + + const Value& Value::At(size_t index) const + { + return operator[](index); + } + Array::ConstIterator Value::Begin() const { return GetArrayInternal().begin(); @@ -695,7 +705,7 @@ namespace AZ::Dom return GetArrayInternal().erase(first, last); } - Array::ContainerType& Value::GetArray() + Array::ContainerType& Value::GetMutableArray() { return GetArrayInternal(); } @@ -766,6 +776,16 @@ namespace AZ::Dom return Value(); } + Node& Value::GetMutableNode() + { + return GetNodeInternal(); + } + + const Node& Value::GetNode() const + { + return GetNodeInternal(); + } + int64_t Value::GetInt64() const { switch (m_value.index()) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 61c3207ea4..39ae5a5c37 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -162,10 +162,10 @@ namespace AZ::Dom Object::Iterator MemberBegin(); Object::Iterator MemberEnd(); + Object::Iterator FindMutableMember(KeyType name); + Object::Iterator FindMutableMember(AZStd::string_view name); Object::ConstIterator FindMember(KeyType name) const; Object::ConstIterator FindMember(AZStd::string_view name) const; - Object::Iterator FindMember(KeyType name); - Object::Iterator FindMember(AZStd::string_view name); Value& MemberReserve(size_t newCapacity); bool HasMember(KeyType name) const; @@ -185,7 +185,7 @@ namespace AZ::Dom Object::Iterator EraseMember(KeyType name); Object::Iterator EraseMember(AZStd::string_view name); - Object::ContainerType& GetObject(); + Object::ContainerType& GetMutableObject(); const Object::ContainerType& GetObject() const; // Array API (also used by Node)... @@ -199,6 +199,9 @@ namespace AZ::Dom Value& operator[](size_t index); const Value& operator[](size_t index) const; + Value& MutableAt(size_t index); + const Value& At(size_t index) const; + Array::ConstIterator Begin() const; Array::ConstIterator End() const; Array::Iterator Begin(); @@ -211,7 +214,7 @@ namespace AZ::Dom Array::Iterator Erase(Array::ConstIterator pos); Array::Iterator Erase(Array::ConstIterator first, Array::ConstIterator last); - Array::ContainerType& GetArray(); + Array::ContainerType& GetMutableArray(); const Array::ContainerType& GetArray() const; // Node API (supports both object + array API, plus a dedicated NodeName)... @@ -230,6 +233,9 @@ namespace AZ::Dom //! Convenience method, gets the first non-node element of a Node. Value GetNodeValue() const; + Node& GetMutableNode(); + const Node& GetNode() const; + // int API... int64_t GetInt64() const; void SetInt64(int64_t); diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index 75cb71248f..84e2e16958 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -295,4 +295,90 @@ namespace AZ::Dom::Tests PerformValueChecks(); } + + TEST_F(DomValueTests, CopyOnWrite_Object) + { + Value v1(Type::ObjectType); + v1["foo"] = 5; + + Value nestedObject(Type::ObjectType); + v1["obj"] = nestedObject; + + Value v2 = v1; + EXPECT_EQ(&v1.GetObject(), &v2.GetObject()); + EXPECT_EQ(&v1.FindMember("obj")->second.GetObject(), &v2.FindMember("obj")->second.GetObject()); + + v2["foo"] = 0; + + EXPECT_NE(&v1.GetObject(), &v2.GetObject()); + EXPECT_EQ(&v1.FindMember("obj")->second.GetObject(), &v2.FindMember("obj")->second.GetObject()); + + v2["obj"]["key"] = true; + + EXPECT_NE(&v1.GetObject(), &v2.GetObject()); + EXPECT_NE(&v1.FindMember("obj")->second.GetObject(), &v2.FindMember("obj")->second.GetObject()); + + v2 = v1; + + EXPECT_EQ(&v1.GetObject(), &v2.GetObject()); + EXPECT_EQ(&v1.FindMember("obj")->second.GetObject(), &v2.FindMember("obj")->second.GetObject()); + } + + TEST_F(DomValueTests, CopyOnWrite_Array) + { + Value v1(Type::ArrayType); + v1.PushBack(1); + v1.PushBack(2); + + Value nestedArray(Type::ArrayType); + v1.PushBack(nestedArray); + Value v2 = v1; + + EXPECT_EQ(&v1.GetArray(), &v2.GetArray()); + EXPECT_EQ(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + + v2[0] = 0; + + EXPECT_NE(&v1.GetArray(), &v2.GetArray()); + EXPECT_EQ(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + + v2[2].PushBack(42); + + EXPECT_NE(&v1.GetArray(), &v2.GetArray()); + EXPECT_NE(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + + v2 = v1; + + EXPECT_EQ(&v1.GetArray(), &v2.GetArray()); + EXPECT_EQ(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + } + + TEST_F(DomValueTests, CopyOnWrite_Node) + { + Value v1; + v1.SetNode("TopLevel"); + + v1.PushBack(1); + v1.PushBack(2); + v1["obj"].SetNode("Nested"); + Value v2 = v1; + + EXPECT_EQ(&v1.GetNode(), &v2.GetNode()); + EXPECT_EQ(&v1["obj"].GetNode(), &v2["obj"].GetNode()); + + v2[0] = 0; + + EXPECT_NE(&v1.GetNode(), &v2.GetNode()); + EXPECT_EQ(&v1["obj"].GetNode(), &v2["obj"].GetNode()); + + v2["obj"].PushBack(42); + + EXPECT_NE(&v1.GetNode(), &v2.GetNode()); + EXPECT_NE(&v1["obj"].GetNode(), &v2["obj"].GetNode()); + + v2 = v1; + + EXPECT_EQ(&v1.GetNode(), &v2.GetNode()); + EXPECT_EQ(&v1["obj"].GetNode(), &v2["obj"].GetNode()); + } } // namespace AZ::Dom::Tests From 1af39a5c5cc26028f04e00c8504b44cfa17a4462 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Fri, 10 Dec 2021 15:57:52 -0800 Subject: [PATCH 008/108] Add benchmarks, some light optimizations like SSO Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp | 12 ++ Code/Framework/AzCore/AzCore/DOM/DomUtils.h | 3 + Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 49 ++++++-- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 37 ++++++ .../AzCore/AzCore/DOM/DomValueWriter.cpp | 51 ++++++-- .../AzCore/AzCore/DOM/DomValueWriter.h | 11 +- .../AzCore/AzCore/Memory/PoolAllocator.h | 18 +-- .../AzCore/Tests/DOM/DomJsonBenchmarks.cpp | 42 ++++++- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 117 ++++++++++++++++++ .../AzCore/Tests/DOM/DomValueTests.cpp | 19 ++- 10 files changed, 319 insertions(+), 40 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp index 2e78661518..46fa5b9bac 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp @@ -21,4 +21,16 @@ namespace AZ::Dom::Utils { return backend.ReadFromBufferInPlace(string.data(), string.size(), visitor); } + + AZ::Outcome AZ::Dom::Utils::WriteToValue(Backend::WriteCallback writeCallback) + { + Value value; + AZStd::unique_ptr writer = value.GetWriteHandler(); + Visitor::Result result = writeCallback(*writer); + if (!result.IsSuccess()) + { + return AZ::Failure(result.GetError().FormatVisitorErrorMessage()); + } + return AZ::Success(AZStd::move(value)); + } } // namespace AZ::Dom::Utils diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.h b/Code/Framework/AzCore/AzCore/DOM/DomUtils.h index 84a6eb5687..f03e5b66b8 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.h @@ -9,9 +9,12 @@ #pragma once #include +#include namespace AZ::Dom::Utils { Visitor::Result ReadFromString(Backend& backend, AZStd::string_view string, AZ::Dom::Lifetime lifetime, Visitor& visitor); Visitor::Result ReadFromStringInPlace(Backend& backend, AZStd::string& string, Visitor& visitor); + + AZ::Outcome WriteToValue(Backend::WriteCallback writeCallback); } // namespace AZ::Dom::Utils diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index d9398da116..d8650601ba 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -19,7 +19,7 @@ namespace AZ::Dom { if (refCountedPointer.use_count() > 1) { - AZStd::shared_ptr newPointer = AZStd::make_shared(); + AZStd::shared_ptr newPointer = AZStd::allocate_shared(AZStdAlloc()); *newPointer = *refCountedPointer; refCountedPointer = AZStd::move(newPointer); } @@ -71,8 +71,8 @@ namespace AZ::Dom } Value::Value(Value&& value) noexcept - : m_value(value.m_value) { + operator=(value); } Value::Value(AZStd::string_view string, bool copy) @@ -174,7 +174,7 @@ namespace AZ::Dom Value& Value::operator=(Value&& other) noexcept { - m_value = other.m_value; + m_value.swap(other.m_value); return *this; } @@ -212,7 +212,7 @@ namespace AZ::Dom void Value::Swap(Value& other) noexcept { - AZStd::swap(m_value, other.m_value); + m_value.swap(other.m_value); } Type Dom::Value::GetType() const @@ -229,14 +229,15 @@ namespace AZ::Dom return AZStd::get(m_value) ? Type::TrueType : Type::FalseType; case 5: // AZStd::string_view case 6: // AZStd::shared_ptr + case 7: // ShortStringType return Type::StringType; - case 7: // ObjectPtr + case 8: // ObjectPtr return Type::ObjectType; - case 8: // ArrayPtr + case 9: // ArrayPtr return Type::ArrayType; - case 9: // NodePtr + case 10: // NodePtr return Type::NodeType; - case 10: // AZStd::any* + case 11: // AZStd::any* return Type::OpaqueType; } AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); @@ -310,7 +311,7 @@ namespace AZ::Dom Value& Value::SetObject() { - m_value = AZStd::make_shared(); + m_value = AZStd::allocate_shared(AZStdAlloc()); return *this; } @@ -511,6 +512,7 @@ namespace AZ::Dom Value& Value::AddMember(KeyType name, const Value& value) { Object::ContainerType& object = GetObjectInternal(); + object.reserve((object.size() / Object::ReserveIncrement + 1) * Object::ReserveIncrement); if (auto memberIt = FindMutableMember(name); memberIt != object.end()) { memberIt->second = value; @@ -613,7 +615,7 @@ namespace AZ::Dom Value& Value::SetArray() { - m_value = AZStd::make_shared(); + m_value = AZStd::allocate_shared(AZStdAlloc()); return *this; } @@ -685,7 +687,9 @@ namespace AZ::Dom Value& Value::PushBack(Value value) { - GetArrayInternal().push_back(AZStd::move(value)); + Array::ContainerType& array = GetArrayInternal(); + array.reserve((array.size() / Array::ReserveIncrement + 1) * Array::ReserveIncrement); + array.push_back(AZStd::move(value)); return *this; } @@ -717,7 +721,7 @@ namespace AZ::Dom void Value::SetNode(AZ::Name name) { - m_value = AZStd::make_shared(name); + m_value = AZStd::allocate_shared(AZStdAlloc(), name); } void Value::SetNode(AZStd::string_view name) @@ -899,6 +903,11 @@ namespace AZ::Dom return AZStd::get(m_value); case 6: // AZStd::shared_ptr return *AZStd::get>(m_value); + case 7: // ShortStringType + { + const ShortStringType& ShortString = AZStd::get(m_value); + return { ShortString.m_data.data(), ShortString.m_size }; + } } AZ_Assert(false, "AZ::Dom::Value: Called GetString on a non-string type"); return {}; @@ -911,12 +920,26 @@ namespace AZ::Dom void Value::SetString(AZStd::string_view value) { + if (value.size() <= ShortStringSize) + { + ShortStringType buffer; + buffer.m_size = value.size(); + memcpy(buffer.m_data.data(), value.data(), buffer.m_size); + m_value = buffer; + } m_value = value; } void Value::CopyFromString(AZStd::string_view value) { - m_value = AZStd::make_shared(value); + if (value.size() <= ShortStringSize) + { + SetString(value); + } + else + { + m_value = AZStd::allocate_shared(AZStdAlloc(), value); + } } AZStd::any& Value::GetOpaqueValue() const diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 39ae5a5c37..4dd3bde197 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -11,11 +11,13 @@ #include #include #include +#include #include #include #include #include #include +#include namespace AZ::Dom { @@ -34,6 +36,22 @@ namespace AZ::Dom OpaqueType = 8, }; + class ValueAllocator final : public ThreadPoolBase + { + public: + AZ_CLASS_ALLOCATOR(ValueAllocator, SystemAllocator, 0); + AZ_TYPE_INFO(ValueAllocator, "{5BC8B389-72C7-459E-B502-12E74D61869F}"); + + ValueAllocator() + : ThreadPoolBase("DomValueAllocator", "Allocator for AZ::Dom::Value") + { + } + }; + + // class ValueAllocator : public Internal::PoolAllocatorHelper; using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; + static constexpr const size_t ReserveIncrement = 4; private: ContainerType m_values; @@ -59,6 +78,7 @@ namespace AZ::Dom using ContainerType = AZStd::vector; using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; + static constexpr const size_t ReserveIncrement = 8; private: ContainerType m_values; @@ -293,6 +313,18 @@ namespace AZ::Dom explicit Value(AZStd::any* opaqueValue); + static constexpr const size_t ShortStringSize = sizeof(AZStd::string_view) - sizeof(size_t); + struct ShortStringType + { + AZStd::array m_data; + size_t m_size; + + bool operator==(const ShortStringType& other) const + { + return m_size == other.m_size ? memcmp(m_data.data(), other.m_data.data(), m_size) == 0 : false; + } + }; + // If using the the copy on write model, anything stored internally as a shared_ptr will // detach and copy when doing a mutating operation if use_count() > 1. @@ -311,6 +343,7 @@ namespace AZ::Dom // StringType AZStd::string_view, AZStd::shared_ptr, + ShortStringType, // ObjectType ObjectPtr, // ArrayType @@ -320,6 +353,10 @@ namespace AZ::Dom // OpaqueType AZStd::any*>; + static_assert( + sizeof(ValueType) == sizeof(AZStd::variant), + "ValueType should have no members larger than ShortStringType"); + ValueType m_value; }; } // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index a760cc5b28..cf46a77d54 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -103,35 +103,68 @@ namespace AZ::Dom } const ValueInfo& topEntry = m_entryStack.top(); - if (topEntry.m_container.GetType() != containerType) + Value& container = topEntry.m_container; + ValueBuffer& buffer = GetValueBuffer(); + + if (container.GetType() != containerType) { return VisitorFailure( VisitorErrorCode::InternalError, AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName)); } - if (topEntry.m_attributeCount != attributeCount) + if (buffer.m_attributes.size() != attributeCount) { return VisitorFailure( VisitorErrorCode::InternalError, AZStd::string::format( "AZ::Dom::ValueWriter: %s expected %llu attributes but received %llu attributes instead", endMethodName, attributeCount, - topEntry.m_attributeCount)); + buffer.m_attributes.size())); } - if (topEntry.m_elementCount != elementCount) + if (buffer.m_elements.size() != elementCount) { return VisitorFailure( VisitorErrorCode::InternalError, AZStd::string::format( "AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount, - topEntry.m_elementCount)); + buffer.m_elements.size())); + } + if (buffer.m_attributes.size() > 0) + { + container.MemberReserve(buffer.m_attributes.size()); + for (AZStd::pair& entry : buffer.m_attributes) + { + container.AddMember(AZStd::move(entry.first), AZStd::move(entry.second)); + } + buffer.m_attributes.clear(); + } + + if(buffer.m_elements.size() > 0) + { + container.Reserve(buffer.m_elements.size()); + for (Value& entry : buffer.m_elements) + { + container.PushBack(AZStd::move(entry)); + } + buffer.m_elements.clear(); } m_entryStack.pop(); return FinishWrite(); } + ValueWriter::ValueBuffer& ValueWriter::GetValueBuffer() + { + if (m_entryStack.size() <= m_valueBuffers.size()) + { + return m_valueBuffers[m_entryStack.size() - 1]; + } + + m_valueBuffers.resize(m_entryStack.size()); + return m_valueBuffers[m_entryStack.size() - 1]; + } + Visitor::Result ValueWriter::EndObject(AZ::u64 attributeCount) { return EndContainer(Type::ObjectType, attributeCount, 0); @@ -192,16 +225,16 @@ namespace AZ::Dom m_entryStack.top().m_value.Swap(value); ValueInfo& newEntry = m_entryStack.top(); + constexpr const size_t reserveSize = 8; + if (!newEntry.m_key.IsEmpty()) { - newEntry.m_container.AddMember(newEntry.m_key, AZStd::move(value)); + GetValueBuffer().m_attributes.emplace_back(AZStd::move(newEntry.m_key), AZStd::move(value)); newEntry.m_key = AZ::Name(); - ++newEntry.m_attributeCount; } else { - newEntry.m_container.PushBack(AZStd::move(value)); - ++newEntry.m_elementCount; + GetValueBuffer().m_elements.emplace_back(AZStd::move(value)); } return VisitorSuccess(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h index fb5f4324a6..617184a926 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h @@ -48,11 +48,18 @@ namespace AZ::Dom KeyType m_key; Value m_value; Value& m_container; - AZ::u64 m_attributeCount = 0; - AZ::u64 m_elementCount = 0; }; + struct ValueBuffer + { + AZStd::vector m_elements; + AZStd::vector> m_attributes; + }; + + ValueBuffer& GetValueBuffer(); + Value& m_result; AZStd::stack m_entryStack; + AZStd::vector m_valueBuffers; }; } // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/Memory/PoolAllocator.h b/Code/Framework/AzCore/AzCore/Memory/PoolAllocator.h index 72418b3d6e..bf24f04156 100644 --- a/Code/Framework/AzCore/AzCore/Memory/PoolAllocator.h +++ b/Code/Framework/AzCore/AzCore/Memory/PoolAllocator.h @@ -25,12 +25,12 @@ namespace AZ * Template you can use to create your own thread pool allocators, as you can't inherit from ThreadPoolAllocator. * This is the case because we use tread local storage and we need separate "static" instance for each allocator. */ - template + template class PoolAllocatorHelper - : public SimpleSchemaAllocator + : public SimpleSchemaAllocator { public: - using Base = SimpleSchemaAllocator; + using Base = SimpleSchemaAllocator; using pointer_type = typename Base::pointer_type; using size_type = typename Base::size_type; using difference_type = typename Base::difference_type; @@ -140,13 +140,13 @@ namespace AZ * use PoolAllocatorThreadSafe or do the sync yourself. */ class PoolAllocator - : public Internal::PoolAllocatorHelper + : public Internal::PoolAllocatorHelper { public: AZ_CLASS_ALLOCATOR(PoolAllocator, SystemAllocator, 0); AZ_TYPE_INFO(PoolAllocator, "{D3DC61AF-0949-4BFA-87E0-62FA03A4C025}"); - using Base = Internal::PoolAllocatorHelper; + using Base = Internal::PoolAllocatorHelper; PoolAllocator(const char* name = "PoolAllocator", const char* desc = "Generic pool allocator for small objects") : Base(name, desc) @@ -154,21 +154,21 @@ namespace AZ } }; - template - using ThreadPoolBase = Internal::PoolAllocatorHelper >; + template + using ThreadPoolBase = Internal::PoolAllocatorHelper, ProfileAllocations >; /*! * Thread safe pool allocator. If you want to create your own thread pool heap, * inherit from ThreadPoolBase, as we need unique static variable for allocator type. */ class ThreadPoolAllocator final - : public ThreadPoolBase + : public ThreadPoolBase { public: AZ_CLASS_ALLOCATOR(ThreadPoolAllocator, SystemAllocator, 0); AZ_TYPE_INFO(ThreadPoolAllocator, "{05B4857F-CD06-4942-99FD-CA6A7BAE855A}"); - using Base = ThreadPoolBase; + using Base = ThreadPoolBase; ThreadPoolAllocator() : Base("PoolAllocatorThreadSafe", "Generic thread safe pool allocator for small objects") diff --git a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp index 0baa4aeb53..3e6143e805 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp @@ -8,9 +8,10 @@ #if defined(HAVE_BENCHMARK) -#include #include #include +#include +#include #include #include #include @@ -25,22 +26,26 @@ namespace Benchmark { UnitTest::AllocatorsBenchmarkFixture::SetUp(st); AZ::NameDictionary::Create(); + AZ::AllocatorInstance::Create(); } void SetUp(::benchmark::State& st) override { UnitTest::AllocatorsBenchmarkFixture::SetUp(st); AZ::NameDictionary::Create(); + AZ::AllocatorInstance::Create(); } void TearDown(::benchmark::State& st) override { + AZ::AllocatorInstance::Destroy(); AZ::NameDictionary::Destroy(); UnitTest::AllocatorsBenchmarkFixture::TearDown(st); } void TearDown(const ::benchmark::State& st) override { + AZ::AllocatorInstance::Destroy(); AZ::NameDictionary::Destroy(); UnitTest::AllocatorsBenchmarkFixture::TearDown(st); } @@ -143,6 +148,30 @@ namespace Benchmark } BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDocumentInPlace) + BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDomValueInPlace)(benchmark::State& state) + { + AZ::Dom::JsonBackend backend; + AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)); + + for (auto _ : state) + { + state.PauseTiming(); + AZStd::string payloadCopy = serializedPayload; + state.ResumeTiming(); + + auto result = AZ::Dom::Utils::WriteToValue( + [&](AZ::Dom::Visitor& visitor) + { + return AZ::Dom::Utils::ReadFromStringInPlace(backend, payloadCopy, visitor); + }); + + benchmark::DoNotOptimize(result.GetValue()); + } + + state.SetBytesProcessed(serializedPayload.size() * state.iterations()); + } + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDomValueInPlace) + BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDocument)(benchmark::State& state) { AZ::Dom::JsonBackend backend; @@ -179,6 +208,17 @@ namespace Benchmark } BENCHMARK_REGISTER_JSON(DomJsonBenchmark, JsonUtilsDeserializeToDocument) + BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonPayloadGeneration)(benchmark::State& state) + { + for (auto _ : state) + { + benchmark::DoNotOptimize(GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1))); + } + + state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations()); + } + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonPayloadGeneration) + #undef BENCHMARK_REGISTER_JSON } // namespace Benchmark diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index e69de29bb2..d11ef7f69e 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +namespace AZ::Dom::Benchmark +{ + class DomValueBenchmark : public UnitTest::AllocatorsBenchmarkFixture + { + public: + void SetUp(const ::benchmark::State& st) override + { + UnitTest::AllocatorsBenchmarkFixture::SetUp(st); + AZ::NameDictionary::Create(); + AZ::AllocatorInstance::Create(); + } + + void SetUp(::benchmark::State& st) override + { + UnitTest::AllocatorsBenchmarkFixture::SetUp(st); + AZ::NameDictionary::Create(); + AZ::AllocatorInstance::Create(); + } + + void TearDown(::benchmark::State& st) override + { + AZ::AllocatorInstance::Destroy(); + AZ::NameDictionary::Destroy(); + UnitTest::AllocatorsBenchmarkFixture::TearDown(st); + } + + void TearDown(const ::benchmark::State& st) override + { + AZ::AllocatorInstance::Destroy(); + AZ::NameDictionary::Destroy(); + UnitTest::AllocatorsBenchmarkFixture::TearDown(st); + } + + Value GenerateDomBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength) + { + Value root(Type::ObjectType); + + AZStd::string entryTemplate; + while (entryTemplate.size() < static_cast(stringTemplateLength)) + { + entryTemplate += "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor "; + } + entryTemplate.resize(stringTemplateLength); + AZStd::string buffer; + + auto createString = [&](int n) -> Value + { + return Value(AZStd::string::format("#%i %s", n, entryTemplate.c_str()), true); + }; + + auto createEntry = [&](int n) -> Value + { + Value entry(Type::ObjectType); + entry.AddMember("string", createString(n)); + entry.AddMember("int", n); + entry.AddMember("double", static_cast(n) * 0.5); + entry.AddMember("bool", n % 2 == 0); + entry.AddMember("null", Value(Type::NullType)); + return entry; + }; + + auto createArray = [&]() -> Value + { + Value array(Type::ArrayType); + for (int i = 0; i < entryCount; ++i) + { + array.PushBack(createEntry(i)); + } + return array; + }; + + auto createObject = [&]() -> Value + { + Value object; + object.SetObject(); + for (int i = 0; i < entryCount; ++i) + { + buffer = AZStd::string::format("Key%i", i); + object.AddMember(AZ::Name(buffer), createArray()); + } + return object; + }; + + root["entries"] = createObject(); + + return root; + } + }; + + BENCHMARK_DEFINE_F(DomValueBenchmark, ValuePayloadGeneration)(benchmark::State& state) + { + for (auto _ : state) + { + benchmark::DoNotOptimize(GenerateDomBenchmarkPayload(state.range(0), state.range(1))); + } + + state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations()); + } + BENCHMARK_REGISTER_F(DomValueBenchmark, ValuePayloadGeneration) + ->Args({ 10, 5 }) + ->Args({ 10, 500 }) + ->Args({ 100, 5 }) + ->Args({ 100, 500 }) + ->Unit(benchmark::kMillisecond); +} // namespace AZ::Dom::Benchmark diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index 84e2e16958..125f426e02 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -25,12 +25,14 @@ namespace AZ::Dom::Tests { UnitTest::AllocatorsFixture::SetUp(); NameDictionary::Create(); + AZ::AllocatorInstance::Create(); } void TearDown() override { m_value = Value(); + AZ::AllocatorInstance::Destroy(); NameDictionary::Destroy(); UnitTest::AllocatorsFixture::TearDown(); } @@ -279,19 +281,24 @@ namespace AZ::Dom::Tests TEST_F(DomValueTests, String) { + const char* s1 = "reference string long enough to avoid SSO"; + const char* s2 = "copy string long enough to avoid SSO"; + m_value.SetObject(); - AZStd::string stringToReference = "foo"; + AZStd::string stringToReference = s1; m_value["no_copy"] = Value(stringToReference, false); - AZStd::string stringToCopy = "bar"; + AZStd::string stringToCopy = s2; m_value["copy"] = Value(stringToCopy, true); EXPECT_EQ(m_value["no_copy"].GetType(), Type::StringType); - EXPECT_EQ(m_value["no_copy"].GetString(), stringToReference); - EXPECT_EQ(m_value["no_copy"].GetString().data(), stringToReference.data()); + EXPECT_EQ(m_value["no_copy"].GetString(), s1); + stringToReference.at(0) = 'F'; + EXPECT_NE(m_value["no_copy"].GetString(), s1); EXPECT_EQ(m_value["copy"].GetType(), Type::StringType); - EXPECT_EQ(m_value["copy"].GetString(), stringToCopy); - EXPECT_NE(m_value["copy"].GetString().data(), stringToCopy.data()); + EXPECT_EQ(m_value["copy"].GetString(), s2); + stringToCopy.at(0) = 'F'; + EXPECT_EQ(m_value["copy"].GetString(), s2); PerformValueChecks(); } From 809ee2dce96fb3464a7a5d5a020469843dcdedc0 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Fri, 10 Dec 2021 16:18:38 -0800 Subject: [PATCH 009/108] Fix "force string copy" logic Signed-off-by: Nicholas Van Sickle --- .../AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp b/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp index 17f9bfea54..bc8ac9167c 100644 --- a/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp @@ -361,7 +361,7 @@ namespace AZ::Dom::Json bool RapidJsonReadHandler::String(const char* str, rapidjson::SizeType length, bool copy) { - const Lifetime lifetime = copy ? m_stringLifetime : Lifetime::Temporary; + const Lifetime lifetime = !copy ? m_stringLifetime : Lifetime::Temporary; return CheckResult(m_visitor->String(AZStd::string_view(str, length), lifetime)); } @@ -377,7 +377,7 @@ namespace AZ::Dom::Json { m_visitor->Key(AZ::Name(key)); } - const Lifetime lifetime = copy ? m_stringLifetime : Lifetime::Temporary; + const Lifetime lifetime = !copy ? m_stringLifetime : Lifetime::Temporary; return CheckResult(m_visitor->RawKey(key, lifetime)); } From 1f2635d24bdaa200e256312df2df364b9cd26c2c Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Fri, 10 Dec 2021 16:35:26 -0800 Subject: [PATCH 010/108] Switch to the high pref heap allocator, roll back pool interface changes Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 13 ++++++------- .../AzCore/AzCore/Memory/PoolAllocator.h | 18 +++++++++--------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 4dd3bde197..9399e10d15 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -36,22 +37,20 @@ namespace AZ::Dom OpaqueType = 8, }; - class ValueAllocator final : public ThreadPoolBase + class ValueAllocator final : public SimpleSchemaAllocator { public: - AZ_CLASS_ALLOCATOR(ValueAllocator, SystemAllocator, 0); AZ_TYPE_INFO(ValueAllocator, "{5BC8B389-72C7-459E-B502-12E74D61869F}"); + using Base = SimpleSchemaAllocator; + ValueAllocator() - : ThreadPoolBase("DomValueAllocator", "Allocator for AZ::Dom::Value") + : Base("DomValueAllocator", "Allocator for AZ::Dom::Value") { + DisableOverriding(); } }; - // class ValueAllocator : public Internal::PoolAllocatorHelper + template class PoolAllocatorHelper - : public SimpleSchemaAllocator + : public SimpleSchemaAllocator { public: - using Base = SimpleSchemaAllocator; + using Base = SimpleSchemaAllocator; using pointer_type = typename Base::pointer_type; using size_type = typename Base::size_type; using difference_type = typename Base::difference_type; @@ -140,13 +140,13 @@ namespace AZ * use PoolAllocatorThreadSafe or do the sync yourself. */ class PoolAllocator - : public Internal::PoolAllocatorHelper + : public Internal::PoolAllocatorHelper { public: AZ_CLASS_ALLOCATOR(PoolAllocator, SystemAllocator, 0); AZ_TYPE_INFO(PoolAllocator, "{D3DC61AF-0949-4BFA-87E0-62FA03A4C025}"); - using Base = Internal::PoolAllocatorHelper; + using Base = Internal::PoolAllocatorHelper; PoolAllocator(const char* name = "PoolAllocator", const char* desc = "Generic pool allocator for small objects") : Base(name, desc) @@ -154,21 +154,21 @@ namespace AZ } }; - template - using ThreadPoolBase = Internal::PoolAllocatorHelper, ProfileAllocations >; + template + using ThreadPoolBase = Internal::PoolAllocatorHelper >; /*! * Thread safe pool allocator. If you want to create your own thread pool heap, * inherit from ThreadPoolBase, as we need unique static variable for allocator type. */ class ThreadPoolAllocator final - : public ThreadPoolBase + : public ThreadPoolBase { public: AZ_CLASS_ALLOCATOR(ThreadPoolAllocator, SystemAllocator, 0); AZ_TYPE_INFO(ThreadPoolAllocator, "{05B4857F-CD06-4942-99FD-CA6A7BAE855A}"); - using Base = ThreadPoolBase; + using Base = ThreadPoolBase; ThreadPoolAllocator() : Base("PoolAllocatorThreadSafe", "Generic thread safe pool allocator for small objects") From 5da5ff90670c5260019989de8881d5e67b96ca4c Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Fri, 10 Dec 2021 17:13:23 -0800 Subject: [PATCH 011/108] Removed file size limit on .shadervariantlist files. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp | 4 ++-- Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 5eaa0d9ddb..8dc67bb3d1 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -241,7 +241,7 @@ namespace AZ { // Need to get the name of the shader file from the template so that we can preprocess the shader data and setup // source file dependencies. - if (!RPI::JsonUtils::LoadObjectFromFile(variantListFullPath, shaderVariantList)) + if (!RPI::JsonUtils::LoadObjectFromFile(variantListFullPath, shaderVariantList, AZStd::numeric_limits::max())) { AZ_Error(ShaderVariantAssetBuilderName, false, "Failed to parse Shader Variant List Descriptor JSON from [%s]", variantListFullPath.c_str()); return LoadResult{LoadResult::Code::Error}; @@ -635,7 +635,7 @@ namespace AZ AzFramework::StringFunc::Path::ConstructFull(request.m_watchFolder.data(), request.m_sourceFile.data(), variantListFullPath, true); RPI::ShaderVariantListSourceData shaderVariantListDescriptor; - if (!RPI::JsonUtils::LoadObjectFromFile(variantListFullPath, shaderVariantListDescriptor)) + if (!RPI::JsonUtils::LoadObjectFromFile(variantListFullPath, shaderVariantListDescriptor, AZStd::numeric_limits::max())) { AZ_Assert(false, "Failed to parse Shader Variant List Descriptor JSON [%s]", variantListFullPath.c_str()); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h index 4715acd64c..9f4cdcf31b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/JsonUtils.h @@ -29,7 +29,7 @@ namespace AZ //! Loads serialized object data from a json file at the specified path //! Errors will be reported using AZ trace template - bool LoadObjectFromFile(const AZStd::string& path, ObjectType& objectData); + bool LoadObjectFromFile(const AZStd::string& path, ObjectType& objectData, size_t maxFileSize = DefaultMaxFileSize); //! Saves serialized object data to a json file at the specified path //! Errors will be reported using AZ trace @@ -39,11 +39,11 @@ namespace AZ // Definitions... template - bool LoadObjectFromFile(const AZStd::string& path, ObjectType& objectData) + bool LoadObjectFromFile(const AZStd::string& path, ObjectType& objectData, size_t maxFileSize) { objectData = ObjectType(); - auto loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(path, DefaultMaxFileSize); + auto loadOutcome = AZ::JsonSerializationUtils::ReadJsonFile(path, maxFileSize); if (!loadOutcome.IsSuccess()) { AZ_Error("AZ::RPI::JsonUtils", false, "%s", loadOutcome.GetError().c_str()); From c53c97cf5f80bda645654cc4613be86a9eccc373 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Sat, 11 Dec 2021 15:54:57 -0800 Subject: [PATCH 012/108] Add another round of benchmarks Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 12 +- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 2 + .../AzCore/AzCore/DOM/DomValueWriter.cpp | 6 + .../AzCore/AzCore/DOM/DomValueWriter.h | 1 + .../AzCore/AzCore/DOM/DomVisitor.cpp | 5 + Code/Framework/AzCore/AzCore/DOM/DomVisitor.h | 2 + .../AzCore/Tests/DOM/DomJsonBenchmarks.cpp | 86 ++++++++++++-- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 110 +++++++++++++++++- 8 files changed, 210 insertions(+), 14 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index d8650601ba..ed4488267a 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -61,6 +61,11 @@ namespace AZ::Dom return m_children; } + Value::Value(AZStd::shared_ptr string) + : m_value(string) + { + } + Value::Value() { } @@ -895,6 +900,11 @@ namespace AZ::Dom m_value = aznumeric_cast(value); } + void Value::SetString(AZStd::shared_ptr string) + { + m_value = string; + } + AZStd::string_view Value::GetString() const { switch (m_value.index()) @@ -992,7 +1002,7 @@ namespace AZ::Dom } else if constexpr (AZStd::is_same_v>) { - result = visitor.String(*arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); + result = visitor.RefCountedString(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); } else if constexpr (AZStd::is_same_v) { diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 9399e10d15..ac6a9d0c51 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -127,6 +127,7 @@ namespace AZ::Dom Value(const Value&); Value(Value&&) noexcept; Value(AZStd::string_view string, bool copy); + Value(AZStd::shared_ptr string); Value(int32_t value); Value(uint32_t value); @@ -281,6 +282,7 @@ namespace AZ::Dom AZStd::string_view GetString() const; size_t GetStringLength() const; void SetString(AZStd::string_view); + void SetString(AZStd::shared_ptr); void CopyFromString(AZStd::string_view); // opaque type API... diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index cf46a77d54..a8cc1f3947 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -68,6 +68,12 @@ namespace AZ::Dom return FinishWrite(); } + Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr value, [[maybe_unused]] Lifetime lifetime) + { + CurrentValue().SetString(value); + return FinishWrite(); + } + Visitor::Result ValueWriter::StartObject() { CurrentValue().SetObject(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h index 617184a926..4c1d5a26ee 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h @@ -26,6 +26,7 @@ namespace AZ::Dom Result Double(double value) override; Result String(AZStd::string_view value, Lifetime lifetime) override; + Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) override; Result StartObject() override; Result EndObject(AZ::u64 attributeCount) override; Result Key(AZ::Name key) override; diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp index ad314da385..af64c4cea8 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp @@ -105,6 +105,11 @@ namespace AZ::Dom return VisitorSuccess(); } + Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) + { + return String(*value, lifetime); + } + Visitor::Result Visitor::OpaqueValue([[maybe_unused]] const OpaqueType& value, [[maybe_unused]] Lifetime lifetime) { if (!SupportsOpaqueValues()) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h index bbe78131c3..3439a566e2 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace AZ::Dom { @@ -170,6 +171,7 @@ namespace AZ::Dom //! Operates on a string value. As strings are a reference type. //! Storage semantics are provided to indicate where the value may be stored persistently or requires a copy. virtual Result String(AZStd::string_view value, Lifetime lifetime); + virtual Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime); //! Operates on an opaque value. As opaque values are a reference type, storage semantics are provided to //! indicate where the value may be stored persistently or requires a copy. //! The base implementation of OpaqueValue rejects the operation, as opaque values are meant for special diff --git a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp index 3e6143e805..98e62f4aa6 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp @@ -50,7 +50,7 @@ namespace Benchmark UnitTest::AllocatorsBenchmarkFixture::TearDown(st); } - AZStd::string GenerateDomJsonBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength) + rapidjson::Document GenerateDomJsonBenchmarkDocument(int64_t entryCount, int64_t stringTemplateLength) { rapidjson::Document document; document.SetObject(); @@ -108,6 +108,13 @@ namespace Benchmark document.SetObject(); document.AddMember("entries", createObject(), document.GetAllocator()); + return document; + } + + AZStd::string GenerateDomJsonBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength) + { + rapidjson::Document document = GenerateDomJsonBenchmarkDocument(entryCount, stringTemplateLength); + AZStd::string serializedJson; auto result = AZ::JsonSerializationUtils::WriteJsonString(document, serializedJson); AZ_Assert(result.IsSuccess(), "Failed to serialize generated JSON"); @@ -124,7 +131,7 @@ namespace Benchmark ->Args({ 100, 500 }) \ ->Unit(benchmark::kMillisecond); - BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDocumentInPlace)(benchmark::State& state) + BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToRapidjsonInPlace)(benchmark::State& state) { AZ::Dom::JsonBackend backend; AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)); @@ -146,9 +153,9 @@ namespace Benchmark state.SetBytesProcessed(serializedPayload.size() * state.iterations()); } - BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDocumentInPlace) + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToRapidjsonInPlace) - BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDomValueInPlace)(benchmark::State& state) + BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToAzDomValueInPlace)(benchmark::State& state) { AZ::Dom::JsonBackend backend; AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)); @@ -170,9 +177,9 @@ namespace Benchmark state.SetBytesProcessed(serializedPayload.size() * state.iterations()); } - BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDomValueInPlace) + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToAzDomValueInPlace) - BENCHMARK_DEFINE_F(DomJsonBenchmark, DomDeserializeToDocument)(benchmark::State& state) + BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToRapidjson)(benchmark::State& state) { AZ::Dom::JsonBackend backend; AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)); @@ -190,9 +197,29 @@ namespace Benchmark state.SetBytesProcessed(serializedPayload.size() * state.iterations()); } - BENCHMARK_REGISTER_JSON(DomJsonBenchmark, DomDeserializeToDocument) + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToRapidjson) - BENCHMARK_DEFINE_F(DomJsonBenchmark, JsonUtilsDeserializeToDocument)(benchmark::State& state) + BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToAzDomValue)(benchmark::State& state) + { + AZ::Dom::JsonBackend backend; + AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)); + + for (auto _ : state) + { + auto result = AZ::Dom::Utils::WriteToValue( + [&](AZ::Dom::Visitor& visitor) + { + return AZ::Dom::Utils::ReadFromString(backend, serializedPayload, AZ::Dom::Lifetime::Temporary, visitor); + }); + + benchmark::DoNotOptimize(result.GetValue()); + } + + state.SetBytesProcessed(serializedPayload.size() * state.iterations()); + } + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToAzDomValue) + + BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonDeserializeToRapidjson)(benchmark::State& state) { AZ::Dom::JsonBackend backend; AZStd::string serializedPayload = GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)); @@ -206,9 +233,9 @@ namespace Benchmark state.SetBytesProcessed(serializedPayload.size() * state.iterations()); } - BENCHMARK_REGISTER_JSON(DomJsonBenchmark, JsonUtilsDeserializeToDocument) + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonDeserializeToRapidjson) - BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonPayloadGeneration)(benchmark::State& state) + BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonMakeComplexObject)(benchmark::State& state) { for (auto _ : state) { @@ -217,7 +244,44 @@ namespace Benchmark state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations()); } - BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonPayloadGeneration) + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonMakeComplexObject) + + BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonLookupMemberByString)(benchmark::State& state) + { + rapidjson::Document document(rapidjson::kObjectType); + AZStd::vector keys; + for (int64_t i = 0; i < state.range(0); ++i) + { + AZStd::string key(AZStd::string::format("key%" PRId64, i)); + keys.push_back(key); + document.AddMember(rapidjson::Value(key.data(), static_cast(key.size()), document.GetAllocator()), rapidjson::Value(i), document.GetAllocator()); + } + + for (auto _ : state) + { + for (const AZStd::string& key : keys) + { + benchmark::DoNotOptimize(document.FindMember(key.data())); + } + } + + state.SetItemsProcessed(state.iterations() * state.range(0)); + } + BENCHMARK_REGISTER_F(DomJsonBenchmark, RapidjsonLookupMemberByString)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonDeepCopy)(benchmark::State& state) + { + rapidjson::Document original = GenerateDomJsonBenchmarkDocument(state.range(0), state.range(1)); + + for (auto _ : state) + { + rapidjson::Document copy; + original.Accept(copy); + } + + state.SetItemsProcessed(state.iterations()); + } + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonDeepCopy) #undef BENCHMARK_REGISTER_JSON } // namespace Benchmark diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index d11ef7f69e..e3a0db594c 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace AZ::Dom::Benchmark { @@ -99,7 +100,7 @@ namespace AZ::Dom::Benchmark } }; - BENCHMARK_DEFINE_F(DomValueBenchmark, ValuePayloadGeneration)(benchmark::State& state) + BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueMakeComplexObject)(benchmark::State& state) { for (auto _ : state) { @@ -108,10 +109,115 @@ namespace AZ::Dom::Benchmark state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations()); } - BENCHMARK_REGISTER_F(DomValueBenchmark, ValuePayloadGeneration) + BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueMakeComplexObject) ->Args({ 10, 5 }) ->Args({ 10, 500 }) ->Args({ 100, 5 }) ->Args({ 100, 500 }) ->Unit(benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueShallowCopy)(benchmark::State& state) + { + Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + + for (auto _ : state) + { + Value copy = original; + benchmark::DoNotOptimize(copy); + } + + state.SetItemsProcessed(state.iterations()); + } + BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueShallowCopy) + ->Args({ 10, 5 }) + ->Args({ 10, 500 }) + ->Args({ 100, 5 }) + ->Args({ 100, 500 }) + ->Unit(benchmark::kNanosecond); + + BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueShallowCopyAndMutate)(benchmark::State& state) + { + Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + + for (auto _ : state) + { + Value copy = original; + copy["entries"]["Key0"].PushBack(42); + benchmark::DoNotOptimize(copy); + } + + state.SetItemsProcessed(state.iterations()); + } + BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueShallowCopyAndMutate) + ->Args({ 10, 5 }) + ->Args({ 10, 500 }) + ->Args({ 100, 5 }) + ->Args({ 100, 500 }) + ->Unit(benchmark::kNanosecond); + + BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueDeepCopy)(benchmark::State& state) + { + Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); + + for (auto _ : state) + { + Value copy = original.DeepCopy(); + benchmark::DoNotOptimize(copy); + } + + state.SetItemsProcessed(state.iterations()); + } + BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueDeepCopy) + ->Args({ 10, 5 }) + ->Args({ 10, 500 }) + ->Args({ 100, 5 }) + ->Args({ 100, 500 }) + ->Unit(benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByName)(benchmark::State& state) + { + Value value(Type::ObjectType); + AZStd::vector keys; + for (int64_t i = 0; i < state.range(0); ++i) + { + AZ::Name key(AZStd::string::format("key%" PRId64, i)); + keys.push_back(key); + value[key] = i; + } + + for (auto _ : state) + { + for (const AZ::Name& key : keys) + { + benchmark::DoNotOptimize(value[key]); + } + } + + state.SetItemsProcessed(state.iterations() * state.range(0)); + } + BENCHMARK_REGISTER_F(DomValueBenchmark, LookupMemberByName)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByString)(benchmark::State& state) + { + Value value(Type::ObjectType); + AZStd::vector keys; + for (int64_t i = 0; i < state.range(0); ++i) + { + AZStd::string key(AZStd::string::format("key%" PRId64, i)); + keys.push_back(key); + value[key] = i; + } + + for (auto _ : state) + { + for (const AZStd::string& key : keys) + { + benchmark::DoNotOptimize(value[key]); + } + } + + state.SetItemsProcessed(state.iterations() * state.range(0)); + } + BENCHMARK_REGISTER_F(DomValueBenchmark, LookupMemberByString)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); + } // namespace AZ::Dom::Benchmark From cc120c772cab1ba8a601ca063a85d7e9838b00c2 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Sun, 12 Dec 2021 12:58:52 -0800 Subject: [PATCH 013/108] Add RapidjsonCopyAndMutate to compare w/ shallow copy Signed-off-by: Nicholas Van Sickle --- .../AzCore/Tests/DOM/DomJsonBenchmarks.cpp | 20 ++++++++++++++++++- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp index 98e62f4aa6..477802dc37 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp @@ -276,13 +276,31 @@ namespace Benchmark for (auto _ : state) { rapidjson::Document copy; - original.Accept(copy); + copy.CopyFrom(original, copy.GetAllocator(), true); + benchmark::DoNotOptimize(copy); } state.SetItemsProcessed(state.iterations()); } + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonDeepCopy) + BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonCopyAndMutate)(benchmark::State& state) + { + rapidjson::Document original = GenerateDomJsonBenchmarkDocument(state.range(0), state.range(1)); + + for (auto _ : state) + { + rapidjson::Document copy; + copy.CopyFrom(original, copy.GetAllocator(), true); + copy["entries"]["Key0"].PushBack(42, copy.GetAllocator()); + benchmark::DoNotOptimize(copy); + } + + state.SetItemsProcessed(state.iterations()); + } + BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonCopyAndMutate) + #undef BENCHMARK_REGISTER_JSON } // namespace Benchmark diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index e3a0db594c..3e02eaff2e 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -135,7 +135,7 @@ namespace AZ::Dom::Benchmark ->Args({ 100, 500 }) ->Unit(benchmark::kNanosecond); - BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueShallowCopyAndMutate)(benchmark::State& state) + BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueCopyAndMutate)(benchmark::State& state) { Value original = GenerateDomBenchmarkPayload(state.range(0), state.range(1)); @@ -148,7 +148,7 @@ namespace AZ::Dom::Benchmark state.SetItemsProcessed(state.iterations()); } - BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueShallowCopyAndMutate) + BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueCopyAndMutate) ->Args({ 10, 5 }) ->Args({ 10, 500 }) ->Args({ 100, 5 }) From d9ac3c21208442916f3345c01e73306a722beb82 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Sun, 12 Dec 2021 13:56:10 -0800 Subject: [PATCH 014/108] Tidy up Type enum Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 82 +++++++++---------- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 18 ++-- .../AzCore/AzCore/DOM/DomValueWriter.cpp | 12 +-- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 12 +-- .../AzCore/Tests/DOM/DomValueTests.cpp | 38 ++++----- 5 files changed, 81 insertions(+), 81 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index ed4488267a..59e21a7d8b 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -141,31 +141,31 @@ namespace AZ::Dom { switch (type) { - case Type::NullType: + case Type::Null: // Null is the default initialized value break; - case Type::FalseType: + case Type::False: m_value = false; break; - case Type::TrueType: + case Type::True: m_value = true; break; - case Type::ObjectType: + case Type::Object: SetObject(); break; - case Type::ArrayType: + case Type::Array: SetArray(); break; - case Type::StringType: + case Type::String: SetString(""); break; - case Type::NumberType: + case Type::Number: m_value = 0.0; break; - case Type::NodeType: + case Type::Node: SetNode(""); break; - case Type::OpaqueType: + case Type::Opaque: AZ_Assert(false, "AZ::Dom::Value may not be constructed with an empty opaque type"); break; } @@ -225,43 +225,43 @@ namespace AZ::Dom switch (m_value.index()) { case 0: // AZStd::monostate - return Type::NullType; + return Type::Null; case 1: // int64_t case 2: // uint64_t case 3: // double - return Type::NumberType; + return Type::Number; case 4: // bool - return AZStd::get(m_value) ? Type::TrueType : Type::FalseType; + return AZStd::get(m_value) ? Type::True : Type::False; case 5: // AZStd::string_view case 6: // AZStd::shared_ptr case 7: // ShortStringType - return Type::StringType; + return Type::String; case 8: // ObjectPtr - return Type::ObjectType; + return Type::Object; case 9: // ArrayPtr - return Type::ArrayType; + return Type::Array; case 10: // NodePtr - return Type::NodeType; + return Type::Node; case 11: // AZStd::any* - return Type::OpaqueType; + return Type::Opaque; } AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); - return Type::NullType; + return Type::Null; } bool Value::IsNull() const { - return GetType() == Type::NullType; + return GetType() == Type::Null; } bool Value::IsFalse() const { - return GetType() == Type::FalseType; + return GetType() == Type::False; } bool Value::IsTrue() const { - return GetType() == Type::TrueType; + return GetType() == Type::True; } bool Value::IsBool() const @@ -271,27 +271,27 @@ namespace AZ::Dom bool Value::IsNode() const { - return GetType() == Type::NodeType; + return GetType() == Type::Node; } bool Value::IsObject() const { - return GetType() == Type::ObjectType; + return GetType() == Type::Object; } bool Value::IsArray() const { - return GetType() == Type::ArrayType; + return GetType() == Type::Array; } bool Value::IsOpaqueValue() const { - return GetType() == Type::OpaqueType; + return GetType() == Type::Opaque; } bool Value::IsNumber() const { - return GetType() == Type::NumberType; + return GetType() == Type::Number; } bool Value::IsInt() const @@ -311,7 +311,7 @@ namespace AZ::Dom bool Value::IsString() const { - return GetType() == Type::StringType; + return GetType() == Type::String; } Value& Value::SetObject() @@ -322,13 +322,13 @@ namespace AZ::Dom const Node& Value::GetNodeInternal() const { - AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: attempted to retrieve a node from a non-node value"); + AZ_Assert(GetType() == Type::Node, "AZ::Dom::Value: attempted to retrieve a node from a non-node value"); return *AZStd::get(m_value); } Node& Value::GetNodeInternal() { - AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: attempted to retrieve a node from a non-node value"); + AZ_Assert(GetType() == Type::Node, "AZ::Dom::Value: attempted to retrieve a node from a non-node value"); return *CheckCopyOnWrite(AZStd::get(m_value)); } @@ -336,9 +336,9 @@ namespace AZ::Dom { const Type type = GetType(); AZ_Assert( - type == Type::ObjectType || type == Type::NodeType, + type == Type::Object || type == Type::Node, "AZ::Dom::Value: attempted to retrieve an object from a value that isn't an object or a node"); - if (type == Type::ObjectType) + if (type == Type::Object) { return AZStd::get(m_value)->m_values; } @@ -352,9 +352,9 @@ namespace AZ::Dom { const Type type = GetType(); AZ_Assert( - type == Type::ObjectType || type == Type::NodeType, + type == Type::Object || type == Type::Node, "AZ::Dom::Value: attempted to retrieve an object from a value that isn't an object or a node"); - if (type == Type::ObjectType) + if (type == Type::Object) { return CheckCopyOnWrite(AZStd::get(m_value))->m_values; } @@ -368,9 +368,9 @@ namespace AZ::Dom { const Type type = GetType(); AZ_Assert( - type == Type::ArrayType || type == Type::NodeType, + type == Type::Array || type == Type::Node, "AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or a node"); - if (type == Type::ArrayType) + if (type == Type::Array) { return AZStd::get(m_value)->m_values; } @@ -384,9 +384,9 @@ namespace AZ::Dom { const Type type = GetType(); AZ_Assert( - type == Type::ArrayType || type == Type::NodeType, + type == Type::Array || type == Type::Node, "AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or node"); - if (type == Type::ArrayType) + if (type == Type::Array) { return CheckCopyOnWrite(AZStd::get(m_value))->m_values; } @@ -751,13 +751,13 @@ namespace AZ::Dom void Value::SetNodeValue(Value value) { - AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: Attempted to set value for non-node type"); + AZ_Assert(GetType() == Type::Node, "AZ::Dom::Value: Attempted to set value for non-node type"); Array::ContainerType& nodeChildren = GetArrayInternal(); // Set the first non-node child, if one is found for (Value& entry : nodeChildren) { - if (entry.GetType() != Type::NodeType) + if (entry.GetType() != Type::Node) { entry = AZStd::move(value); return; @@ -770,13 +770,13 @@ namespace AZ::Dom Value Value::GetNodeValue() const { - AZ_Assert(GetType() == Type::NodeType, "AZ::Dom::Value: Attempted to get value for non-node type"); + AZ_Assert(GetType() == Type::Node, "AZ::Dom::Value: Attempted to get value for non-node type"); const Array::ContainerType& nodeChildren = GetArrayInternal(); // Get the first non-node child, if one is found for (const Value& entry : nodeChildren) { - if (entry.GetType() != Type::NodeType) + if (entry.GetType() != Type::Node) { return entry; } diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index ac6a9d0c51..274f6b1934 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -26,15 +26,15 @@ namespace AZ::Dom enum class Type { - NullType = 0, - FalseType = 1, - TrueType = 2, - ObjectType = 3, - ArrayType = 4, - StringType = 5, - NumberType = 6, - NodeType = 7, - OpaqueType = 8, + Null = 0, + False = 1, + True = 2, + Object = 3, + Array = 4, + String = 5, + Number = 6, + Node = 7, + Opaque = 8, }; class ValueAllocator final : public SimpleSchemaAllocator diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index a8cc1f3947..3e48c097c8 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -87,13 +87,13 @@ namespace AZ::Dom const char* endMethodName; switch (containerType) { - case Type::ObjectType: + case Type::Object: endMethodName = "EndObject"; break; - case Type::ArrayType: + case Type::Array: endMethodName = "EndArray"; break; - case Type::NodeType: + case Type::Node: endMethodName = "EndNode"; break; default: @@ -173,7 +173,7 @@ namespace AZ::Dom Visitor::Result ValueWriter::EndObject(AZ::u64 attributeCount) { - return EndContainer(Type::ObjectType, attributeCount, 0); + return EndContainer(Type::Object, attributeCount, 0); } Visitor::Result ValueWriter::Key(AZ::Name key) @@ -199,7 +199,7 @@ namespace AZ::Dom Visitor::Result ValueWriter::EndArray(AZ::u64 elementCount) { - return EndContainer(Type::ArrayType, 0, elementCount); + return EndContainer(Type::Array, 0, elementCount); } Visitor::Result ValueWriter::StartNode(AZ::Name name) @@ -217,7 +217,7 @@ namespace AZ::Dom Visitor::Result ValueWriter::EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) { - return EndContainer(Type::NodeType, attributeCount, elementCount); + return EndContainer(Type::Node, attributeCount, elementCount); } Visitor::Result ValueWriter::FinishWrite() diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index 3e02eaff2e..51d2e5c10c 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -46,7 +46,7 @@ namespace AZ::Dom::Benchmark Value GenerateDomBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength) { - Value root(Type::ObjectType); + Value root(Type::Object); AZStd::string entryTemplate; while (entryTemplate.size() < static_cast(stringTemplateLength)) @@ -63,18 +63,18 @@ namespace AZ::Dom::Benchmark auto createEntry = [&](int n) -> Value { - Value entry(Type::ObjectType); + Value entry(Type::Object); entry.AddMember("string", createString(n)); entry.AddMember("int", n); entry.AddMember("double", static_cast(n) * 0.5); entry.AddMember("bool", n % 2 == 0); - entry.AddMember("null", Value(Type::NullType)); + entry.AddMember("null", Value(Type::Null)); return entry; }; auto createArray = [&]() -> Value { - Value array(Type::ArrayType); + Value array(Type::Array); for (int i = 0; i < entryCount; ++i) { array.PushBack(createEntry(i)); @@ -176,7 +176,7 @@ namespace AZ::Dom::Benchmark BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByName)(benchmark::State& state) { - Value value(Type::ObjectType); + Value value(Type::Object); AZStd::vector keys; for (int64_t i = 0; i < state.range(0); ++i) { @@ -199,7 +199,7 @@ namespace AZ::Dom::Benchmark BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByString)(benchmark::State& state) { - Value value(Type::ObjectType); + Value value(Type::Object); AZStd::vector keys; for (int64_t i = 0; i < state.range(0); ++i) { diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index 125f426e02..62f3ad7601 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -79,7 +79,7 @@ namespace AZ::Dom::Tests m_value.SetArray(); for (int j = 0; j < 5; ++j) { - Value nestedArray(Type::ArrayType); + Value nestedArray(Type::Array); for (int i = 0; i < 5; ++i) { nestedArray.PushBack(Value(i)); @@ -127,7 +127,7 @@ namespace AZ::Dom::Tests m_value.SetObject(); for (int j = 0; j < 3; ++j) { - Value nestedObject(Type::ObjectType); + Value nestedObject(Type::Object); for (int i = 0; i < 5; ++i) { nestedObject.AddMember(AZStd::string::format("Key%i", i), Value(i)); @@ -189,7 +189,7 @@ namespace AZ::Dom::Tests for (int i = 0; i < 5; ++i) { - Value childNode(Type::NodeType); + Value childNode(Type::Node); childNode.SetNodeName(childNodeName); childNode.SetNodeValue(i); @@ -218,9 +218,9 @@ namespace AZ::Dom::Tests m_value["int64_min"] = AZStd::numeric_limits::min(); m_value["int64_max"] = AZStd::numeric_limits::max(); - EXPECT_EQ(m_value["int64_min"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["int64_min"].GetType(), Type::Number); EXPECT_EQ(m_value["int64_min"].GetInt64(), AZStd::numeric_limits::min()); - EXPECT_EQ(m_value["int64_max"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["int64_max"].GetType(), Type::Number); EXPECT_EQ(m_value["int64_max"].GetInt64(), AZStd::numeric_limits::max()); PerformValueChecks(); @@ -232,9 +232,9 @@ namespace AZ::Dom::Tests m_value["uint64_min"] = AZStd::numeric_limits::min(); m_value["uint64_max"] = AZStd::numeric_limits::max(); - EXPECT_EQ(m_value["uint64_min"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["uint64_min"].GetType(), Type::Number); EXPECT_EQ(m_value["uint64_min"].GetInt64(), AZStd::numeric_limits::min()); - EXPECT_EQ(m_value["uint64_max"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["uint64_max"].GetType(), Type::Number); EXPECT_EQ(m_value["uint64_max"].GetInt64(), AZStd::numeric_limits::max()); PerformValueChecks(); @@ -246,9 +246,9 @@ namespace AZ::Dom::Tests m_value["double_min"] = AZStd::numeric_limits::min(); m_value["double_max"] = AZStd::numeric_limits::max(); - EXPECT_EQ(m_value["double_min"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["double_min"].GetType(), Type::Number); EXPECT_EQ(m_value["double_min"].GetDouble(), AZStd::numeric_limits::min()); - EXPECT_EQ(m_value["double_max"].GetType(), Type::NumberType); + EXPECT_EQ(m_value["double_max"].GetType(), Type::Number); EXPECT_EQ(m_value["double_max"].GetDouble(), AZStd::numeric_limits::max()); PerformValueChecks(); @@ -257,9 +257,9 @@ namespace AZ::Dom::Tests TEST_F(DomValueTests, Null) { m_value.SetObject(); - m_value["null_value"] = Value(Type::NullType); + m_value["null_value"] = Value(Type::Null); - EXPECT_EQ(m_value["null_value"].GetType(), Type::NullType); + EXPECT_EQ(m_value["null_value"].GetType(), Type::Null); EXPECT_EQ(m_value["null_type"], Value()); PerformValueChecks(); @@ -271,9 +271,9 @@ namespace AZ::Dom::Tests m_value["true_value"] = true; m_value["false_value"] = false; - EXPECT_EQ(m_value["true_value"].GetType(), Type::TrueType); + EXPECT_EQ(m_value["true_value"].GetType(), Type::True); EXPECT_EQ(m_value["true_value"].GetBool(), true); - EXPECT_EQ(m_value["false_value"].GetType(), Type::FalseType); + EXPECT_EQ(m_value["false_value"].GetType(), Type::False); EXPECT_EQ(m_value["false_value"].GetBool(), false); PerformValueChecks(); @@ -290,12 +290,12 @@ namespace AZ::Dom::Tests AZStd::string stringToCopy = s2; m_value["copy"] = Value(stringToCopy, true); - EXPECT_EQ(m_value["no_copy"].GetType(), Type::StringType); + EXPECT_EQ(m_value["no_copy"].GetType(), Type::String); EXPECT_EQ(m_value["no_copy"].GetString(), s1); stringToReference.at(0) = 'F'; EXPECT_NE(m_value["no_copy"].GetString(), s1); - EXPECT_EQ(m_value["copy"].GetType(), Type::StringType); + EXPECT_EQ(m_value["copy"].GetType(), Type::String); EXPECT_EQ(m_value["copy"].GetString(), s2); stringToCopy.at(0) = 'F'; EXPECT_EQ(m_value["copy"].GetString(), s2); @@ -305,10 +305,10 @@ namespace AZ::Dom::Tests TEST_F(DomValueTests, CopyOnWrite_Object) { - Value v1(Type::ObjectType); + Value v1(Type::Object); v1["foo"] = 5; - Value nestedObject(Type::ObjectType); + Value nestedObject(Type::Object); v1["obj"] = nestedObject; Value v2 = v1; @@ -333,11 +333,11 @@ namespace AZ::Dom::Tests TEST_F(DomValueTests, CopyOnWrite_Array) { - Value v1(Type::ArrayType); + Value v1(Type::Array); v1.PushBack(1); v1.PushBack(2); - Value nestedArray(Type::ArrayType); + Value nestedArray(Type::Array); v1.PushBack(nestedArray); Value v2 = v1; From e080ade885d84fa0bd0852b705dd46670b5e78bf Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Sun, 12 Dec 2021 14:20:16 -0800 Subject: [PATCH 015/108] Switch high perf allocator back on for containers, modest perf boost Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 274f6b1934..4b09068ec4 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -24,6 +24,7 @@ namespace AZ::Dom { using KeyType = AZ::Name; + //! The type of underlying value stored in a value. \see Value enum class Type { Null = 0, @@ -37,6 +38,9 @@ namespace AZ::Dom Opaque = 8, }; + //! The allocator used by Value. + //! Value heap allocates shared_ptrs for its container storage (Array / Object / Node) alongside the vector + //! contents of its container storage. class ValueAllocator final : public SimpleSchemaAllocator { public: @@ -56,7 +60,7 @@ namespace AZ::Dom class Array { public: - using ContainerType = AZStd::vector; + using ContainerType = AZStd::vector>; using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; static constexpr const size_t ReserveIncrement = 4; @@ -74,7 +78,7 @@ namespace AZ::Dom { public: using EntryType = AZStd::pair; - using ContainerType = AZStd::vector; + using ContainerType = AZStd::vector>; using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; static constexpr const size_t ReserveIncrement = 8; From 0216d0ae9f75927491feab2effa0e2273374fbc3 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Dec 2021 09:11:06 -0800 Subject: [PATCH 016/108] Clarify shared string semantics Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 16 +++++----- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 30 +++++++------------ .../AzCore/AzCore/DOM/DomValueWriter.cpp | 2 +- .../AzCore/AzCore/DOM/DomValueWriter.h | 2 +- .../AzCore/AzCore/DOM/DomVisitor.cpp | 2 +- Code/Framework/AzCore/AzCore/DOM/DomVisitor.h | 11 +++++-- 6 files changed, 30 insertions(+), 33 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 59e21a7d8b..72eb7ebadd 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -61,7 +61,7 @@ namespace AZ::Dom return m_children; } - Value::Value(AZStd::shared_ptr string) + Value::Value(AZStd::shared_ptr string) : m_value(string) { } @@ -233,7 +233,7 @@ namespace AZ::Dom case 4: // bool return AZStd::get(m_value) ? Type::True : Type::False; case 5: // AZStd::string_view - case 6: // AZStd::shared_ptr + case 6: // AZStd::shared_ptr case 7: // ShortStringType return Type::String; case 8: // ObjectPtr @@ -900,7 +900,7 @@ namespace AZ::Dom m_value = aznumeric_cast(value); } - void Value::SetString(AZStd::shared_ptr string) + void Value::SetString(AZStd::shared_ptr string) { m_value = string; } @@ -911,8 +911,8 @@ namespace AZ::Dom { case 5: // AZStd::string_view return AZStd::get(m_value); - case 6: // AZStd::shared_ptr - return *AZStd::get>(m_value); + case 6: // AZStd::shared_ptr + return *AZStd::get>(m_value); case 7: // ShortStringType { const ShortStringType& ShortString = AZStd::get(m_value); @@ -948,7 +948,7 @@ namespace AZ::Dom } else { - m_value = AZStd::allocate_shared(AZStdAlloc(), value); + m_value = AZStd::allocate_shared(AZStdAlloc(), value); } } @@ -1000,7 +1000,7 @@ namespace AZ::Dom { result = visitor.String(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); } - else if constexpr (AZStd::is_same_v>) + else if constexpr (AZStd::is_same_v>) { result = visitor.RefCountedString(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); } @@ -1096,7 +1096,7 @@ namespace AZ::Dom if (IsString() && other.IsString()) { // If we both hold the same ref counted string we don't need to do a full comparison - if (AZStd::holds_alternative>(m_value) && m_value == other.m_value) + if (AZStd::holds_alternative>(m_value) && m_value == other.m_value) { return true; } diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 4b09068ec4..1a09b9a3c8 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -39,8 +39,7 @@ namespace AZ::Dom }; //! The allocator used by Value. - //! Value heap allocates shared_ptrs for its container storage (Array / Object / Node) alongside the vector - //! contents of its container storage. + //! Value heap allocates shared_ptrs for its container storage (Array / Object / Node) alongside class ValueAllocator final : public SimpleSchemaAllocator { public: @@ -131,7 +130,7 @@ namespace AZ::Dom Value(const Value&); Value(Value&&) noexcept; Value(AZStd::string_view string, bool copy); - Value(AZStd::shared_ptr string); + Value(AZStd::shared_ptr string); Value(int32_t value); Value(uint32_t value); @@ -242,10 +241,6 @@ namespace AZ::Dom const Array::ContainerType& GetArray() const; // Node API (supports both object + array API, plus a dedicated NodeName)... - // bool CanConvertToNodeFromObject() const; - // Value& ConvertToNodeFromObject(); - // Value& ConvertToObjectFromNode(); - void SetNode(AZ::Name name); void SetNode(AZStd::string_view name); @@ -282,14 +277,14 @@ namespace AZ::Dom float GetFloat() const; void SetFloat(float); - // string API... + // String API... AZStd::string_view GetString() const; size_t GetStringLength() const; void SetString(AZStd::string_view); - void SetString(AZStd::shared_ptr); + void SetString(AZStd::shared_ptr); void CopyFromString(AZStd::string_view); - // opaque type API... + // Opaque type API... AZStd::any& GetOpaqueValue() const; //! This sets this Value to represent a value of an type that the DOM has //! no formal knowledge of. Where possible, it should be preferred to @@ -298,10 +293,10 @@ namespace AZ::Dom //! values. void SetOpaqueValue(AZStd::any&); - // null API... + // Null API... void SetNull(); - // Visitor API + // Visitor API... Visitor::Result Accept(Visitor& visitor, bool copyStrings) const; AZStd::unique_ptr GetWriteHandler(); @@ -330,12 +325,9 @@ namespace AZ::Dom } }; - // If using the the copy on write model, anything stored internally as a shared_ptr will - // detach and copy when doing a mutating operation if use_count() > 1. - - // This internal storage will not have a 1:1 mapping to the public Type, as there may be - // multiple storage options (e.g. strings being stored as non-owning string_view or - // owning shared_ptr) + //! The internal storage type for Value. + //! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes + //! for the same type in some instances, such as string storage using ValueType = AZStd::variant< // NullType AZStd::monostate, @@ -347,7 +339,7 @@ namespace AZ::Dom bool, // StringType AZStd::string_view, - AZStd::shared_ptr, + AZStd::shared_ptr, ShortStringType, // ObjectType ObjectPtr, diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index 3e48c097c8..ef99809290 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -68,7 +68,7 @@ namespace AZ::Dom return FinishWrite(); } - Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr value, [[maybe_unused]] Lifetime lifetime) + Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr value, [[maybe_unused]] Lifetime lifetime) { CurrentValue().SetString(value); return FinishWrite(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h index 4c1d5a26ee..6086ff4fe5 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h @@ -26,7 +26,7 @@ namespace AZ::Dom Result Double(double value) override; Result String(AZStd::string_view value, Lifetime lifetime) override; - Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) override; + Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) override; Result StartObject() override; Result EndObject(AZ::u64 attributeCount) override; Result Key(AZ::Name key) override; diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp index af64c4cea8..5e3d6c2882 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp @@ -105,7 +105,7 @@ namespace AZ::Dom return VisitorSuccess(); } - Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) + Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) { return String(*value, lifetime); } diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h index 3439a566e2..938df1bb5a 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h @@ -168,10 +168,15 @@ namespace AZ::Dom virtual Result Uint64(AZ::u64 value); //! Operates on a double precision, 64 bit floating point value. virtual Result Double(double value); - //! Operates on a string value. As strings are a reference type. - //! Storage semantics are provided to indicate where the value may be stored persistently or requires a copy. + //! Operates on a string value. As strings are a reference type, + //! storage semantics are provided to indicate where the value may be stored persistently or requires a copy. + //! \param lifetime Specifies the lifetime of this string - if the string has a temporary lifetime, it cannot + //! safely be stored as a reference. virtual Result String(AZStd::string_view value, Lifetime lifetime); - virtual Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime); + //! Operates on a ref-counted string value. S + //! \param lifetime Specifies the lifetime of this string. If the string has a temporary lifetime, it may not + //! be safely stored as a reference, but may still be safely stored as a ref-counted shared_ptr. + virtual Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime); //! Operates on an opaque value. As opaque values are a reference type, storage semantics are provided to //! indicate where the value may be stored persistently or requires a copy. //! The base implementation of OpaqueValue rejects the operation, as opaque values are meant for special From 8da04f15d3a7e7c1b02e0d3431fe0bd90dfb481c Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Dec 2021 11:15:02 -0800 Subject: [PATCH 017/108] Add some Value documentation Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 36 +++++++++---- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 50 +++++++++++++------ .../AzCore/Tests/DOM/DomValueTests.cpp | 16 +++--- 3 files changed, 68 insertions(+), 34 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 72eb7ebadd..dcecc67460 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -144,12 +144,9 @@ namespace AZ::Dom case Type::Null: // Null is the default initialized value break; - case Type::False: + case Type::Bool: m_value = false; break; - case Type::True: - m_value = true; - break; case Type::Object: SetObject(); break; @@ -159,8 +156,14 @@ namespace AZ::Dom case Type::String: SetString(""); break; - case Type::Number: - m_value = 0.0; + case Type::Int64: + m_value = int64_t{}; + break; + case Type::Uint64: + m_value = uint64_t{}; + break; + case Type::Double: + m_value = double{}; break; case Type::Node: SetNode(""); @@ -227,11 +230,13 @@ namespace AZ::Dom case 0: // AZStd::monostate return Type::Null; case 1: // int64_t + return Type::Int64; case 2: // uint64_t + return Type::Uint64; case 3: // double - return Type::Number; + return Type::Double; case 4: // bool - return AZStd::get(m_value) ? Type::True : Type::False; + return Type::Bool; case 5: // AZStd::string_view case 6: // AZStd::shared_ptr case 7: // ShortStringType @@ -256,12 +261,12 @@ namespace AZ::Dom bool Value::IsFalse() const { - return GetType() == Type::False; + return IsBool() && !AZStd::get(m_value); } bool Value::IsTrue() const { - return GetType() == Type::True; + return IsBool() && AZStd::get(m_value); } bool Value::IsBool() const @@ -291,7 +296,16 @@ namespace AZ::Dom bool Value::IsNumber() const { - return GetType() == Type::Number; + switch (GetType()) + { + case Type::Int64: + [[fallthrough]]; + case Type::Uint64: + [[fallthrough]]; + case Type::Double: + return true; + } + return false; } bool Value::IsInt() const diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 1a09b9a3c8..7ba73a8a4b 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -10,15 +10,15 @@ #include #include +#include #include #include -#include +#include #include #include #include #include #include -#include namespace AZ::Dom { @@ -27,19 +27,20 @@ namespace AZ::Dom //! The type of underlying value stored in a value. \see Value enum class Type { - Null = 0, - False = 1, - True = 2, - Object = 3, - Array = 4, - String = 5, - Number = 6, - Node = 7, - Opaque = 8, + Null, + Bool, + Object, + Array, + String, + Int64, + Uint64, + Double, + Node, + Opaque, }; //! The allocator used by Value. - //! Value heap allocates shared_ptrs for its container storage (Array / Object / Node) alongside + //! Value heap allocates shared_ptrs for its container storage (Array / Object / Node) alongside class ValueAllocator final : public SimpleSchemaAllocator { public: @@ -56,6 +57,7 @@ namespace AZ::Dom class Value; + //! Internal storage for a Value array: an ordered list of Values. class Array { public: @@ -73,6 +75,7 @@ namespace AZ::Dom using ArrayPtr = AZStd::shared_ptr; using ConstArrayPtr = AZStd::shared_ptr; + //! Internal storage for a Value object: an ordered list of Name / Value pairs. class Object { public: @@ -91,6 +94,9 @@ namespace AZ::Dom using ObjectPtr = AZStd::shared_ptr; using ConstObjectPtr = AZStd::shared_ptr; + //! Storage for a Value node: a named Value with both properties and children. + //! Properties are stored as an ordered list of Name / Value pairs. + //! Children are stored as an oredered list of Values. class Node { public: @@ -122,6 +128,21 @@ namespace AZ::Dom using NodePtr = AZStd::shared_ptr; using ConstNodePtr = AZStd::shared_ptr; + //! Value is a typed union of Dom types that can represent the types provdied by AZ::Dom::Visitor. + //! Value can be one of the following types: + //! - Null: a type with no value, this is the default type for Value + //! - Bool: a true or false boolean value + //! - Object: a container with an ordered list of Name/Value pairs, analagous to a JSON object + //! - Array: a container with an ordered list of Values, analagous to a JSON array + //! - String: a UTF-8 string + //! - Int64: a signed, 64-bit integer + //! - Uint64: an unsigned, 64-bit integer + //! - Double: a double precision floating point value + //! - Node: a container with a Name, an ordered list of Name/Values pairs (attributes), and an ordered list of Values (children), + //! analagous to an XML node + //! - Opaque: an arbitrary value stored in an AZStd::any. This is a non-serializable representation of an entry used only for in-memory + //! options. This is intended to be used as an intermediate value over the course of DOM transformation and as a proxy to pass through + //! types of which the DOM has no knowledge to other systems. class Value { public: @@ -327,7 +348,7 @@ namespace AZ::Dom //! The internal storage type for Value. //! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes - //! for the same type in some instances, such as string storage + //! for the same type in some instances, such as string storage using ValueType = AZStd::variant< // NullType AZStd::monostate, @@ -351,8 +372,7 @@ namespace AZ::Dom AZStd::any*>; static_assert( - sizeof(ValueType) == sizeof(AZStd::variant), - "ValueType should have no members larger than ShortStringType"); + sizeof(ValueType) == sizeof(AZStd::variant), "ValueType should have no members larger than ShortStringType"); ValueType m_value; }; diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index 62f3ad7601..b88ab746b9 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -218,9 +218,9 @@ namespace AZ::Dom::Tests m_value["int64_min"] = AZStd::numeric_limits::min(); m_value["int64_max"] = AZStd::numeric_limits::max(); - EXPECT_EQ(m_value["int64_min"].GetType(), Type::Number); + EXPECT_EQ(m_value["int64_min"].GetType(), Type::Int64); EXPECT_EQ(m_value["int64_min"].GetInt64(), AZStd::numeric_limits::min()); - EXPECT_EQ(m_value["int64_max"].GetType(), Type::Number); + EXPECT_EQ(m_value["int64_max"].GetType(), Type::Int64); EXPECT_EQ(m_value["int64_max"].GetInt64(), AZStd::numeric_limits::max()); PerformValueChecks(); @@ -232,9 +232,9 @@ namespace AZ::Dom::Tests m_value["uint64_min"] = AZStd::numeric_limits::min(); m_value["uint64_max"] = AZStd::numeric_limits::max(); - EXPECT_EQ(m_value["uint64_min"].GetType(), Type::Number); + EXPECT_EQ(m_value["uint64_min"].GetType(), Type::Uint64); EXPECT_EQ(m_value["uint64_min"].GetInt64(), AZStd::numeric_limits::min()); - EXPECT_EQ(m_value["uint64_max"].GetType(), Type::Number); + EXPECT_EQ(m_value["uint64_max"].GetType(), Type::Uint64); EXPECT_EQ(m_value["uint64_max"].GetInt64(), AZStd::numeric_limits::max()); PerformValueChecks(); @@ -246,9 +246,9 @@ namespace AZ::Dom::Tests m_value["double_min"] = AZStd::numeric_limits::min(); m_value["double_max"] = AZStd::numeric_limits::max(); - EXPECT_EQ(m_value["double_min"].GetType(), Type::Number); + EXPECT_EQ(m_value["double_min"].GetType(), Type::Double); EXPECT_EQ(m_value["double_min"].GetDouble(), AZStd::numeric_limits::min()); - EXPECT_EQ(m_value["double_max"].GetType(), Type::Number); + EXPECT_EQ(m_value["double_max"].GetType(), Type::Double); EXPECT_EQ(m_value["double_max"].GetDouble(), AZStd::numeric_limits::max()); PerformValueChecks(); @@ -271,9 +271,9 @@ namespace AZ::Dom::Tests m_value["true_value"] = true; m_value["false_value"] = false; - EXPECT_EQ(m_value["true_value"].GetType(), Type::True); + EXPECT_EQ(m_value["true_value"].GetType(), Type::Bool); EXPECT_EQ(m_value["true_value"].GetBool(), true); - EXPECT_EQ(m_value["false_value"].GetType(), Type::False); + EXPECT_EQ(m_value["false_value"].GetType(), Type::Bool); EXPECT_EQ(m_value["false_value"].GetBool(), false); PerformValueChecks(); From d044f51a8913f60666e379fe143affeaa3dc79a6 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Dec 2021 11:21:38 -0800 Subject: [PATCH 018/108] Remove DomDocument for now Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomDocument.cpp | 0 Code/Framework/AzCore/AzCore/DOM/DomDocument.h | 0 Code/Framework/AzCore/AzCore/azcore_files.cmake | 2 -- 3 files changed, 2 deletions(-) delete mode 100644 Code/Framework/AzCore/AzCore/DOM/DomDocument.cpp delete mode 100644 Code/Framework/AzCore/AzCore/DOM/DomDocument.h diff --git a/Code/Framework/AzCore/AzCore/DOM/DomDocument.cpp b/Code/Framework/AzCore/AzCore/DOM/DomDocument.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Code/Framework/AzCore/AzCore/DOM/DomDocument.h b/Code/Framework/AzCore/AzCore/DOM/DomDocument.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index e17fb941b8..ef2511bddc 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -127,8 +127,6 @@ set(FILES Debug/TraceReflection.h DOM/DomBackend.cpp DOM/DomBackend.h - DOM/DomDocument.cpp - DOM/DomDocument.h DOM/DomUtils.cpp DOM/DomUtils.h DOM/DomValue.cpp From 202226c2cb616dd62c3353ee3adfed805ae2ab60 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Dec 2021 11:31:23 -0800 Subject: [PATCH 019/108] Document short string usage Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 7ba73a8a4b..5cb67123e5 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -334,6 +334,8 @@ namespace AZ::Dom explicit Value(AZStd::any* opaqueValue); + // Determine the short string buffer size based on the size of our largest internal type (string_view) + // minus the size of the short string size field. static constexpr const size_t ShortStringSize = sizeof(AZStd::string_view) - sizeof(size_t); struct ShortStringType { @@ -348,7 +350,7 @@ namespace AZ::Dom //! The internal storage type for Value. //! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes - //! for the same type in some instances, such as string storage + //! for the same type in some instances, such as string storage. using ValueType = AZStd::variant< // NullType AZStd::monostate, From af91cea8ef25280af54c4d37dadcdb073bca50c7 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Dec 2021 11:56:53 -0800 Subject: [PATCH 020/108] Add copy-on-write note Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 5cb67123e5..ecaea3db3d 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -143,6 +143,10 @@ namespace AZ::Dom //! - Opaque: an arbitrary value stored in an AZStd::any. This is a non-serializable representation of an entry used only for in-memory //! options. This is intended to be used as an intermediate value over the course of DOM transformation and as a proxy to pass through //! types of which the DOM has no knowledge to other systems. + //! \note Value is a copy-on-write data structure and may be cheaply returned by value. Heap allocated data larger than the size of the + //! value itself (objects, arrays, and nodes) are copied by new Values only when their contents change, so care should be taken in + //! performance critical code to avoid mutation operations such as operator[] to avoid copies. It is recommended that an immutable Value + //! be explicitly be stored as a `const Value` to avoid accidental detach and copy operations. class Value { public: From 946a77e9144c582f99f024c88f7831191a1150f9 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Dec 2021 12:06:24 -0800 Subject: [PATCH 021/108] Document ValueWriter, add basic OpaqueValue handling Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp | 6 ++++++ Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h | 6 ++++++ Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp | 2 +- Code/Framework/AzCore/AzCore/DOM/DomVisitor.h | 3 +-- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index ef99809290..172f7f2a92 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -220,6 +220,12 @@ namespace AZ::Dom return EndContainer(Type::Node, attributeCount, elementCount); } + Visitor::Result ValueWriter::OpaqueValue(OpaqueType& value) + { + CurrentValue().SetOpaqueValue(value); + return FinishWrite(); + } + Visitor::Result ValueWriter::FinishWrite() { if (m_entryStack.empty()) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h index 6086ff4fe5..7430ff910b 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h @@ -13,6 +13,8 @@ namespace AZ::Dom { + //! Visitor that writes to a Value. + //! Supports all Visitor operations. class ValueWriter : public Visitor { public: @@ -36,6 +38,7 @@ namespace AZ::Dom Result StartNode(AZ::Name name) override; Result RawStartNode(AZStd::string_view name, Lifetime lifetime) override; Result EndNode(AZ::u64 attributeCount, AZ::u64 elementCount) override; + Result OpaqueValue(OpaqueType& value) override; private: Result FinishWrite(); @@ -60,7 +63,10 @@ namespace AZ::Dom ValueBuffer& GetValueBuffer(); Value& m_result; + // Stores info about the current value being processed AZStd::stack m_entryStack; + // Provides temporary storage for elements and attributes to prevent extra heap allocations + // These buffers persist to be reused even as the entry stack changes AZStd::vector m_valueBuffers; }; } // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp index 5e3d6c2882..4e13a2a95c 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp @@ -110,7 +110,7 @@ namespace AZ::Dom return String(*value, lifetime); } - Visitor::Result Visitor::OpaqueValue([[maybe_unused]] const OpaqueType& value, [[maybe_unused]] Lifetime lifetime) + Visitor::Result Visitor::OpaqueValue([[maybe_unused]] OpaqueType& value) { if (!SupportsOpaqueValues()) { diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h index 938df1bb5a..3bf1b3419b 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h @@ -181,8 +181,7 @@ namespace AZ::Dom //! indicate where the value may be stored persistently or requires a copy. //! The base implementation of OpaqueValue rejects the operation, as opaque values are meant for special //! cases with specific implementations, not generic usage. - //! Storage semantics are provided to indicate where the value may be stored persistently or requires a copy. - virtual Result OpaqueValue(const OpaqueType& value, Lifetime lifetime); + virtual Result OpaqueValue(OpaqueType& value); //! Operates on a raw value encoded as a UTF-8 string that hasn't had its type deduced. //! Visitors that support raw values (\see VisitorFlags::SupportsRawValues) may parse the raw value and //! forward it to the corresponding value call or calls of their choice. From aa9799a63b0b9c413e5f1431a299d41275648987 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 13 Dec 2021 15:05:17 -0800 Subject: [PATCH 022/108] Use the high perf allocator for DomValueWriter Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h index 7430ff910b..488535ace6 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h @@ -56,17 +56,17 @@ namespace AZ::Dom struct ValueBuffer { - AZStd::vector m_elements; - AZStd::vector> m_attributes; + Array::ContainerType m_elements; + Object::ContainerType m_attributes; }; ValueBuffer& GetValueBuffer(); Value& m_result; // Stores info about the current value being processed - AZStd::stack m_entryStack; + AZStd::stack>> m_entryStack; // Provides temporary storage for elements and attributes to prevent extra heap allocations // These buffers persist to be reused even as the entry stack changes - AZStd::vector m_valueBuffers; + AZStd::vector> m_valueBuffers; }; } // namespace AZ::Dom From 352b4ab6907eb9bf7890bd4670c34a1781d12409 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 15 Dec 2021 10:23:58 -0800 Subject: [PATCH 023/108] Make DomValue final Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index ecaea3db3d..1b69c73ecc 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -147,7 +147,7 @@ namespace AZ::Dom //! value itself (objects, arrays, and nodes) are copied by new Values only when their contents change, so care should be taken in //! performance critical code to avoid mutation operations such as operator[] to avoid copies. It is recommended that an immutable Value //! be explicitly be stored as a `const Value` to avoid accidental detach and copy operations. - class Value + class Value final { public: // Constructors... From 9b5dcf82b5972037daf9f114e79dee6618de88e7 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 16 Dec 2021 20:46:12 -0800 Subject: [PATCH 024/108] updates extend editor_entity_utils.py functionality Signed-off-by: Scott Murray --- .../editor_entity_utils.py | 200 +++++++++++++++--- 1 file changed, 172 insertions(+), 28 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index 72530325e0..b9f7576f1c 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -29,6 +29,11 @@ class EditorComponent: which also assigns self.id and self.type_id to the EditorComponent object. """ + def __init__(self, type_id): + self.type_id = type_id + self.id = None + self.property_tree = None + def get_component_name(self) -> str: """ Used to get name of component @@ -50,6 +55,9 @@ class EditorComponent: 7. prop_tree.get_container_item(path, key) :return: Property tree object of a component """ + if self.property_tree is not None: + return self.property_tree + build_prop_tree_outcome = editor.EditorComponentAPIBus( bus.Broadcast, "BuildComponentPropertyTreeEditor", self.id ) @@ -58,7 +66,114 @@ class EditorComponent: ), f"Failure: Could not build property tree of component: '{self.get_component_name()}'" prop_tree = build_prop_tree_outcome.GetValue() Report.info(prop_tree.build_paths_list()) - return prop_tree + self.property_tree = prop_tree + return self.property_tree + + def is_property_container(self, component_property_path: str) -> bool: + """ + + """ + if self.property_tree is None: + self.get_property_tree() + result = self.property_tree.is_container(component_property_path) + if not result: + Report.info(f"{self.get_component_name()}: '{component_property_path}' is not a container") + return result + + def get_container_count(self, component_property_path: str) -> int: + """ + Used to get the count of items in the container. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :return: Count of items in the container as unsigned integer + """ + if self.is_property_container(component_property_path): + container_count_outcome = self.property_tree.get_container_count(component_property_path) + assert ( + container_count_outcome.IsSuccess() + ), f"Failure: get_container_count did not return success for '{component_property_path}'" + return container_count_outcome.GetValue() + + def reset_container(self, component_property_path: str) -> bool: + """ + Used to rest a container to empty + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :return: Boolean success + """ + if self.is_property_container(component_property_path): + reset_outcome = self.property_tree.reset_container(component_property_path) + return reset_outcome.IsSuccess() + else: + return False + + def append_container_item(self, component_property_path: str, value: any) -> bool: + """ + Used to append a container item without providing an index key. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param value: Value to be set + :return: Boolean success + """ + if self.is_property_container(component_property_path): + append_outcome = self.property_tree.append_container_item(component_property_path, value) + return append_outcome.IsSuccess() + else: + return False + + def add_container_item(self, component_property_path: str, key: any, value: any) -> bool: + """ + Used to add a container item at a specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key, although this could be any unique unused key value + :param value: Value to be set + :return: Boolean success + """ + if self.is_property_container(component_property_path): + add_outcome = self.property_tree.add_container_item(component_property_path, key, value) + return add_outcome.IsSuccess() + else: + return False + + def get_container_item(self, component_property_path: str, key: any) -> any: + """ + Used to retrieve a container item value at the specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key + :return: Value stored at the key specified + """ + if self.is_property_container(component_property_path): + get_outcome = self.property_tree.get_container_item(component_property_path, key) + assert ( + get_outcome.IsSuccess() + ), f"Failure: could not get a value for {self.get_component_name()}: '{component_property_path}' [{key}]" + return get_outcome.GetValue() + else: + return None + + def remove_container_item(self, component_property_path: str, key: any) -> bool: + """ + Used to remove a container item value at the specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key + :return: Boolean success + """ + if self.is_property_container(component_property_path): + remove_outcome = self.property_tree.remove_container_item(component_property_path, key) + return remove_outcome.IsSuccess() + else: + return False + + def update_container_item(self, component_property_path: str, key: any, value: any): + """ + Used to update a container item at a specified key. In practice key should be an integer index. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :param key: Zero index integer key + :param value: Value to be set + :return: Boolean success + """ + if self.is_property_container(component_property_path): + update_outcome = self.property_tree.update_container_item(component_property_path, key, value) + return update_outcome.IsSuccess() + else: + return False def get_component_property_value(self, component_property_path: str): """ @@ -101,16 +216,25 @@ class EditorComponent: """ editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [self.id]) + def enable_component(self): + """ + used to enable the componet using its id value + """ + editor.EditorComponentAPIBus(bus.Broadcast, "EnabledComponents", [self.id]) + @staticmethod - def get_type_ids(component_names: list) -> list: + def get_type_ids(component_names: list, entity_type: str ='Game') -> list: """ Used to get type ids of given components list :param: component_names: List of components to get type ids :return: List of type ids of given components. """ + if entity_type.lower() == 'level': + entity_type = azlmbr.entity.EntityType().Level + else: + entity_type = azlmbr.entity.EntityType().Game type_ids = editor.EditorComponentAPIBus( - bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, azlmbr.entity.EntityType().Game - ) + bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, entity_type) return type_ids @@ -278,8 +402,7 @@ class EditorEntity: components = [] type_ids = EditorComponent.get_type_ids(component_names) for type_id in type_ids: - new_comp = EditorComponent() - new_comp.type_id = type_id + new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorComponentAPIBus( bus.Broadcast, "AddComponentsOfType", self.id, [type_id] ) @@ -291,6 +414,27 @@ class EditorEntity: self.components.append(new_comp) return components + def remove_component(self, component_name: str) -> None: + """ + Used to remove a component from Entity + :param component_name: String of component name to remove + :return: None + """ + self.remove_components([component_name]) + + def remove_components(self, component_names: list): + """ + Used to remove a list of components from Entity + :param component_names: List of component names to remove + :return: None + """ + type_ids = EditorComponent.get_type_ids(component_names) + for type_id in type_ids: + remove_outcome = editor.EditorComponentAPIBus(bus.Broadcast, "RemoveComponents", self.id, [type_id]) + assert ( + remove_outcome.IsSuccess() + ), f"Failure: could not remove component from '{self.get_name()}'" + def get_components_of_type(self, component_names: list) -> List[EditorComponent]: """ Used to get components of type component_name that already exists on Entity @@ -300,8 +444,7 @@ class EditorEntity: component_list = [] type_ids = EditorComponent.get_type_ids(component_names) for type_id in type_ids: - component = EditorComponent() - component.type_id = type_id + component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorComponentAPIBus( bus.Broadcast, "GetComponentOfType", self.id, type_id ) @@ -359,6 +502,21 @@ class EditorEntity: set_status = self.get_start_status() assert set_status == status_to_set, f"Failed to set start status of {desired_start_status} to {self.get_name}" + def is_locked(self) -> bool: + """ + Used to get the locked status of the entity + :return: Boolean True if locked False if not locked + """ + return editor.EditorEntityInfoRequestBus(bus.Event, "IsLocked", self.id) + + def set_lock_state(self, is_locked: bool) -> None: + """ + Sets the lock state on the object to locked or not locked. + :param is_locked: True for locking, False to unlock. + :return: None + """ + editor.EditorEntityAPIBus(bus.Event, "SetLockState", self.id, is_locked) + def delete(self) -> None: """ Used to delete the Entity. @@ -488,18 +646,6 @@ class EditorLevelEntity: EditorLevelComponentAPIBus requests. """ - @staticmethod - def get_type_ids(component_names: list) -> list: - """ - Used to get type ids of given components list for EntityType Level - :param: component_names: List of components to get type ids - :return: List of type ids of given components. - """ - type_ids = editor.EditorComponentAPIBus( - bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, azlmbr.entity.EntityType().Level - ) - return type_ids - @staticmethod def add_component(component_name: str) -> EditorComponent: """ @@ -518,10 +664,9 @@ class EditorLevelEntity: :return: List of newly added components to the level """ components = [] - type_ids = EditorLevelEntity.get_type_ids(component_names) + type_ids = EditorComponent.get_type_ids(component_names, 'level') for type_id in type_ids: - new_comp = EditorComponent() - new_comp.type_id = type_id + new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorLevelComponentAPIBus( bus.Broadcast, "AddComponentsOfType", [type_id] ) @@ -540,10 +685,9 @@ class EditorLevelEntity: :return: List of Level Component objects of given component name """ component_list = [] - type_ids = EditorLevelEntity.get_type_ids(component_names) + type_ids = EditorComponent.get_type_ids(component_names, 'level') for type_id in type_ids: - component = EditorComponent() - component.type_id = type_id + component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorLevelComponentAPIBus( bus.Broadcast, "GetComponentOfType", type_id ) @@ -562,7 +706,7 @@ class EditorLevelEntity: :param component_name: Name of component to check for :return: True, if level has specified component. Else, False """ - type_ids = EditorLevelEntity.get_type_ids([component_name]) + type_ids = EditorComponent.get_type_ids([component_name], 'level') return editor.EditorLevelComponentAPIBus(bus.Broadcast, "HasComponentOfType", type_ids[0]) @staticmethod @@ -572,5 +716,5 @@ class EditorLevelEntity: :param component_name: Name of component to check for :return: integer count of occurences of level component attached to level or zero if none are present """ - type_ids = EditorLevelEntity.get_type_ids([component_name]) + type_ids = EditorComponent.get_type_ids([component_name], 'level') return editor.EditorLevelComponentAPIBus(bus.Broadcast, "CountComponentsOfType", type_ids[0]) From 291e172f9e13285f4e5c6a90eea7740a804ab88a Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 16 Dec 2021 21:01:39 -0800 Subject: [PATCH 025/108] fixing some docstrings Signed-off-by: Scott Murray --- .../editor_python_test_tools/editor_entity_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index b9f7576f1c..58d9e30f81 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -71,7 +71,9 @@ class EditorComponent: def is_property_container(self, component_property_path: str) -> bool: """ - + Used to determine if a component property is a container. Containers are similar to a dictionary with int keys. + :param component_property_path: String of component property. (e.g. 'Settings|Visible') + :return: Boolean True if the property is a container False if it is not. """ if self.property_tree is None: self.get_property_tree() @@ -255,7 +257,7 @@ class EditorEntity: """ Entity class is used to create and interact with Editor Entities. Example: To create Editor Entity, Use the code: - test_entity = Entity.create_editor_entity("TestEntity") + test_entity = EditorEntity.create_editor_entity("TestEntity") # This creates a python object with 'test_entity' linked to entity name "TestEntity" in Editor. # To add component, use: test_entity.add_component() From bbd00adadeaf315a615b1e08259f44763a5272fb Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 20 Dec 2021 16:54:06 -0800 Subject: [PATCH 026/108] Address some AZ::Dom::Value feedback - Use a vector for shared string storage (to avoid the double heap allocation for AZStd::string) - Use a shared heap allocated any for opaque types (instead of an unsafe ref) - Add a string comparison key lookup benchmark to measure the impact of Name Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 49 ++++++++------- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 59 +++++++++---------- .../AzCore/AzCore/DOM/DomValueWriter.cpp | 2 +- .../AzCore/AzCore/DOM/DomValueWriter.h | 2 +- .../AzCore/AzCore/DOM/DomVisitor.cpp | 4 +- Code/Framework/AzCore/AzCore/DOM/DomVisitor.h | 5 +- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 29 +++++++++ 7 files changed, 91 insertions(+), 59 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index dcecc67460..3dafc02c6e 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -19,7 +19,7 @@ namespace AZ::Dom { if (refCountedPointer.use_count() > 1) { - AZStd::shared_ptr newPointer = AZStd::allocate_shared(AZStdAlloc()); + AZStd::shared_ptr newPointer = AZStd::allocate_shared(StdValueAllocator()); *newPointer = *refCountedPointer; refCountedPointer = AZStd::move(newPointer); } @@ -92,12 +92,12 @@ namespace AZ::Dom } } - Value::Value(AZStd::any* value) - : m_value(value) + Value::Value(const AZStd::any& value) + : m_value(AZStd::allocate_shared(StdValueAllocator(), value)) { } - Value Value::FromOpaqueValue(AZStd::any& value) + Value Value::FromOpaqueValue(const AZStd::any& value) { return Value(&value); } @@ -330,7 +330,7 @@ namespace AZ::Dom Value& Value::SetObject() { - m_value = AZStd::allocate_shared(AZStdAlloc()); + m_value = AZStd::allocate_shared(StdValueAllocator()); return *this; } @@ -634,7 +634,7 @@ namespace AZ::Dom Value& Value::SetArray() { - m_value = AZStd::allocate_shared(AZStdAlloc()); + m_value = AZStd::allocate_shared(StdValueAllocator()); return *this; } @@ -740,7 +740,7 @@ namespace AZ::Dom void Value::SetNode(AZ::Name name) { - m_value = AZStd::allocate_shared(AZStdAlloc(), name); + m_value = AZStd::allocate_shared(StdValueAllocator(), name); } void Value::SetNode(AZStd::string_view name) @@ -914,9 +914,9 @@ namespace AZ::Dom m_value = aznumeric_cast(value); } - void Value::SetString(AZStd::shared_ptr string) + void Value::SetString(SharedStringType sharedString) { - m_value = string; + m_value = sharedString; } AZStd::string_view Value::GetString() const @@ -925,12 +925,15 @@ namespace AZ::Dom { case 5: // AZStd::string_view return AZStd::get(m_value); - case 6: // AZStd::shared_ptr - return *AZStd::get>(m_value); + case 6: // AZStd::shared_ptr> + { + auto& buffer = *AZStd::get(m_value); + return { buffer.data(), buffer.size() }; + } case 7: // ShortStringType { - const ShortStringType& ShortString = AZStd::get(m_value); - return { ShortString.m_data.data(), ShortString.m_size }; + const ShortStringType& shortString = AZStd::get(m_value); + return { shortString.data(), shortString.size() }; } } AZ_Assert(false, "AZ::Dom::Value: Called GetString on a non-string type"); @@ -947,8 +950,8 @@ namespace AZ::Dom if (value.size() <= ShortStringSize) { ShortStringType buffer; - buffer.m_size = value.size(); - memcpy(buffer.m_data.data(), value.data(), buffer.m_size); + buffer.resize_no_construct(value.size()); + memcpy(buffer.data(), value.data(), value.size()); m_value = buffer; } m_value = value; @@ -962,18 +965,20 @@ namespace AZ::Dom } else { - m_value = AZStd::allocate_shared(AZStdAlloc(), value); + SharedStringType sharedString = + AZStd::allocate_shared(StdValueAllocator(), value.begin(), value.end()); + m_value = AZStd::move(sharedString); } } - AZStd::any& Value::GetOpaqueValue() const + const AZStd::any& Value::GetOpaqueValue() const { - return *AZStd::get(m_value); + return *AZStd::get>(m_value); } - void Value::SetOpaqueValue(AZStd::any& value) + void Value::SetOpaqueValue(const AZStd::any& value) { - m_value = &value; + m_value = AZStd::allocate_shared(StdValueAllocator(), value); } void Value::SetNull() @@ -1014,7 +1019,7 @@ namespace AZ::Dom { result = visitor.String(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); } - else if constexpr (AZStd::is_same_v>) + else if constexpr (AZStd::is_same_v) { result = visitor.RefCountedString(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent); } @@ -1110,7 +1115,7 @@ namespace AZ::Dom if (IsString() && other.IsString()) { // If we both hold the same ref counted string we don't need to do a full comparison - if (AZStd::holds_alternative>(m_value) && m_value == other.m_value) + if (AZStd::holds_alternative(m_value) && m_value == other.m_value) { return true; } diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 1b69c73ecc..bc1b790009 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -55,13 +55,15 @@ namespace AZ::Dom } }; + using StdValueAllocator = AZStdAlloc; + class Value; //! Internal storage for a Value array: an ordered list of Values. class Array { public: - using ContainerType = AZStd::vector>; + using ContainerType = AZStd::vector; using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; static constexpr const size_t ReserveIncrement = 4; @@ -80,7 +82,7 @@ namespace AZ::Dom { public: using EntryType = AZStd::pair; - using ContainerType = AZStd::vector>; + using ContainerType = AZStd::vector; using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; static constexpr const size_t ReserveIncrement = 8; @@ -150,6 +152,13 @@ namespace AZ::Dom class Value final { public: + // Determine the short string buffer size based on the size of our largest internal type (string_view) + // minus the size of the short string size field. + static constexpr const size_t ShortStringSize = sizeof(AZStd::string_view) - 2; + using ShortStringType = AZStd::fixed_string; + using SharedStringContainer = AZStd::vector; + using SharedStringType = AZStd::shared_ptr; + // Constructors... Value(); Value(const Value&); @@ -167,7 +176,7 @@ namespace AZ::Dom explicit Value(Type type); - static Value FromOpaqueValue(AZStd::any& value); + static Value FromOpaqueValue(const AZStd::any& value); // Equality / comparison / swap... Value& operator=(const Value&); @@ -306,17 +315,17 @@ namespace AZ::Dom AZStd::string_view GetString() const; size_t GetStringLength() const; void SetString(AZStd::string_view); - void SetString(AZStd::shared_ptr); + void SetString(SharedStringType sharedString); void CopyFromString(AZStd::string_view); // Opaque type API... - AZStd::any& GetOpaqueValue() const; + const AZStd::any& GetOpaqueValue() const; //! This sets this Value to represent a value of an type that the DOM has //! no formal knowledge of. Where possible, it should be preferred to //! serialize an opaque type into a DOM value instead, as serializers //! and other systems will have no means of dealing with fully arbitrary //! values. - void SetOpaqueValue(AZStd::any&); + void SetOpaqueValue(const AZStd::any&); // Null API... void SetNull(); @@ -336,49 +345,37 @@ namespace AZ::Dom const Array::ContainerType& GetArrayInternal() const; Array::ContainerType& GetArrayInternal(); - explicit Value(AZStd::any* opaqueValue); - - // Determine the short string buffer size based on the size of our largest internal type (string_view) - // minus the size of the short string size field. - static constexpr const size_t ShortStringSize = sizeof(AZStd::string_view) - sizeof(size_t); - struct ShortStringType - { - AZStd::array m_data; - size_t m_size; - - bool operator==(const ShortStringType& other) const - { - return m_size == other.m_size ? memcmp(m_data.data(), other.m_data.data(), m_size) == 0 : false; - } - }; + explicit Value(const AZStd::any& opaqueValue); //! The internal storage type for Value. //! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes //! for the same type in some instances, such as string storage. using ValueType = AZStd::variant< - // NullType + // Null AZStd::monostate, - // NumberType + // Int64 int64_t, + // Uint64 uint64_t, + // Double double, - // FalseType & TrueType + // Bool bool, // StringType AZStd::string_view, - AZStd::shared_ptr, + SharedStringType, ShortStringType, - // ObjectType + // Object ObjectPtr, - // ArrayType + // Array ArrayPtr, - // NodeType + // Node NodePtr, - // OpaqueType - AZStd::any*>; + // Opaque + AZStd::shared_ptr>; static_assert( - sizeof(ValueType) == sizeof(AZStd::variant), "ValueType should have no members larger than ShortStringType"); + sizeof(ValueType) == sizeof(ShortStringType) + sizeof(size_t), "ValueType should have no members larger than ShortStringType"); ValueType m_value; }; diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index 172f7f2a92..9b814b1bff 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -68,7 +68,7 @@ namespace AZ::Dom return FinishWrite(); } - Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr value, [[maybe_unused]] Lifetime lifetime) + Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr> value, [[maybe_unused]] Lifetime lifetime) { CurrentValue().SetString(value); return FinishWrite(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h index 488535ace6..4fdea293eb 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.h @@ -28,7 +28,7 @@ namespace AZ::Dom Result Double(double value) override; Result String(AZStd::string_view value, Lifetime lifetime) override; - Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) override; + Result RefCountedString(AZStd::shared_ptr> value, Lifetime lifetime) override; Result StartObject() override; Result EndObject(AZ::u64 attributeCount) override; Result Key(AZ::Name key) override; diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp index 4e13a2a95c..0da4bcd5d3 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.cpp @@ -105,9 +105,9 @@ namespace AZ::Dom return VisitorSuccess(); } - Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr value, Lifetime lifetime) + Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr> value, Lifetime lifetime) { - return String(*value, lifetime); + return String({ value->data(), value->size() }, lifetime); } Visitor::Result Visitor::OpaqueValue([[maybe_unused]] OpaqueType& value) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h index 3bf1b3419b..f9930f93c6 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomVisitor.h @@ -11,8 +11,9 @@ #include #include #include -#include +#include #include +#include namespace AZ::Dom { @@ -176,7 +177,7 @@ namespace AZ::Dom //! Operates on a ref-counted string value. S //! \param lifetime Specifies the lifetime of this string. If the string has a temporary lifetime, it may not //! be safely stored as a reference, but may still be safely stored as a ref-counted shared_ptr. - virtual Result RefCountedString(AZStd::shared_ptr value, Lifetime lifetime); + virtual Result RefCountedString(AZStd::shared_ptr> value, Lifetime lifetime); //! Operates on an opaque value. As opaque values are a reference type, storage semantics are provided to //! indicate where the value may be stored persistently or requires a copy. //! The base implementation of OpaqueValue rejects the operation, as opaque values are meant for special diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index 51d2e5c10c..af5b367d63 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -220,4 +220,33 @@ namespace AZ::Dom::Benchmark } BENCHMARK_REGISTER_F(DomValueBenchmark, LookupMemberByString)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); + BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByStringComparison)(benchmark::State& state) + { + Value value(Type::Object); + AZStd::vector keys; + for (int64_t i = 0; i < state.range(0); ++i) + { + AZStd::string key(AZStd::string::format("key%" PRId64, i)); + keys.push_back(key); + value[key] = i; + } + + for (auto _ : state) + { + for (const AZStd::string& key : keys) + { + const Object::ContainerType& object = value.GetObject(); + benchmark::DoNotOptimize(AZStd::find_if( + object.cbegin(), object.cend(), + [&key](const Object::EntryType& entry) + { + return key == entry.first.GetStringView(); + })); + } + } + + state.SetItemsProcessed(state.iterations() * state.range(0)); + } + BENCHMARK_REGISTER_F(DomValueBenchmark, LookupMemberByStringComparison)->Arg(100)->Arg(1000)->Arg(10000)->Unit(benchmark::kMillisecond); + } // namespace AZ::Dom::Benchmark From 1da99eaea02874f22c1fde8df07e7e730dbd3c6a Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Mon, 20 Dec 2021 18:27:00 -0800 Subject: [PATCH 027/108] Add type-safe GetTypeIndex instead of hardcoded index lookups Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 96 ++++++++++++++----- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 54 +++++------ 2 files changed, 97 insertions(+), 53 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 3dafc02c6e..3836568f37 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -26,6 +26,51 @@ namespace AZ::Dom return refCountedPointer; } + namespace Internal + { + template + constexpr size_t GetTypeIndexInternal(size_t index = 0) + { + static_assert(false, "Type not found in ValueType"); + return index; + } + + template + constexpr size_t GetTypeIndexInternal(size_t index = 0) + { + if constexpr (AZStd::is_same_v) + { + return index; + } + else + { + return GetTypeIndexInternal(index + 1); + } + } + + template + struct ExtractTypeArgs + { + }; + + template class TypeToExtract, typename... Args> + struct ExtractTypeArgs> + { + template + static constexpr size_t GetTypeIndex() + { + return GetTypeIndexInternal(); + } + }; + } // namespace Internal + + // Helper function, looks up the index of a type within Value::m_value's storage + template + constexpr size_t GetTypeIndex() + { + return Internal::ExtractTypeArgs::GetTypeIndex(); + } + Node::Node(AZ::Name name) : m_name(name) { @@ -227,27 +272,27 @@ namespace AZ::Dom { switch (m_value.index()) { - case 0: // AZStd::monostate + case GetTypeIndex(): return Type::Null; - case 1: // int64_t + case GetTypeIndex(): return Type::Int64; - case 2: // uint64_t + case GetTypeIndex(): return Type::Uint64; - case 3: // double + case GetTypeIndex(): return Type::Double; - case 4: // bool + case GetTypeIndex(): return Type::Bool; - case 5: // AZStd::string_view - case 6: // AZStd::shared_ptr - case 7: // ShortStringType + case GetTypeIndex(): + case GetTypeIndex(): + case GetTypeIndex(): return Type::String; - case 8: // ObjectPtr + case GetTypeIndex(): return Type::Object; - case 9: // ArrayPtr + case GetTypeIndex(): return Type::Array; - case 10: // NodePtr + case GetTypeIndex(): return Type::Node; - case 11: // AZStd::any* + case GetTypeIndex>(): return Type::Opaque; } AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); @@ -813,11 +858,11 @@ namespace AZ::Dom { switch (m_value.index()) { - case 1: // int64_t + case GetTypeIndex(): return AZStd::get(m_value); - case 2: // uint64_t + case GetTypeIndex(): return aznumeric_cast(AZStd::get(m_value)); - case 3: // double + case GetTypeIndex(): return aznumeric_cast(AZStd::get(m_value)); } AZ_Assert(false, "AZ::Dom::Value: Called GetInt on a non-numeric type"); @@ -843,11 +888,11 @@ namespace AZ::Dom { switch (m_value.index()) { - case 1: // int64_t + case GetTypeIndex(): return aznumeric_cast(AZStd::get(m_value)); - case 2: // uint64_t + case GetTypeIndex(): return AZStd::get(m_value); - case 3: // double + case GetTypeIndex(): return aznumeric_cast(AZStd::get(m_value)); } AZ_Assert(false, "AZ::Dom::Value: Called GetInt on a non-numeric type"); @@ -888,11 +933,11 @@ namespace AZ::Dom { switch (m_value.index()) { - case 1: // int64_t + case GetTypeIndex(): return aznumeric_cast(AZStd::get(m_value)); - case 2: // uint64_t + case GetTypeIndex(): return aznumeric_cast(AZStd::get(m_value)); - case 3: // double + case GetTypeIndex(): return AZStd::get(m_value); } AZ_Assert(false, "AZ::Dom::Value: Called GetInt on a non-numeric type"); @@ -923,14 +968,14 @@ namespace AZ::Dom { switch (m_value.index()) { - case 5: // AZStd::string_view + case GetTypeIndex(): return AZStd::get(m_value); - case 6: // AZStd::shared_ptr> + case GetTypeIndex(): { auto& buffer = *AZStd::get(m_value); return { buffer.data(), buffer.size() }; } - case 7: // ShortStringType + case GetTypeIndex(): { const ShortStringType& shortString = AZStd::get(m_value); return { shortString.data(), shortString.size() }; @@ -965,8 +1010,7 @@ namespace AZ::Dom } else { - SharedStringType sharedString = - AZStd::allocate_shared(StdValueAllocator(), value.begin(), value.end()); + SharedStringType sharedString = AZStd::allocate_shared(StdValueAllocator(), value.begin(), value.end()); m_value = AZStd::move(sharedString); } } diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index bc1b790009..86e98030e2 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -159,6 +159,33 @@ namespace AZ::Dom using SharedStringContainer = AZStd::vector; using SharedStringType = AZStd::shared_ptr; + //! The internal storage type for Value. + //! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes + //! for the same type in some instances, such as string storage. + using ValueType = AZStd::variant< + // Null + AZStd::monostate, + // Int64 + int64_t, + // Uint64 + uint64_t, + // Double + double, + // Bool + bool, + // StringType + AZStd::string_view, + SharedStringType, + ShortStringType, + // Object + ObjectPtr, + // Array + ArrayPtr, + // Node + NodePtr, + // Opaque + AZStd::shared_ptr>; + // Constructors... Value(); Value(const Value&); @@ -347,33 +374,6 @@ namespace AZ::Dom explicit Value(const AZStd::any& opaqueValue); - //! The internal storage type for Value. - //! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes - //! for the same type in some instances, such as string storage. - using ValueType = AZStd::variant< - // Null - AZStd::monostate, - // Int64 - int64_t, - // Uint64 - uint64_t, - // Double - double, - // Bool - bool, - // StringType - AZStd::string_view, - SharedStringType, - ShortStringType, - // Object - ObjectPtr, - // Array - ArrayPtr, - // Node - NodePtr, - // Opaque - AZStd::shared_ptr>; - static_assert( sizeof(ValueType) == sizeof(ShortStringType) + sizeof(size_t), "ValueType should have no members larger than ShortStringType"); From 37330c43a9408ad9ffcd726c14f510c4b5d264f5 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 21 Dec 2021 15:47:42 -0800 Subject: [PATCH 028/108] Address some more Generic Dom Value perf feedback Signed-off-by: Nicholas Van Sickle --- .../Backends/JSON/JsonSerializationUtils.cpp | 4 -- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 57 ++++++++++--------- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 4 +- .../AzCore/AzCore/DOM/DomValueWriter.cpp | 26 ++++----- .../AzCore/Tests/DOM/DomJsonBenchmarks.cpp | 26 ++++++--- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 16 +++++- 6 files changed, 77 insertions(+), 56 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp b/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp index bc8ac9167c..3baf78b63d 100644 --- a/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/Backends/JSON/JsonSerializationUtils.cpp @@ -373,10 +373,6 @@ namespace AZ::Dom::Json bool RapidJsonReadHandler::Key(const char* str, rapidjson::SizeType length, [[maybe_unused]] bool copy) { AZStd::string_view key = AZStd::string_view(str, length); - if (!m_visitor->SupportsRawKeys()) - { - m_visitor->Key(AZ::Name(key)); - } const Lifetime lifetime = !copy ? m_stringLifetime : Lifetime::Temporary; return CheckResult(m_visitor->RawKey(key, lifetime)); } diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 3836568f37..407d1e66a2 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -17,13 +17,15 @@ namespace AZ::Dom template AZStd::shared_ptr& CheckCopyOnWrite(AZStd::shared_ptr& refCountedPointer) { - if (refCountedPointer.use_count() > 1) + if (refCountedPointer.use_count() == 1) { - AZStd::shared_ptr newPointer = AZStd::allocate_shared(StdValueAllocator()); - *newPointer = *refCountedPointer; - refCountedPointer = AZStd::move(newPointer); + return refCountedPointer; + } + else + { + refCountedPointer = AZStd::allocate_shared(StdValueAllocator(), *refCountedPointer); + return refCountedPointer; } - return refCountedPointer; } namespace Internal @@ -72,7 +74,7 @@ namespace AZ::Dom } Node::Node(AZ::Name name) - : m_name(name) + : m_name(AZStd::move(name)) { } @@ -83,7 +85,7 @@ namespace AZ::Dom void Node::SetName(AZ::Name name) { - m_name = name; + m_name = AZStd::move(name); } Object::ContainerType& Node::GetProperties() @@ -106,8 +108,8 @@ namespace AZ::Dom return m_children; } - Value::Value(AZStd::shared_ptr string) - : m_value(string) + Value::Value(SharedStringType sharedString) + : m_value(AZStd::move(sharedString)) { } @@ -122,18 +124,19 @@ namespace AZ::Dom Value::Value(Value&& value) noexcept { - operator=(value); + memcpy(this, &value, sizeof(Value)); + memset(&value, 0, sizeof(Value)); } - Value::Value(AZStd::string_view string, bool copy) + Value::Value(AZStd::string_view stringView, bool copy) { if (copy) { - CopyFromString(string); + CopyFromString(stringView); } else { - SetString(string); + SetString(stringView); } } @@ -227,7 +230,9 @@ namespace AZ::Dom Value& Value::operator=(Value&& other) noexcept { - m_value.swap(other.m_value); + SetNull(); + memcpy(this, &other, sizeof(Value)); + memset(&other, 0, sizeof(Value)); return *this; } @@ -265,7 +270,10 @@ namespace AZ::Dom void Value::Swap(Value& other) noexcept { - m_value.swap(other.m_value); + AZStd::aligned_storage_for_t temp; + memcpy(&temp, this, sizeof(Value)); + memcpy(this, &other, sizeof(Value)); + memcpy(&other, &temp, sizeof(Value)); } Type Dom::Value::GetType() const @@ -583,7 +591,7 @@ namespace AZ::Dom } else { - object.emplace_back(name, value); + object.emplace_back(AZStd::move(name), value); } return *this; } @@ -602,7 +610,7 @@ namespace AZ::Dom } else { - object.emplace_back(name, value); + object.emplace_back(AZStd::move(name), value); } return *this; } @@ -636,15 +644,12 @@ namespace AZ::Dom Object::Iterator Value::RemoveMember(Object::Iterator pos) { Object::ContainerType& object = GetObjectInternal(); - Object::Iterator nextIndex = object.end(); - auto lastEntry = object.end() - 1; - if (pos != lastEntry) + if (!object.empty()) { - AZStd::swap(*pos, *lastEntry); - nextIndex = pos; + AZStd::swap(*pos, object.back()); + object.pop_back(); } - object.resize(object.size() - 1); - return nextIndex; + return object.end(); } Object::Iterator Value::EraseMember(Object::ConstIterator pos) @@ -785,7 +790,7 @@ namespace AZ::Dom void Value::SetNode(AZ::Name name) { - m_value = AZStd::allocate_shared(StdValueAllocator(), name); + m_value = AZStd::allocate_shared(StdValueAllocator(), AZStd::move(name)); } void Value::SetNode(AZStd::string_view name) @@ -800,7 +805,7 @@ namespace AZ::Dom void Value::SetNodeName(AZ::Name name) { - GetNodeInternal().SetName(name); + GetNodeInternal().SetName(AZStd::move(name)); } void Value::SetNodeName(AZStd::string_view name) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 86e98030e2..a777640aaf 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -190,8 +190,8 @@ namespace AZ::Dom Value(); Value(const Value&); Value(Value&&) noexcept; - Value(AZStd::string_view string, bool copy); - Value(AZStd::shared_ptr string); + Value(AZStd::string_view stringView, bool copy); + Value(SharedStringType sharedString); Value(int32_t value); Value(uint32_t value); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index 9b814b1bff..3259579aaa 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -82,6 +82,16 @@ namespace AZ::Dom return VisitorSuccess(); } + template + void MoveVectorMemory(AZStd::vector& dest, AZStd::vector& source) + { + dest.resize_no_construct(source.size()); + const size_t size = sizeof(T) * source.size(); + memcpy(dest.data(), source.data(), size); + memset(source.data(), 0, size); + source.resize(0); + } + Visitor::Result ValueWriter::EndContainer(Type containerType, AZ::u64 attributeCount, AZ::u64 elementCount) { const char* endMethodName; @@ -138,22 +148,12 @@ namespace AZ::Dom } if (buffer.m_attributes.size() > 0) { - container.MemberReserve(buffer.m_attributes.size()); - for (AZStd::pair& entry : buffer.m_attributes) - { - container.AddMember(AZStd::move(entry.first), AZStd::move(entry.second)); - } - buffer.m_attributes.clear(); + MoveVectorMemory(container.GetMutableObject(), buffer.m_attributes); } if(buffer.m_elements.size() > 0) { - container.Reserve(buffer.m_elements.size()); - for (Value& entry : buffer.m_elements) - { - container.PushBack(AZStd::move(entry)); - } - buffer.m_elements.clear(); + MoveVectorMemory(container.GetMutableArray(), buffer.m_elements); } m_entryStack.pop(); @@ -180,7 +180,7 @@ namespace AZ::Dom { AZ_Assert(!m_entryStack.empty(), "Attempmted to push a key with no object"); AZ_Assert(!m_entryStack.top().m_container.IsArray(), "Attempted to push a key to an array"); - m_entryStack.top().m_key = key; + m_entryStack.top().m_key = AZStd::move(key); return VisitorSuccess(); } diff --git a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp index 477802dc37..8eda110e7b 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomJsonBenchmarks.cpp @@ -120,6 +120,16 @@ namespace Benchmark AZ_Assert(result.IsSuccess(), "Failed to serialize generated JSON"); return serializedJson; } + + template + void TakeAndDiscardWithoutTimingDtor(T&& value, benchmark::State& state) + { + { + T instance = AZStd::move(value); + state.PauseTiming(); + } + state.ResumeTiming(); + } }; // Helper macro for registering JSON benchmarks @@ -148,7 +158,7 @@ namespace Benchmark return AZ::Dom::Utils::ReadFromStringInPlace(backend, payloadCopy, visitor); }); - benchmark::DoNotOptimize(result.GetValue()); + TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state); } state.SetBytesProcessed(serializedPayload.size() * state.iterations()); @@ -172,7 +182,7 @@ namespace Benchmark return AZ::Dom::Utils::ReadFromStringInPlace(backend, payloadCopy, visitor); }); - benchmark::DoNotOptimize(result.GetValue()); + TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state); } state.SetBytesProcessed(serializedPayload.size() * state.iterations()); @@ -192,7 +202,7 @@ namespace Benchmark return AZ::Dom::Utils::ReadFromString(backend, serializedPayload, AZ::Dom::Lifetime::Temporary, visitor); }); - benchmark::DoNotOptimize(result.GetValue()); + TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state); } state.SetBytesProcessed(serializedPayload.size() * state.iterations()); @@ -212,7 +222,7 @@ namespace Benchmark return AZ::Dom::Utils::ReadFromString(backend, serializedPayload, AZ::Dom::Lifetime::Temporary, visitor); }); - benchmark::DoNotOptimize(result.GetValue()); + TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state); } state.SetBytesProcessed(serializedPayload.size() * state.iterations()); @@ -228,7 +238,7 @@ namespace Benchmark { auto result = AZ::JsonSerializationUtils::ReadJsonString(serializedPayload); - benchmark::DoNotOptimize(result.GetValue()); + TakeAndDiscardWithoutTimingDtor(result.TakeValue(), state); } state.SetBytesProcessed(serializedPayload.size() * state.iterations()); @@ -239,7 +249,7 @@ namespace Benchmark { for (auto _ : state) { - benchmark::DoNotOptimize(GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1))); + TakeAndDiscardWithoutTimingDtor(GenerateDomJsonBenchmarkPayload(state.range(0), state.range(1)), state); } state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations()); @@ -277,7 +287,7 @@ namespace Benchmark { rapidjson::Document copy; copy.CopyFrom(original, copy.GetAllocator(), true); - benchmark::DoNotOptimize(copy); + TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state); } state.SetItemsProcessed(state.iterations()); @@ -294,7 +304,7 @@ namespace Benchmark rapidjson::Document copy; copy.CopyFrom(original, copy.GetAllocator(), true); copy["entries"]["Key0"].PushBack(42, copy.GetAllocator()); - benchmark::DoNotOptimize(copy); + TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state); } state.SetItemsProcessed(state.iterations()); diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index af5b367d63..12684c64bc 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -98,13 +98,23 @@ namespace AZ::Dom::Benchmark return root; } + + template + void TakeAndDiscardWithoutTimingDtor(T&& value, benchmark::State& state) + { + { + T instance = AZStd::move(value); + state.PauseTiming(); + } + state.ResumeTiming(); + } }; BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueMakeComplexObject)(benchmark::State& state) { for (auto _ : state) { - benchmark::DoNotOptimize(GenerateDomBenchmarkPayload(state.range(0), state.range(1))); + TakeAndDiscardWithoutTimingDtor(GenerateDomBenchmarkPayload(state.range(0), state.range(1)), state); } state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations()); @@ -143,7 +153,7 @@ namespace AZ::Dom::Benchmark { Value copy = original; copy["entries"]["Key0"].PushBack(42); - benchmark::DoNotOptimize(copy); + TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state); } state.SetItemsProcessed(state.iterations()); @@ -162,7 +172,7 @@ namespace AZ::Dom::Benchmark for (auto _ : state) { Value copy = original.DeepCopy(); - benchmark::DoNotOptimize(copy); + TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state); } state.SetItemsProcessed(state.iterations()); From 68c93273d687bda5c57e88d9ab630ca6ee03b6f1 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 21 Dec 2021 16:09:11 -0800 Subject: [PATCH 029/108] Add 8 and 16 bit numeric type API Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 20 +++++++++++++++++++ Code/Framework/AzCore/AzCore/DOM/DomValue.h | 12 +++++++++++ 2 files changed, 32 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 407d1e66a2..f9f4f726dd 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -150,6 +150,26 @@ namespace AZ::Dom return Value(&value); } + Value::Value(int8_t value) + : m_value(aznumeric_cast(value)) + { + } + + Value::Value(uint8_t value) + : m_value(aznumeric_cast(value)) + { + } + + Value::Value(int16_t value) + : m_value(aznumeric_cast(value)) + { + } + + Value::Value(uint16_t value) + : m_value(aznumeric_cast(value)) + { + } + Value::Value(int32_t value) : m_value(aznumeric_cast(value)) { diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index a777640aaf..7ef794486e 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -193,6 +193,10 @@ namespace AZ::Dom Value(AZStd::string_view stringView, bool copy); Value(SharedStringType sharedString); + Value(int8_t value); + Value(uint8_t value); + Value(int16_t value); + Value(uint16_t value); Value(int32_t value); Value(uint32_t value); Value(int64_t value); @@ -321,12 +325,20 @@ namespace AZ::Dom void SetInt64(int64_t); int32_t GetInt32() const; void SetInt32(int32_t); + int16_t GetInt16() const; + void SetInt16(int16_t); + int8_t GetInt8() const; + void SetInt8(int8_t); // uint API... uint64_t GetUint64() const; void SetUint64(uint64_t); uint32_t GetUint32() const; void SetUint32(uint32_t); + uint16_t GetUint16() const; + void SetUint16(uint16_t); + uint8_t GetUint8() const; + void SetUint8(uint8_t); // bool API... bool GetBool() const; From deb3568aaa15e962b49fb5a0aa6b19960866fa73 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 21 Dec 2021 16:19:32 -0800 Subject: [PATCH 030/108] Fix up a couple opaque value cases Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 4 ++-- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index f9f4f726dd..01d7bcf6e1 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -1042,7 +1042,7 @@ namespace AZ::Dom const AZStd::any& Value::GetOpaqueValue() const { - return *AZStd::get>(m_value); + return *AZStd::get(m_value); } void Value::SetOpaqueValue(const AZStd::any& value) @@ -1165,7 +1165,7 @@ namespace AZ::Dom result = visitor.EndNode(object.size(), arrayContainer.size()); } } - else if constexpr (AZStd::is_same_v) + else if constexpr (AZStd::is_same_v) { result = visitor.OpaqueValue(*arg); } diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 7ef794486e..b9c1062ed7 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -158,6 +158,7 @@ namespace AZ::Dom using ShortStringType = AZStd::fixed_string; using SharedStringContainer = AZStd::vector; using SharedStringType = AZStd::shared_ptr; + using OpaqueStorageType = AZStd::shared_ptr; //! The internal storage type for Value. //! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes @@ -184,7 +185,7 @@ namespace AZ::Dom // Node NodePtr, // Opaque - AZStd::shared_ptr>; + OpaqueStorageType>; // Constructors... Value(); From fd70a2207e68dc456a91e23e5446f64b5a6971a6 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 21 Dec 2021 16:47:13 -0800 Subject: [PATCH 031/108] Address a few other small pieces of feedback Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 14 +++++--------- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 8 ++++---- .../Framework/AzCore/AzCore/DOM/DomValueWriter.cpp | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 01d7bcf6e1..7659afa070 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -113,10 +113,6 @@ namespace AZ::Dom { } - Value::Value() - { - } - Value::Value(const Value& value) : m_value(value.m_value) { @@ -344,7 +340,7 @@ namespace AZ::Dom bool Value::IsBool() const { - return AZStd::holds_alternative(m_value); + return GetType() == Type::Bool; } bool Value::IsNode() const @@ -383,17 +379,17 @@ namespace AZ::Dom bool Value::IsInt() const { - return AZStd::holds_alternative(m_value); + return GetType() == Type::Int64; } bool Value::IsUint() const { - return AZStd::holds_alternative(m_value); + return GetType() == Type::Uint64; } bool Value::IsDouble() const { - return AZStd::holds_alternative(m_value); + return GetType() == Type::Double; } bool Value::IsString() const @@ -666,7 +662,7 @@ namespace AZ::Dom Object::ContainerType& object = GetObjectInternal(); if (!object.empty()) { - AZStd::swap(*pos, object.back()); + *pos = AZStd::move(object.back()); object.pop_back(); } return object.end(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index b9c1062ed7..b73da92d23 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -103,9 +103,9 @@ namespace AZ::Dom { public: Node() = default; - Node(AZ::Name name); - Node(const Node&) = default; - Node(Node&&) = default; + explicit Node(AZ::Name name); + explicit Node(const Node&) = default; + explicit Node(Node&&) = default; Node& operator=(const Node&) = default; Node& operator=(Node&&) = default; @@ -188,7 +188,7 @@ namespace AZ::Dom OpaqueStorageType>; // Constructors... - Value(); + Value() = default; Value(const Value&); Value(Value&&) noexcept; Value(AZStd::string_view stringView, bool copy); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index 3259579aaa..f8ca56ea32 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -70,7 +70,7 @@ namespace AZ::Dom Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr> value, [[maybe_unused]] Lifetime lifetime) { - CurrentValue().SetString(value); + CurrentValue().SetString(AZStd::move(value)); return FinishWrite(); } From f69b9b817c19b73921d5e4095d309a51b656fe8c Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 22 Dec 2021 11:03:51 -0800 Subject: [PATCH 032/108] Round of clang compile fixes Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp | 2 +- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 10 ++-------- Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp | 7 +++---- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp index 46fa5b9bac..d65497e194 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp @@ -22,7 +22,7 @@ namespace AZ::Dom::Utils return backend.ReadFromBufferInPlace(string.data(), string.size(), visitor); } - AZ::Outcome AZ::Dom::Utils::WriteToValue(Backend::WriteCallback writeCallback) + AZ::Outcome WriteToValue(Backend::WriteCallback writeCallback) { Value value; AZStd::unique_ptr writer = value.GetWriteHandler(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 7659afa070..7401a5ac98 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -6,8 +6,6 @@ * */ -#pragma once - #include #include #include @@ -31,11 +29,7 @@ namespace AZ::Dom namespace Internal { template - constexpr size_t GetTypeIndexInternal(size_t index = 0) - { - static_assert(false, "Type not found in ValueType"); - return index; - } + constexpr size_t GetTypeIndexInternal(size_t index = 0); template constexpr size_t GetTypeIndexInternal(size_t index = 0) @@ -143,7 +137,7 @@ namespace AZ::Dom Value Value::FromOpaqueValue(const AZStd::any& value) { - return Value(&value); + return Value(value); } Value::Value(int8_t value) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index f8ca56ea32..b7ed44f8de 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -129,7 +129,7 @@ namespace AZ::Dom AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName)); } - if (buffer.m_attributes.size() != attributeCount) + if (static_cast(buffer.m_attributes.size()) != attributeCount) { return VisitorFailure( VisitorErrorCode::InternalError, @@ -138,7 +138,7 @@ namespace AZ::Dom buffer.m_attributes.size())); } - if (buffer.m_elements.size() != elementCount) + if (static_cast(buffer.m_elements.size()) != elementCount) { return VisitorFailure( VisitorErrorCode::InternalError, @@ -146,6 +146,7 @@ namespace AZ::Dom "AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount, buffer.m_elements.size())); } + if (buffer.m_attributes.size() > 0) { MoveVectorMemory(container.GetMutableObject(), buffer.m_attributes); @@ -237,8 +238,6 @@ namespace AZ::Dom m_entryStack.top().m_value.Swap(value); ValueInfo& newEntry = m_entryStack.top(); - constexpr const size_t reserveSize = 8; - if (!newEntry.m_key.IsEmpty()) { GetValueBuffer().m_attributes.emplace_back(AZStd::move(newEntry.m_key), AZStd::move(value)); From 8732fab19284ca5736d30f1406659949bed02710 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 22 Dec 2021 12:35:44 -0800 Subject: [PATCH 033/108] One more compile fix Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index b7ed44f8de..210d1fa123 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -134,7 +134,7 @@ namespace AZ::Dom return VisitorFailure( VisitorErrorCode::InternalError, AZStd::string::format( - "AZ::Dom::ValueWriter: %s expected %llu attributes but received %llu attributes instead", endMethodName, attributeCount, + "AZ::Dom::ValueWriter: %s expected %llu attributes but received %zu attributes instead", endMethodName, attributeCount, buffer.m_attributes.size())); } @@ -143,7 +143,7 @@ namespace AZ::Dom return VisitorFailure( VisitorErrorCode::InternalError, AZStd::string::format( - "AZ::Dom::ValueWriter: %s expected %llu elements but received %llu elements instead", endMethodName, elementCount, + "AZ::Dom::ValueWriter: %s expected %llu elements but received %zu elements instead", endMethodName, elementCount, buffer.m_elements.size())); } From a7d173db3d530dbf0d5f0067e05e4bd8ea422406 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Mon, 3 Jan 2022 16:15:35 -0800 Subject: [PATCH 034/108] changes from review and switching to assert model instead of return bool Signed-off-by: Scott Murray --- .../editor_entity_utils.py | 164 ++++++++++-------- 1 file changed, 93 insertions(+), 71 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index 58d9e30f81..0878431054 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -8,7 +8,8 @@ SPDX-License-Identifier: Apache-2.0 OR MIT # Built-in Imports from __future__ import annotations from typing import List, Tuple, Union - +from enum import Enum +import warnings # Open 3D Engine Imports import azlmbr @@ -21,15 +22,21 @@ import azlmbr.legacy.general as general from editor_python_test_tools.utils import Report +class Entity_Type(Enum): + GAME = azlmbr.entity.EntityType().Game + LEVEL = azlmbr.entity.EntityType().Level + + class EditorComponent: """ EditorComponent class used to set and get the component property value using path EditorComponent object is returned from either of EditorEntity.add_component() or Entity.add_components() or EditorEntity.get_components_of_type() which also assigns self.id and self.type_id to the EditorComponent object. + self.type_id is the UUID for the component type as provided by an ebus call. """ - def __init__(self, type_id): + def __init__(self, type_id: uuid): self.type_id = type_id self.id = None self.property_tree = None @@ -88,51 +95,59 @@ class EditorComponent: :param component_property_path: String of component property. (e.g. 'Settings|Visible') :return: Count of items in the container as unsigned integer """ - if self.is_property_container(component_property_path): - container_count_outcome = self.property_tree.get_container_count(component_property_path) - assert ( - container_count_outcome.IsSuccess() - ), f"Failure: get_container_count did not return success for '{component_property_path}'" - return container_count_outcome.GetValue() + assert ( + self.is_property_container(component_property_path) + ), f"Failure: '{component_property_path}' is not a property container" + container_count_outcome = self.property_tree.get_container_count(component_property_path) + assert ( + container_count_outcome.IsSuccess() + ), f"Failure: get_container_count did not return success for '{component_property_path}'" + return container_count_outcome.GetValue() - def reset_container(self, component_property_path: str) -> bool: + def reset_container(self, component_property_path: str): """ Used to rest a container to empty :param component_property_path: String of component property. (e.g. 'Settings|Visible') - :return: Boolean success + :return: None """ - if self.is_property_container(component_property_path): - reset_outcome = self.property_tree.reset_container(component_property_path) - return reset_outcome.IsSuccess() - else: - return False + assert ( + self.is_property_container(component_property_path) + ), f"Failure: '{component_property_path}' is not a property container" + reset_outcome = self.property_tree.reset_container(component_property_path) + assert ( + reset_outcome.IsSuccess() + ), f"Failure: could not reset_container on '{component_property_path}'" - def append_container_item(self, component_property_path: str, value: any) -> bool: + def append_container_item(self, component_property_path: str, value: any): """ Used to append a container item without providing an index key. :param component_property_path: String of component property. (e.g. 'Settings|Visible') :param value: Value to be set - :return: Boolean success + :return: None """ - if self.is_property_container(component_property_path): - append_outcome = self.property_tree.append_container_item(component_property_path, value) - return append_outcome.IsSuccess() - else: - return False + assert ( + self.is_property_container(component_property_path) + ), f"Failure: '{component_property_path}' is not a property container" + append_outcome = self.property_tree.append_container_item(component_property_path, value) + assert ( + append_outcome.IsSuccess() + ), f"Failure: could not append_container_item to '{component_property_path}'" - def add_container_item(self, component_property_path: str, key: any, value: any) -> bool: + def add_container_item(self, component_property_path: str, key: any, value: any): """ Used to add a container item at a specified key. In practice key should be an integer index. :param component_property_path: String of component property. (e.g. 'Settings|Visible') :param key: Zero index integer key, although this could be any unique unused key value :param value: Value to be set - :return: Boolean success + :return: None """ - if self.is_property_container(component_property_path): - add_outcome = self.property_tree.add_container_item(component_property_path, key, value) - return add_outcome.IsSuccess() - else: - return False + assert ( + self.is_property_container(component_property_path) + ), f"Failure: '{component_property_path}' is not a property container" + add_outcome = self.property_tree.add_container_item(component_property_path, key, value) + assert ( + add_outcome.IsSuccess() + ), f"Failure: could not add_container_item '{key}' to '{component_property_path}'" def get_container_item(self, component_property_path: str, key: any) -> any: """ @@ -141,27 +156,29 @@ class EditorComponent: :param key: Zero index integer key :return: Value stored at the key specified """ - if self.is_property_container(component_property_path): - get_outcome = self.property_tree.get_container_item(component_property_path, key) - assert ( - get_outcome.IsSuccess() - ), f"Failure: could not get a value for {self.get_component_name()}: '{component_property_path}' [{key}]" - return get_outcome.GetValue() - else: - return None + assert ( + self.is_property_container(component_property_path) + ), f"Failure: '{component_property_path}' is not a property container" + get_outcome = self.property_tree.get_container_item(component_property_path, key) + assert ( + get_outcome.IsSuccess() + ), f"Failure: could not get a value for {self.get_component_name()}: '{component_property_path}' [{key}]" + return get_outcome.GetValue() - def remove_container_item(self, component_property_path: str, key: any) -> bool: + def remove_container_item(self, component_property_path: str, key: any): """ Used to remove a container item value at the specified key. In practice key should be an integer index. :param component_property_path: String of component property. (e.g. 'Settings|Visible') :param key: Zero index integer key - :return: Boolean success + :return: None """ - if self.is_property_container(component_property_path): - remove_outcome = self.property_tree.remove_container_item(component_property_path, key) - return remove_outcome.IsSuccess() - else: - return False + assert ( + self.is_property_container(component_property_path) + ), f"Failure: '{component_property_path}' is not a property container" + remove_outcome = self.property_tree.remove_container_item(component_property_path, key) + assert ( + remove_outcome.IsSuccess() + ), f"Failure: could not remove_container_item '{key}' from '{component_property_path}'" def update_container_item(self, component_property_path: str, key: any, value: any): """ @@ -169,13 +186,15 @@ class EditorComponent: :param component_property_path: String of component property. (e.g. 'Settings|Visible') :param key: Zero index integer key :param value: Value to be set - :return: Boolean success + :return: None """ - if self.is_property_container(component_property_path): - update_outcome = self.property_tree.update_container_item(component_property_path, key, value) - return update_outcome.IsSuccess() - else: - return False + assert ( + self.is_property_container(component_property_path) + ), f"Failure: '{component_property_path}' is not a property container" + update_outcome = self.property_tree.update_container_item(component_property_path, key, value) + assert ( + update_outcome.IsSuccess() + ), f"Failure: could not update '{key}' in '{component_property_path}'" def get_component_property_value(self, component_property_path: str): """ @@ -211,30 +230,33 @@ class EditorComponent: """ return editor.EditorComponentAPIBus(bus.Broadcast, "IsComponentEnabled", self.id) + def set_enabled(self, new_state: bool): + """ + Used to set the component enabled state + :param new_state: Boolean enabled True, disabled False + :return: None + """ + if new_state: + editor.EditorComponentAPIBus(bus.Broadcast, "EnableComponents", [self.id]) + else: + editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [self.id]) + def disable_component(self): """ Used to disable the component using its id value. :return: None """ + warnings.warn("disable_component is deprecated, use set_enabled(False) instead.", DeprecationWarning) editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [self.id]) - def enable_component(self): - """ - used to enable the componet using its id value - """ - editor.EditorComponentAPIBus(bus.Broadcast, "EnabledComponents", [self.id]) - @staticmethod - def get_type_ids(component_names: list, entity_type: str ='Game') -> list: + def get_type_ids(component_names: list, entity_type: Entity_Type = Entity_Type.GAME) -> list: """ Used to get type ids of given components list - :param: component_names: List of components to get type ids - :return: List of type ids of given components. + :param component_names: List of components to get type ids + :param entity_type: Entity_Type enum value Entity_Type.GAME is the default + :return: List of type ids of given components. Type id is a UUID as provided by the ebus call """ - if entity_type.lower() == 'level': - entity_type = azlmbr.entity.EntityType().Level - else: - entity_type = azlmbr.entity.EntityType().Game type_ids = editor.EditorComponentAPIBus( bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, entity_type) return type_ids @@ -402,7 +424,7 @@ class EditorEntity: :return: List of newly added components to the entity """ components = [] - type_ids = EditorComponent.get_type_ids(component_names) + type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.GAME) for type_id in type_ids: new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorComponentAPIBus( @@ -430,7 +452,7 @@ class EditorEntity: :param component_names: List of component names to remove :return: None """ - type_ids = EditorComponent.get_type_ids(component_names) + type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.GAME) for type_id in type_ids: remove_outcome = editor.EditorComponentAPIBus(bus.Broadcast, "RemoveComponents", self.id, [type_id]) assert ( @@ -444,7 +466,7 @@ class EditorEntity: :return: List of Entity Component objects of given component name """ component_list = [] - type_ids = EditorComponent.get_type_ids(component_names) + type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.GAME) for type_id in type_ids: component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorComponentAPIBus( @@ -464,7 +486,7 @@ class EditorEntity: :param component_name: Name of component to check for :return: True, if entity has specified component. Else, False """ - type_ids = EditorComponent.get_type_ids([component_name]) + type_ids = EditorComponent.get_type_ids([component_name], Entity_Type.GAME) return editor.EditorComponentAPIBus(bus.Broadcast, "HasComponentOfType", self.id, type_ids[0]) def get_start_status(self) -> int: @@ -666,7 +688,7 @@ class EditorLevelEntity: :return: List of newly added components to the level """ components = [] - type_ids = EditorComponent.get_type_ids(component_names, 'level') + type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.LEVEL) for type_id in type_ids: new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorLevelComponentAPIBus( @@ -687,7 +709,7 @@ class EditorLevelEntity: :return: List of Level Component objects of given component name """ component_list = [] - type_ids = EditorComponent.get_type_ids(component_names, 'level') + type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.LEVEL) for type_id in type_ids: component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorLevelComponentAPIBus( @@ -708,7 +730,7 @@ class EditorLevelEntity: :param component_name: Name of component to check for :return: True, if level has specified component. Else, False """ - type_ids = EditorComponent.get_type_ids([component_name], 'level') + type_ids = EditorComponent.get_type_ids([component_name], Entity_Type.LEVEL) return editor.EditorLevelComponentAPIBus(bus.Broadcast, "HasComponentOfType", type_ids[0]) @staticmethod @@ -718,5 +740,5 @@ class EditorLevelEntity: :param component_name: Name of component to check for :return: integer count of occurences of level component attached to level or zero if none are present """ - type_ids = EditorComponent.get_type_ids([component_name], 'level') + type_ids = EditorComponent.get_type_ids([component_name], Entity_Type.LEVEL) return editor.EditorLevelComponentAPIBus(bus.Broadcast, "CountComponentsOfType", type_ids[0]) From c7d72bc6b68a93e194466eac80fdb17d78acf22f Mon Sep 17 00:00:00 2001 From: Tobias Alexander Franke Date: Wed, 17 Nov 2021 15:30:46 +0800 Subject: [PATCH 035/108] Ragdoll saving issue Signed-off-by: T.J. McGrath-Daly --- .../Code/Source/Editor/Plugins/Ragdoll/RagdollNodeWidget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeWidget.cpp index 29745beb68..538ad3ba52 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/Ragdoll/RagdollNodeWidget.cpp @@ -125,6 +125,10 @@ namespace EMotionFX Physics::RagdollNodeConfiguration* ragdollNodeConfig = GetRagdollNodeConfig(); if (ragdollNodeConfig) { + AzPhysics::JointConfiguration* jointLimitConfig = ragdollNodeConfig->m_jointConfig.get(); + jointLimitConfig->SetPropertyVisibility(AzPhysics::JointConfiguration::PropertyVisibility::ParentLocalRotation, jointLimitConfig != nullptr); + jointLimitConfig->SetPropertyVisibility(AzPhysics::JointConfiguration::PropertyVisibility::ChildLocalRotation, jointLimitConfig != nullptr); + m_addColliderButton->show(); m_addRemoveButton->setText("Remove from ragdoll"); From e4880cf9a18617b2504cf64ac73bc6b16996777c Mon Sep 17 00:00:00 2001 From: Tobias Alexander Franke Date: Tue, 21 Dec 2021 19:35:34 +0800 Subject: [PATCH 036/108] Fix: Right hand bones misplaced Signed-off-by: T.J. McGrath-Daly --- .../Code/EMotionFX/Rendering/Common/RenderUtil.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp index 6fd28ee72f..b1dd26061a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RenderUtil.cpp @@ -952,7 +952,15 @@ namespace MCommon } else { - worldTM = AZ::Transform::CreateFromQuaternion(MCore::AzEulerAnglesToAzQuat(0.0f, 0.0f, MCore::Math::DegreesToRadians(180.0f))); + if (direction.GetX() > 0) + { + worldTM = AZ::Transform::CreateFromQuaternion(MCore::AzEulerAnglesToAzQuat(MCore::Math::DegreesToRadians(180.0f), 0.0f, MCore::Math::DegreesToRadians(180.0f))); + } + else + { + worldTM = AZ::Transform::CreateFromQuaternion(MCore::AzEulerAnglesToAzQuat(0.0f, 0.0f, 0.0f)); + } + } // set the cylinder to the given position From a891993c35091f4eb3f18ff1ac91c944b08d22ef Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Tue, 4 Jan 2022 09:58:30 -0800 Subject: [PATCH 037/108] Remove 'INF' from integer widget and replace it with better formatted integers. Also fix warning message with invalid param Signed-off-by: mrieggeramzn --- .../UI/PropertyEditor/PropertyIntCtrlCommon.h | 39 +++++++------------ 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h index bb7d03367b..7d3e7191e3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h @@ -93,23 +93,13 @@ namespace AzToolsFramework toolTipString += "\n"; } toolTipString += "["; - if (propertyControl->minimum() <= aznumeric_cast(QtWidgetLimits::Min())) - { - toolTipString += "-" + QObject::tr(PropertyQTConstant_InfinityString); - } - else - { - toolTipString += QString::number(propertyControl->minimum()); - } + + const QString minString = QLocale().toString(propertyControl->minimum()); + const QString maxString = QLocale().toString(propertyControl->maximum()); + + toolTipString += minString; toolTipString += ", "; - if (propertyControl->maximum() >= aznumeric_cast(QtWidgetLimits::Max())) - { - toolTipString += QObject::tr(PropertyQTConstant_InfinityString); - } - else - { - toolTipString += QString::number(propertyControl->maximum()); - } + toolTipString += maxString; toolTipString += "]"; return true; } @@ -128,15 +118,12 @@ namespace AzToolsFramework { toolTipString += "\n"; } - toolTipString += "[" + QString::number(propertyControl->minimum()) + ", "; - if (propertyControl->maximum() >= aznumeric_cast(QtWidgetLimits::Max())) - { - toolTipString += QObject::tr(PropertyQTConstant_InfinityString); - } - else - { - toolTipString += QString::number(propertyControl->maximum()); - } + + const QString minString = QLocale().toString(propertyControl->minimum()); + const QString maxString = QLocale().toString(propertyControl->maximum()); + + toolTipString += "[" + minString + ", "; + toolTipString += maxString; toolTipString += "]"; return true; } @@ -196,7 +183,7 @@ namespace AzToolsFramework } else { - AZ_WarningOnce("AzToolsFramework", false, "Property %s: 'Min' attribute from property '%s' into widget", debugName); + AZ_WarningOnce("AzToolsFramework", false, "Failed to read 'Min' attribute from property '%s' into widget", debugName); } } else if (attrib == AZ::Edit::Attributes::Max) From d343caa3f2d846610b4b1a29adac682d9e567867 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 4 Jan 2022 11:58:17 -0800 Subject: [PATCH 038/108] add optional force_get to get_property_tree Signed-off-by: Scott Murray --- .../editor_python_test_tools/editor_entity_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index 0878431054..4dd7ec1446 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -50,7 +50,7 @@ class EditorComponent: assert len(type_names) != 0, "Component object does not have type id" return type_names[0] - def get_property_tree(self): + def get_property_tree(self, force_get: bool = False): """ Used to get the property tree object of component that has following functions associated with it: 1. prop_tree.is_container(path) @@ -60,9 +60,10 @@ class EditorComponent: 5. prop_tree.remove_container_item(path, key) 6. prop_tree.update_container_item(path, key, value) 7. prop_tree.get_container_item(path, key) + :param force_get: Force a fresh property tree to be returned rather than using an existing self.property_tree :return: Property tree object of a component """ - if self.property_tree is not None: + if (not force_get) and (self.property_tree is not None): return self.property_tree build_prop_tree_outcome = editor.EditorComponentAPIBus( @@ -244,6 +245,7 @@ class EditorComponent: def disable_component(self): """ Used to disable the component using its id value. + Deprecation warning! Use set_enable(False) instead as this method is in deprecation :return: None """ warnings.warn("disable_component is deprecated, use set_enabled(False) instead.", DeprecationWarning) From 30e21bc2d115f9309a3629df0ac71837861d8e8a Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Tue, 4 Jan 2022 14:52:00 -0800 Subject: [PATCH 039/108] Updating formatting Signed-off-by: mrieggeramzn --- .../UI/PropertyEditor/PropertyIntCtrlCommon.h | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h index 7d3e7191e3..504e3fd0dc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h @@ -92,15 +92,11 @@ namespace AzToolsFramework { toolTipString += "\n"; } - toolTipString += "["; const QString minString = QLocale().toString(propertyControl->minimum()); const QString maxString = QLocale().toString(propertyControl->maximum()); + toolTipString += QString("[%1, %2]").arg(minString).arg(maxString); - toolTipString += minString; - toolTipString += ", "; - toolTipString += maxString; - toolTipString += "]"; return true; } return false; @@ -121,10 +117,8 @@ namespace AzToolsFramework const QString minString = QLocale().toString(propertyControl->minimum()); const QString maxString = QLocale().toString(propertyControl->maximum()); + toolTipString += QString("[%1, %2]").arg(minString).arg(maxString); - toolTipString += "[" + minString + ", "; - toolTipString += maxString; - toolTipString += "]"; return true; } return false; From 41c0fb2b02a285c2682785d8ae22e54a652a1f0a Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Tue, 4 Jan 2022 17:41:58 -0800 Subject: [PATCH 040/108] Address some review feedback Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp | 2 +- Code/Framework/AzCore/AzCore/DOM/DomUtils.h | 2 +- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 248 +++++++++++------- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 38 +-- .../AzCore/AzCore/DOM/DomValueWriter.cpp | 4 +- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 4 +- .../AzCore/Tests/DOM/DomValueTests.cpp | 46 ++-- 7 files changed, 203 insertions(+), 141 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp index d65497e194..73c4bd2d76 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp @@ -22,7 +22,7 @@ namespace AZ::Dom::Utils return backend.ReadFromBufferInPlace(string.data(), string.size(), visitor); } - AZ::Outcome WriteToValue(Backend::WriteCallback writeCallback) + AZ::Outcome WriteToValue(const Backend::WriteCallback& writeCallback) { Value value; AZStd::unique_ptr writer = value.GetWriteHandler(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.h b/Code/Framework/AzCore/AzCore/DOM/DomUtils.h index f03e5b66b8..ebe4273b48 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.h @@ -16,5 +16,5 @@ namespace AZ::Dom::Utils Visitor::Result ReadFromString(Backend& backend, AZStd::string_view string, AZ::Dom::Lifetime lifetime, Visitor& visitor); Visitor::Result ReadFromStringInPlace(Backend& backend, AZStd::string& string, Visitor& visitor); - AZ::Outcome WriteToValue(Backend::WriteCallback writeCallback); + AZ::Outcome WriteToValue(const Backend::WriteCallback& writeCallback); } // namespace AZ::Dom::Utils diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 7401a5ac98..8c002b7091 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -12,22 +12,22 @@ namespace AZ::Dom { - template - AZStd::shared_ptr& CheckCopyOnWrite(AZStd::shared_ptr& refCountedPointer) - { - if (refCountedPointer.use_count() == 1) - { - return refCountedPointer; - } - else - { - refCountedPointer = AZStd::allocate_shared(StdValueAllocator(), *refCountedPointer); - return refCountedPointer; - } - } - namespace Internal { + template + AZStd::shared_ptr& CheckCopyOnWrite(AZStd::shared_ptr& refCountedPointer) + { + if (refCountedPointer.use_count() == 1) + { + return refCountedPointer; + } + else + { + refCountedPointer = AZStd::allocate_shared(StdValueAllocator(), *refCountedPointer); + return refCountedPointer; + } + } + template constexpr size_t GetTypeIndexInternal(size_t index = 0); @@ -288,107 +288,173 @@ namespace AZ::Dom Type Dom::Value::GetType() const { - switch (m_value.index()) - { - case GetTypeIndex(): - return Type::Null; - case GetTypeIndex(): - return Type::Int64; - case GetTypeIndex(): - return Type::Uint64; - case GetTypeIndex(): - return Type::Double; - case GetTypeIndex(): - return Type::Bool; - case GetTypeIndex(): - case GetTypeIndex(): - case GetTypeIndex(): - return Type::String; - case GetTypeIndex(): - return Type::Object; - case GetTypeIndex(): - return Type::Array; - case GetTypeIndex(): - return Type::Node; - case GetTypeIndex>(): - return Type::Opaque; - } - AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); - return Type::Null; + return AZStd::visit( + [](auto&& value) -> Type + { + using CurrentType = AZStd::decay_t; + if constexpr (AZStd::is_same_v) + { + return Type::Null; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Int64; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Uint64; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Double; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Bool; + } + else if constexpr (AZStd::is_same_v) + { + return Type::String; + } + else if constexpr (AZStd::is_same_v) + { + return Type::String; + } + else if constexpr (AZStd::is_same_v) + { + return Type::String; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Object; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Array; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Node; + } + else if constexpr (AZStd::is_same_v) + { + return Type::Opaque; + } + else + { + static_assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); + } + }, + m_value); } bool Value::IsNull() const { - return GetType() == Type::Null; + return AZStd::holds_alternative(m_value); } bool Value::IsFalse() const { - return IsBool() && !AZStd::get(m_value); + const bool* value = AZStd::get_if(&m_value); + return value != nullptr ? !(*value) : false; } bool Value::IsTrue() const { - return IsBool() && AZStd::get(m_value); + const bool* value = AZStd::get_if(&m_value); + return value != nullptr ? *value : false; } bool Value::IsBool() const { - return GetType() == Type::Bool; + return AZStd::holds_alternative(m_value); } bool Value::IsNode() const { - return GetType() == Type::Node; + return AZStd::holds_alternative(m_value); } bool Value::IsObject() const { - return GetType() == Type::Object; + return AZStd::holds_alternative(m_value); } bool Value::IsArray() const { - return GetType() == Type::Array; + return AZStd::holds_alternative(m_value); } bool Value::IsOpaqueValue() const { - return GetType() == Type::Opaque; + return AZStd::holds_alternative(m_value); } bool Value::IsNumber() const { - switch (GetType()) - { - case Type::Int64: - [[fallthrough]]; - case Type::Uint64: - [[fallthrough]]; - case Type::Double: - return true; - } - return false; + return AZStd::visit( + [](auto&& value) -> bool + { + using CurrentType = AZStd::decay_t; + if constexpr (AZStd::is_same_v) + { + return true; + } + else if constexpr (AZStd::is_same_v) + { + return true; + } + else if constexpr (AZStd::is_same_v) + { + return true; + } + else + { + return false; + } + }, + m_value); } bool Value::IsInt() const { - return GetType() == Type::Int64; + return AZStd::holds_alternative(m_value); } bool Value::IsUint() const { - return GetType() == Type::Uint64; + return AZStd::holds_alternative(m_value); } bool Value::IsDouble() const { - return GetType() == Type::Double; + return AZStd::holds_alternative(m_value); } bool Value::IsString() const { - return GetType() == Type::String; + return AZStd::visit( + [](auto&& value) -> bool + { + using CurrentType = AZStd::decay_t; + if constexpr (AZStd::is_same_v) + { + return true; + } + else if constexpr (AZStd::is_same_v) + { + return true; + } + else if constexpr (AZStd::is_same_v) + { + return true; + } + else + { + return false; + } + }, + m_value); } Value& Value::SetObject() @@ -406,7 +472,7 @@ namespace AZ::Dom Node& Value::GetNodeInternal() { AZ_Assert(GetType() == Type::Node, "AZ::Dom::Value: attempted to retrieve a node from a non-node value"); - return *CheckCopyOnWrite(AZStd::get(m_value)); + return *Internal::CheckCopyOnWrite(AZStd::get(m_value)); } const Object::ContainerType& Value::GetObjectInternal() const @@ -433,11 +499,11 @@ namespace AZ::Dom "AZ::Dom::Value: attempted to retrieve an object from a value that isn't an object or a node"); if (type == Type::Object) { - return CheckCopyOnWrite(AZStd::get(m_value))->m_values; + return Internal::CheckCopyOnWrite(AZStd::get(m_value))->m_values; } else { - return CheckCopyOnWrite(AZStd::get(m_value))->GetProperties(); + return Internal::CheckCopyOnWrite(AZStd::get(m_value))->GetProperties(); } } @@ -465,11 +531,11 @@ namespace AZ::Dom "AZ::Dom::Value: attempted to retrieve an array from a value that isn't an array or node"); if (type == Type::Array) { - return CheckCopyOnWrite(AZStd::get(m_value))->m_values; + return Internal::CheckCopyOnWrite(AZStd::get(m_value))->m_values; } else { - return CheckCopyOnWrite(AZStd::get(m_value))->GetChildren(); + return Internal::CheckCopyOnWrite(AZStd::get(m_value))->GetChildren(); } } @@ -698,22 +764,22 @@ namespace AZ::Dom return *this; } - size_t Value::Size() const + size_t Value::ArraySize() const { return GetArrayInternal().size(); } - size_t Value::Capacity() const + size_t Value::ArrayCapacity() const { return GetArrayInternal().capacity(); } - bool Value::Empty() const + bool Value::IsArrayEmpty() const { return GetArrayInternal().empty(); } - void Value::Clear() + void Value::ClearArray() { GetArrayInternal().clear(); } @@ -728,43 +794,43 @@ namespace AZ::Dom return GetArrayInternal()[index]; } - Value& Value::MutableAt(size_t index) + Value& Value::MutableArrayAt(size_t index) { return operator[](index); } - const Value& Value::At(size_t index) const + const Value& Value::ArrayAt(size_t index) const { return operator[](index); } - Array::ConstIterator Value::Begin() const + Array::ConstIterator Value::ArrayBegin() const { return GetArrayInternal().begin(); } - Array::ConstIterator Value::End() const + Array::ConstIterator Value::ArrayEnd() const { return GetArrayInternal().end(); } - Array::Iterator Value::Begin() + Array::Iterator Value::ArrayBegin() { return GetArrayInternal().begin(); } - Array::Iterator Value::End() + Array::Iterator Value::ArrayEnd() { return GetArrayInternal().end(); } - Value& Value::Reserve(size_t newCapacity) + Value& Value::ArrayReserve(size_t newCapacity) { GetArrayInternal().reserve(newCapacity); return *this; } - Value& Value::PushBack(Value value) + Value& Value::ArrayPushBack(Value value) { Array::ContainerType& array = GetArrayInternal(); array.reserve((array.size() / Array::ReserveIncrement + 1) * Array::ReserveIncrement); @@ -772,18 +838,18 @@ namespace AZ::Dom return *this; } - Value& Value::PopBack() + Value& Value::ArrayPopBack() { GetArrayInternal().pop_back(); return *this; } - Array::Iterator Value::Erase(Array::ConstIterator pos) + Array::Iterator Value::ArrayErase(Array::ConstIterator pos) { return GetArrayInternal().erase(pos); } - Array::Iterator Value::Erase(Array::ConstIterator first, Array::ConstIterator last) + Array::Iterator Value::ArrayErase(Array::ConstIterator first, Array::ConstIterator last) { return GetArrayInternal().erase(first, last); } @@ -1007,13 +1073,6 @@ namespace AZ::Dom void Value::SetString(AZStd::string_view value) { - if (value.size() <= ShortStringSize) - { - ShortStringType buffer; - buffer.resize_no_construct(value.size()); - memcpy(buffer.data(), value.data(), value.size()); - m_value = buffer; - } m_value = value; } @@ -1021,7 +1080,10 @@ namespace AZ::Dom { if (value.size() <= ShortStringSize) { - SetString(value); + ShortStringType buffer; + buffer.resize_no_construct(value.size()); + memcpy(buffer.data(), value.data(), value.size()); + m_value = buffer; } else { @@ -1035,9 +1097,9 @@ namespace AZ::Dom return *AZStd::get(m_value); } - void Value::SetOpaqueValue(const AZStd::any& value) + void Value::SetOpaqueValue(AZStd::any value) { - m_value = AZStd::allocate_shared(StdValueAllocator(), value); + m_value = AZStd::allocate_shared(StdValueAllocator(), AZStd::move(value)); } void Value::SetNull() diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index b73da92d23..d67947dd0a 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -103,9 +103,9 @@ namespace AZ::Dom { public: Node() = default; + Node(const Node&) = default; + Node(Node&&) = default; explicit Node(AZ::Name name); - explicit Node(const Node&) = default; - explicit Node(Node&&) = default; Node& operator=(const Node&) = default; Node& operator=(Node&&) = default; @@ -174,7 +174,7 @@ namespace AZ::Dom double, // Bool bool, - // StringType + // String AZStd::string_view, SharedStringType, ShortStringType, @@ -280,28 +280,28 @@ namespace AZ::Dom // Array API (also used by Node)... Value& SetArray(); - size_t Size() const; - size_t Capacity() const; - bool Empty() const; - void Clear(); + size_t ArraySize() const; + size_t ArrayCapacity() const; + bool IsArrayEmpty() const; + void ClearArray(); Value& operator[](size_t index); const Value& operator[](size_t index) const; - Value& MutableAt(size_t index); - const Value& At(size_t index) const; + Value& MutableArrayAt(size_t index); + const Value& ArrayAt(size_t index) const; - Array::ConstIterator Begin() const; - Array::ConstIterator End() const; - Array::Iterator Begin(); - Array::Iterator End(); + Array::ConstIterator ArrayBegin() const; + Array::ConstIterator ArrayEnd() const; + Array::Iterator ArrayBegin(); + Array::Iterator ArrayEnd(); - Value& Reserve(size_t newCapacity); - Value& PushBack(Value value); - Value& PopBack(); + Value& ArrayReserve(size_t newCapacity); + Value& ArrayPushBack(Value value); + Value& ArrayPopBack(); - Array::Iterator Erase(Array::ConstIterator pos); - Array::Iterator Erase(Array::ConstIterator first, Array::ConstIterator last); + Array::Iterator ArrayErase(Array::ConstIterator pos); + Array::Iterator ArrayErase(Array::ConstIterator first, Array::ConstIterator last); Array::ContainerType& GetMutableArray(); const Array::ContainerType& GetArray() const; @@ -365,7 +365,7 @@ namespace AZ::Dom //! serialize an opaque type into a DOM value instead, as serializers //! and other systems will have no means of dealing with fully arbitrary //! values. - void SetOpaqueValue(const AZStd::any&); + void SetOpaqueValue(AZStd::any); // Null API... void SetNull(); diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp index 210d1fa123..433e650d04 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValueWriter.cpp @@ -129,7 +129,7 @@ namespace AZ::Dom AZStd::string::format("AZ::Dom::ValueWriter: %s called from within a different container type", endMethodName)); } - if (static_cast(buffer.m_attributes.size()) != attributeCount) + if (aznumeric_cast(buffer.m_attributes.size()) != attributeCount) { return VisitorFailure( VisitorErrorCode::InternalError, @@ -138,7 +138,7 @@ namespace AZ::Dom buffer.m_attributes.size())); } - if (static_cast(buffer.m_elements.size()) != elementCount) + if (aznumeric_cast(buffer.m_elements.size()) != elementCount) { return VisitorFailure( VisitorErrorCode::InternalError, diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index 12684c64bc..74eb78be00 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -77,7 +77,7 @@ namespace AZ::Dom::Benchmark Value array(Type::Array); for (int i = 0; i < entryCount; ++i) { - array.PushBack(createEntry(i)); + array.ArrayPushBack(createEntry(i)); } return array; }; @@ -152,7 +152,7 @@ namespace AZ::Dom::Benchmark for (auto _ : state) { Value copy = original; - copy["entries"]["Key0"].PushBack(42); + copy["entries"]["Key0"].ArrayPushBack(42); TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state); } diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index b88ab746b9..3cbd532b13 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -55,7 +55,7 @@ namespace AZ::Dom::Tests m_value.SetArray(); EXPECT_TRUE(m_value.IsArray()); - EXPECT_EQ(m_value.Size(), 0); + EXPECT_EQ(m_value.ArraySize(), 0); PerformValueChecks(); } @@ -66,8 +66,8 @@ namespace AZ::Dom::Tests for (int i = 0; i < 5; ++i) { - m_value.PushBack(Value(i)); - EXPECT_EQ(m_value.Size(), i + 1); + m_value.ArrayPushBack(Value(i)); + EXPECT_EQ(m_value.ArraySize(), i + 1); EXPECT_EQ(m_value[i].GetInt32(), i); } @@ -82,15 +82,15 @@ namespace AZ::Dom::Tests Value nestedArray(Type::Array); for (int i = 0; i < 5; ++i) { - nestedArray.PushBack(Value(i)); + nestedArray.ArrayPushBack(Value(i)); } - m_value.PushBack(AZStd::move(nestedArray)); + m_value.ArrayPushBack(AZStd::move(nestedArray)); } - EXPECT_EQ(m_value.Size(), 5); + EXPECT_EQ(m_value.ArraySize(), 5); for (int i = 0; i < 3; ++i) { - EXPECT_EQ(m_value[i].Size(), 5); + EXPECT_EQ(m_value[i].ArraySize(), 5); for (int j = 0; j < 5; ++j) { EXPECT_EQ(m_value[i][j].GetInt32(), j); @@ -154,7 +154,7 @@ namespace AZ::Dom::Tests m_value.SetNode("Test"); EXPECT_EQ(m_value.GetNodeName(), AZ::Name("Test")); EXPECT_EQ(m_value.MemberCount(), 0); - EXPECT_EQ(m_value.Size(), 0); + EXPECT_EQ(m_value.ArraySize(), 0); PerformValueChecks(); } @@ -165,8 +165,8 @@ namespace AZ::Dom::Tests for (int i = 0; i < 10; ++i) { - m_value.PushBack(Value(i)); - EXPECT_EQ(m_value.Size(), i + 1); + m_value.ArrayPushBack(Value(i)); + EXPECT_EQ(m_value.ArraySize(), i + 1); EXPECT_EQ(m_value[i].GetInt32(), i); if (i < 5) @@ -196,10 +196,10 @@ namespace AZ::Dom::Tests childNode.AddMember("foo", i); childNode.AddMember("bar", Value("test", false)); - m_value.PushBack(childNode); + m_value.ArrayPushBack(childNode); } - EXPECT_EQ(m_value.Size(), 5); + EXPECT_EQ(m_value.ArraySize(), 5); for (int i = 0; i < 5; ++i) { const Value& childNode = m_value[i]; @@ -334,30 +334,30 @@ namespace AZ::Dom::Tests TEST_F(DomValueTests, CopyOnWrite_Array) { Value v1(Type::Array); - v1.PushBack(1); - v1.PushBack(2); + v1.ArrayPushBack(1); + v1.ArrayPushBack(2); Value nestedArray(Type::Array); - v1.PushBack(nestedArray); + v1.ArrayPushBack(nestedArray); Value v2 = v1; EXPECT_EQ(&v1.GetArray(), &v2.GetArray()); - EXPECT_EQ(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + EXPECT_EQ(&v1.ArrayAt(2).GetArray(), &v2.ArrayAt(2).GetArray()); v2[0] = 0; EXPECT_NE(&v1.GetArray(), &v2.GetArray()); - EXPECT_EQ(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + EXPECT_EQ(&v1.ArrayAt(2).GetArray(), &v2.ArrayAt(2).GetArray()); - v2[2].PushBack(42); + v2[2].ArrayPushBack(42); EXPECT_NE(&v1.GetArray(), &v2.GetArray()); - EXPECT_NE(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + EXPECT_NE(&v1.ArrayAt(2).GetArray(), &v2.ArrayAt(2).GetArray()); v2 = v1; EXPECT_EQ(&v1.GetArray(), &v2.GetArray()); - EXPECT_EQ(&v1.At(2).GetArray(), &v2.At(2).GetArray()); + EXPECT_EQ(&v1.ArrayAt(2).GetArray(), &v2.ArrayAt(2).GetArray()); } TEST_F(DomValueTests, CopyOnWrite_Node) @@ -365,8 +365,8 @@ namespace AZ::Dom::Tests Value v1; v1.SetNode("TopLevel"); - v1.PushBack(1); - v1.PushBack(2); + v1.ArrayPushBack(1); + v1.ArrayPushBack(2); v1["obj"].SetNode("Nested"); Value v2 = v1; @@ -378,7 +378,7 @@ namespace AZ::Dom::Tests EXPECT_NE(&v1.GetNode(), &v2.GetNode()); EXPECT_EQ(&v1["obj"].GetNode(), &v2["obj"].GetNode()); - v2["obj"].PushBack(42); + v2["obj"].ArrayPushBack(42); EXPECT_NE(&v1.GetNode(), &v2.GetNode()); EXPECT_NE(&v1["obj"].GetNode(), &v2["obj"].GetNode()); From 8ed3da5b7f9916474e3e1de2188d23093bf68549 Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Wed, 5 Jan 2022 10:24:53 -0800 Subject: [PATCH 041/108] Adding header file Signed-off-by: mrieggeramzn --- .../AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h index 504e3fd0dc..ed428eeac5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h @@ -14,6 +14,7 @@ #include #include #include +#include namespace AzToolsFramework { From acc6248ec98ef8cd24ea057f679d90ca6be812e5 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 5 Jan 2022 11:31:09 -0800 Subject: [PATCH 042/108] Move deep comparison / copy to utils Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp | 148 +++++++++++++++++ Code/Framework/AzCore/AzCore/DOM/DomUtils.h | 3 + Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 155 +++--------------- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 13 +- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 3 +- .../AzCore/Tests/DOM/DomValueTests.cpp | 6 +- 6 files changed, 186 insertions(+), 142 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp index 73c4bd2d76..c604373296 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.cpp @@ -33,4 +33,152 @@ namespace AZ::Dom::Utils } return AZ::Success(AZStd::move(value)); } + + bool DeepCompareIsEqual(const Value& lhs, const Value& rhs) + { + const Value::ValueType& lhsValue = lhs.GetInternalValue(); + const Value::ValueType& rhsValue = rhs.GetInternalValue(); + + if (lhs.IsString() && rhs.IsString()) + { + // If we both hold the same ref counted string we don't need to do a full comparison + if (AZStd::holds_alternative(lhsValue) && lhsValue == rhsValue) + { + return true; + } + return lhs.GetString() == rhs.GetString(); + } + + return AZStd::visit( + [&](auto&& ourValue) -> bool + { + using Alternative = AZStd::decay_t; + + if constexpr (AZStd::is_same_v) + { + if (!rhs.IsObject()) + { + return false; + } + auto&& theirValue = AZStd::get>(rhsValue); + if (ourValue == theirValue) + { + return true; + } + + const Object::ContainerType& ourValues = ourValue->GetValues(); + const Object::ContainerType& theirValues = theirValue->GetValues(); + + if (ourValues.size() != theirValues.size()) + { + return false; + } + + for (size_t i = 0; i < ourValues.size(); ++i) + { + const Object::EntryType& lhsChild = ourValues[i]; + const Object::EntryType& rhsChild = theirValues[i]; + if (lhsChild.first != rhsChild.first || !DeepCompareIsEqual(lhsChild.second, rhsChild.second)) + { + return false; + } + } + + return true; + } + else if constexpr (AZStd::is_same_v) + { + if (!rhs.IsArray()) + { + return false; + } + auto&& theirValue = AZStd::get>(rhsValue); + if (ourValue == theirValue) + { + return true; + } + + const Array::ContainerType& ourValues = ourValue->GetValues(); + const Array::ContainerType& theirValues = theirValue->GetValues(); + + if (ourValues.size() != theirValues.size()) + { + return false; + } + + for (size_t i = 0; i < ourValues.size(); ++i) + { + const Value& lhsChild = ourValues[i]; + const Value& rhsChild = theirValues[i]; + if (!DeepCompareIsEqual(lhsChild, rhsChild)) + { + return false; + } + } + + return true; + } + else if constexpr (AZStd::is_same_v) + { + if (!rhs.IsNode()) + { + return false; + } + auto&& theirValue = AZStd::get>(rhsValue); + if (ourValue == theirValue) + { + return true; + } + + const Node& ourNode = *ourValue; + const Node& theirNode = *theirValue; + + const Object::ContainerType& ourProperties = ourNode.GetProperties(); + const Object::ContainerType& theirProperties = theirNode.GetProperties(); + + if (ourProperties.size() != theirProperties.size()) + { + return false; + } + + for (size_t i = 0; i < ourProperties.size(); ++i) + { + const Object::EntryType& lhsChild = ourProperties[i]; + const Object::EntryType& rhsChild = theirProperties[i]; + if (lhsChild.first != rhsChild.first || !DeepCompareIsEqual(lhsChild.second, rhsChild.second)) + { + return false; + } + } + + const Array::ContainerType& ourChildren = ourNode.GetChildren(); + const Array::ContainerType& theirChildren = theirNode.GetChildren(); + + for (size_t i = 0; i < ourChildren.size(); ++i) + { + const Value& lhsChild = ourChildren[i]; + const Value& rhsChild = theirChildren[i]; + if (!DeepCompareIsEqual(lhsChild, rhsChild)) + { + return false; + } + } + + return true; + } + else + { + return lhs == rhs; + } + }, + lhsValue); + } + + Value DeepCopy(const Value& value, bool copyStrings) + { + Value copiedValue; + AZStd::unique_ptr writer = copiedValue.GetWriteHandler(); + value.Accept(*writer, copyStrings); + return copiedValue; + } } // namespace AZ::Dom::Utils diff --git a/Code/Framework/AzCore/AzCore/DOM/DomUtils.h b/Code/Framework/AzCore/AzCore/DOM/DomUtils.h index ebe4273b48..5403b93714 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomUtils.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomUtils.h @@ -17,4 +17,7 @@ namespace AZ::Dom::Utils Visitor::Result ReadFromStringInPlace(Backend& backend, AZStd::string& string, Visitor& visitor); AZ::Outcome WriteToValue(const Backend::WriteCallback& writeCallback); + + bool DeepCompareIsEqual(const Value& lhs, const Value& rhs); + Value DeepCopy(const Value& value, bool copyStrings = true); } // namespace AZ::Dom::Utils diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 8c002b7091..af6d86d699 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -67,6 +67,16 @@ namespace AZ::Dom return Internal::ExtractTypeArgs::GetTypeIndex(); } + const Array::ContainerType& Array::GetValues() const + { + return m_values; + } + + const Object::ContainerType& Object::GetValues() const + { + return m_values; + } + Node::Node(AZ::Name name) : m_name(AZStd::move(name)) { @@ -130,8 +140,8 @@ namespace AZ::Dom } } - Value::Value(const AZStd::any& value) - : m_value(AZStd::allocate_shared(StdValueAllocator(), value)) + Value::Value(AZStd::any opaqueValue) + : m_value(AZStd::allocate_shared(StdValueAllocator(), AZStd::move(opaqueValue))) { } @@ -660,7 +670,9 @@ namespace AZ::Dom Value& Value::AddMember(KeyType name, const Value& value) { Object::ContainerType& object = GetObjectInternal(); - object.reserve((object.size() / Object::ReserveIncrement + 1) * Object::ReserveIncrement); + // Reserve in ReserveIncremenet chunks instead of the default vector doubling strategy + // Profiling has found that this is an aggregate performance gain for typical workflows + object.reserve(AZ_SIZE_ALIGN_UP(object.size() + 1, Object::ReserveIncrement)); if (auto memberIt = FindMutableMember(name); memberIt != object.end()) { memberIt->second = value; @@ -833,7 +845,9 @@ namespace AZ::Dom Value& Value::ArrayPushBack(Value value) { Array::ContainerType& array = GetArrayInternal(); - array.reserve((array.size() / Array::ReserveIncrement + 1) * Array::ReserveIncrement); + // Reserve in ReserveIncremenet chunks instead of the default vector doubling strategy + // Profiling has found that this is an aggregate performance gain for typical workflows + array.reserve(AZ_SIZE_ALIGN_UP(array.size() + 1, Array::ReserveIncrement)); array.push_back(AZStd::move(value)); return *this; } @@ -1231,137 +1245,8 @@ namespace AZ::Dom return AZStd::make_unique(*this); } - bool Value::DeepCompareIsEqual(const Value& other) const + const Value::ValueType& Value::GetInternalValue() const { - if (IsString() && other.IsString()) - { - // If we both hold the same ref counted string we don't need to do a full comparison - if (AZStd::holds_alternative(m_value) && m_value == other.m_value) - { - return true; - } - return GetString() == other.GetString(); - } - - if (m_value.index() != other.m_value.index()) - { - return false; - } - - return AZStd::visit( - [&](auto&& ourValue) -> bool - { - using Alternative = AZStd::decay_t; - auto&& theirValue = AZStd::get>(other.m_value); - - if constexpr (AZStd::is_same_v) - { - return true; - } - else if constexpr (AZStd::is_same_v) - { - if (ourValue == theirValue) - { - return true; - } - - if (ourValue->m_values.size() != theirValue->m_values.size()) - { - return false; - } - - for (size_t i = 0; i < ourValue->m_values.size(); ++i) - { - const Object::EntryType& lhs = ourValue->m_values[i]; - const Object::EntryType& rhs = theirValue->m_values[i]; - if (lhs.first != rhs.first || !lhs.second.DeepCompareIsEqual(rhs.second)) - { - return false; - } - } - - return true; - } - else if constexpr (AZStd::is_same_v) - { - if (ourValue == theirValue) - { - return true; - } - - if (ourValue->m_values.size() != theirValue->m_values.size()) - { - return false; - } - - for (size_t i = 0; i < ourValue->m_values.size(); ++i) - { - const Value& lhs = ourValue->m_values[i]; - const Value& rhs = theirValue->m_values[i]; - if (!lhs.DeepCompareIsEqual(rhs)) - { - return false; - } - } - - return true; - } - else if constexpr (AZStd::is_same_v) - { - if (ourValue == theirValue) - { - return true; - } - - const Node& ourNode = *ourValue; - const Node& theirNode = *theirValue; - - const Object::ContainerType& ourProperties = ourNode.GetProperties(); - const Object::ContainerType& theirProperties = theirNode.GetProperties(); - - if (ourProperties.size() != theirProperties.size()) - { - return false; - } - - for (size_t i = 0; i < ourProperties.size(); ++i) - { - const Object::EntryType& lhs = ourProperties[i]; - const Object::EntryType& rhs = theirProperties[i]; - if (lhs.first != rhs.first || !lhs.second.DeepCompareIsEqual(rhs.second)) - { - return false; - } - } - - const Array::ContainerType& ourChildren = ourNode.GetChildren(); - const Array::ContainerType& theirChildren = theirNode.GetChildren(); - - for (size_t i = 0; i < ourChildren.size(); ++i) - { - const Value& lhs = ourChildren[i]; - const Value& rhs = theirChildren[i]; - if (!lhs.DeepCompareIsEqual(rhs)) - { - return false; - } - } - - return true; - } - else - { - return ourValue == theirValue; - } - }, - m_value); - } - - Value Value::DeepCopy(bool copyStrings) const - { - Value newValue; - AZStd::unique_ptr writer = newValue.GetWriteHandler(); - Accept(*writer, copyStrings); - return newValue; + return m_value; } } // namespace AZ::Dom diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index d67947dd0a..a6990fcbce 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -67,6 +67,9 @@ namespace AZ::Dom using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; static constexpr const size_t ReserveIncrement = 4; + static_assert((ReserveIncrement & (ReserveIncrement - 1)) == 0, "ReserveIncremenet must be a power of 2"); + + const ContainerType& GetValues() const; private: ContainerType m_values; @@ -86,6 +89,9 @@ namespace AZ::Dom using Iterator = ContainerType::iterator; using ConstIterator = ContainerType::const_iterator; static constexpr const size_t ReserveIncrement = 8; + static_assert((ReserveIncrement & (ReserveIncrement - 1)) == 0, "ReserveIncremenet must be a power of 2"); + + const ContainerType& GetValues() const; private: ContainerType m_values; @@ -374,8 +380,9 @@ namespace AZ::Dom Visitor::Result Accept(Visitor& visitor, bool copyStrings) const; AZStd::unique_ptr GetWriteHandler(); - bool DeepCompareIsEqual(const Value& other) const; - Value DeepCopy(bool copyStrings = true) const; + //! Gets the internal value of this Value. Note that this value's types may not correspond one-to-one with the Type enumeration, + //! as internally the same type might have different storage mechanisms. Where possible, prefer using the typed API. + const ValueType& GetInternalValue() const; private: const Node& GetNodeInternal() const; @@ -385,7 +392,7 @@ namespace AZ::Dom const Array::ContainerType& GetArrayInternal() const; Array::ContainerType& GetArrayInternal(); - explicit Value(const AZStd::any& opaqueValue); + explicit Value(AZStd::any opaqueValue); static_assert( sizeof(ValueType) == sizeof(ShortStringType) + sizeof(size_t), "ValueType should have no members larger than ShortStringType"); diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index 74eb78be00..b20091b232 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -171,7 +172,7 @@ namespace AZ::Dom::Benchmark for (auto _ : state) { - Value copy = original.DeepCopy(); + Value copy = Utils::DeepCopy(original); TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state); } diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index 3cbd532b13..a98eb307a2 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -41,10 +41,10 @@ namespace AZ::Dom::Tests { Value shallowCopy = m_value; EXPECT_EQ(m_value, shallowCopy); - EXPECT_TRUE(m_value.DeepCompareIsEqual(shallowCopy)); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_value, shallowCopy)); - Value deepCopy = m_value.DeepCopy(); - EXPECT_TRUE(m_value.DeepCompareIsEqual(deepCopy)); + Value deepCopy = Utils::DeepCopy(m_value); + EXPECT_TRUE(Utils::DeepCompareIsEqual(m_value, deepCopy)); } Value m_value; From d347a9d2c034dea3878ce357060b7e040bee6885 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 5 Jan 2022 12:56:22 -0800 Subject: [PATCH 043/108] Fix Linux build (a static_assert unfortunately fires for Clang) Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index af6d86d699..824b38e47b 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -352,7 +352,7 @@ namespace AZ::Dom } else { - static_assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); + AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type"); } }, m_value); From 7d9f9f99e657af79cbe6000ccadfa79272c4410f Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Wed, 5 Jan 2022 14:50:03 -0800 Subject: [PATCH 044/108] fix unit test Signed-off-by: mrieggeramzn --- .../Tests/PropertyIntCtrlCommonTests.h | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h index 712eeb99b7..d4f0c8d705 100644 --- a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h +++ b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h @@ -12,6 +12,7 @@ #include #include "IntegerPrimtitiveTestConfig.h" #include +#include #include namespace UnitTest @@ -83,18 +84,6 @@ namespace UnitTest widget->setMaximum(widget->maximum() - 1); } - static std::string GetToolTipStringAtLimits() - { - if constexpr (std::is_signed::value) - { - return "[-INF, INF]"; - } - else - { - return "[0, INF]"; - } - } - void PropertyCtrlHandlersCreated() { using ::testing::Ne; @@ -125,15 +114,19 @@ namespace UnitTest auto& widget = m_widget; auto& handler = m_handler; QString tooltip; - std::string expected; + std::stringstream expected; // Retrieve the tooltip string for this widget auto success = handler->ModifyTooltip(widget, tooltip); - expected = GetToolTipStringAtLimits(); + + const QString minString = QLocale().toString(widget->minimum()); + const QString maxString = QLocale().toString(widget->maximum()); + + expected << "[" << minString.toStdString() << ", " << maxString.toStdString() << "]"; // Expect the operation to be successful and a valid limit tooltip string generated EXPECT_TRUE(success); - EXPECT_STREQ(tooltip.toStdString().c_str(), expected.c_str()); + EXPECT_STREQ(tooltip.toStdString().c_str(), expected.str().c_str()); } void HandlerMinMaxLessLimit_ModifyHandler_ExpectSuccessAndValidLessLimitToolTipString() @@ -149,7 +142,11 @@ namespace UnitTest // Retrieve the tooltip string for this widget auto success = handler->ModifyTooltip(widget, tooltip); - expected << "[" << widget->minimum() << ", " << widget->maximum() << "]"; + + const QString minString = QLocale().toString(widget->minimum()); + const QString maxString = QLocale().toString(widget->maximum()); + + expected << "[" << minString.toStdString() << ", " << maxString.toStdString() << "]"; // Expect the operation to be successful and a valid less than limit tooltip string generated EXPECT_TRUE(success); From 0bcb514c27299df1f09c8cdfe8e6e94247ff2f89 Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Wed, 5 Jan 2022 15:56:53 -0800 Subject: [PATCH 045/108] removing qlocale.h compile issue Signed-off-by: mrieggeramzn --- .../AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h index d4f0c8d705..1bd6f72a19 100644 --- a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h +++ b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h @@ -12,7 +12,6 @@ #include #include "IntegerPrimtitiveTestConfig.h" #include -#include #include namespace UnitTest From d378544bbc813d87db5b0a897e6024a914d72aae Mon Sep 17 00:00:00 2001 From: evanchia Date: Wed, 5 Jan 2022 17:06:44 -0800 Subject: [PATCH 046/108] Fixing crash log name bugs in test tools Signed-off-by: evanchia --- .../_internal/pytest_plugin/test_tools_fixtures.py | 2 +- .../ly_test_tools/o3de/editor_test_utils.py | 11 ++++++++++- .../LyTestTools/tests/unit/test_editor_test_utils.py | 12 +++++++++--- Tools/LyTestTools/tests/unit/test_fixtures.py | 11 +++++------ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/_internal/pytest_plugin/test_tools_fixtures.py b/Tools/LyTestTools/ly_test_tools/_internal/pytest_plugin/test_tools_fixtures.py index af29064766..1c17d6d519 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/pytest_plugin/test_tools_fixtures.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/pytest_plugin/test_tools_fixtures.py @@ -413,7 +413,7 @@ def crash_log_watchdog(request, workspace): def _crash_log_watchdog(request, workspace, raise_on_crash): """Separate implementation to call directly during unit tests""" - error_log = os.path.join(workspace.paths.project_log(), 'error.log') + error_log = workspace.paths.crash_log() crash_log_watchdog = ly_test_tools.environment.watchdog.CrashLogWatchdog( error_log, raise_on_condition=raise_on_crash) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py index 9f1e01342c..54ac67f56e 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py @@ -10,6 +10,7 @@ from __future__ import annotations import os import time import logging +import re import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.environment.waiter as waiter @@ -71,7 +72,15 @@ def retrieve_crash_output(run_id: int, workspace: AbstractWorkspaceManager, time :return str: The contents of the editor crash file (error.log) """ crash_info = "-- No crash log available --" - crash_log = os.path.join(retrieve_log_path(run_id, workspace), 'error.log') + error_log_regex = "" + log_path = retrieve_log_path(run_id, workspace) + # Gather all of the files in the log directory + dir_files = [f for f in os.listdir(log_path) if os.path.isfile(os.path.join(log_path, f))] + for file_name in dir_files: + # Search for all .log files with either "crash" or "error" because they could be renamed + if ("error" in file_name.lower() or "crash" in file_name.lower()) and (file_name.endswith(".log")): + crash_log = os.path.join(log_path, file_name) + break try: waiter.wait_for(lambda: os.path.exists(crash_log), timeout=timeout) except AssertionError: diff --git a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py index cd361d9e8a..f7678c44c0 100644 --- a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py +++ b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py @@ -59,22 +59,28 @@ class TestEditorTestUtils(unittest.TestCase): assert expected == editor_test_utils.retrieve_log_path(0, mock_workspace) + @mock.patch('os.listdir') @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') + @mock.patch('os.path.isfile', mock.MagicMock()) @mock.patch('ly_test_tools.environment.waiter.wait_for', mock.MagicMock()) - def test_RetrieveCrashOutput_CrashLogExists_ReturnsLogInfo(self, mock_retrieve_log_path): - mock_retrieve_log_path.return_value = 'mock_log_path' + def test_RetrieveCrashOutput_CrashLogExists_ReturnsLogInfo(self, mock_retrieve_log_path, mock_listdir): + mock_retrieve_log_path.return_value = 'mock_path' mock_workspace = mock.MagicMock() mock_log = 'mock crash info' + mock_listdir.return_value = ['mock_error_log.log'] with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: assert mock_log == editor_test_utils.retrieve_crash_output(0, mock_workspace, 0) + @mock.patch('os.listdir') @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') + @mock.patch('os.path.isfile', mock.MagicMock()) @mock.patch('ly_test_tools.environment.waiter.wait_for', mock.MagicMock()) - def test_RetrieveCrashOutput_CrashLogNotExists_ReturnsError(self, mock_retrieve_log_path): + def test_RetrieveCrashOutput_CrashLogNotExists_ReturnsError(self, mock_retrieve_log_path, mock_listdir): mock_retrieve_log_path.return_value = 'mock_log_path' mock_workspace = mock.MagicMock() error_message = "No crash log available" + mock_listdir.return_value = ['mock_file.log'] assert error_message in editor_test_utils.retrieve_crash_output(0, mock_workspace, 0) diff --git a/Tools/LyTestTools/tests/unit/test_fixtures.py b/Tools/LyTestTools/tests/unit/test_fixtures.py index 32dc204bd2..eb36cf6998 100755 --- a/Tools/LyTestTools/tests/unit/test_fixtures.py +++ b/Tools/LyTestTools/tests/unit/test_fixtures.py @@ -323,20 +323,19 @@ class TestFixtures(object): @mock.patch('ly_test_tools.environment.watchdog.CrashLogWatchdog') def test_CrashLogWatchdog_Instantiates_CreatesWatchdog(self, under_test): mock_workspace = mock.MagicMock() - mock_path = 'C:/foo' - mock_workspace.paths.project_log.return_value = mock_path + mock_workspace.paths.crash_log.return_value = mock.MagicMock() mock_request = mock.MagicMock() mock_request.addfinalizer = mock.MagicMock() mock_raise_on_crash = mock.MagicMock() mock_watchdog = test_tools_fixtures._crash_log_watchdog(mock_request, mock_workspace, mock_raise_on_crash) - under_test.assert_called_once_with(os.path.join(mock_path, 'error.log'), raise_on_condition=mock_raise_on_crash) + under_test.assert_called_once_with(mock_workspace.paths.crash_log.return_value, raise_on_condition=mock_raise_on_crash) @mock.patch('ly_test_tools.environment.watchdog.CrashLogWatchdog.start') def test_CrashLogWatchdog_Instantiates_StartsThread(self, under_test): mock_workspace = mock.MagicMock() mock_path = 'C:/foo' - mock_workspace.paths.project_log.return_value = mock_path + mock_workspace.paths.crash_log.return_value = mock_path mock_request = mock.MagicMock() mock_request.addfinalizer = mock.MagicMock() mock_raise_on_crash = mock.MagicMock() @@ -348,7 +347,7 @@ class TestFixtures(object): def test_CrashLogWatchdog_Instantiates_AddsTeardown(self): mock_workspace = mock.MagicMock() mock_path = 'C:/foo' - mock_workspace.paths.project_log.return_value = mock_path + mock_workspace.paths.crash_log.return_value = mock_path mock_request = mock.MagicMock() mock_request.addfinalizer = mock.MagicMock() mock_raise_on_crash = mock.MagicMock() @@ -361,7 +360,7 @@ class TestFixtures(object): def test_CrashLogWatchdog_Teardown_CallsStop(self, mock_stop): mock_workspace = mock.MagicMock() mock_path = 'C:/foo' - mock_workspace.paths.project_log.return_value = mock_path + mock_workspace.paths.crash_log.return_value = mock_path mock_request = mock.MagicMock() mock_request.addfinalizer = mock.MagicMock() mock_raise_condition = mock.MagicMock() From 52ab5a1c0fb5f0744df0c879844ca3512b48109d Mon Sep 17 00:00:00 2001 From: evanchia Date: Wed, 5 Jan 2022 17:10:18 -0800 Subject: [PATCH 047/108] removing unused import Signed-off-by: evanchia --- Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py index 54ac67f56e..69c6eda2ee 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py @@ -10,7 +10,6 @@ from __future__ import annotations import os import time import logging -import re import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.environment.waiter as waiter From 5f9a4a5eed421480094884b2b78ac309d2d77fde Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 5 Jan 2022 17:21:55 -0800 Subject: [PATCH 048/108] docstring clarification and addressing review comments Signed-off-by: Scott Murray --- .../editor_entity_utils.py | 95 +++++++++++-------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index 4dd7ec1446..d354c4ece6 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -22,7 +22,7 @@ import azlmbr.legacy.general as general from editor_python_test_tools.utils import Report -class Entity_Type(Enum): +class EditorEntityType(Enum): GAME = azlmbr.entity.EntityType().Game LEVEL = azlmbr.entity.EntityType().Level @@ -39,7 +39,7 @@ class EditorComponent: def __init__(self, type_id: uuid): self.type_id = type_id self.id = None - self.property_tree = None + self.property_tree_editor = None def get_component_name(self) -> str: """ @@ -52,7 +52,7 @@ class EditorComponent: def get_property_tree(self, force_get: bool = False): """ - Used to get the property tree object of component that has following functions associated with it: + Used to get and cache the property tree editor of component that has following functions associated with it: 1. prop_tree.is_container(path) 2. prop_tree.get_container_count(path) 3. prop_tree.reset_container(path) @@ -60,32 +60,36 @@ class EditorComponent: 5. prop_tree.remove_container_item(path, key) 6. prop_tree.update_container_item(path, key, value) 7. prop_tree.get_container_item(path, key) - :param force_get: Force a fresh property tree to be returned rather than using an existing self.property_tree - :return: Property tree object of a component + :param force_get: Force a fresh property tree editor rather than the cached self.property_tree_editor + :return: Property tree editor of the component """ - if (not force_get) and (self.property_tree is not None): - return self.property_tree + if (not force_get) and (self.property_tree_editor is not None): + return self.property_tree_editor build_prop_tree_outcome = editor.EditorComponentAPIBus( bus.Broadcast, "BuildComponentPropertyTreeEditor", self.id ) assert ( build_prop_tree_outcome.IsSuccess() - ), f"Failure: Could not build property tree of component: '{self.get_component_name()}'" + ), f"Failure: Could not build property tree editor of component: '{self.get_component_name()}'" prop_tree = build_prop_tree_outcome.GetValue() Report.info(prop_tree.build_paths_list()) - self.property_tree = prop_tree - return self.property_tree + self.property_tree_editor = prop_tree + return self.property_tree_editor def is_property_container(self, component_property_path: str) -> bool: """ - Used to determine if a component property is a container. Containers are similar to a dictionary with int keys. + Used to determine if a component property is a container. + Containers are a collection of same typed values that can expand/shrink to contain more or less. + There are two types of containers; indexed and associative. + Indexed containers use integer key and are something like a linked list + Associative containers utilize keys of the same type which could be any supported type. :param component_property_path: String of component property. (e.g. 'Settings|Visible') :return: Boolean True if the property is a container False if it is not. """ - if self.property_tree is None: + if self.property_tree_editor is None: self.get_property_tree() - result = self.property_tree.is_container(component_property_path) + result = self.property_tree_editor.is_container(component_property_path) if not result: Report.info(f"{self.get_component_name()}: '{component_property_path}' is not a container") return result @@ -99,7 +103,7 @@ class EditorComponent: assert ( self.is_property_container(component_property_path) ), f"Failure: '{component_property_path}' is not a property container" - container_count_outcome = self.property_tree.get_container_count(component_property_path) + container_count_outcome = self.property_tree_editor.get_container_count(component_property_path) assert ( container_count_outcome.IsSuccess() ), f"Failure: get_container_count did not return success for '{component_property_path}'" @@ -107,21 +111,22 @@ class EditorComponent: def reset_container(self, component_property_path: str): """ - Used to rest a container to empty + Used to reset a container to empty :param component_property_path: String of component property. (e.g. 'Settings|Visible') :return: None """ assert ( self.is_property_container(component_property_path) ), f"Failure: '{component_property_path}' is not a property container" - reset_outcome = self.property_tree.reset_container(component_property_path) + reset_outcome = self.property_tree_editor.reset_container(component_property_path) assert ( reset_outcome.IsSuccess() ), f"Failure: could not reset_container on '{component_property_path}'" def append_container_item(self, component_property_path: str, value: any): """ - Used to append a container item without providing an index key. + Used to append a value to an indexed container item without providing an index key. + Append will fail on an associative container :param component_property_path: String of component property. (e.g. 'Settings|Visible') :param value: Value to be set :return: None @@ -129,38 +134,44 @@ class EditorComponent: assert ( self.is_property_container(component_property_path) ), f"Failure: '{component_property_path}' is not a property container" - append_outcome = self.property_tree.append_container_item(component_property_path, value) + append_outcome = self.property_tree_editor.append_container_item(component_property_path, value) assert ( append_outcome.IsSuccess() ), f"Failure: could not append_container_item to '{component_property_path}'" def add_container_item(self, component_property_path: str, key: any, value: any): """ - Used to add a container item at a specified key. In practice key should be an integer index. + Used to add a container item at a specified key. + There are two types of containers; indexed and associative. + Indexed containers use integer key. + Associative containers utilize keys of the same type which could be any supported type. :param component_property_path: String of component property. (e.g. 'Settings|Visible') - :param key: Zero index integer key, although this could be any unique unused key value + :param key: Zero index integer key or any supported type for associative container :param value: Value to be set :return: None """ assert ( self.is_property_container(component_property_path) ), f"Failure: '{component_property_path}' is not a property container" - add_outcome = self.property_tree.add_container_item(component_property_path, key, value) + add_outcome = self.property_tree_editor.add_container_item(component_property_path, key, value) assert ( add_outcome.IsSuccess() ), f"Failure: could not add_container_item '{key}' to '{component_property_path}'" def get_container_item(self, component_property_path: str, key: any) -> any: """ - Used to retrieve a container item value at the specified key. In practice key should be an integer index. + Used to retrieve a container item value at the specified key. + There are two types of containers; indexed and associative. + Indexed containers use integer key. + Associative containers utilize keys of the same type which could be any supported type. :param component_property_path: String of component property. (e.g. 'Settings|Visible') - :param key: Zero index integer key + :param key: Zero index integer key or any supported type for associative container :return: Value stored at the key specified """ assert ( self.is_property_container(component_property_path) ), f"Failure: '{component_property_path}' is not a property container" - get_outcome = self.property_tree.get_container_item(component_property_path, key) + get_outcome = self.property_tree_editor.get_container_item(component_property_path, key) assert ( get_outcome.IsSuccess() ), f"Failure: could not get a value for {self.get_component_name()}: '{component_property_path}' [{key}]" @@ -168,31 +179,37 @@ class EditorComponent: def remove_container_item(self, component_property_path: str, key: any): """ - Used to remove a container item value at the specified key. In practice key should be an integer index. + Used to remove a container item value at the specified key. + There are two types of containers; indexed and associative. + Indexed containers use integer key. + Associative containers utilize keys of the same type which could be any supported type. :param component_property_path: String of component property. (e.g. 'Settings|Visible') - :param key: Zero index integer key + :param key: Zero index integer key or any supported type for associative container :return: None """ assert ( self.is_property_container(component_property_path) ), f"Failure: '{component_property_path}' is not a property container" - remove_outcome = self.property_tree.remove_container_item(component_property_path, key) + remove_outcome = self.property_tree_editor.remove_container_item(component_property_path, key) assert ( remove_outcome.IsSuccess() ), f"Failure: could not remove_container_item '{key}' from '{component_property_path}'" def update_container_item(self, component_property_path: str, key: any, value: any): """ - Used to update a container item at a specified key. In practice key should be an integer index. + Used to update a container item at a specified key. + There are two types of containers; indexed and associative. + Indexed containers use integer key. + Associative containers utilize keys of the same type which could be any supported type. :param component_property_path: String of component property. (e.g. 'Settings|Visible') - :param key: Zero index integer key + :param key: Zero index integer key or any supported type for associative container :param value: Value to be set :return: None """ assert ( self.is_property_container(component_property_path) ), f"Failure: '{component_property_path}' is not a property container" - update_outcome = self.property_tree.update_container_item(component_property_path, key, value) + update_outcome = self.property_tree_editor.update_container_item(component_property_path, key, value) assert ( update_outcome.IsSuccess() ), f"Failure: could not update '{key}' in '{component_property_path}'" @@ -252,7 +269,7 @@ class EditorComponent: editor.EditorComponentAPIBus(bus.Broadcast, "DisableComponents", [self.id]) @staticmethod - def get_type_ids(component_names: list, entity_type: Entity_Type = Entity_Type.GAME) -> list: + def get_type_ids(component_names: list, entity_type: EditorEntityType = EditorEntityType.GAME) -> list: """ Used to get type ids of given components list :param component_names: List of components to get type ids @@ -426,7 +443,7 @@ class EditorEntity: :return: List of newly added components to the entity """ components = [] - type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.GAME) + type_ids = EditorComponent.get_type_ids(component_names, EditorEntityType.GAME) for type_id in type_ids: new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorComponentAPIBus( @@ -454,7 +471,7 @@ class EditorEntity: :param component_names: List of component names to remove :return: None """ - type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.GAME) + type_ids = EditorComponent.get_type_ids(component_names, EditorEntityType.GAME) for type_id in type_ids: remove_outcome = editor.EditorComponentAPIBus(bus.Broadcast, "RemoveComponents", self.id, [type_id]) assert ( @@ -468,7 +485,7 @@ class EditorEntity: :return: List of Entity Component objects of given component name """ component_list = [] - type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.GAME) + type_ids = EditorComponent.get_type_ids(component_names, EditorEntityType.GAME) for type_id in type_ids: component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorComponentAPIBus( @@ -488,7 +505,7 @@ class EditorEntity: :param component_name: Name of component to check for :return: True, if entity has specified component. Else, False """ - type_ids = EditorComponent.get_type_ids([component_name], Entity_Type.GAME) + type_ids = EditorComponent.get_type_ids([component_name], EditorEntityType.GAME) return editor.EditorComponentAPIBus(bus.Broadcast, "HasComponentOfType", self.id, type_ids[0]) def get_start_status(self) -> int: @@ -690,7 +707,7 @@ class EditorLevelEntity: :return: List of newly added components to the level """ components = [] - type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.LEVEL) + type_ids = EditorComponent.get_type_ids(component_names, EditorEntityType.LEVEL) for type_id in type_ids: new_comp = EditorComponent(type_id) add_component_outcome = editor.EditorLevelComponentAPIBus( @@ -711,7 +728,7 @@ class EditorLevelEntity: :return: List of Level Component objects of given component name """ component_list = [] - type_ids = EditorComponent.get_type_ids(component_names, Entity_Type.LEVEL) + type_ids = EditorComponent.get_type_ids(component_names, EditorEntityType.LEVEL) for type_id in type_ids: component = EditorComponent(type_id) get_component_of_type_outcome = editor.EditorLevelComponentAPIBus( @@ -732,7 +749,7 @@ class EditorLevelEntity: :param component_name: Name of component to check for :return: True, if level has specified component. Else, False """ - type_ids = EditorComponent.get_type_ids([component_name], Entity_Type.LEVEL) + type_ids = EditorComponent.get_type_ids([component_name], EditorEntityType.LEVEL) return editor.EditorLevelComponentAPIBus(bus.Broadcast, "HasComponentOfType", type_ids[0]) @staticmethod @@ -742,5 +759,5 @@ class EditorLevelEntity: :param component_name: Name of component to check for :return: integer count of occurences of level component attached to level or zero if none are present """ - type_ids = EditorComponent.get_type_ids([component_name], Entity_Type.LEVEL) + type_ids = EditorComponent.get_type_ids([component_name], EditorEntityType.LEVEL) return editor.EditorLevelComponentAPIBus(bus.Broadcast, "CountComponentsOfType", type_ids[0]) From f1c8fbe7c07fadb288466909877f8a445b04e469 Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Thu, 6 Jan 2022 13:45:54 -0800 Subject: [PATCH 049/108] remove std and replace with az Signed-off-by: mrieggeramzn --- .../Tests/PropertyIntCtrlCommonTests.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h index 1bd6f72a19..6710d4b7cd 100644 --- a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h +++ b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h @@ -113,19 +113,17 @@ namespace UnitTest auto& widget = m_widget; auto& handler = m_handler; QString tooltip; - std::stringstream expected; // Retrieve the tooltip string for this widget auto success = handler->ModifyTooltip(widget, tooltip); const QString minString = QLocale().toString(widget->minimum()); const QString maxString = QLocale().toString(widget->maximum()); - - expected << "[" << minString.toStdString() << ", " << maxString.toStdString() << "]"; + const AZStd::string expected = AZStd::string::format("[%d, %d]", minString.toStdString().c_str(), maxString.toStdString().c_str()); // Expect the operation to be successful and a valid limit tooltip string generated EXPECT_TRUE(success); - EXPECT_STREQ(tooltip.toStdString().c_str(), expected.str().c_str()); + EXPECT_STREQ(tooltip.toStdString().c_str(), expected.c_str()); } void HandlerMinMaxLessLimit_ModifyHandler_ExpectSuccessAndValidLessLimitToolTipString() @@ -134,7 +132,6 @@ namespace UnitTest auto& widget = m_widget; auto& handler = m_handler; QString tooltip; - std::stringstream expected; // That is not at the extremeties of the type range limit SetWidgetRangeToNonExtremeties(widget); @@ -145,11 +142,11 @@ namespace UnitTest const QString minString = QLocale().toString(widget->minimum()); const QString maxString = QLocale().toString(widget->maximum()); - expected << "[" << minString.toStdString() << ", " << maxString.toStdString() << "]"; + const AZStd::string expected = AZStd::string::format("[%d, %d]", minString.toStdString().c_str(), maxString.toStdString().c_str()); // Expect the operation to be successful and a valid less than limit tooltip string generated EXPECT_TRUE(success); - EXPECT_STREQ(tooltip.toStdString().c_str(), expected.str().c_str()); + EXPECT_STREQ(tooltip.toStdString().c_str(), expected.c_str()); } void EmitWidgetValueChanged() From 273d6e225aaf76436566cdfb56f53a6f1000e15b Mon Sep 17 00:00:00 2001 From: mrieggeramzn Date: Thu, 6 Jan 2022 14:00:33 -0800 Subject: [PATCH 050/108] Previous commit wasnt correct. Should be using a string not a int Signed-off-by: mrieggeramzn --- .../AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h index 6710d4b7cd..b73e9e0a26 100644 --- a/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h +++ b/Code/Framework/AzToolsFramework/Tests/PropertyIntCtrlCommonTests.h @@ -119,7 +119,7 @@ namespace UnitTest const QString minString = QLocale().toString(widget->minimum()); const QString maxString = QLocale().toString(widget->maximum()); - const AZStd::string expected = AZStd::string::format("[%d, %d]", minString.toStdString().c_str(), maxString.toStdString().c_str()); + const AZStd::string expected = AZStd::string::format("[%s, %s]", minString.toStdString().c_str(), maxString.toStdString().c_str()); // Expect the operation to be successful and a valid limit tooltip string generated EXPECT_TRUE(success); @@ -142,7 +142,7 @@ namespace UnitTest const QString minString = QLocale().toString(widget->minimum()); const QString maxString = QLocale().toString(widget->maximum()); - const AZStd::string expected = AZStd::string::format("[%d, %d]", minString.toStdString().c_str(), maxString.toStdString().c_str()); + const AZStd::string expected = AZStd::string::format("[%s, %s]", minString.toStdString().c_str(), maxString.toStdString().c_str()); // Expect the operation to be successful and a valid less than limit tooltip string generated EXPECT_TRUE(success); From e7f573d22a37321ecdd6de0578d527f0186115a6 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 6 Jan 2022 16:48:07 -0800 Subject: [PATCH 051/108] Make Value ctor explicit Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 30 ------------ Code/Framework/AzCore/AzCore/DOM/DomValue.h | 49 +++++++++---------- .../AzCore/Tests/DOM/DomValueBenchmarks.cpp | 8 +-- .../AzCore/Tests/DOM/DomValueTests.cpp | 33 +++++++------ 4 files changed, 44 insertions(+), 76 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index 824b38e47b..f48586709d 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -969,16 +969,6 @@ namespace AZ::Dom m_value = value; } - int32_t Value::GetInt32() const - { - return aznumeric_cast(GetInt64()); - } - - void Value::SetInt32(int32_t value) - { - m_value = aznumeric_cast(value); - } - uint64_t Value::GetUint64() const { switch (m_value.index()) @@ -999,16 +989,6 @@ namespace AZ::Dom m_value = value; } - uint32_t Value::GetUint32() const - { - return aznumeric_cast(GetUint64()); - } - - void Value::SetUint32(uint32_t value) - { - m_value = aznumeric_cast(value); - } - bool Value::GetBool() const { if (IsBool()) @@ -1044,16 +1024,6 @@ namespace AZ::Dom m_value = value; } - float Value::GetFloat() const - { - return aznumeric_cast(GetDouble()); - } - - void Value::SetFloat(float value) - { - m_value = aznumeric_cast(value); - } - void Value::SetString(SharedStringType sharedString) { m_value = sharedString; diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index a6990fcbce..fa496e8dfc 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -198,28 +198,39 @@ namespace AZ::Dom Value(const Value&); Value(Value&&) noexcept; Value(AZStd::string_view stringView, bool copy); - Value(SharedStringType sharedString); + explicit Value(const ValueType&); + explicit Value(ValueType&&); + explicit Value(SharedStringType sharedString); - Value(int8_t value); - Value(uint8_t value); - Value(int16_t value); - Value(uint16_t value); - Value(int32_t value); - Value(uint32_t value); - Value(int64_t value); - Value(uint64_t value); - Value(float value); - Value(double value); - Value(bool value); + explicit Value(int8_t value); + explicit Value(uint8_t value); + explicit Value(int16_t value); + explicit Value(uint16_t value); + explicit Value(int32_t value); + explicit Value(uint32_t value); + explicit Value(int64_t value); + explicit Value(uint64_t value); + explicit Value(float value); + explicit Value(double value); + explicit Value(bool value); explicit Value(Type type); + template + explicit Value(T, AZStd::enable_if_t>* enabled = 0) = delete; + static Value FromOpaqueValue(const AZStd::any& value); // Equality / comparison / swap... Value& operator=(const Value&); Value& operator=(Value&&) noexcept; + template + Value& operator=(T value) + { + return operator=(Value(value)); + } + bool operator==(const Value& rhs) const; bool operator!=(const Value& rhs) const; @@ -330,22 +341,10 @@ namespace AZ::Dom // int API... int64_t GetInt64() const; void SetInt64(int64_t); - int32_t GetInt32() const; - void SetInt32(int32_t); - int16_t GetInt16() const; - void SetInt16(int16_t); - int8_t GetInt8() const; - void SetInt8(int8_t); // uint API... uint64_t GetUint64() const; void SetUint64(uint64_t); - uint32_t GetUint32() const; - void SetUint32(uint32_t); - uint16_t GetUint16() const; - void SetUint16(uint16_t); - uint8_t GetUint8() const; - void SetUint8(uint8_t); // bool API... bool GetBool() const; @@ -354,8 +353,6 @@ namespace AZ::Dom // double API... double GetDouble() const; void SetDouble(double); - float GetFloat() const; - void SetFloat(float); // String API... AZStd::string_view GetString() const; diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp index b20091b232..40b96e148b 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueBenchmarks.cpp @@ -66,9 +66,9 @@ namespace AZ::Dom::Benchmark { Value entry(Type::Object); entry.AddMember("string", createString(n)); - entry.AddMember("int", n); - entry.AddMember("double", static_cast(n) * 0.5); - entry.AddMember("bool", n % 2 == 0); + entry.AddMember("int", Value(n)); + entry.AddMember("double", Value(static_cast(n) * 0.5)); + entry.AddMember("bool", Value(n % 2 == 0)); entry.AddMember("null", Value(Type::Null)); return entry; }; @@ -153,7 +153,7 @@ namespace AZ::Dom::Benchmark for (auto _ : state) { Value copy = original; - copy["entries"]["Key0"].ArrayPushBack(42); + copy["entries"]["Key0"].ArrayPushBack(Value(42)); TakeAndDiscardWithoutTimingDtor(AZStd::move(copy), state); } diff --git a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp index a98eb307a2..10e9f29a44 100644 --- a/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp +++ b/Code/Framework/AzCore/Tests/DOM/DomValueTests.cpp @@ -68,7 +68,7 @@ namespace AZ::Dom::Tests { m_value.ArrayPushBack(Value(i)); EXPECT_EQ(m_value.ArraySize(), i + 1); - EXPECT_EQ(m_value[i].GetInt32(), i); + EXPECT_EQ(m_value[i].GetInt64(), i); } PerformValueChecks(); @@ -76,6 +76,7 @@ namespace AZ::Dom::Tests TEST_F(DomValueTests, NestedArrays) { + Value x(5); m_value.SetArray(); for (int j = 0; j < 5; ++j) { @@ -93,7 +94,7 @@ namespace AZ::Dom::Tests EXPECT_EQ(m_value[i].ArraySize(), 5); for (int j = 0; j < 5; ++j) { - EXPECT_EQ(m_value[i][j].GetInt32(), j); + EXPECT_EQ(m_value[i][j].GetInt64(), j); } } @@ -116,7 +117,7 @@ namespace AZ::Dom::Tests AZStd::string key = AZStd::string::format("Key%i", i); m_value.AddMember(key, Value(i)); EXPECT_EQ(m_value.MemberCount(), i + 1); - EXPECT_EQ(m_value[key].GetInt32(), i); + EXPECT_EQ(m_value[key].GetInt64(), i); } PerformValueChecks(); @@ -142,7 +143,7 @@ namespace AZ::Dom::Tests EXPECT_EQ(nestedObject.MemberCount(), 5); for (int i = 0; i < 5; ++i) { - EXPECT_EQ(nestedObject[AZStd::string::format("Key%i", i)].GetInt32(), i); + EXPECT_EQ(nestedObject[AZStd::string::format("Key%i", i)].GetInt64(), i); } } @@ -167,14 +168,14 @@ namespace AZ::Dom::Tests { m_value.ArrayPushBack(Value(i)); EXPECT_EQ(m_value.ArraySize(), i + 1); - EXPECT_EQ(m_value[i].GetInt32(), i); + EXPECT_EQ(m_value[i].GetInt64(), i); if (i < 5) { AZ::Name key = AZ::Name(AZStd::string::format("TwoTimes%i", i)); m_value.AddMember(key, Value(i * 2)); EXPECT_EQ(m_value.MemberCount(), i + 1); - EXPECT_EQ(m_value[key].GetInt32(), i * 2); + EXPECT_EQ(m_value[key].GetInt64(), i * 2); } } @@ -191,9 +192,9 @@ namespace AZ::Dom::Tests { Value childNode(Type::Node); childNode.SetNodeName(childNodeName); - childNode.SetNodeValue(i); + childNode.SetNodeValue(Value(i)); - childNode.AddMember("foo", i); + childNode.AddMember("foo", Value(i)); childNode.AddMember("bar", Value("test", false)); m_value.ArrayPushBack(childNode); @@ -204,8 +205,8 @@ namespace AZ::Dom::Tests { const Value& childNode = m_value[i]; EXPECT_EQ(childNode.GetNodeName(), childNodeName); - EXPECT_EQ(childNode.GetNodeValue().GetInt32(), i); - EXPECT_EQ(childNode["foo"].GetInt32(), i); + EXPECT_EQ(childNode.GetNodeValue().GetInt64(), i); + EXPECT_EQ(childNode["foo"].GetInt64(), i); EXPECT_EQ(childNode["bar"].GetString(), "test"); } @@ -334,8 +335,8 @@ namespace AZ::Dom::Tests TEST_F(DomValueTests, CopyOnWrite_Array) { Value v1(Type::Array); - v1.ArrayPushBack(1); - v1.ArrayPushBack(2); + v1.ArrayPushBack(Value(1)); + v1.ArrayPushBack(Value(2)); Value nestedArray(Type::Array); v1.ArrayPushBack(nestedArray); @@ -349,7 +350,7 @@ namespace AZ::Dom::Tests EXPECT_NE(&v1.GetArray(), &v2.GetArray()); EXPECT_EQ(&v1.ArrayAt(2).GetArray(), &v2.ArrayAt(2).GetArray()); - v2[2].ArrayPushBack(42); + v2[2].ArrayPushBack(Value(42)); EXPECT_NE(&v1.GetArray(), &v2.GetArray()); EXPECT_NE(&v1.ArrayAt(2).GetArray(), &v2.ArrayAt(2).GetArray()); @@ -365,8 +366,8 @@ namespace AZ::Dom::Tests Value v1; v1.SetNode("TopLevel"); - v1.ArrayPushBack(1); - v1.ArrayPushBack(2); + v1.ArrayPushBack(Value(1)); + v1.ArrayPushBack(Value(2)); v1["obj"].SetNode("Nested"); Value v2 = v1; @@ -378,7 +379,7 @@ namespace AZ::Dom::Tests EXPECT_NE(&v1.GetNode(), &v2.GetNode()); EXPECT_EQ(&v1["obj"].GetNode(), &v2["obj"].GetNode()); - v2["obj"].ArrayPushBack(42); + v2["obj"].ArrayPushBack(Value(42)); EXPECT_NE(&v1.GetNode(), &v2.GetNode()); EXPECT_NE(&v1["obj"].GetNode(), &v2["obj"].GetNode()); From 25924c3d384452e67775b2a4c11a84df09cf99d4 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 6 Jan 2022 16:54:57 -0800 Subject: [PATCH 052/108] Use more explicit operator= override Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index fa496e8dfc..23f4bd570f 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -225,10 +225,12 @@ namespace AZ::Dom Value& operator=(const Value&); Value& operator=(Value&&) noexcept; - template - Value& operator=(T value) + //! Assignment operator to allow forwarding types constructible via Value(T) to be assigned + template + auto operator=(T&& arg) + -> AZStd::enable_if_t, Value> && AZStd::is_constructible_v, Value&> { - return operator=(Value(value)); + return operator=(Value(AZStd::forward(arg))); } bool operator==(const Value& rhs) const; From 839bbd734aea320ebf383c6b390cf52a6d867f54 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Thu, 6 Jan 2022 16:55:24 -0800 Subject: [PATCH 053/108] Make operator== avoid implicit comparisons Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp index f48586709d..6d944c9f45 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.cpp @@ -262,21 +262,6 @@ namespace AZ::Dom { return GetString() == rhs.GetString(); } - else if (IsNumber() && rhs.IsNumber()) - { - if (IsInt()) - { - return GetInt64() == rhs.GetInt64(); - } - else if (IsUint()) - { - return GetUint64() == rhs.GetUint64(); - } - else - { - return GetDouble() == rhs.GetDouble(); - } - } else { return m_value == rhs.m_value; From 2492c0a4f4db175268742fe9dcf4191d4ad44bea Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Thu, 6 Jan 2022 17:56:00 -0800 Subject: [PATCH 054/108] enum must be dereferenced with .value also added get_outcome.GetError() to pull more information from any get_container_item failures Signed-off-by: Scott Murray --- .../editor_python_test_tools/editor_entity_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index d354c4ece6..bf27ec06e0 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -174,7 +174,9 @@ class EditorComponent: get_outcome = self.property_tree_editor.get_container_item(component_property_path, key) assert ( get_outcome.IsSuccess() - ), f"Failure: could not get a value for {self.get_component_name()}: '{component_property_path}' [{key}]" + ), ( + f"Failure: could not get a value for {self.get_component_name()}: '{component_property_path}' [{key}]. " + f"Error returned by get_container_item: {get_outcome.GetError()}") return get_outcome.GetValue() def remove_container_item(self, component_property_path: str, key: any): @@ -277,7 +279,7 @@ class EditorComponent: :return: List of type ids of given components. Type id is a UUID as provided by the ebus call """ type_ids = editor.EditorComponentAPIBus( - bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, entity_type) + bus.Broadcast, "FindComponentTypeIdsByEntityType", component_names, entity_type.value) return type_ids From 8b9e3d2175bb7766e0e9e81f0bba310cafd14a90 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Fri, 7 Jan 2022 09:53:14 -0800 Subject: [PATCH 055/108] Simplify disabling Value ctor for pointer types Signed-off-by: Nicholas Van Sickle --- Code/Framework/AzCore/AzCore/DOM/DomValue.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/DOM/DomValue.h b/Code/Framework/AzCore/AzCore/DOM/DomValue.h index 23f4bd570f..ecf8326525 100644 --- a/Code/Framework/AzCore/AzCore/DOM/DomValue.h +++ b/Code/Framework/AzCore/AzCore/DOM/DomValue.h @@ -216,8 +216,9 @@ namespace AZ::Dom explicit Value(Type type); + // Disable accidental calls to Value(bool) with pointer types template - explicit Value(T, AZStd::enable_if_t>* enabled = 0) = delete; + explicit Value(T*) = delete; static Value FromOpaqueValue(const AZStd::any& value); From bcc83aaaf2473ff1ee8fd9f9629e830df48ae222 Mon Sep 17 00:00:00 2001 From: evanchia Date: Mon, 10 Jan 2022 16:04:21 -0800 Subject: [PATCH 056/108] Found actual issue where the logs were being routed to the artifact folder Signed-off-by: evanchia --- .../LyTestTools/ly_test_tools/o3de/editor_test.py | 13 +++++++++++-- .../ly_test_tools/o3de/editor_test_utils.py | 14 ++++---------- .../tests/unit/test_editor_test_utils.py | 7 +++++-- .../tests/unit/test_o3de_editor_test.py | 13 +++++++++++++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py index fd2157d1cc..c97298573e 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py @@ -771,7 +771,8 @@ class EditorTestSuite(): output = editor.get_output() return_code = editor.get_returncode() editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) - + # Save the editor log + workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(), log_name)) if return_code == 0: test_result = Result.Pass.create(test_spec, output, editor_log_content) else: @@ -779,6 +780,9 @@ class EditorTestSuite(): if has_crashed: test_result = Result.Crash.create(test_spec, output, return_code, editor_utils.retrieve_crash_output (run_id, workspace, self._TIMEOUT_CRASH_LOG), None) + # Save the crash log + crash_file_name = os.path.basename(workspace.paths.crash_log()) + workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(), crash_file_name)) editor_utils.cycle_crash_report(run_id, workspace) else: test_result = Result.Fail.create(test_spec, output, editor_log_content) @@ -842,7 +846,8 @@ class EditorTestSuite(): output = editor.get_output() return_code = editor.get_returncode() editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) - + # Save the editor log + workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(), log_name)) if return_code == 0: # No need to scrap the output, as all the tests have passed for test_spec in test_spec_list: @@ -863,6 +868,10 @@ class EditorTestSuite(): # The first test with "Unknown" result (no data in output) is likely the one that crashed crash_error = editor_utils.retrieve_crash_output(run_id, workspace, self._TIMEOUT_CRASH_LOG) + # Save the crash log + crash_file_name = os.path.basename(workspace.paths.crash_log()) + workspace.artifact_manager.save_artifact( + os.path.join(editor_utils.retrieve_log_path(), crash_file_name)) editor_utils.cycle_crash_report(run_id, workspace) results[test_spec_name] = Result.Crash.create(result.test_spec, output, return_code, crash_error, result.editor_log) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py index 69c6eda2ee..246fba16aa 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py @@ -71,15 +71,9 @@ def retrieve_crash_output(run_id: int, workspace: AbstractWorkspaceManager, time :return str: The contents of the editor crash file (error.log) """ crash_info = "-- No crash log available --" - error_log_regex = "" - log_path = retrieve_log_path(run_id, workspace) - # Gather all of the files in the log directory - dir_files = [f for f in os.listdir(log_path) if os.path.isfile(os.path.join(log_path, f))] - for file_name in dir_files: - # Search for all .log files with either "crash" or "error" because they could be renamed - if ("error" in file_name.lower() or "crash" in file_name.lower()) and (file_name.endswith(".log")): - crash_log = os.path.join(log_path, file_name) - break + # Grab the file name of the crash log which can be different depending on platform + crash_file_name = os.path.basename(workspace.paths.crash_log()) + crash_log = os.path.join(retrieve_log_path(run_id, workspace), crash_file_name) try: waiter.wait_for(lambda: os.path.exists(crash_log), timeout=timeout) except AssertionError: @@ -100,7 +94,7 @@ def cycle_crash_report(run_id: int, workspace: AbstractWorkspaceManager) -> None :param workspace: Workspace fixture """ log_path = retrieve_log_path(run_id, workspace) - files_to_cycle = ['error.log', 'error.dmp'] + files_to_cycle = ['crash.log', 'error.log', 'error.dmp'] for filename in files_to_cycle: filepath = os.path.join(log_path, filename) name, ext = os.path.splitext(filename) diff --git a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py index f7678c44c0..6e2ec59721 100644 --- a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py +++ b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py @@ -61,6 +61,8 @@ class TestEditorTestUtils(unittest.TestCase): @mock.patch('os.listdir') @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') + @mock.patch('os.path.join', mock.MagicMock()) + @mock.patch('os.path.basename', mock.MagicMock()) @mock.patch('os.path.isfile', mock.MagicMock()) @mock.patch('ly_test_tools.environment.waiter.wait_for', mock.MagicMock()) def test_RetrieveCrashOutput_CrashLogExists_ReturnsLogInfo(self, mock_retrieve_log_path, mock_listdir): @@ -79,6 +81,7 @@ class TestEditorTestUtils(unittest.TestCase): def test_RetrieveCrashOutput_CrashLogNotExists_ReturnsError(self, mock_retrieve_log_path, mock_listdir): mock_retrieve_log_path.return_value = 'mock_log_path' mock_workspace = mock.MagicMock() + mock_workspace.paths.crash_log.return_value = 'mock_file.log' error_message = "No crash log available" mock_listdir.return_value = ['mock_file.log'] @@ -91,7 +94,7 @@ class TestEditorTestUtils(unittest.TestCase): @mock.patch('os.path.exists') def test_CycleCrashReport_DmpExists_NamedCorrectly(self, mock_exists, mock_retrieve_log_path, mock_strftime, mock_rename): - mock_exists.side_effect = [False, True] + mock_exists.side_effect = [False, False, True] mock_retrieve_log_path.return_value = 'mock_log_path' mock_workspace = mock.MagicMock() mock_strftime.return_value = 'mock_strftime' @@ -107,7 +110,7 @@ class TestEditorTestUtils(unittest.TestCase): @mock.patch('os.path.exists') def test_CycleCrashReport_LogExists_NamedCorrectly(self, mock_exists, mock_retrieve_log_path, mock_strftime, mock_rename): - mock_exists.side_effect = [True, False] + mock_exists.side_effect = [False, True, False] mock_retrieve_log_path.return_value = 'mock_log_path' mock_workspace = mock.MagicMock() mock_strftime.return_value = 'mock_strftime' diff --git a/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py b/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py index 2b6ae5b471..054159cd16 100644 --- a/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py +++ b/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py @@ -589,6 +589,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') @mock.patch('ly_test_tools.o3de.editor_test_utils.get_testcase_module_filepath') @mock.patch('ly_test_tools.o3de.editor_test_utils.cycle_crash_report') + @mock.patch('os.path.join', mock.MagicMock()) def test_ExecEditorTest_TestSucceeds_ReturnsPass(self, mock_cycle_crash, mock_get_testcase_filepath, mock_retrieve_log, mock_retrieve_editor_log, mock_get_output_results, mock_create): @@ -616,6 +617,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') @mock.patch('ly_test_tools.o3de.editor_test_utils.get_testcase_module_filepath') @mock.patch('ly_test_tools.o3de.editor_test_utils.cycle_crash_report') + @mock.patch('os.path.join', mock.MagicMock()) def test_ExecEditorTest_TestFails_ReturnsFail(self, mock_cycle_crash, mock_get_testcase_filepath, mock_retrieve_log, mock_retrieve_editor_log, mock_get_output_results, mock_create): @@ -644,6 +646,8 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') @mock.patch('ly_test_tools.o3de.editor_test_utils.get_testcase_module_filepath') @mock.patch('ly_test_tools.o3de.editor_test_utils.cycle_crash_report') + @mock.patch('os.path.join', mock.MagicMock()) + @mock.patch('os.path.basename', mock.MagicMock()) def test_ExecEditorTest_TestCrashes_ReturnsCrash(self, mock_cycle_crash, mock_get_testcase_filepath, mock_retrieve_log, mock_retrieve_editor_log, mock_get_output_results, mock_retrieve_crash, mock_create): @@ -699,10 +703,14 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') @mock.patch('ly_test_tools.o3de.editor_test_utils.get_testcase_module_filepath') @mock.patch('ly_test_tools.o3de.editor_test_utils.cycle_crash_report') + @mock.patch('os.path.join', mock.MagicMock()) def test_ExecEditorMultitest_AllTestsPass_ReturnsPasses(self, mock_cycle_crash, mock_get_testcase_filepath, mock_retrieve_log, mock_retrieve_editor_log, mock_create): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() mock_workspace = mock.MagicMock() + mock_artifact_manager = mock.MagicMock() + mock_artifact_manager.save_artifact.return_value = mock.MagicMock() + mock_workspace.artifact_manager = mock_artifact_manager mock_workspace.paths.engine_root.return_value = "" mock_editor = mock.MagicMock() mock_editor.get_returncode.return_value = 0 @@ -727,6 +735,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') @mock.patch('ly_test_tools.o3de.editor_test_utils.get_testcase_module_filepath') @mock.patch('ly_test_tools.o3de.editor_test_utils.cycle_crash_report') + @mock.patch('os.path.join', mock.MagicMock()) def test_ExecEditorMultitest_OneFailure_CallsCorrectFunc(self, mock_cycle_crash, mock_get_testcase_filepath, mock_retrieve_log, mock_retrieve_editor_log, mock_get_results): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() @@ -752,6 +761,8 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') @mock.patch('ly_test_tools.o3de.editor_test_utils.get_testcase_module_filepath') @mock.patch('ly_test_tools.o3de.editor_test_utils.cycle_crash_report') + @mock.patch('os.path.join', mock.MagicMock()) + @mock.patch('os.path.basename', mock.MagicMock()) def test_ExecEditorMultitest_OneCrash_ReportsOnUnknownResult(self, mock_cycle_crash, mock_get_testcase_filepath, mock_retrieve_log, mock_retrieve_editor_log, mock_get_results, mock_retrieve_crash, mock_create): @@ -787,6 +798,8 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test_utils.retrieve_log_path') @mock.patch('ly_test_tools.o3de.editor_test_utils.get_testcase_module_filepath') @mock.patch('ly_test_tools.o3de.editor_test_utils.cycle_crash_report') + @mock.patch('os.path.join', mock.MagicMock()) + @mock.patch('os.path.basename', mock.MagicMock()) def test_ExecEditorMultitest_ManyUnknown_ReportsUnknownResults(self, mock_cycle_crash, mock_get_testcase_filepath, mock_retrieve_log, mock_retrieve_editor_log, mock_get_results, mock_retrieve_crash, mock_create): From ba9731bec60e084ec5675073ee6dfc3e5daac396 Mon Sep 17 00:00:00 2001 From: evanchia Date: Mon, 10 Jan 2022 16:13:14 -0800 Subject: [PATCH 057/108] added missing params Signed-off-by: evanchia --- Tools/LyTestTools/ly_test_tools/o3de/editor_test.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py index c97298573e..eaa285a81e 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py @@ -772,7 +772,7 @@ class EditorTestSuite(): return_code = editor.get_returncode() editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) # Save the editor log - workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(), log_name)) + workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(run_id, workspace), log_name)) if return_code == 0: test_result = Result.Pass.create(test_spec, output, editor_log_content) else: @@ -782,7 +782,7 @@ class EditorTestSuite(): (run_id, workspace, self._TIMEOUT_CRASH_LOG), None) # Save the crash log crash_file_name = os.path.basename(workspace.paths.crash_log()) - workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(), crash_file_name)) + workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(run_id, workspace), crash_file_name)) editor_utils.cycle_crash_report(run_id, workspace) else: test_result = Result.Fail.create(test_spec, output, editor_log_content) @@ -847,7 +847,7 @@ class EditorTestSuite(): return_code = editor.get_returncode() editor_log_content = editor_utils.retrieve_editor_log_content(run_id, log_name, workspace) # Save the editor log - workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(), log_name)) + workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(run_id, workspace), log_name)) if return_code == 0: # No need to scrap the output, as all the tests have passed for test_spec in test_spec_list: @@ -871,7 +871,7 @@ class EditorTestSuite(): # Save the crash log crash_file_name = os.path.basename(workspace.paths.crash_log()) workspace.artifact_manager.save_artifact( - os.path.join(editor_utils.retrieve_log_path(), crash_file_name)) + os.path.join(editor_utils.retrieve_log_path(run_id, workspace), crash_file_name)) editor_utils.cycle_crash_report(run_id, workspace) results[test_spec_name] = Result.Crash.create(result.test_spec, output, return_code, crash_error, result.editor_log) From 8fd6d534b3a7fc486315f7ab7c22578ae38f31d4 Mon Sep 17 00:00:00 2001 From: evanchia Date: Mon, 10 Jan 2022 16:27:07 -0800 Subject: [PATCH 058/108] forgot to change editor command line string Signed-off-by: evanchia --- Tools/LyTestTools/ly_test_tools/o3de/editor_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py index eaa285a81e..8bd4fbe29a 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py @@ -762,7 +762,7 @@ class EditorTestSuite(): cmdline = [ "--runpythontest", test_filename, "-logfile", f"@log@/{log_name}", - "-project-log-path", ly_test_tools._internal.pytest_plugin.output_path] + test_cmdline_args + "-project-log-path", editor_utils.retrieve_log_path(run_id, workspace)] + test_cmdline_args editor.args.extend(cmdline) editor.start(backupFiles = False, launch_ap = False, configure_settings=False) @@ -834,7 +834,7 @@ class EditorTestSuite(): cmdline = [ "--runpythontest", test_filenames_str, "-logfile", f"@log@/{log_name}", - "-project-log-path", ly_test_tools._internal.pytest_plugin.output_path] + test_cmdline_args + "-project-log-path", editor_utils.retrieve_log_path(run_id, workspace)] + test_cmdline_args editor.args.extend(cmdline) editor.start(backupFiles = False, launch_ap = False, configure_settings=False) From a690c76ad4716233f726f60277f72636eebaf295 Mon Sep 17 00:00:00 2001 From: santorac <55155825+santorac@users.noreply.github.com> Date: Wed, 12 Jan 2022 08:54:22 -0800 Subject: [PATCH 059/108] Fixed depth clipping artifacts for parallax PDO. (#6837) The "precise" keyword was recently added to several shader inputs, but one was missed. This led to inconsistency between the depth and forward passes which resulted in artifacts when parallax pixel depth offset was in use. See https://github.com/o3de/o3de/pull/6536 Testing: I used AtomSampleViewer to make a local baseline of all screenshots in _fulltestsuite_.bv.lua. The only change was to the parallax test cases, which were a clear improvement. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com> --- .../Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl index 264542cd0a..04fd104407 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DepthPass_WithPS.azsl @@ -63,7 +63,7 @@ VSDepthOutput MainVS(VSInput IN) struct PSDepthOutput { - float m_depth : SV_Depth; + precise float m_depth : SV_Depth; }; PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) From e31fa88c0093219fd3db6bda1918f88d572ebd46 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 12 Jan 2022 11:13:40 -0600 Subject: [PATCH 060/108] Removed unused legacy show icons option Signed-off-by: Chris Galvan --- .../EditorPreferencesPageViewportGeneral.cpp | 10 -- .../EditorPreferencesPageViewportGeneral.h | 2 - Code/Editor/EditorViewportWidget.cpp | 2 - Code/Editor/Objects/BaseObject.cpp | 151 ------------------ Code/Editor/Objects/BaseObject.h | 10 -- .../Objects/ComponentEntityObject.cpp | 91 ----------- .../Objects/ComponentEntityObject.h | 2 - Code/Editor/Settings.cpp | 7 - Code/Editor/Settings.h | 7 - 9 files changed, 282 deletions(-) diff --git a/Code/Editor/EditorPreferencesPageViewportGeneral.cpp b/Code/Editor/EditorPreferencesPageViewportGeneral.cpp index 77560e24f8..f33cc3f725 100644 --- a/Code/Editor/EditorPreferencesPageViewportGeneral.cpp +++ b/Code/Editor/EditorPreferencesPageViewportGeneral.cpp @@ -41,8 +41,6 @@ void CEditorPreferencesPage_ViewportGeneral::Reflect(AZ::SerializeContext& seria ->Field("ShowBBoxes", &Display::m_showBBoxes) ->Field("DrawEntityLabels", &Display::m_drawEntityLabels) ->Field("ShowTriggerBounds", &Display::m_showTriggerBounds) - ->Field("ShowIcons", &Display::m_showIcons) - ->Field("DistanceScaleIcons", &Display::m_distanceScaleIcons) ->Field("ShowFrozenHelpers", &Display::m_showFrozenHelpers) ->Field("FillSelectedShapes", &Display::m_fillSelectedShapes) ->Field("ShowGridGuide", &Display::m_showGridGuide) @@ -118,10 +116,6 @@ void CEditorPreferencesPage_ViewportGeneral::Reflect(AZ::SerializeContext& seria AZ::Edit::UIHandlers::CheckBox, &Display::m_drawEntityLabels, "Always Draw Entity Labels", "Always Draw Entity Labels") ->DataElement( AZ::Edit::UIHandlers::CheckBox, &Display::m_showTriggerBounds, "Always Show Trigger Bounds", "Always Show Trigger Bounds") - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &Display::m_showIcons, "Show Object Icons", "Show Object Icons") - ->DataElement( - AZ::Edit::UIHandlers::CheckBox, &Display::m_distanceScaleIcons, "Scale Object Icons with Distance", - "Scale Object Icons with Distance") ->DataElement( AZ::Edit::UIHandlers::CheckBox, &Display::m_showFrozenHelpers, "Show Helpers of Frozen Objects", "Show Helpers of Frozen Objects") @@ -244,8 +238,6 @@ void CEditorPreferencesPage_ViewportGeneral::OnApply() } gSettings.viewports.bDrawEntityLabels = m_display.m_drawEntityLabels; gSettings.viewports.bShowTriggerBounds = m_display.m_showTriggerBounds; - gSettings.viewports.bShowIcons = m_display.m_showIcons; - gSettings.viewports.bDistanceScaleIcons = m_display.m_distanceScaleIcons; gSettings.viewports.nShowFrozenHelpers = m_display.m_showFrozenHelpers; gSettings.viewports.bFillSelectedShapes = m_display.m_fillSelectedShapes; gSettings.viewports.bShowGridGuide = m_display.m_showGridGuide; @@ -300,8 +292,6 @@ void CEditorPreferencesPage_ViewportGeneral::InitializeSettings() m_display.m_showBBoxes = (ds->GetRenderFlags() & RENDER_FLAG_BBOX) == RENDER_FLAG_BBOX; m_display.m_drawEntityLabels = gSettings.viewports.bDrawEntityLabels; m_display.m_showTriggerBounds = gSettings.viewports.bShowTriggerBounds; - m_display.m_showIcons = gSettings.viewports.bShowIcons; - m_display.m_distanceScaleIcons = gSettings.viewports.bDistanceScaleIcons; m_display.m_showFrozenHelpers = gSettings.viewports.nShowFrozenHelpers; m_display.m_fillSelectedShapes = gSettings.viewports.bFillSelectedShapes; m_display.m_showGridGuide = gSettings.viewports.bShowGridGuide; diff --git a/Code/Editor/EditorPreferencesPageViewportGeneral.h b/Code/Editor/EditorPreferencesPageViewportGeneral.h index be89cc6df4..2d2a207d6c 100644 --- a/Code/Editor/EditorPreferencesPageViewportGeneral.h +++ b/Code/Editor/EditorPreferencesPageViewportGeneral.h @@ -62,8 +62,6 @@ private: bool m_showBBoxes; bool m_drawEntityLabels; bool m_showTriggerBounds; - bool m_showIcons; - bool m_distanceScaleIcons; bool m_showFrozenHelpers; bool m_fillSelectedShapes; bool m_showGridGuide; diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index 828812fb7e..e9a57dba4f 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -1027,8 +1027,6 @@ void EditorViewportWidget::OnTitleMenu(QMenu* menu) AZ::ViewportHelpers::AddCheckbox(menu, tr("Show Safe Frame"), &gSettings.viewports.bShowSafeFrame); AZ::ViewportHelpers::AddCheckbox(menu, tr("Show Construction Plane"), &gSettings.snap.constructPlaneDisplay); AZ::ViewportHelpers::AddCheckbox(menu, tr("Show Trigger Bounds"), &gSettings.viewports.bShowTriggerBounds); - AZ::ViewportHelpers::AddCheckbox(menu, tr("Show Icons"), &gSettings.viewports.bShowIcons, &gSettings.viewports.bShowSizeBasedIcons); - AZ::ViewportHelpers::AddCheckbox(menu, tr("Show Size-based Icons"), &gSettings.viewports.bShowSizeBasedIcons, &gSettings.viewports.bShowIcons); AZ::ViewportHelpers::AddCheckbox(menu, tr("Show Helpers of Frozen Objects"), &gSettings.viewports.nShowFrozenHelpers); if (!m_predefinedAspectRatios.IsEmpty()) diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index 86840789dd..5ae68eaad7 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -761,72 +761,6 @@ void CBaseObject::SetModified(bool) { } -void CBaseObject::DrawDefault(DisplayContext& dc, const QColor& labelColor) -{ - Vec3 wp = GetWorldPos(); - - bool bDisplaySelectionHelper = false; - if (!CanBeDrawn(dc, bDisplaySelectionHelper)) - { - return; - } - - // Draw link between parent and child. - if (dc.flags & DISPLAY_LINKS) - { - if (GetParent()) - { - dc.DrawLine(GetParentAttachPointWorldTM().GetTranslation(), wp, IsFrozen() ? kLinkColorGray : kLinkColorParent, IsFrozen() ? kLinkColorGray : kLinkColorChild); - } - size_t nChildCount = GetChildCount(); - for (size_t i = 0; i < nChildCount; ++i) - { - const CBaseObject* pChild = GetChild(i); - dc.DrawLine(pChild->GetParentAttachPointWorldTM().GetTranslation(), pChild->GetWorldPos(), pChild->IsFrozen() ? kLinkColorGray : kLinkColorParent, pChild->IsFrozen() ? kLinkColorGray : kLinkColorChild); - } - } - - // Draw Bounding box - if (dc.flags & DISPLAY_BBOX) - { - AABB box; - GetBoundBox(box); - dc.SetColor(Vec3(1, 1, 1)); - dc.DrawWireBox(box.min, box.max); - } - - if (IsHighlighted()) - { - DrawHighlight(dc); - } - - if (IsSelected()) - { - DrawArea(dc); - - CSelectionGroup* pSelection = GetObjectManager()->GetSelection(); - - // If the number of selected object is over 2, the merged boundbox should be used to render the measurement axis. - if (!pSelection || (pSelection && pSelection->GetCount() == 1)) - { - DrawDimensions(dc); - } - } - - if (bDisplaySelectionHelper) - { - DrawSelectionHelper(dc, wp, labelColor, 1.0f); - } - else if (!(dc.flags & DISPLAY_HIDENAMES)) - { - DrawLabel(dc, wp, labelColor); - } - - SetDrawTextureIconProperties(dc, wp); - DrawTextureIcon(dc, wp); - DrawWarningIcons(dc, wp); -} - ////////////////////////////////////////////////////////////////////////// void CBaseObject::DrawDimensions(DisplayContext&, AABB*) { @@ -850,91 +784,6 @@ void CBaseObject::DrawSelectionHelper(DisplayContext& dc, const Vec3& pos, const dc.SetState(nPrevState); } -////////////////////////////////////////////////////////////////////////// -void CBaseObject::SetDrawTextureIconProperties(DisplayContext& dc, const Vec3& pos, float alpha, int texIconFlags) -{ - if (gSettings.viewports.bShowIcons || gSettings.viewports.bShowSizeBasedIcons) - { - if (IsHighlighted()) - { - dc.SetColor(QColor(255, 120, 0), 0.8f * alpha); - } - else if (IsSelected()) - { - dc.SetSelectedColor(alpha); - } - else if (IsFrozen()) - { - dc.SetFreezeColor(); - } - else - { - dc.SetColor(QColor(255, 255, 255), alpha); - } - - m_vDrawIconPos = pos; - - int nIconFlags = texIconFlags; - if (CheckFlags(OBJFLAG_SHOW_ICONONTOP)) - { - Vec3 objectPos = GetWorldPos(); - - AABB box; - GetBoundBox(box); - m_vDrawIconPos.z = (m_vDrawIconPos.z - objectPos.z) + box.max.z; - nIconFlags |= DisplayContext::TEXICON_ALIGN_BOTTOM; - } - m_nIconFlags = nIconFlags; - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseObject::DrawTextureIcon(DisplayContext& dc, [[maybe_unused]] const Vec3& pos, [[maybe_unused]] float alpha) -{ - if (m_nTextureIcon && (gSettings.viewports.bShowIcons || gSettings.viewports.bShowSizeBasedIcons)) - { - dc.DrawTextureLabel(GetTextureIconDrawPos(), OBJECT_TEXTURE_ICON_SIZEX, OBJECT_TEXTURE_ICON_SIZEY, GetTextureIcon(), GetTextureIconFlags()); - } -} - -////////////////////////////////////////////////////////////////////////// -void CBaseObject::DrawWarningIcons(DisplayContext& dc, const Vec3&) -{ - if (gSettings.viewports.bShowIcons || gSettings.viewports.bShowSizeBasedIcons) - { - const int warningIconSizeX = OBJECT_TEXTURE_ICON_SIZEX / 2; - const int warningIconSizeY = OBJECT_TEXTURE_ICON_SIZEY / 2; - - const int iconOffsetX = m_nTextureIcon ? (-OBJECT_TEXTURE_ICON_SIZEX / 2) : 0; - const int iconOffsetY = m_nTextureIcon ? (-OBJECT_TEXTURE_ICON_SIZEY / 2) : 0; - - if (gSettings.viewports.bShowScaleWarnings) - { - const EScaleWarningLevel scaleWarningLevel = GetScaleWarningLevel(); - - if (scaleWarningLevel != eScaleWarningLevel_None) - { - dc.SetColor(QColor(255, scaleWarningLevel == eScaleWarningLevel_RescaledNonUniform ? 50 : 255, 50), 1.0f); - dc.DrawTextureLabel(GetTextureIconDrawPos(), warningIconSizeX, warningIconSizeY, - GetIEditor()->GetIconManager()->GetIconTexture(eIcon_ScaleWarning), GetTextureIconFlags(), - -warningIconSizeX / 2, iconOffsetX - (warningIconSizeY / 2)); - } - } - - if (gSettings.viewports.bShowRotationWarnings) - { - const ERotationWarningLevel rotationWarningLevel = GetRotationWarningLevel(); - if (rotationWarningLevel != eRotationWarningLevel_None) - { - dc.SetColor(QColor(255, rotationWarningLevel == eRotationWarningLevel_RotatedNonRectangular ? 50 : 255, 50), 1.0f); - dc.DrawTextureLabel(GetTextureIconDrawPos(), warningIconSizeX, warningIconSizeY, - GetIEditor()->GetIconManager()->GetIconTexture(eIcon_RotationWarning), GetTextureIconFlags(), - warningIconSizeX / 2, iconOffsetY - (warningIconSizeY / 2)); - } - } - } -} - ////////////////////////////////////////////////////////////////////////// void CBaseObject::DrawLabel(DisplayContext& dc, const Vec3& pos, const QColor& lC, float alpha, float size) { diff --git a/Code/Editor/Objects/BaseObject.h b/Code/Editor/Objects/BaseObject.h index f78755e81d..fea248c7f7 100644 --- a/Code/Editor/Objects/BaseObject.h +++ b/Code/Editor/Objects/BaseObject.h @@ -398,9 +398,6 @@ public: // Interface to be implemented in plugins. ////////////////////////////////////////////////////////////////////////// - //! Draw object to specified viewport. - virtual void Display([[maybe_unused]] DisplayContext& disp) {} - //! Perform intersection testing of this object. //! Return true if was hit. virtual bool HitTest([[maybe_unused]] HitContext& hc) { return false; }; @@ -529,8 +526,6 @@ protected: void ResolveParent(CBaseObject* object); void SetColor(const QColor& color); - //! Draw default object items. - virtual void DrawDefault(DisplayContext& dc, const QColor& labelColor = QColor(255, 255, 255)); //! Draw object label. void DrawLabel(DisplayContext& dc, const Vec3& pos, const QColor& labelColor = QColor(255, 255, 255), float alpha = 1.0f, float size = 1.f); //! Draw 3D Axis at object position. @@ -539,10 +534,6 @@ protected: void DrawArea(DisplayContext& dc); //! Draw selection helper. void DrawSelectionHelper(DisplayContext& dc, const Vec3& pos, const QColor& labelColor = QColor(255, 255, 255), float alpha = 1.0f); - //! Draw helper icon. - virtual void DrawTextureIcon(DisplayContext& dc, const Vec3& pos, float alpha = 1.0f); - //! Draw warning icons - virtual void DrawWarningIcons(DisplayContext& dc, const Vec3& pos); //! Check if dimension's figures can be displayed before draw them. virtual void DrawDimensions(DisplayContext& dc, AABB* pMergedBoundBox = nullptr); @@ -575,7 +566,6 @@ protected: //! Only used by ObjectManager. bool IsPotentiallyVisible() const; - void SetDrawTextureIconProperties(DisplayContext& dc, const Vec3& pos, float alpha = 1.0f, int texIconFlags = 0); const Vec3& GetTextureIconDrawPos(){ return m_vDrawIconPos; }; int GetTextureIconFlags(){ return m_nIconFlags; }; diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp index fbb700723b..a70c200417 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp @@ -723,97 +723,6 @@ CComponentEntityObject* CComponentEntityObject::FindObjectForEntity(AZ::EntityId return nullptr; } -void CComponentEntityObject::Display(DisplayContext& dc) -{ - if (!(dc.flags & DISPLAY_2D)) - { - m_entityIconVisible = false; - } - - bool displaySelectionHelper = false; - if (!CanBeDrawn(dc, displaySelectionHelper)) - { - return; - } - - DrawDefault(dc); - - bool showIcons = m_hasIcon; - if (showIcons) - { - SEditorSettings* editorSettings = GetIEditor()->GetEditorSettings(); - if (!editorSettings->viewports.bShowIcons && !editorSettings->viewports.bShowSizeBasedIcons) - { - showIcons = false; - } - } - - if (m_entityId.IsValid()) - { - // Draw link to parent if this or the parent object are selected. - { - AZ::EntityId parentId; - EBUS_EVENT_ID_RESULT(parentId, m_entityId, AZ::TransformBus, GetParentId); - if (parentId.IsValid()) - { - bool isParentVisible = false; - AzToolsFramework::EditorEntityInfoRequestBus::EventResult(isParentVisible, parentId, &AzToolsFramework::EditorEntityInfoRequestBus::Events::IsVisible); - - CComponentEntityObject* parentObject = CComponentEntityObject::FindObjectForEntity(parentId); - if (isParentVisible && (IsSelected() || (parentObject && parentObject->IsSelected()))) - { - const QColor kLinkColorParent(0, 255, 255); - const QColor kLinkColorChild(0, 0, 255); - - AZ::Vector3 parentTranslation; - EBUS_EVENT_ID_RESULT(parentTranslation, parentId, AZ::TransformBus, GetWorldTranslation); - dc.DrawLine(AZVec3ToLYVec3(parentTranslation), GetWorldTM().GetTranslation(), kLinkColorParent, kLinkColorChild); - } - } - } - - // Don't draw icons if we have an ancestor in the same location that has an icon - makes sure - // ancestor icons draw on top and are able to be selected over children. Also check if a descendant - // is selected at the same location. In cases of entity hierarchies where numerous ancestors have - // no position offset, we need this so the ancestors don't draw over us when we're selected - if (showIcons) - { - if ((dc.flags & DISPLAY_2D) || - IsSelected() || - IsAncestorIconDrawingAtSameLocation() || - IsDescendantSelectedAtSameLocation()) - { - showIcons = false; - } - } - - // Allow components to override in-editor visualization. - { - const AzFramework::DisplayContextRequestGuard displayContextGuard(dc); - - AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; - AzFramework::DebugDisplayRequestBus::Bind( - debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); - AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus."); - - AzFramework::DebugDisplayRequests* debugDisplay = - AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); - - AzFramework::EntityDebugDisplayEventBus::Event( - m_entityId, &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport, - AzFramework::ViewportInfo{ dc.GetView()->asCViewport()->GetViewportId() }, - *debugDisplay); - } - } -} - -void CComponentEntityObject::DrawDefault(DisplayContext& dc, const QColor& labelColor) -{ - CEntityObject::DrawDefault(dc, labelColor); - - DrawAccent(dc); -} - bool CComponentEntityObject::IsIsolated() const { return m_isIsolated; diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h index 7ccea8da84..62209965a5 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h @@ -55,7 +55,6 @@ public: bool SetRotation(const Quat& rotate, int flags) override; bool SetScale(const Vec3& scale, int flags) override; void InvalidateTM(int nWhyFlags) override; - void Display(DisplayContext& disp) override; bool HitTest(HitContext& hc) override; void GetLocalBounds(AABB& box) override; void GetBoundBox(AABB& box) override; @@ -69,7 +68,6 @@ public: void DetachThis(bool bKeepPos = true) override; XmlNodeRef Export(const QString& levelPath, XmlNodeRef& xmlNode) override; void DeleteEntity() override; - void DrawDefault(DisplayContext& dc, const QColor& labelColor = QColor(255, 255, 255)) override; bool IsIsolated() const override; bool IsSelected() const override; diff --git a/Code/Editor/Settings.cpp b/Code/Editor/Settings.cpp index acb48c3545..8561e6dba3 100644 --- a/Code/Editor/Settings.cpp +++ b/Code/Editor/Settings.cpp @@ -142,9 +142,6 @@ SEditorSettings::SEditorSettings() viewports.bShowMeshStatsOnMouseOver = false; viewports.bDrawEntityLabels = false; viewports.bShowTriggerBounds = false; - viewports.bShowIcons = true; - viewports.bDistanceScaleIcons = true; - viewports.bShowSizeBasedIcons = false; viewports.nShowFrozenHelpers = true; viewports.bFillSelectedShapes = false; viewports.nTopMapTextureResolution = 512; @@ -534,8 +531,6 @@ void SEditorSettings::Save(bool isEditorClosing) SaveValue("Settings", "ShowMeshStatsOnMouseOver", viewports.bShowMeshStatsOnMouseOver); SaveValue("Settings", "DrawEntityLabels", viewports.bDrawEntityLabels); SaveValue("Settings", "ShowTriggerBounds", viewports.bShowTriggerBounds); - SaveValue("Settings", "ShowIcons", viewports.bShowIcons); - SaveValue("Settings", "ShowSizeBasedIcons", viewports.bShowSizeBasedIcons); SaveValue("Settings", "ShowFrozenHelpers", viewports.nShowFrozenHelpers); SaveValue("Settings", "FillSelectedShapes", viewports.bFillSelectedShapes); SaveValue("Settings", "MapTextureResolution", viewports.nTopMapTextureResolution); @@ -736,8 +731,6 @@ void SEditorSettings::Load() LoadValue("Settings", "ShowMeshStatsOnMouseOver", viewports.bShowMeshStatsOnMouseOver); LoadValue("Settings", "DrawEntityLabels", viewports.bDrawEntityLabels); LoadValue("Settings", "ShowTriggerBounds", viewports.bShowTriggerBounds); - LoadValue("Settings", "ShowIcons", viewports.bShowIcons); - LoadValue("Settings", "ShowSizeBasedIcons", viewports.bShowSizeBasedIcons); LoadValue("Settings", "ShowFrozenHelpers", viewports.nShowFrozenHelpers); LoadValue("Settings", "FillSelectedShapes", viewports.bFillSelectedShapes); LoadValue("Settings", "MapTextureResolution", viewports.nTopMapTextureResolution); diff --git a/Code/Editor/Settings.h b/Code/Editor/Settings.h index 9276d9b715..0ebb70501d 100644 --- a/Code/Editor/Settings.h +++ b/Code/Editor/Settings.h @@ -136,13 +136,6 @@ struct SViewportsSettings bool bDrawEntityLabels; //! Show Trigger bounds. bool bShowTriggerBounds; - //! Show Icons in viewport. - bool bShowIcons; - //! Scale icons with distance, so they aren't a fixed size no matter how far away you are - bool bDistanceScaleIcons; - - //! Show Size-based Icons in viewport. - bool bShowSizeBasedIcons; //! Show Helpers in viewport for frozen objects. int nShowFrozenHelpers; From bd65da39d0033b504d7da196e86cd9e5a30ec337 Mon Sep 17 00:00:00 2001 From: lsemp3d <58790905+lsemp3d@users.noreply.github.com> Date: Wed, 12 Jan 2022 10:20:04 -0800 Subject: [PATCH 061/108] Updated node subtitle Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> --- .../EBus/Senders/UiFlipbookAnimationBus.names | 75 ++++++++++++------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/UiFlipbookAnimationBus.names b/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/UiFlipbookAnimationBus.names index c0f62a816b..e869048b0c 100644 --- a/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/UiFlipbookAnimationBus.names +++ b/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/UiFlipbookAnimationBus.names @@ -21,7 +21,8 @@ }, "details": { "name": "Get Loop Type", - "tooltip": "Gets the type of looping behavior for the animation" + "tooltip": "Gets the type of looping behavior for the animation", + "subtitle": "UI Flipbook" }, "results": [ { @@ -44,7 +45,8 @@ }, "details": { "name": "Get Reverse Delay", - "tooltip": "Gets the delay (in seconds) before playing the reverse loop sequence (PingPong loop types only)" + "tooltip": "Gets the delay (in seconds) before playing the reverse loop sequence (PingPong loop types only)", + "subtitle": "UI Flipbook" }, "results": [ { @@ -67,7 +69,8 @@ }, "details": { "name": "Set Is Auto Play Enabled", - "tooltip": "Sets whether the animation will begin playing as soon as the element is activated" + "tooltip": "Sets whether the animation will begin playing as soon as the element is activated", + "subtitle": "UI Flipbook" }, "params": [ { @@ -91,7 +94,8 @@ }, "details": { "name": "Set Current Frame", - "tooltip": "Sets the frame to immediately display for the animation" + "tooltip": "Sets the frame to immediately display for the animation", + "subtitle": "UI Flipbook" }, "params": [ { @@ -115,7 +119,8 @@ }, "details": { "name": "Get Loop Start Frame", - "tooltip": "Gets the first frame that is displayed within an animation loop. Applicable only when the \"Loop Type\" is set to anything other than \"None\"" + "tooltip": "Gets the first frame that is displayed within an animation loop. Applicable only when the \"Loop Type\" is set to anything other than \"None\"", + "subtitle": "UI Flipbook" }, "results": [ { @@ -138,7 +143,8 @@ }, "details": { "name": "Set Loop Type", - "tooltip": "Sets the type of looping behavior for this animation" + "tooltip": "Sets the type of looping behavior for this animation", + "subtitle": "UI Flipbook" }, "params": [ { @@ -162,7 +168,8 @@ }, "details": { "name": "Get Start Delay", - "tooltip": "Gets the delay (in seconds) before playing the flipbook (applied only once during playback)" + "tooltip": "Gets the delay (in seconds) before playing the flipbook (applied only once during playback)", + "subtitle": "UI Flipbook" }, "results": [ { @@ -185,7 +192,8 @@ }, "details": { "name": "Set Start Delay", - "tooltip": "Sets the delay (in seconds) before playing the flipbook (applied only once during playback)" + "tooltip": "Sets the delay (in seconds) before playing the flipbook (applied only once during playback)", + "subtitle": "UI Flipbook" }, "params": [ { @@ -209,7 +217,8 @@ }, "details": { "name": "Get Current Frame", - "tooltip": "Gets the frame of the animation currently displayed" + "tooltip": "Gets the frame of the animation currently displayed", + "subtitle": "UI Flipbook" }, "results": [ { @@ -232,7 +241,8 @@ }, "details": { "name": "Get Framerate", - "tooltip": "Gets the speed used to determine when to transition to the next frame. Framerate is defined relative to unit of time, specified by FramerateUnits" + "tooltip": "Gets the speed used to determine when to transition to the next frame. Framerate is defined relative to unit of time, specified by FramerateUnits", + "subtitle": "UI Flipbook" }, "results": [ { @@ -255,7 +265,8 @@ }, "details": { "name": "Set Loop Delay", - "tooltip": "Sets the delay (in seconds) before playing the loop sequence" + "tooltip": "Sets the delay (in seconds) before playing the loop sequence", + "subtitle": "UI Flipbook" }, "params": [ { @@ -279,7 +290,8 @@ }, "details": { "name": "Get Start Frame", - "tooltip": "Gets the first frame to display when starting the animation" + "tooltip": "Gets the first frame to display when starting the animation", + "subtitle": "UI Flipbook" }, "results": [ { @@ -302,7 +314,8 @@ }, "details": { "name": "Set Framerate Unit", - "tooltip": "Sets the framerate unit (0 = Frames per second, 1 = Seconds per frame)" + "tooltip": "Sets the framerate unit (0 = Frames per second, 1 = Seconds per frame)", + "subtitle": "UI Flipbook" }, "params": [ { @@ -326,7 +339,8 @@ }, "details": { "name": "Is Playing", - "tooltip": "Returns whether the animation is currently playing" + "tooltip": "Returns whether the animation is currently playing", + "subtitle": "UI Flipbook" }, "results": [ { @@ -349,7 +363,8 @@ }, "details": { "name": "Set End Frame", - "tooltip": "Sets the last frame to display for the animation" + "tooltip": "Sets the last frame to display for the animation", + "subtitle": "UI Flipbook" }, "params": [ { @@ -373,7 +388,8 @@ }, "details": { "name": "Set Loop Start Frame", - "tooltip": "Sets the first frame that is displayed within an animation loop. Applicable only when the \"Loop Type\" is set to anything other than \"None\"" + "tooltip": "Sets the first frame that is displayed within an animation loop. Applicable only when the \"Loop Type\" is set to anything other than \"None\"", + "subtitle": "UI Flipbook" }, "params": [ { @@ -397,7 +413,8 @@ }, "details": { "name": "Set Reverse Delay", - "tooltip": "Sets the delay (in seconds) before playing the reverse loop sequence (PingPong loop types only)" + "tooltip": "Sets the delay (in seconds) before playing the reverse loop sequence (PingPong loop types only)", + "subtitle": "UI Flipbook" }, "params": [ { @@ -421,7 +438,8 @@ }, "details": { "name": "Stop", - "tooltip": "Ends the animation" + "tooltip": "Ends the animation", + "subtitle": "UI Flipbook" } }, { @@ -436,7 +454,8 @@ }, "details": { "name": "Set Framerate", - "tooltip": "Sets the speed used to determine when to transition to the next frame. Framerate is defined relative to unit of time, specified by FramerateUnits" + "tooltip": "Sets the speed used to determine when to transition to the next frame. Framerate is defined relative to unit of time, specified by FramerateUnits", + "subtitle": "UI Flipbook" }, "params": [ { @@ -460,7 +479,8 @@ }, "details": { "name": "Is Auto Play Enabled", - "tooltip": "Returns whether the animation will begin playing as soon as the element is activated" + "tooltip": "Returns whether the animation will begin playing as soon as the element is activated", + "subtitle": "UI Flipbook" }, "results": [ { @@ -483,7 +503,8 @@ }, "details": { "name": "Start", - "tooltip": "Begins playing the flipbook animation" + "tooltip": "Begins playing the flipbook animation", + "subtitle": "UI Flipbook" } }, { @@ -498,7 +519,8 @@ }, "details": { "name": "Set Start Frame", - "tooltip": "Sets the first frame to display when starting the animation" + "tooltip": "Sets the first frame to display when starting the animation", + "subtitle": "UI Flipbook" }, "params": [ { @@ -522,7 +544,8 @@ }, "details": { "name": "Get End Frame", - "tooltip": "Gets the last frame to display for the animation" + "tooltip": "Gets the last frame to display for the animation", + "subtitle": "UI Flipbook" }, "results": [ { @@ -545,7 +568,8 @@ }, "details": { "name": "Get Framerate Unit", - "tooltip": "Gets the framerate unit (0 = Frames per second, 1 = Seconds per frame)" + "tooltip": "Gets the framerate unit (0 = Frames per second, 1 = Seconds per frame)", + "subtitle": "UI Flipbook" }, "results": [ { @@ -568,7 +592,8 @@ }, "details": { "name": "Get Loop Delay", - "tooltip": "Gets the delay (in seconds) before playing the loop sequence" + "tooltip": "Gets the delay (in seconds) before playing the loop sequence", + "subtitle": "UI Flipbook" }, "results": [ { From 5b195cb028781c8738da4d9e7ff587f0f940c0aa Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 12 Jan 2022 12:33:36 -0600 Subject: [PATCH 062/108] Removed some unused variables Signed-off-by: Chris Galvan --- Code/Editor/Objects/BaseObject.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Code/Editor/Objects/BaseObject.cpp b/Code/Editor/Objects/BaseObject.cpp index 5ae68eaad7..c14547407b 100644 --- a/Code/Editor/Objects/BaseObject.cpp +++ b/Code/Editor/Objects/BaseObject.cpp @@ -36,12 +36,6 @@ // To use the Andrew's algorithm in order to make convex hull from the points, this header is needed. #include "Util/GeometryUtil.h" -namespace { - QColor kLinkColorParent = QColor(0, 255, 255); - QColor kLinkColorChild = QColor(0, 0, 255); - QColor kLinkColorGray = QColor(128, 128, 128); -} - extern CObjectManager* g_pObjectManager; ////////////////////////////////////////////////////////////////////////// From 068244b1bb28191758637028864505c2b727b890 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Wed, 12 Jan 2022 12:00:33 -0800 Subject: [PATCH 063/108] Remove quotes around list of paths (#6857) Signed-off-by: amzn-sj --- cmake/Platform/Mac/runtime_dependencies_mac.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in index 51e6e5830c..c27bf1fde4 100644 --- a/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in +++ b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in @@ -187,7 +187,7 @@ if(@target_file_dir@ MATCHES ".app/Contents/MacOS") ) file(GLOB_RECURSE exe_file_list "${bundle_path}/Contents/Frameworks/Python.framework/**/*.exe") if(exe_file_list) - file(REMOVE_RECURSE "${exe_file_list}") + file(REMOVE_RECURSE ${exe_file_list}) endif() execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink include/python3.7m Headers WORKING_DIRECTORY "${bundle_path}/Contents/Frameworks/Python.framework/Versions/3.7" From 5dc442fcb0f2946cd104849b9bc814be134b9426 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Wed, 12 Jan 2022 12:07:57 -0800 Subject: [PATCH 064/108] [Terrain] First pass of the ProcessList and ProcessRegion APIs for retrieving surface data (#6729) * [Terrain] First pass of the ProcessList and ProcessRegion APIs for retrieving surface data Signed-off-by: amzn-sj * Add a couple of more tests. The expected values were plugged in based on the values generated by the brute force approach. Signed-off-by: amzn-sj * Move some declarations out of loops since they can be reused. Signed-off-by: amzn-sj * Update all the per position callbacks to pass SurfacePoint refs. Construct only one SurfacePoint object outside the loop which can be reused. Signed-off-by: amzn-sj * Update tests to use the new per position callbacks Signed-off-by: amzn-sj * Add ProcessRegion functions to the terrain benchmark. Signed-off-by: amzn-sj * Change C style static casts to aznumeric_cast. Add maybe_unused to unused params in benchmarks. Signed-off-by: amzn-sj * Update the ProcessList API functions to use array_view instead of a vector. This includes some additional changes to satisfy build dependencies. Signed-off-by: amzn-sj * Add ProcessList API functions to benchmarks Signed-off-by: amzn-sj * Update the ProcessList API functions to take Vector2 as input positions Signed-off-by: amzn-sj * Revert changes to AtomCore library split. Add partial implementation of span(mostly just copied over from array_view) to AzCore std containers. Signed-off-by: amzn-sj * Adding some const/non-const overloads that were missing in span Signed-off-by: amzn-sj * Move input position list generation to a function Signed-off-by: amzn-sj * Bring back Vector3 version of ProcessList functions. Rename Vector2 version to follow similar pattern as the Get functions. Signed-off-by: amzn-sj * Split span.h into .h/.inl files Signed-off-by: amzn-sj * Add [mayby_unused] for unused parameters to fix build errors Signed-off-by: amzn-sj --- .../AzCore/AzCore/std/azstd_files.cmake | 2 + .../AzCore/AzCore/std/containers/span.h | 137 ++++++++ .../AzCore/AzCore/std/containers/span.inl | 150 ++++++++ .../Terrain/TerrainDataRequestBus.h | 50 +++ .../Mocks/Terrain/MockTerrainDataRequestBus.h | 24 ++ .../Source/TerrainSystem/TerrainSystem.cpp | 282 +++++++++++++-- .../Code/Source/TerrainSystem/TerrainSystem.h | 47 +++ .../Code/Tests/TerrainSystemBenchmarks.cpp | 262 ++++++++++++++ Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 330 ++++++++++++++++++ 9 files changed, 1251 insertions(+), 33 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/std/containers/span.h create mode 100644 Code/Framework/AzCore/AzCore/std/containers/span.inl diff --git a/Code/Framework/AzCore/AzCore/std/azstd_files.cmake b/Code/Framework/AzCore/AzCore/std/azstd_files.cmake index 2746489f8c..d516a56295 100644 --- a/Code/Framework/AzCore/AzCore/std/azstd_files.cmake +++ b/Code/Framework/AzCore/AzCore/std/azstd_files.cmake @@ -64,6 +64,8 @@ set(FILES containers/rbtree.h containers/ring_buffer.h containers/set.h + containers/span.h + containers/span.inl containers/stack.h containers/unordered_map.h containers/unordered_set.h diff --git a/Code/Framework/AzCore/AzCore/std/containers/span.h b/Code/Framework/AzCore/AzCore/std/containers/span.h new file mode 100644 index 0000000000..8f68e921d8 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/std/containers/span.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include + +namespace AZStd +{ + /** + * First pass partial implementation of span copied over from array_view. It + * returns non-const iterator/pointers. first(), last(), and subspan() + * are yet to be implemented. It does not maintain storage for the data, + * but just holds pointers to mark the beginning and end of the array. + * It can be conveniently constructed from a variety of other container + * types like array, vector, and fixed_vector. + * + * Example: + * Given "void Func(AZStd::span a) {...}" you can call... + * - Func({1,2,3}); + * - AZStd::array a = {1,2,3}; + * Func(a); + * - AZStd::vector v = {1,2,3}; + * Func(v); + * - AZStd::fixed_vector fv = {1,2,3}; + * Func(fv); + * + * Since the span does not copy and store any data, it is only valid as long as the data used to create it is valid. + */ + template + class span final + { + public: + using value_type = Element; + + using pointer = value_type*; + using const_pointer = const value_type*; + + using reference = value_type&; + using const_reference = const value_type&; + + using size_type = AZStd::size_t; + using difference_type = AZStd::ptrdiff_t; + + using iterator = value_type*; + using const_iterator = const value_type*; + using reverse_iterator = AZStd::reverse_iterator; + using const_reverse_iterator = AZStd::reverse_iterator; + + constexpr span(); + + ~span() = default; + + constexpr span(pointer s, size_type length); + + constexpr span(pointer first, const_pointer last); + + // We explicitly delete this constructor because it's too easy to accidentally + // create a span to just the first element instead of an entire array. + constexpr span(const_pointer s) = delete; + + template + constexpr span(AZStd::array& data); + + constexpr span(AZStd::vector& data); + + template + constexpr span(AZStd::fixed_vector& data); + + template + constexpr span(const AZStd::array& data); + + constexpr span(const AZStd::vector& data); + + template + constexpr span(const AZStd::fixed_vector& data); + + constexpr span(const span&) = default; + + constexpr span(span&& other); + + constexpr span& operator=(const span& other) = default; + + constexpr span& operator=(span&& other); + + constexpr size_type size() const; + + constexpr bool empty() const; + + constexpr pointer data(); + constexpr const_pointer data() const; + + constexpr const_reference operator[](size_type index) const; + constexpr reference operator[](size_type index); + + constexpr void erase(); + + constexpr iterator begin(); + constexpr iterator end(); + constexpr const_iterator begin() const; + constexpr const_iterator end() const; + + constexpr const_iterator cbegin() const; + constexpr const_iterator cend() const; + + constexpr reverse_iterator rbegin(); + constexpr reverse_iterator rend(); + constexpr const_reverse_iterator rbegin() const; + constexpr const_reverse_iterator rend() const; + + constexpr const_reverse_iterator crbegin() const; + constexpr const_reverse_iterator crend() const; + + friend bool operator==(span lhs, span rhs) + { + return lhs.m_begin == rhs.m_begin && lhs.m_end == rhs.m_end; + } + + friend bool operator!=(span lhs, span rhs) { return !(lhs == rhs); } + friend bool operator< (span lhs, span rhs) { return lhs.m_begin < rhs.m_begin || lhs.m_begin == rhs.m_begin && lhs.m_end < rhs.m_end; } + friend bool operator> (span lhs, span rhs) { return lhs.m_begin > rhs.m_begin || lhs.m_begin == rhs.m_begin && lhs.m_end > rhs.m_end; } + friend bool operator<=(span lhs, span rhs) { return lhs == rhs || lhs < rhs; } + friend bool operator>=(span lhs, span rhs) { return lhs == rhs || lhs > rhs; } + + private: + pointer m_begin; + pointer m_end; + }; +} // namespace AZStd + +#include diff --git a/Code/Framework/AzCore/AzCore/std/containers/span.inl b/Code/Framework/AzCore/AzCore/std/containers/span.inl new file mode 100644 index 0000000000..c33e4a7227 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/std/containers/span.inl @@ -0,0 +1,150 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +namespace AZStd +{ + template + inline constexpr span::span() + : m_begin(nullptr) + , m_end(nullptr) + { } + + template + inline constexpr span::span(pointer s, size_type length) + : m_begin(s) + , m_end(m_begin + length) + { + if (length == 0) erase(); + } + + template + inline constexpr span::span(pointer first, const_pointer last) + : m_begin(first) + , m_end(last) + { } + + template + template + inline constexpr span::span(AZStd::array& data) + : m_begin(data.data()) + , m_end(m_begin + data.size()) + { } + + template + inline constexpr span::span(AZStd::vector& data) + : m_begin(data.data()) + , m_end(m_begin + data.size()) + { } + + template + template + inline constexpr span::span(AZStd::fixed_vector& data) + : m_begin(data.data()) + , m_end(m_begin + data.size()) + { } + + template + template + inline constexpr span::span(const AZStd::array& data) + : m_begin(data.data()) + , m_end(m_begin + data.size()) + { } + + template + inline constexpr span::span(const AZStd::vector& data) + : m_begin(data.data()) + , m_end(m_begin + data.size()) + { } + + template + template + inline constexpr span::span(const AZStd::fixed_vector& data) + : m_begin(data.data()) + , m_end(m_begin + data.size()) + { } + + template + inline constexpr span::span(span&& other) + : span(other.m_begin, other.m_end) + { +#if AZ_DEBUG_BUILD // Clearing the original pointers isn't necessary, but is good for debugging + other.m_begin = nullptr; + other.m_end = nullptr; +#endif + } + + template + inline constexpr AZStd::size_t span::size() const { return m_end - m_begin; } + + template + inline constexpr bool span::empty() const { return m_end == m_begin; } + + template + inline constexpr Element* span::data() { return m_begin; } + + template + inline constexpr const Element* span::data() const { return m_begin; } + + template + inline constexpr span& span::operator=(span&& other) + { + m_begin = other.m_begin; + m_end = other.m_end; +#if AZ_DEBUG_BUILD // Clearing the original pointers isn't necessary, but is good for debugging + other.m_begin = nullptr; + other.m_end = nullptr; +#endif + return *this; + } + + template + inline constexpr const Element& span::operator[](AZStd::size_t index) const + { + AZ_Assert(index < size(), "index value is out of range"); + return m_begin[index]; + } + + template + inline constexpr Element& span::operator[](AZStd::size_t index) + { + AZ_Assert(index < size(), "index value is out of range"); + return m_begin[index]; + } + + template + inline constexpr void span::erase() { m_begin = m_end = nullptr; } + + template + inline constexpr Element* span::begin() { return m_begin; } + template + inline constexpr Element* span::end() { return m_end; } + template + inline constexpr const Element* span::begin() const { return m_begin; } + template + inline constexpr const Element* span::end() const { return m_end; } + + template + inline constexpr const Element* span::cbegin() const { return m_begin; } + template + inline constexpr const Element* span::cend() const { return m_end; } + + template + inline constexpr AZStd::reverse_iterator span::rbegin() { return AZStd::reverse_iterator(m_end); } + template + inline constexpr AZStd::reverse_iterator span::rend() { return AZStd::reverse_iterator(m_begin); } + template + inline constexpr AZStd::reverse_iterator span::rbegin() const { return AZStd::reverse_iterator(m_end); } + template + inline constexpr AZStd::reverse_iterator span::rend() const { return AZStd::reverse_iterator(m_begin); } + + template + inline constexpr AZStd::reverse_iterator span::crbegin() const { return AZStd::reverse_iterator(cend()); } + template + inline constexpr AZStd::reverse_iterator span::crend() const { return AZStd::reverse_iterator(cbegin()); } +} // namespace AZStd diff --git a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h index 2572a07494..0d16bf3460 100644 --- a/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h +++ b/Code/Framework/AzFramework/AzFramework/Terrain/TerrainDataRequestBus.h @@ -11,12 +11,15 @@ #include #include #include +#include #include namespace AzFramework { namespace Terrain { + typedef AZStd::function SurfacePointRegionFillCallback; + typedef AZStd::function SurfacePointListFillCallback; //! Shared interface for terrain system implementations class TerrainDataRequests @@ -131,6 +134,53 @@ namespace AzFramework Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const = 0; + //! Given a list of XY coordinates, call the provided callback function with surface data corresponding to each + //! XY coordinate in the list. + virtual void ProcessHeightsFromList(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessNormalsFromList(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessSurfaceWeightsFromList(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessSurfacePointsFromList(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessHeightsFromListOfVector2(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessNormalsFromListOfVector2(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessSurfaceWeightsFromListOfVector2(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessSurfacePointsFromListOfVector2(const AZStd::span& inPositions, + SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + + //! Given a region(aabb) and a step size, call the provided callback function with surface data corresponding to the + //! coordinates in the region. + virtual void ProcessHeightsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessNormalsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessSurfaceWeightsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + virtual void ProcessSurfacePointsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const = 0; + + private: // Private variations of the GetSurfacePoint API exposed to BehaviorContext that returns a value instead of // using an "out" parameter. The "out" parameter is useful for reusing memory allocated in SurfacePoint when diff --git a/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h b/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h index dbce11d639..f3a6cc07b3 100644 --- a/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h +++ b/Code/Framework/AzFramework/Tests/Mocks/Terrain/MockTerrainDataRequestBus.h @@ -76,5 +76,29 @@ namespace UnitTest GetSurfacePointFromVector2, void(const AZ::Vector2&, AzFramework::SurfaceData::SurfacePoint&, Sampler, bool*)); MOCK_CONST_METHOD5( GetSurfacePointFromFloats, void(float, float, AzFramework::SurfaceData::SurfacePoint&, Sampler, bool*)); + MOCK_CONST_METHOD3( + ProcessHeightsFromList, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD3( + ProcessNormalsFromList, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD3( + ProcessSurfaceWeightsFromList, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD3( + ProcessSurfacePointsFromList, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD3( + ProcessHeightsFromListOfVector2, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD3( + ProcessNormalsFromListOfVector2, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD3( + ProcessSurfaceWeightsFromListOfVector2, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD3( + ProcessSurfacePointsFromListOfVector2, void(const AZStd::span&, AzFramework::Terrain::SurfacePointListFillCallback, Sampler)); + MOCK_CONST_METHOD4( + ProcessHeightsFromRegion, void(const AZ::Aabb&, const AZ::Vector2&, AzFramework::Terrain::SurfacePointRegionFillCallback, Sampler)); + MOCK_CONST_METHOD4( + ProcessNormalsFromRegion, void(const AZ::Aabb&, const AZ::Vector2&, AzFramework::Terrain::SurfacePointRegionFillCallback, Sampler)); + MOCK_CONST_METHOD4( + ProcessSurfaceWeightsFromRegion, void(const AZ::Aabb&, const AZ::Vector2&, AzFramework::Terrain::SurfacePointRegionFillCallback, Sampler)); + MOCK_CONST_METHOD4( + ProcessSurfacePointsFromRegion, void(const AZ::Aabb&, const AZ::Vector2&, AzFramework::Terrain::SurfacePointRegionFillCallback, Sampler)); }; } // namespace UnitTest diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index 7c8b6021af..2ecd13b5ad 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -530,9 +530,171 @@ const char* TerrainSystem::GetMaxSurfaceName( return ""; } -/* +void TerrainSystem::ProcessHeightsFromList( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } -void TerrainSystem::ProcessHeightsFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, Sampler sampleFilter, SurfacePointRegionFillCallback perPositionCallback, TerrainDataReadyCallback onComplete) + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position = position; + surfacePoint.m_position.SetZ(GetHeight(position, sampleFilter, &terrainExists)); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessNormalsFromList( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position = position; + surfacePoint.m_normal = GetNormal(position, sampleFilter, &terrainExists); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessSurfaceWeightsFromList( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position = position; + GetSurfaceWeights(position, surfacePoint.m_surfaceTags, sampleFilter, &terrainExists); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessSurfacePointsFromList( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position = position; + GetSurfacePoint(position, surfacePoint, sampleFilter, &terrainExists); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessHeightsFromListOfVector2( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position.Set(position.GetX(), position.GetY(), 0.0f); + surfacePoint.m_position.SetZ(GetHeightFromVector2(position, sampleFilter, &terrainExists)); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessNormalsFromListOfVector2( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position.Set(position.GetX(), position.GetY(), 0.0f); + surfacePoint.m_normal = GetNormalFromVector2(position, sampleFilter, &terrainExists); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessSurfaceWeightsFromListOfVector2( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position.Set(position.GetX(), position.GetY(), 0.0f); + GetSurfaceWeightsFromVector2(position, surfacePoint.m_surfaceTags, sampleFilter, &terrainExists); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessSurfacePointsFromListOfVector2( + const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + if (!perPositionCallback) + { + return; + } + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (const auto& position : inPositions) + { + bool terrainExists = false; + surfacePoint.m_position.Set(position.GetX(), position.GetY(), 0.0f); + GetSurfacePointFromVector2(position, surfacePoint, sampleFilter, &terrainExists); + perPositionCallback(surfacePoint, terrainExists); + } +} + +void TerrainSystem::ProcessHeightsFromRegion( + const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter) const { // Don't bother processing if we don't have a callback if (!perPositionCallback) @@ -540,30 +702,29 @@ void TerrainSystem::ProcessHeightsFromRegion(const AZ::Aabb& inRegion, const AZ: return; } - uint32_t numSamplesX = static_cast((inRegion.GetMax().GetX() - inRegion.GetMin().GetX()) / stepSize.GetX()); - uint32_t numSamplesY = static_cast((inRegion.GetMax().GetY() - inRegion.GetMin().GetY()) / stepSize.GetY()); - - for (uint32_t y = 0; y < numSamplesY; y++) + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) { - for (uint32_t x = 0; x < numSamplesX; x++) + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) { - float fx = (float)(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - float fy = (float)(inRegion.GetMin().GetY() + (y * stepSize.GetY())); - - SurfaceData::SurfacePoint surfacePoint; - GetHeight(AZ::Vector3(fx, fy, 0.0f), sampleFilter, surfacePoint.m_position); - perPositionCallback(surfacePoint, x, y); + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, 0.0f); + surfacePoint.m_position.SetZ(GetHeight(surfacePoint.m_position, sampleFilter, &terrainExists)); + perPositionCallback(x, y, surfacePoint, terrainExists); } } - - if (onComplete) - { - onComplete(); - } } - -void TerrainSystem::ProcessSurfacePointsFromRegion(const AZ::Aabb& inRegion, const AZ::Vector2 stepSize, Sampler sampleFilter, SurfacePointRegionFillCallback perPositionCallback, TerrainDataReadyCallback onComplete) +void TerrainSystem::ProcessNormalsFromRegion( + const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter) const { // Don't bother processing if we don't have a callback if (!perPositionCallback) @@ -571,28 +732,83 @@ void TerrainSystem::ProcessSurfacePointsFromRegion(const AZ::Aabb& inRegion, con return; } - uint32_t numSamplesX = static_cast((inRegion.GetMax().GetX() - inRegion.GetMin().GetX()) / stepSize.GetX()); - uint32_t numSamplesY = static_cast((inRegion.GetMax().GetY() - inRegion.GetMin().GetY()) / stepSize.GetY()); + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); - for (uint32_t y = 0; y < numSamplesY; y++) + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) { - for (uint32_t x = 0; x < numSamplesX; x++) + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) { - float fx = (float)(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - float fy = (float)(inRegion.GetMin().GetY() + (y * stepSize.GetY())); - - SurfaceData::SurfacePoint surfacePoint; - GetSurfacePoint(AZ::Vector3(fx, fy, inRegion.GetMin().GetZ()), sampleFilter, surfacePoint); - perPositionCallback(surfacePoint, x, y); + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, 0.0f); + surfacePoint.m_normal = GetNormal(surfacePoint.m_position, sampleFilter, &terrainExists); + perPositionCallback(x, y, surfacePoint, terrainExists); } } +} - if (onComplete) +void TerrainSystem::ProcessSurfaceWeightsFromRegion( + const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + // Don't bother processing if we don't have a callback + if (!perPositionCallback) { - onComplete(); + return; + } + + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) + { + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, 0.0f); + GetSurfaceWeights(surfacePoint.m_position, surfacePoint.m_surfaceTags, sampleFilter, &terrainExists); + perPositionCallback(x, y, surfacePoint, terrainExists); + } + } +} + +void TerrainSystem::ProcessSurfacePointsFromRegion( + const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter) const +{ + // Don't bother processing if we don't have a callback + if (!perPositionCallback) + { + return; + } + + const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + + AzFramework::SurfaceData::SurfacePoint surfacePoint; + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) + { + bool terrainExists = false; + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + surfacePoint.m_position.Set(fx, fy, 0.0f); + GetSurfacePoint(surfacePoint.m_position, surfacePoint, sampleFilter, &terrainExists); + perPositionCallback(x, y, surfacePoint, terrainExists); + } } } -*/ void TerrainSystem::RegisterArea(AZ::EntityId areaId) { diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index d7267476ed..7c6e0cd91e 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -135,6 +136,52 @@ namespace Terrain Sampler sampleFilter = Sampler::DEFAULT, bool* terrainExistsPtr = nullptr) const override; + //! Given a list of XY coordinates, call the provided callback function with surface data corresponding to each + //! XY coordinate in the list. + virtual void ProcessHeightsFromList(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessNormalsFromList(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessSurfaceWeightsFromList(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessSurfacePointsFromList(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessHeightsFromListOfVector2(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessNormalsFromListOfVector2(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessSurfaceWeightsFromListOfVector2(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessSurfacePointsFromListOfVector2(const AZStd::span& inPositions, + AzFramework::Terrain::SurfacePointListFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + + //! Given a region(aabb) and a step size, call the provided callback function with surface data corresponding to the + //! coordinates in the region. + virtual void ProcessHeightsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessNormalsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessSurfaceWeightsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + virtual void ProcessSurfacePointsFromRegion(const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize, + AzFramework::Terrain::SurfacePointRegionFillCallback perPositionCallback, + Sampler sampleFilter = Sampler::DEFAULT) const override; + private: void ClampPosition(float x, float y, AZ::Vector2& outPosition, AZ::Vector2& normalizedDelta) const; diff --git a/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp b/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp index 3d0cb5222e..85dd5dc0c4 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemBenchmarks.cpp @@ -281,6 +281,22 @@ namespace UnitTest surfaceGradientShapeRequests.clear(); } + void GenerateInputPositionsList(const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, AZStd::vector& positions) + { + const size_t numSamplesX = aznumeric_cast(ceil(worldBounds.GetExtents().GetX() / queryResolution.GetX())); + const size_t numSamplesY = aznumeric_cast(ceil(worldBounds.GetExtents().GetY() / queryResolution.GetY())); + + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(worldBounds.GetMin().GetY() + (y * queryResolution.GetY())); + for (size_t x = 0; x < numSamplesX; x++) + { + float fx = aznumeric_cast(worldBounds.GetMin().GetX() + (x * queryResolution.GetX())); + positions.emplace_back(fx, fy, 0.0f); + } + } + } + protected: AZStd::unique_ptr m_app; }; @@ -322,6 +338,72 @@ namespace UnitTest ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) ->Unit(::benchmark::kMillisecond); + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessHeightsRegion)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + []([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + auto perPositionCallback = []([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint.m_position.GetZ()); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessHeightsFromRegion, worldBounds, queryResolution, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessHeightsRegion) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessHeightsList)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + [this]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + AZStd::vector inPositions; + GenerateInputPositionsList(queryResolution, worldBounds, inPositions); + + auto perPositionCallback = [](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint.m_position.GetZ()); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessHeightsFromList, inPositions, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessHeightsList) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 4096, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetNormal)(benchmark::State& state) { // Run the benchmark @@ -353,6 +435,66 @@ namespace UnitTest ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) ->Unit(::benchmark::kMillisecond); + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessNormalsRegion)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + []([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + auto perPositionCallback = []([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint.m_normal); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessNormalsFromRegion, worldBounds, queryResolution, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessNormalsRegion) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessNormalsList)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + [this]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + AZStd::vector inPositions; + GenerateInputPositionsList(queryResolution, worldBounds, inPositions); + + auto perPositionCallback = [](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint.m_normal); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessNormalsFromList, inPositions, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessNormalsList) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetSurfaceWeights)(benchmark::State& state) { // Run the benchmark @@ -385,6 +527,66 @@ namespace UnitTest ->Args({ 2048, 4, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) ->Unit(::benchmark::kMillisecond); + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfaceWeightsRegion)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + []([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + auto perPositionCallback = []([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint.m_surfaceTags); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessSurfaceWeightsFromRegion, worldBounds, queryResolution, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfaceWeightsRegion) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 2, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 2, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 4, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 4, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfaceWeightsList)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + [this]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + AZStd::vector inPositions; + GenerateInputPositionsList(queryResolution, worldBounds, inPositions); + + auto perPositionCallback = [](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint.m_surfaceTags); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessSurfaceWeightsFromList, inPositions, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfaceWeightsList) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 2, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 2, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 1024, 4, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 4, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_GetSurfacePoints)(benchmark::State& state) { // Run the benchmark @@ -416,6 +618,66 @@ namespace UnitTest ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfacePointsRegion)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + []([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + auto perPositionCallback = []([[maybe_unused]] size_t xIndex, [[maybe_unused]] size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessSurfacePointsFromRegion, worldBounds, queryResolution, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfacePointsRegion) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); + + BENCHMARK_DEFINE_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfacePointsList)(benchmark::State& state) + { + // Run the benchmark + RunTerrainApiBenchmark( + state, + [this]([[maybe_unused]] const AZ::Vector2& queryResolution, const AZ::Aabb& worldBounds, + AzFramework::Terrain::TerrainDataRequests::Sampler sampler) + { + AZStd::vector inPositions; + GenerateInputPositionsList(queryResolution, worldBounds, inPositions); + + auto perPositionCallback = [](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + benchmark::DoNotOptimize(surfacePoint); + }; + + AzFramework::Terrain::TerrainDataRequestBus::Broadcast( + &AzFramework::Terrain::TerrainDataRequests::ProcessSurfacePointsFromList, inPositions, perPositionCallback, sampler); + } + ); + } + + BENCHMARK_REGISTER_F(TerrainSystemBenchmarkFixture, BM_ProcessSurfacePointsList) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP) }) + ->Args({ 1024, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Args({ 2048, 1, static_cast(AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT) }) + ->Unit(::benchmark::kMillisecond); #endif } diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp index e5434c0a1d..a5798a3dad 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -41,6 +41,28 @@ namespace UnitTest float m_expectedHeight = 0.0f; }; + struct NormalTestPoint + { + AZ::Vector2 m_testLocation = AZ::Vector2::CreateZero(); + AZ::Vector3 m_expectedNormal = AZ::Vector3::CreateZero(); + }; + + struct HeightTestRegionPoints + { + size_t m_xIndex; + size_t m_yIndex; + float m_expectedHeight; + AZ::Vector2 m_testLocation = AZ::Vector2::CreateZero(); + }; + + struct NormalTestRegionPoints + { + size_t m_xIndex; + size_t m_yIndex; + AZ::Vector3 m_expectedNormal = AZ::Vector3::CreateZero(); + AZ::Vector2 m_testLocation = AZ::Vector2::CreateZero(); + }; + AZ::ComponentApplication m_app; AZStd::unique_ptr> m_boxShapeRequests; @@ -572,4 +594,312 @@ namespace UnitTest EXPECT_EQ(tagWeight.m_surfaceType, tagWeight1.m_surfaceType); EXPECT_NEAR(tagWeight.m_weight, tagWeight1.m_weight, 0.01f); } + + TEST_F(TerrainSystemTest, TerrainProcessHeightsFromListWithBilinearSamplers) + { + // This repeats the same test as TerrainHeightQueriesWithBilinearSamplersUseQueryGridToInterpolate + // The difference is that it tests the ProcessHeightsFromList variation. + + const AZ::Aabb spawnerBox = AZ::Aabb::CreateFromMinMaxValues(-10.0f, -10.0f, -5.0f, 10.0f, 10.0f, 15.0f); + const float amplitudeMeters = 10.0f; + const float frequencyMeters = 1.0f; + auto entity = CreateAndActivateMockTerrainLayerSpawner( + spawnerBox, + [amplitudeMeters, frequencyMeters](AZ::Vector3& position, bool& terrainExists) + { + // Our generated height will be X + Y. + float expectedHeight = position.GetX() + position.GetY(); + + // If either X or Y aren't evenly divisible by the query frequency, add a scaled value to our generated height. + // This will show up as an unexpected height "spike" if it gets used in any bilinear filter queries. + float unexpectedVariance = + amplitudeMeters * (fmodf(position.GetX(), frequencyMeters) + fmodf(position.GetY(), frequencyMeters)); + position.SetZ(expectedHeight + unexpectedVariance); + terrainExists = true; + }); + + // Create and activate the terrain system with our testing defaults for world bounds, and a query resolution at 1 meter intervals. + const AZ::Vector2 queryResolution(frequencyMeters); + auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution); + + // Test some points and verify that the results are the expected bilinear filtered result, + // whether they're in positive or negative space. + // (Z contains the the expected result for convenience). + const HeightTestPoint testPoints[] = { + + // Queries directly on grid points. These should return values of X + Y. + { AZ::Vector2(0.0f, 0.0f), 0.0f }, // Should return a height of 0 + 0 + { AZ::Vector2(1.0f, 0.0f), 1.0f }, // Should return a height of 1 + 0 + { AZ::Vector2(0.0f, 1.0f), 1.0f }, // Should return a height of 0 + 1 + { AZ::Vector2(1.0f, 1.0f), 2.0f }, // Should return a height of 1 + 1 + { AZ::Vector2(3.0f, 5.0f), 8.0f }, // Should return a height of 3 + 5 + + { AZ::Vector2(-1.0f, 0.0f), -1.0f }, // Should return a height of -1 + 0 + { AZ::Vector2(0.0f, -1.0f), -1.0f }, // Should return a height of 0 + -1 + { AZ::Vector2(-1.0f, -1.0f), -2.0f }, // Should return a height of -1 + -1 + { AZ::Vector2(-3.0f, -5.0f), -8.0f }, // Should return a height of -3 + -5 + + // Queries that are on a grid edge (one axis on the grid, the other somewhere in-between). + // These should just be a linear interpolation of the points, so it should still be X + Y. + + { AZ::Vector2(0.25f, 0.0f), 0.25f }, // Should return a height of -0.25 + 0 + { AZ::Vector2(3.75f, 0.0f), 3.75f }, // Should return a height of -3.75 + 0 + { AZ::Vector2(0.0f, 0.25f), 0.25f }, // Should return a height of 0 + -0.25 + { AZ::Vector2(0.0f, 3.75f), 3.75f }, // Should return a height of 0 + -3.75 + + { AZ::Vector2(2.0f, 3.75f), 5.75f }, // Should return a height of -2 + -3.75 + { AZ::Vector2(2.25f, 4.0f), 6.25f }, // Should return a height of -2.25 + -4 + + { AZ::Vector2(-0.25f, 0.0f), -0.25f }, // Should return a height of -0.25 + 0 + { AZ::Vector2(-3.75f, 0.0f), -3.75f }, // Should return a height of -3.75 + 0 + { AZ::Vector2(0.0f, -0.25f), -0.25f }, // Should return a height of 0 + -0.25 + { AZ::Vector2(0.0f, -3.75f), -3.75f }, // Should return a height of 0 + -3.75 + + { AZ::Vector2(-2.0f, -3.75f), -5.75f }, // Should return a height of -2 + -3.75 + { AZ::Vector2(-2.25f, -4.0f), -6.25f }, // Should return a height of -2.25 + -4 + + // Queries inside a grid square (both axes are in-between grid points) + // This is a full bilinear interpolation, but because we're using X + Y for our heights, the interpolated values + // should *still* be X + Y assuming the points were sampled correctly from the grid points. + + { AZ::Vector2(3.25f, 5.25f), 8.5f }, // Should return a height of 3.25 + 5.25 + { AZ::Vector2(7.71f, 9.74f), 17.45f }, // Should return a height of 7.71 + 9.74 + + { AZ::Vector2(-3.25f, -5.25f), -8.5f }, // Should return a height of -3.25 + -5.25 + { AZ::Vector2(-7.71f, -9.74f), -17.45f }, // Should return a height of -7.71 + -9.74 + }; + + auto perPositionCallback = [&testPoints](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists){ + bool found = false; + for (auto& testPoint : testPoints) + { + if (testPoint.m_testLocation.GetX() == surfacePoint.m_position.GetX() && testPoint.m_testLocation.GetY() == surfacePoint.m_position.GetY()) + { + constexpr float epsilon = 0.0001f; + EXPECT_NEAR(surfacePoint.m_position.GetZ(), testPoint.m_expectedHeight, epsilon); + found = true; + break; + } + } + EXPECT_EQ(found, true); + }; + + AZStd::vector inPositions; + for (auto& testPoint : testPoints) + { + AZ::Vector3 position(testPoint.m_testLocation.GetX(), testPoint.m_testLocation.GetY(), 0.0f); + inPositions.push_back(position); + } + + terrainSystem->ProcessHeightsFromList(inPositions, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR); + } + + TEST_F(TerrainSystemTest, TerrainProcessNormalsFromListWithBilinearSamplers) + { + // Similar to TerrainProcessHeightsFromListWithBilinearSamplers but for normals + + const AZ::Aabb spawnerBox = AZ::Aabb::CreateFromMinMaxValues(-10.0f, -10.0f, -5.0f, 10.0f, 10.0f, 15.0f); + const float amplitudeMeters = 10.0f; + const float frequencyMeters = 1.0f; + auto entity = CreateAndActivateMockTerrainLayerSpawner( + spawnerBox, + [amplitudeMeters, frequencyMeters](AZ::Vector3& position, bool& terrainExists) + { + // Our generated height will be X + Y. + float expectedHeight = position.GetX() + position.GetY(); + + // If either X or Y aren't evenly divisible by the query frequency, add a scaled value to our generated height. + // This will show up as an unexpected height "spike" if it gets used in any bilinear filter queries. + float unexpectedVariance = + amplitudeMeters * (fmodf(position.GetX(), frequencyMeters) + fmodf(position.GetY(), frequencyMeters)); + position.SetZ(expectedHeight + unexpectedVariance); + terrainExists = true; + }); + + // Create and activate the terrain system with our testing defaults for world bounds, and a query resolution at 1 meter intervals. + const AZ::Vector2 queryResolution(frequencyMeters); + auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution); + + const NormalTestPoint testPoints[] = { + + { AZ::Vector2(0.0f, 0.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(1.0f, 0.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(0.0f, 1.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(1.0f, 1.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(3.0f, 5.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + + { AZ::Vector2(-1.0f, 0.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(0.0f, -1.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(-1.0f, -1.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(-3.0f, -5.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + + { AZ::Vector2(0.25f, 0.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(3.75f, 0.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(0.0f, 0.25f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(0.0f, 3.75f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + + { AZ::Vector2(2.0f, 3.75f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(2.25f, 4.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + + { AZ::Vector2(-0.25f, 0.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(-3.75f, 0.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(0.0f, -0.25f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(0.0f, -3.75f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + + { AZ::Vector2(-2.0f, -3.75f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(-2.25f, -4.0f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + + { AZ::Vector2(3.25f, 5.25f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(7.71f, 9.74f), AZ::Vector3(-0.0292f, 0.9991f, 0.0292f) }, + + { AZ::Vector2(-3.25f, -5.25f), AZ::Vector3(-0.5773f, -0.5773f, 0.5773f) }, + { AZ::Vector2(-7.71f, -9.74f), AZ::Vector3(-0.0366f, -0.9986f, 0.0366f) }, + }; + + auto perPositionCallback = [&testPoints](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists){ + bool found = false; + for (auto& testPoint : testPoints) + { + if (testPoint.m_testLocation.GetX() == surfacePoint.m_position.GetX() && testPoint.m_testLocation.GetY() == surfacePoint.m_position.GetY()) + { + constexpr float epsilon = 0.0001f; + EXPECT_NEAR(surfacePoint.m_normal.GetX(), testPoint.m_expectedNormal.GetX(), epsilon); + EXPECT_NEAR(surfacePoint.m_normal.GetY(), testPoint.m_expectedNormal.GetY(), epsilon); + EXPECT_NEAR(surfacePoint.m_normal.GetZ(), testPoint.m_expectedNormal.GetZ(), epsilon); + found = true; + break; + } + } + EXPECT_EQ(found, true); + }; + + AZStd::vector inPositions; + for (auto& testPoint : testPoints) + { + AZ::Vector3 position(testPoint.m_testLocation.GetX(), testPoint.m_testLocation.GetY(), 0.0f); + inPositions.push_back(position); + } + + terrainSystem->ProcessNormalsFromList(inPositions, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR); + } + + TEST_F(TerrainSystemTest, TerrainProcessHeightsFromRegionWithBilinearSamplers) + { + // This repeats the same test as TerrainHeightQueriesWithBilinearSamplersUseQueryGridToInterpolate + // The difference is that it tests the ProcessHeightsFromList variation. + + const AZ::Aabb spawnerBox = AZ::Aabb::CreateFromMinMaxValues(-10.0f, -10.0f, -5.0f, 10.0f, 10.0f, 15.0f); + const float amplitudeMeters = 10.0f; + const float frequencyMeters = 1.0f; + auto entity = CreateAndActivateMockTerrainLayerSpawner( + spawnerBox, + [amplitudeMeters, frequencyMeters](AZ::Vector3& position, bool& terrainExists) + { + // Our generated height will be X + Y. + float expectedHeight = position.GetX() + position.GetY(); + + // If either X or Y aren't evenly divisible by the query frequency, add a scaled value to our generated height. + // This will show up as an unexpected height "spike" if it gets used in any bilinear filter queries. + float unexpectedVariance = + amplitudeMeters * (fmodf(position.GetX(), frequencyMeters) + fmodf(position.GetY(), frequencyMeters)); + position.SetZ(expectedHeight + unexpectedVariance); + terrainExists = true; + }); + + // Create and activate the terrain system with our testing defaults for world bounds, and a query resolution at 1 meter intervals. + const AZ::Vector2 queryResolution(frequencyMeters); + auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution); + + const AZ::Aabb testRegionBox = AZ::Aabb::CreateFromMinMaxValues(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f); + const AZ::Vector2 stepSize(1.0f); + + const HeightTestRegionPoints testPoints[] = { + { 0, 0, -2.0f, AZ::Vector2(-1.0f, -1.0f) }, + { 1, 0, -1.0f, AZ::Vector2(0.0f, -1.0f) }, + { 0, 1, -1.0f, AZ::Vector2(-1.0f, 0.0f) }, + { 1, 1, 0.0f, AZ::Vector2(0.0f, 0.0f) }, + }; + + auto perPositionCallback = [&testPoints](size_t xIndex, size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + bool found = false; + for (auto& testPoint : testPoints) + { + if (testPoint.m_xIndex == xIndex && testPoint.m_yIndex == yIndex + && testPoint.m_testLocation.GetX() == surfacePoint.m_position.GetX() + && testPoint.m_testLocation.GetY() == surfacePoint.m_position.GetY()) + { + constexpr float epsilon = 0.0001f; + EXPECT_NEAR(surfacePoint.m_position.GetZ(), testPoint.m_expectedHeight, epsilon); + found = true; + break; + } + } + EXPECT_EQ(found, true); + }; + + terrainSystem->ProcessHeightsFromRegion(testRegionBox, stepSize, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR); + } + + TEST_F(TerrainSystemTest, TerrainProcessNormalsFromRegionWithBilinearSamplers) + { + // This repeats the same test as TerrainHeightQueriesWithBilinearSamplersUseQueryGridToInterpolate + // The difference is that it tests the ProcessHeightsFromList variation. + + const AZ::Aabb spawnerBox = AZ::Aabb::CreateFromMinMaxValues(-10.0f, -10.0f, -5.0f, 10.0f, 10.0f, 15.0f); + const float amplitudeMeters = 10.0f; + const float frequencyMeters = 1.0f; + auto entity = CreateAndActivateMockTerrainLayerSpawner( + spawnerBox, + [amplitudeMeters, frequencyMeters](AZ::Vector3& position, bool& terrainExists) + { + // Our generated height will be X + Y. + float expectedHeight = position.GetX() + position.GetY(); + + // If either X or Y aren't evenly divisible by the query frequency, add a scaled value to our generated height. + // This will show up as an unexpected height "spike" if it gets used in any bilinear filter queries. + float unexpectedVariance = + amplitudeMeters * (fmodf(position.GetX(), frequencyMeters) + fmodf(position.GetY(), frequencyMeters)); + position.SetZ(expectedHeight + unexpectedVariance); + terrainExists = true; + }); + + // Create and activate the terrain system with our testing defaults for world bounds, and a query resolution at 1 meter intervals. + const AZ::Vector2 queryResolution(frequencyMeters); + auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution); + + const AZ::Aabb testRegionBox = AZ::Aabb::CreateFromMinMaxValues(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f); + const AZ::Vector2 stepSize(1.0f); + + const NormalTestRegionPoints testPoints[] = { + { 0, 0, AZ::Vector3(-0.5773f, -0.5773f, 0.5773f), AZ::Vector2(-1.0f, -1.0f) }, + { 1, 0, AZ::Vector3(-0.5773f, -0.5773f, 0.5773f), AZ::Vector2(0.0f, -1.0f) }, + { 0, 1, AZ::Vector3(-0.5773f, -0.5773f, 0.5773f), AZ::Vector2(-1.0f, 0.0f) }, + { 1, 1, AZ::Vector3(-0.5773f, -0.5773f, 0.5773f), AZ::Vector2(0.0f, 0.0f) }, + }; + + auto perPositionCallback = [&testPoints](size_t xIndex, size_t yIndex, + const AzFramework::SurfaceData::SurfacePoint& surfacePoint, [[maybe_unused]] bool terrainExists) + { + bool found = false; + for (auto& testPoint : testPoints) + { + if (testPoint.m_xIndex == xIndex && testPoint.m_yIndex == yIndex + && testPoint.m_testLocation.GetX() == surfacePoint.m_position.GetX() + && testPoint.m_testLocation.GetY() == surfacePoint.m_position.GetY()) + { + constexpr float epsilon = 0.0001f; + EXPECT_NEAR(surfacePoint.m_normal.GetX(), testPoint.m_expectedNormal.GetX(), epsilon); + EXPECT_NEAR(surfacePoint.m_normal.GetY(), testPoint.m_expectedNormal.GetY(), epsilon); + EXPECT_NEAR(surfacePoint.m_normal.GetZ(), testPoint.m_expectedNormal.GetZ(), epsilon); + found = true; + break; + } + } + EXPECT_EQ(found, true); + }; + + terrainSystem->ProcessNormalsFromRegion(testRegionBox, stepSize, perPositionCallback, AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR); + } } // namespace UnitTest From aebf93d8824a8b1d8b8e31d7a808161b21357dd8 Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 12 Jan 2022 13:13:52 -0800 Subject: [PATCH 065/108] fixing a typo in docstring Signed-off-by: Scott Murray --- .../editor_python_test_tools/editor_entity_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index bf27ec06e0..c3398406ab 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -264,7 +264,7 @@ class EditorComponent: def disable_component(self): """ Used to disable the component using its id value. - Deprecation warning! Use set_enable(False) instead as this method is in deprecation + Deprecation warning! Use set_enabled(False) instead as this method is in deprecation :return: None """ warnings.warn("disable_component is deprecated, use set_enabled(False) instead.", DeprecationWarning) From 74e40551957548935201d5a935c5a66c9d520310 Mon Sep 17 00:00:00 2001 From: Nicholas Van Sickle Date: Wed, 12 Jan 2022 15:23:06 -0800 Subject: [PATCH 066/108] Fix Prefab instance assets not preloading (#6834) PrefabCatchmentProcessor::ProcessPrefab was no longer updating the ProcessedObjectStore's referenced object list, this change exposes the referenced asset list in the new PrefabDocument API and uses them to update the referenced asset list. Signed-off-by: Nicholas Van Sickle --- .../Prefab/Spawnable/PrefabCatchmentProcessor.cpp | 1 + .../Prefab/Spawnable/PrefabDocument.cpp | 12 +++++++++++- .../Prefab/Spawnable/PrefabDocument.h | 4 ++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp index 40cd52cac8..a5ca034c36 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabCatchmentProcessor.cpp @@ -64,6 +64,7 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils AZStd::move(uniqueName), context.GetSourceUuid(), AZStd::move(serializer)); AZ_Assert(spawnable, "Failed to create a new spawnable."); + object.GetReferencedAssets() = prefab.GetReferencedAssets(); Instance& instance = prefab.GetInstance(); // Resolve entity aliases that store PrefabDOM information to use the spawnable instead. This is done before the entities are // moved from the instance as they'd otherwise can't be found. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp index 04fdea30d2..230c2226cd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.cpp @@ -124,12 +124,22 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils return *m_instance; } + AZStd::vector>& PrefabDocument::GetReferencedAssets() + { + return m_referencedAssets; + } + + const AZStd::vector>& PrefabDocument::GetReferencedAssets() const + { + return m_referencedAssets; + } + bool PrefabDocument::ConstructInstanceFromPrefabDom(const PrefabDom& prefab) { using namespace AzToolsFramework::Prefab; m_instance->Reset(); - if (PrefabDomUtils::LoadInstanceFromPrefabDom(*m_instance, prefab, PrefabDomUtils::LoadFlags::AssignRandomEntityId)) + if (PrefabDomUtils::LoadInstanceFromPrefabDom(*m_instance, prefab, m_referencedAssets, PrefabDomUtils::LoadFlags::AssignRandomEntityId)) { return true; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h index 215daf7f71..661dba5edf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Spawnable/PrefabDocument.h @@ -53,12 +53,16 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils AzToolsFramework::Prefab::Instance& GetInstance(); const AzToolsFramework::Prefab::Instance& GetInstance() const; + AZStd::vector>& GetReferencedAssets(); + const AZStd::vector>& GetReferencedAssets() const; + private: bool ConstructInstanceFromPrefabDom(const PrefabDom& prefab); mutable PrefabDom m_dom; AZStd::unique_ptr m_instance; AZStd::string m_name; + AZStd::vector> m_referencedAssets; mutable bool m_isDirty{ false }; }; } // namespace AzToolsFramework::Prefab::PrefabConversionUtils From 4e755cc258645d29cc286e5ec52b623486e1ca0e Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Wed, 12 Jan 2022 16:21:40 -0800 Subject: [PATCH 067/108] Add variable, datum sanity for user added slots Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../ConnectionFilters/DataConnectionFilters.h | 4 ++-- .../DataConnectionComponent.cpp | 4 ++-- .../Slots/Data/DataSlotComponent.cpp | 11 +++++---- .../Components/Slots/Data/DataSlotComponent.h | 4 ++-- .../Components/Slots/Data/DataSlotBus.h | 4 ++-- .../GraphCanvas/Editor/GraphModelBus.h | 9 +++---- .../SlotContextMenuActions.cpp | 10 ++++---- .../GraphModel/Code/Tests/MockGraphCanvas.cpp | 4 ++-- Gems/GraphModel/Code/Tests/MockGraphCanvas.h | 4 ++-- .../Code/Editor/Components/EditorGraph.cpp | 24 ++++++++++--------- .../ScriptCanvas/Components/EditorGraph.h | 8 +++---- .../View/Windows/ScriptCanvasContextMenus.cpp | 2 +- .../Asset/RuntimeAssetHandler.cpp | 8 ++++++- .../Code/Include/ScriptCanvas/Core/Node.cpp | 4 ++-- .../Code/Include/ScriptCanvas/Core/Node.h | 2 +- .../Code/Include/ScriptCanvas/Core/Slot.cpp | 11 +++++---- .../Code/Include/ScriptCanvas/Core/Slot.h | 4 ++-- .../Grammar/AbstractCodeModel.cpp | 10 ++++---- .../GraphVariableManagerComponent.cpp | 2 +- 19 files changed, 70 insertions(+), 59 deletions(-) diff --git a/Gems/GraphCanvas/Code/Include/GraphCanvas/Components/Connections/ConnectionFilters/DataConnectionFilters.h b/Gems/GraphCanvas/Code/Include/GraphCanvas/Components/Connections/ConnectionFilters/DataConnectionFilters.h index c7721e284d..452b6e744a 100644 --- a/Gems/GraphCanvas/Code/Include/GraphCanvas/Components/Connections/ConnectionFilters/DataConnectionFilters.h +++ b/Gems/GraphCanvas/Code/Include/GraphCanvas/Components/Connections/ConnectionFilters/DataConnectionFilters.h @@ -97,7 +97,7 @@ namespace GraphCanvas // Only want to try to convert to references when we have no connections if (!hasConnections) { - DataSlotRequestBus::EventResult(acceptConnection, sourceEndpoint.GetSlotId(), &DataSlotRequests::CanConvertToReference); + DataSlotRequestBus::EventResult(acceptConnection, sourceEndpoint.GetSlotId(), &DataSlotRequests::CanConvertToReference, false); } } else if (targetType == DataSlotType::Value) @@ -115,7 +115,7 @@ namespace GraphCanvas // Only want to try to convert to references when we have no connections if (!hasConnections) { - DataSlotRequestBus::EventResult(acceptConnection, targetEndpoint.GetSlotId(), &DataSlotRequests::CanConvertToReference); + DataSlotRequestBus::EventResult(acceptConnection, targetEndpoint.GetSlotId(), &DataSlotRequests::CanConvertToReference, false); } } else if (sourceType == DataSlotType::Value) diff --git a/Gems/GraphCanvas/Code/Source/Components/Connections/DataConnections/DataConnectionComponent.cpp b/Gems/GraphCanvas/Code/Source/Components/Connections/DataConnections/DataConnectionComponent.cpp index f4ec0bfa1d..46e6f25978 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Connections/DataConnections/DataConnectionComponent.cpp +++ b/Gems/GraphCanvas/Code/Source/Components/Connections/DataConnections/DataConnectionComponent.cpp @@ -92,7 +92,7 @@ namespace GraphCanvas } else if (sourceSlotType == DataSlotType::Reference) { - DataSlotRequestBus::EventResult(converted, GetTargetSlotId(), &DataSlotRequests::ConvertToReference); + DataSlotRequestBus::EventResult(converted, GetTargetSlotId(), &DataSlotRequests::ConvertToReference, false); } } else if (m_dragContext == DragContext::MoveSource) @@ -103,7 +103,7 @@ namespace GraphCanvas } else if (targetSlotType == DataSlotType::Reference) { - DataSlotRequestBus::EventResult(converted, GetSourceSlotId(), &DataSlotRequests::ConvertToReference); + DataSlotRequestBus::EventResult(converted, GetSourceSlotId(), &DataSlotRequests::ConvertToReference, false); } } else if (m_dragContext == DragContext::TryConnection) diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp index db62b29de5..7eb9187123 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp @@ -294,9 +294,9 @@ namespace GraphCanvas } } - bool DataSlotComponent::ConvertToReference() + bool DataSlotComponent::ConvertToReference(bool isNewSlot) { - if (CanConvertToReference()) + if (CanConvertToReference(isNewSlot)) { AZ::EntityId nodeId = GetNode(); GraphId graphId; @@ -307,7 +307,7 @@ namespace GraphCanvas ScopedGraphUndoBlocker undoBlocker(graphId); bool convertedToReference = false; - GraphModelRequestBus::EventResult(convertedToReference, graphId, &GraphModelRequests::ConvertSlotToReference, Endpoint(nodeId, GetEntityId())); + GraphModelRequestBus::EventResult(convertedToReference, graphId, &GraphModelRequests::ConvertSlotToReference, Endpoint(nodeId, GetEntityId()), isNewSlot); if (convertedToReference) { @@ -326,8 +326,9 @@ namespace GraphCanvas return m_dataSlotType == DataSlotType::Reference; } - bool DataSlotComponent::CanConvertToReference() const + bool DataSlotComponent::CanConvertToReference([[maybe_unused]] bool isNewSlot) const { + // #sc_user_slot_variable_ux make sure this can be converted to reference, or created as one bool canToggleReference = false; if (m_canConvertSlotTypes && DataSlotUtils::IsValueDataSlotType(m_dataSlotType) && !HasConnections()) @@ -336,7 +337,7 @@ namespace GraphCanvas GraphId graphId; SceneMemberRequestBus::EventResult(graphId, nodeId, &SceneMemberRequests::GetScene); - GraphModelRequestBus::EventResult(canToggleReference, graphId, &GraphModelRequests::CanConvertSlotToReference, Endpoint(nodeId, GetEntityId())); + GraphModelRequestBus::EventResult(canToggleReference, graphId, &GraphModelRequests::CanConvertSlotToReference, Endpoint(nodeId, GetEntityId()), isNewSlot); } return canToggleReference; diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h index fb76c2c80e..5bd35d9f34 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.h @@ -47,8 +47,8 @@ namespace GraphCanvas //// // DataSlotRequestBus - bool ConvertToReference() override; - bool CanConvertToReference() const override; + bool ConvertToReference(bool isNewSlot = false) override; + bool CanConvertToReference(bool isNewSlot = false) const override; bool ConvertToValue() override; bool CanConvertToValue() const override; diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Slots/Data/DataSlotBus.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Slots/Data/DataSlotBus.h index 3d007dda91..fbdae8a971 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Slots/Data/DataSlotBus.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Components/Slots/Data/DataSlotBus.h @@ -70,8 +70,8 @@ namespace GraphCanvas static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; using BusIdType = AZ::EntityId; - virtual bool ConvertToReference() = 0; - virtual bool CanConvertToReference() const = 0; + virtual bool ConvertToReference(bool isNewSlot = false) = 0; + virtual bool CanConvertToReference(bool isNewSlot = false) const = 0; virtual bool ConvertToValue() = 0; virtual bool CanConvertToValue() const = 0; diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Editor/GraphModelBus.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Editor/GraphModelBus.h index 769cdb2a10..23aa612dd5 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Editor/GraphModelBus.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Editor/GraphModelBus.h @@ -125,12 +125,12 @@ namespace GraphCanvas return false; } - virtual bool ConvertSlotToReference([[maybe_unused]] const Endpoint& endpoint) + virtual bool ConvertSlotToReference([[maybe_unused]] const Endpoint& endpoint, [[maybe_unused]] bool isNewSlot) { return false; } - virtual bool CanConvertSlotToReference([[maybe_unused]] const Endpoint& endpoint) + virtual bool CanConvertSlotToReference([[maybe_unused]] const Endpoint& endpoint, [[maybe_unused]] bool isNewSlot) { return false; } @@ -145,12 +145,13 @@ namespace GraphCanvas return false; } - virtual bool CanPromoteToVariable([[maybe_unused]] const Endpoint& endpoint) const + virtual bool CanPromoteToVariable([[maybe_unused]] const Endpoint& endpoint, [[maybe_unused]] bool isNewSlot = false) const { return false; } - virtual bool PromoteToVariableAction([[maybe_unused]] const Endpoint& endpoint) + virtual bool PromoteToVariableAction([[maybe_unused]] const Endpoint& endpoint + , [[maybe_unused]] bool isNewSlot) { return false; } diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.cpp b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.cpp index a255c97120..38e97f90cc 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.cpp +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Widgets/EditorContextMenu/ContextMenuActions/SlotMenuActions/SlotContextMenuActions.cpp @@ -258,7 +258,7 @@ namespace GraphCanvas if (DataSlotUtils::IsValueDataSlotType(dataSlotType)) { setText("Convert to Reference"); - DataSlotRequestBus::EventResult(canToggleState, targetId, &DataSlotRequests::CanConvertToReference); + DataSlotRequestBus::EventResult(canToggleState, targetId, &DataSlotRequests::CanConvertToReference, false); } else { @@ -291,7 +291,7 @@ namespace GraphCanvas if (DataSlotUtils::IsValueDataSlotType(dataSlotType)) { - DataSlotRequestBus::EventResult(toggledState, targetId, &DataSlotRequests::ConvertToReference); + DataSlotRequestBus::EventResult(toggledState, targetId, &DataSlotRequests::ConvertToReference, false); } else { @@ -345,14 +345,14 @@ namespace GraphCanvas if (DataSlotUtils::IsValueDataSlotType(dataSlotType)) { - DataSlotRequestBus::EventResult(enableAction, targetId, &DataSlotRequests::CanConvertToReference); + DataSlotRequestBus::EventResult(enableAction, targetId, &DataSlotRequests::CanConvertToReference, false); if (enableAction) { Endpoint endpoint; SlotRequestBus::EventResult(endpoint, targetId, &SlotRequests::GetEndpoint); - GraphModelRequestBus::EventResult(enableAction, graphId, &GraphModelRequests::CanPromoteToVariable, endpoint); + GraphModelRequestBus::EventResult(enableAction, graphId, &GraphModelRequests::CanPromoteToVariable, endpoint, false); } } } @@ -371,7 +371,7 @@ namespace GraphCanvas SlotRequestBus::EventResult(endpoint, targetId, &SlotRequests::GetEndpoint); bool promotedElement = false; - GraphModelRequestBus::EventResult(promotedElement, graphId, &GraphModelRequests::PromoteToVariableAction, endpoint); + GraphModelRequestBus::EventResult(promotedElement, graphId, &GraphModelRequests::PromoteToVariableAction, endpoint, false); if (promotedElement) { diff --git a/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp b/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp index 91a25d6a30..525386a1a3 100644 --- a/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp +++ b/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp @@ -94,12 +94,12 @@ namespace MockGraphCanvasServices GraphCanvas::DataSlotRequestBus::Handler::BusDisconnect(); } - bool MockDataSlotComponent::ConvertToReference() + bool MockDataSlotComponent::ConvertToReference([[maybe_unused]] bool isNewSlot = false) { return false; } - bool MockDataSlotComponent::CanConvertToReference() const + bool MockDataSlotComponent::CanConvertToReference([[maybe_unused]] bool isNewSlot = false) const { return false; } diff --git a/Gems/GraphModel/Code/Tests/MockGraphCanvas.h b/Gems/GraphModel/Code/Tests/MockGraphCanvas.h index c7865e769e..00bd80aa02 100644 --- a/Gems/GraphModel/Code/Tests/MockGraphCanvas.h +++ b/Gems/GraphModel/Code/Tests/MockGraphCanvas.h @@ -72,8 +72,8 @@ namespace MockGraphCanvasServices void Deactivate() override; // GraphCanvas::DataSlotRequestBus overrides ... - bool ConvertToReference() override; - bool CanConvertToReference() const override; + bool ConvertToReference(bool isNewSlot = false) override; + bool CanConvertToReference(bool isNewSlot = false) const override; bool ConvertToValue() override; bool CanConvertToValue() const override; bool IsUserSlot() const override; diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index d713bc09a6..342273cb2e 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -667,7 +667,8 @@ namespace ScriptCanvasEditor } // Now that the slot has a valid type/name, we can actually promote it to a variable - if (PromoteToVariableAction(endpoint) /*&& slot->IsVariableReference()*/) + // #sc_user_slot_variable_ux add a value indicating that the slot is new + if (PromoteToVariableAction(endpoint, true)) { ScriptCanvas::GraphVariable* variable = slot->GetVariable(); @@ -2081,20 +2082,20 @@ namespace ScriptCanvasEditor return false; } - bool Graph::ConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) + bool Graph::ConvertSlotToReference(const GraphCanvas::Endpoint& endpoint, bool isNewSlot) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); ScriptCanvas::Node* canvasNode = FindNode(scEndpoint.GetNodeId()); if (canvasNode) { - return canvasNode->ConvertSlotToReference(scEndpoint.GetSlotId()); + return canvasNode->ConvertSlotToReference(scEndpoint.GetSlotId(), isNewSlot); } return false; } - bool Graph::CanConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) + bool Graph::CanConvertSlotToReference(const GraphCanvas::Endpoint& endpoint, bool isNewSlot) { ScriptCanvas::Endpoint scEndpoint = ConvertToScriptCanvasEndpoint(endpoint); ScriptCanvas::Node* canvasNode = FindNode(scEndpoint.GetNodeId()); @@ -2104,7 +2105,7 @@ namespace ScriptCanvasEditor ScriptCanvas::Slot* slot = canvasNode->GetSlot(scEndpoint.GetSlotId()); if (slot) { - return slot->CanConvertToReference(); + return slot->CanConvertToReference(isNewSlot); } } @@ -2170,7 +2171,7 @@ namespace ScriptCanvasEditor return handledEvent; } - bool Graph::CanPromoteToVariable(const GraphCanvas::Endpoint& endpoint) const + bool Graph::CanPromoteToVariable(const GraphCanvas::Endpoint& endpoint, [[maybe_unused]] bool isNewSlot) const { ScriptCanvas::Endpoint scriptCanvasEndpoint = ConvertToScriptCanvasEndpoint(endpoint); auto activeSlot = FindSlot(scriptCanvasEndpoint); @@ -2189,8 +2190,9 @@ namespace ScriptCanvasEditor return false; } - bool Graph::PromoteToVariableAction(const GraphCanvas::Endpoint& endpoint) + bool Graph::PromoteToVariableAction(const GraphCanvas::Endpoint& endpoint, bool isNewSlot) { + // #sc_user_slot_variable_ux make the fix here...rework is user added or something ScriptCanvas::Endpoint scriptCanvasEndpoint = ConvertToScriptCanvasEndpoint(endpoint); auto activeNode = FindNode(scriptCanvasEndpoint.GetNodeId()); @@ -2282,12 +2284,12 @@ namespace ScriptCanvasEditor AZ::Outcome addOutcome; - // #functions2 slot<->variable re-use the activeDatum, send the pointer (actually, all of the source slot information, and make a special conversion) + // #sc_user_slot_variable_ux re-use the activeDatum, send the pointer (actually, all of the source slot information, and make a special conversion) ScriptCanvas::GraphVariableManagerRequestBus::EventResult(addOutcome, GetScriptCanvasId(), &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, variableDatum, true); if (addOutcome.IsSuccess()) { - GraphCanvas::DataSlotRequestBus::Event(endpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference); + GraphCanvas::DataSlotRequestBus::Event(endpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference, isNewSlot); activeSlot->SetVariableReference(addOutcome.GetValue()); @@ -2319,7 +2321,7 @@ namespace ScriptCanvasEditor { if (!targetSlot->IsVariableReference()) { - GraphCanvas::DataSlotRequestBus::Event(referenceTarget.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference); + GraphCanvas::DataSlotRequestBus::Event(referenceTarget.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference, false); } if (targetSlot->IsVariableReference()) @@ -2884,7 +2886,7 @@ namespace ScriptCanvasEditor for (auto graphCanvasEndpoint : referencableEndpoints) { - GraphCanvas::DataSlotRequestBus::Event(graphCanvasEndpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference); + GraphCanvas::DataSlotRequestBus::Event(graphCanvasEndpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference, false); ScriptCanvas::Endpoint scriptCanvasEndpoint = ConvertToScriptCanvasEndpoint(graphCanvasEndpoint); diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h index 9157aaeac9..ba7ff6abaf 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorGraph.h @@ -175,12 +175,12 @@ namespace ScriptCanvasEditor void RemoveSlot(const GraphCanvas::Endpoint& endpoint) override; bool IsSlotRemovable(const GraphCanvas::Endpoint& endpoint) const override; - bool ConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) override; - bool CanConvertSlotToReference(const GraphCanvas::Endpoint& endpoint) override; + bool ConvertSlotToReference(const GraphCanvas::Endpoint& endpoint, bool isNewSlot = false) override; + bool CanConvertSlotToReference(const GraphCanvas::Endpoint& endpoint, bool isNewSlot = false) override; GraphCanvas::CanHandleMimeEventOutcome CanHandleReferenceMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) override; bool HandleReferenceMimeEvent(const GraphCanvas::Endpoint& endpoint, const QMimeData* mimeData) override; - bool CanPromoteToVariable(const GraphCanvas::Endpoint& endpoint) const override; - bool PromoteToVariableAction(const GraphCanvas::Endpoint& endpoint) override; + bool CanPromoteToVariable(const GraphCanvas::Endpoint& endpoint, bool isNewSlot = false) const override; + bool PromoteToVariableAction(const GraphCanvas::Endpoint& endpoint, bool isNewSlot = false) override; bool SynchronizeReferences(const GraphCanvas::Endpoint& sourceEndpoint, const GraphCanvas::Endpoint& targetEndpoint) override; bool ConvertSlotToValue(const GraphCanvas::Endpoint& endpoint) override; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp index 6402a24b3a..662cec7195 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/ScriptCanvasContextMenus.cpp @@ -516,7 +516,7 @@ namespace ScriptCanvasEditor GraphCanvas::SlotRequestBus::EventResult(endpoint, slotId2, &GraphCanvas::SlotRequests::GetEndpoint); bool promotedElement = false; - GraphCanvas::GraphModelRequestBus::EventResult(promotedElement, graphId2, &GraphCanvas::GraphModelRequests::PromoteToVariableAction, endpoint); + GraphCanvas::GraphModelRequestBus::EventResult(promotedElement, graphId2, &GraphCanvas::GraphModelRequests::PromoteToVariableAction, endpoint, false); if (promotedElement) { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp index 0b94fb370a..a18caf4b87 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Asset/RuntimeAssetHandler.cpp @@ -100,12 +100,18 @@ namespace ScriptCanvas { RuntimeAsset* runtimeAsset = asset.GetAs(); AZ_Assert(runtimeAsset, "This should be a Script Canvas runtime asset, as this is the only type we process!"); + if (runtimeAsset && m_serializeContext) { stream->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); - bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(*stream, runtimeAsset->m_runtimeData, m_serializeContext, AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB)); + const bool loadSuccess = AZ::Utils::LoadObjectFromStreamInPlace(*stream, runtimeAsset->m_runtimeData + , m_serializeContext, AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB)); + AZ_Error("ScriptCanvas", loadSuccess, "ScriptCanvas failed to load runtime asset: %s - %s" + , asset.GetHint().c_str(), asset.GetId().ToString().c_str()); + return loadSuccess ? AZ::Data::AssetHandler::LoadResult::LoadComplete : AZ::Data::AssetHandler::LoadResult::Error; } + return AZ::Data::AssetHandler::LoadResult::Error; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp index c4143e7295..6cf9da1510 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp @@ -2577,11 +2577,11 @@ namespace ScriptCanvas } } - bool Node::ConvertSlotToReference(const SlotId& slotId) + bool Node::ConvertSlotToReference(const SlotId& slotId, bool isNewSlot) { Slot* slot = GetSlot(slotId); - if (slot && slot->ConvertToReference()) + if (slot && slot->ConvertToReference(isNewSlot)) { InitializeVariableReference((*slot), {}); return true; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h index 97916c8af6..f8b4ca7264 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h @@ -498,7 +498,7 @@ namespace ScriptCanvas void SanityCheckDynamicDisplay(); void SanityCheckDynamicDisplay(ExploredDynamicGroupCache& exploredGroupCache); - bool ConvertSlotToReference(const SlotId& slotId); + bool ConvertSlotToReference(const SlotId& slotId, bool isNewSlot = false); bool ConvertSlotToValue(const SlotId& slotId); NamedEndpoint CreateNamedEndpoint(SlotId slotId) const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp index 44d2367156..6aef61b12f 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp @@ -460,14 +460,15 @@ namespace ScriptCanvas && GetDataType() != Data::Type::BehaviorContextObject(GraphScopedVariableId::TYPEINFO_Uuid()); } - bool Slot::CanConvertToReference() const - { - return !m_isUserAdded && CanConvertTypes() && !m_isVariableReference && !m_node->HasConnectedNodes((*this)); + bool Slot::CanConvertToReference(bool isNewSlot) const + { + // #sc_user_slot_variable_ux make sure this can be converted to reference, or created as one + return (!m_isUserAdded || isNewSlot) && CanConvertTypes() && !m_isVariableReference && !m_node->HasConnectedNodes((*this)); } - bool Slot::ConvertToReference() + bool Slot::ConvertToReference(bool isNewSlot) { - if (CanConvertToReference()) + if (CanConvertToReference(isNewSlot)) { m_isVariableReference = true; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h index b182af7c67..5649c3e34c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.h @@ -147,8 +147,8 @@ namespace ScriptCanvas bool CanConvertToValue() const; bool ConvertToValue(); - bool CanConvertToReference() const; - bool ConvertToReference(); + bool CanConvertToReference(bool isNewSlot = false) const; + bool ConvertToReference(bool isNewSlot = false); void SetVariableReference(const VariableId& variableId); const VariableId& GetVariableReference() const; GraphVariable* GetVariable() const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 829a1098dc..299718fd0f 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -237,7 +237,7 @@ namespace ScriptCanvas if (auto datum = variablePair.second.GetDatum()) { - // #functions2 slot<->variable consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering + // #sc_user_slot_variable_ux consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering m_sourceVariableByDatum.insert(AZStd::make_pair(datum, &variablePair.second)); } @@ -248,7 +248,7 @@ namespace ScriptCanvas auto datum = sourceVariable->GetDatum(); AZ_Assert(datum != nullptr, "the datum must be valid"); - // #functions2 slot<->variable check to verify if it is a member variable + // #sc_user_slot_variable_ux check to verify if it is a member variable auto variable = sourceVariable->GetScope() == VariableFlags::Scope::Graph ? AddMemberVariable(*datum, sourceVariable->GetVariableName(), sourceVariable->GetVariableId()) : AddVariable(*datum, sourceVariable->GetVariableName(), sourceVariable->GetVariableId()); @@ -1671,7 +1671,7 @@ namespace ScriptCanvas if (returnValue.second->m_source->m_sourceSlotId == slot->GetId()) { - // #functions2 slot<->variable determine if the root or the function call should be passed in here...the slot/node lead to the user call on the thread, but it may not even be created yet + // #sc_user_slot_variable_ux determine if the root or the function call should be passed in here...the slot/node lead to the user call on the thread, but it may not even be created yet return AZStd::make_pair(root, returnValue.second->m_source); } } @@ -4644,7 +4644,7 @@ namespace ScriptCanvas void AbstractCodeModel::ParseNodelingVariables(const Node& node, NodelingType nodelingType) { - // #functions2 slot<->variable adjust once datums are more coordinated + // #sc_user_slot_variable_ux adjust once datums are more coordinated auto createVariablesSlots = [&](AZStd::unordered_map& variablesBySlots, const AZStd::vector& slots, bool slotHasDatum) { for (const auto& slot : slots) @@ -4660,7 +4660,7 @@ namespace ScriptCanvas return; } - // #functions2 slot<->variable consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering + // #sc_user_slot_variable_ux consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering // auto iter = m_sourceVariableByDatum.find(variableDatum); // if (iter == m_sourceVariableByDatum.end()) // { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp index 58e8be0c37..81383bf747 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp @@ -220,7 +220,7 @@ namespace ScriptCanvas return AZ::Success(newId); } - // #functions2 slot<->variable add this to the graph, using the old datum + // #sc_user_slot_variable_ux add this to the graph, using the old datum AZ::Outcome GraphVariableManagerComponent::AddVariable(AZStd::string_view name, const Datum& value, bool functionScope) { if (FindVariable(name)) From 073994e8e75d1ec3ffafe84a16d1613962b42b34 Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Wed, 12 Jan 2022 17:34:34 -0800 Subject: [PATCH 068/108] Remove quotes around list (#6864) Signed-off-by: amzn-sj --- cmake/Platform/Mac/InstallUtils_mac.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Mac/InstallUtils_mac.cmake.in b/cmake/Platform/Mac/InstallUtils_mac.cmake.in index 3db9903e48..9be6338752 100644 --- a/cmake/Platform/Mac/InstallUtils_mac.cmake.in +++ b/cmake/Platform/Mac/InstallUtils_mac.cmake.in @@ -43,7 +43,7 @@ function(fixup_python_framework framework_path) file(GLOB_RECURSE exe_file_list "${framework_path}/**/*.exe") if(exe_file_list) - file(REMOVE_RECURSE "${exe_file_list}") + file(REMOVE_RECURSE ${exe_file_list}) endif() execute_process(COMMAND "${CMAKE_COMMAND}" -E create_symlink include/python@LY_PYTHON_VERSION_MAJOR_MINOR@m Headers WORKING_DIRECTORY "${framework_path}/Versions/@LY_PYTHON_VERSION_MAJOR_MINOR@" From e224fc2ee5ec2a12e75a10acae268b7b38ae3a32 Mon Sep 17 00:00:00 2001 From: Roman <69218254+amzn-rhhong@users.noreply.github.com> Date: Wed, 12 Jan 2022 22:39:56 -0800 Subject: [PATCH 069/108] Bugfix - ViewportInteractionImp connected to the wrong id in RenderViewportWidget (#6867) Signed-off-by: rhhong --- .../Code/Source/Viewport/RenderViewportWidget.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 505ff70122..b15cf53427 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -68,6 +68,7 @@ namespace AtomToolsFramework { return false; } + const AzFramework::ViewportId newId = m_viewportContext->GetId(); SetControllerList(AZStd::make_shared()); @@ -78,14 +79,14 @@ namespace AtomToolsFramework m_viewportInteractionImpl = AZStd::make_unique(m_defaultCamera); m_viewportInteractionImpl->m_deviceScalingFactorFn = [this] { return aznumeric_cast(devicePixelRatioF()); }; m_viewportInteractionImpl->m_screenSizeFn = [this] { return AzFramework::ScreenSize(width(), height()); }; - m_viewportInteractionImpl->Connect(id); + m_viewportInteractionImpl->Connect(newId); AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Handler::BusConnect(GetId()); AzFramework::InputChannelEventListener::Connect(); AZ::TickBus::Handler::BusConnect(); AzFramework::WindowRequestBus::Handler::BusConnect(params.windowHandle); - m_inputChannelMapper = new AzToolsFramework::QtEventToAzInputMapper(this, id); + m_inputChannelMapper = new AzToolsFramework::QtEventToAzInputMapper(this, newId); // Forward input events to our controller list. QObject::connect(m_inputChannelMapper, &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, this, From ff0df4b8b6e66286c12391522c4814cc7f8864f7 Mon Sep 17 00:00:00 2001 From: Andre Mitchell <47983418+BytesOfPiDev@users.noreply.github.com> Date: Thu, 13 Jan 2022 03:36:19 -0500 Subject: [PATCH 070/108] Update behavior reflection of EMotionFX's MotionEvent to use nullptr instead of empty lambdas. (#6617) Signed-off-by: Andre Mitchell --- .../Integration/System/SystemComponent.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index 15037793f1..08607c330d 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -400,17 +400,16 @@ namespace EMotionFX behaviorContext->EBus("SystemNotificationBus") ; - // In order for a property to be displayed in ScriptCanvas. Both a setter and a getter are necessary(both must be non-null). - // This is being worked on in dragon branch, once this is complete the dummy lambda functions can be removed. + // In order for a property to be displayed in ScriptCanvas. behaviorContext->Class("MotionEvent") - ->Property("entityId", BehaviorValueGetter(&MotionEvent::m_entityId), [](MotionEvent*, const AZ::EntityId&) {}) - ->Property("parameter", BehaviorValueGetter(&MotionEvent::m_parameter), [](MotionEvent*, const char*) {}) - ->Property("eventType", BehaviorValueGetter(&MotionEvent::m_eventType), [](MotionEvent*, const AZ::u32&) {}) - ->Property("eventTypeName", BehaviorValueGetter(&MotionEvent::m_eventTypeName), [](MotionEvent*, const char*) {}) - ->Property("time", BehaviorValueGetter(&MotionEvent::m_time), [](MotionEvent*, const float&) {}) - ->Property("globalWeight", BehaviorValueGetter(&MotionEvent::m_globalWeight), [](MotionEvent*, const float&) {}) - ->Property("localWeight", BehaviorValueGetter(&MotionEvent::m_localWeight), [](MotionEvent*, const float&) {}) - ->Property("isEventStart", BehaviorValueGetter(&MotionEvent::m_isEventStart), [](MotionEvent*, const bool&) {}) + ->Property("entityId", BehaviorValueGetter(&MotionEvent::m_entityId), nullptr) + ->Property("parameter", BehaviorValueGetter(&MotionEvent::m_parameter), nullptr) + ->Property("eventType", BehaviorValueGetter(&MotionEvent::m_eventType), nullptr) + ->Property("eventTypeName", BehaviorValueGetter(&MotionEvent::m_eventTypeName), nullptr) + ->Property("time", BehaviorValueGetter(&MotionEvent::m_time), nullptr) + ->Property("globalWeight", BehaviorValueGetter(&MotionEvent::m_globalWeight), nullptr) + ->Property("localWeight", BehaviorValueGetter(&MotionEvent::m_localWeight), nullptr) + ->Property("isEventStart", BehaviorValueGetter(&MotionEvent::m_isEventStart), nullptr) ; behaviorContext->EBus("ActorNotificationBus") From 6d1a2382e872c74cf51e34127ab4e9573305b1dd Mon Sep 17 00:00:00 2001 From: tjmgd <92784061+tjmgd@users.noreply.github.com> Date: Thu, 13 Jan 2022 13:56:38 +0000 Subject: [PATCH 071/108] Bug hide window (#5939) * [lyn3736] adding init files to module paths (#5111) * fixing class names in PYI files Signed-off-by: jackalbe <23512001+jackalbe@users.noreply.github.com> Signed-off-by: T.J. McGrath-Daly * Fixed crash when typing asset name and clicking browse (#5495) Signed-off-by: T.J. McGrath-Daly * Fixed bug involving inappropriate window Signed-off-by: T.J. McGrath-Daly Co-authored-by: Allen Jackson <23512001+jackalbe@users.noreply.github.com> Co-authored-by: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> --- Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp index d827f657b8..f8414e25e4 100644 --- a/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp +++ b/Gems/AudioSystem/Code/Source/Editor/QConnectionsWidget.cpp @@ -33,6 +33,7 @@ namespace AudioControls { setupUi(this); + m_connectionPropertiesFrame->setHidden(true); m_connectionList->viewport()->installEventFilter(this); m_connectionList->installEventFilter(this); From fed1278fe64e8a435b1c19ba8092b18a98fa9eb1 Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Thu, 13 Jan 2022 08:56:24 -0600 Subject: [PATCH 072/108] AP: product dependency optimization (#6619) * Initial pass at optimizing product path dependency resolution Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add version of StripAssetPlatform that doesn't allocate or copy strings. Re-add missing test and fix up compile errors. Add benchmark test Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Change UpdateProductDependencies to directly call s_InsertProductDependencyQuery.BindAndStep Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add test for same filename on multiple platforms Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Rework search logic to keep track of the source of a search path (source vs product) and keep track of which search matches which dependency to avoid doing another search through every product later on Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Clean up code, expand test Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix paths not being lowercased by SanitizeForDatabase. Fix UpdateProductDependencies not updating existing dependencies Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add test for duplicate dependency matches. Fix saving duplicates Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Clean up code Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Separate test into test and benchmark versions Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Cleanup include Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix includes, switch hardcoded job manager setup to use JobManagerComponent instead Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Replaced wildcard_match with PathView::Match. Changed StripAssetPlatformNoCopy to use TokenizeNext. Removed Environment Create/Destroy calls. Made ScopedAllocatorFixture a base class of ScopedAllocatorSetupFixture Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add AZ Environment create/destroy on AP test environment Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Add missing asserts on database functions Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix incorrect usage of StripAssetPlatformNoCopy Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix source/product dependency type being ignored. Removed need for unordered_set for list of resolved dependencies. Updated unit tests Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Better variable names Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Remove testing code Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix missing includes and namespaces Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> --- .../AzCore/AzCore/UnitTest/TestTypes.h | 40 +- .../assetprocessor_test_files.cmake | 1 + .../native/AssetDatabase/AssetDatabase.cpp | 84 ++-- .../native/AssetManager/AssetCatalog.cpp | 4 +- .../AssetManager/PathDependencyManager.cpp | 187 +++++---- .../AssetManager/PathDependencyManager.h | 23 +- .../AssetManager/assetProcessorManager.cpp | 138 ++++--- .../native/tests/BaseAssetProcessorTest.h | 2 + .../tests/PathDependencyManagerTests.cpp | 362 ++++++++++++++++-- .../AssetProcessorManagerTest.cpp | 79 +++- .../assetmanager/AssetProcessorManagerTest.h | 11 +- .../utilities/PlatformConfiguration.cpp | 14 +- .../native/utilities/assetUtils.cpp | 28 +- .../native/utilities/assetUtils.h | 6 +- 14 files changed, 742 insertions(+), 237 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h b/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h index afa6898944..0b1d7caefe 100644 --- a/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h +++ b/Code/Framework/AzCore/AzCore/UnitTest/TestTypes.h @@ -71,18 +71,35 @@ namespace UnitTest }; /** - * RAII wrapper of AllocatorBase. - * The benefit of using this wrapper instead of AllocatorsTestFixture is that SetUp/TearDown of the allocator is managed - * on construction/destruction, allowing member variables of derived classes to exist as value (and do heap allocation). - */ - class ScopedAllocatorSetupFixture - : public ::testing::Test - , AllocatorsBase + * RAII wrapper of AllocatorBase. + * The benefit of using this wrapper instead of AllocatorsTestFixture is that SetUp/TearDown of the allocator is managed + * on construction/destruction, allowing member variables of derived classes to exist as value (and do heap allocation). + */ + class ScopedAllocatorFixture : AllocatorsBase { public: - ScopedAllocatorSetupFixture() { SetupAllocator(); } - explicit ScopedAllocatorSetupFixture(const AZ::SystemAllocator::Descriptor& allocatorDesc) { SetupAllocator(allocatorDesc); } - ~ScopedAllocatorSetupFixture() { TeardownAllocator(); } + ScopedAllocatorFixture() + { + SetupAllocator(); + } + explicit ScopedAllocatorFixture(const AZ::SystemAllocator::Descriptor& allocatorDesc) + { + SetupAllocator(allocatorDesc); + } + ~ScopedAllocatorFixture() override + { + TeardownAllocator(); + } + }; + + // Like ScopedAllocatorFixture, but includes the Test base class + class ScopedAllocatorSetupFixture + : public ::testing::Test + , public ScopedAllocatorFixture + { + public: + ScopedAllocatorSetupFixture() = default; + explicit ScopedAllocatorSetupFixture(const AZ::SystemAllocator::Descriptor& allocatorDesc) : ScopedAllocatorFixture(allocatorDesc){} }; /** @@ -114,6 +131,7 @@ namespace UnitTest using AllocatorsFixture = AllocatorsTestFixture; #if defined(HAVE_BENCHMARK) + /** * Helper class to handle the boiler plate of setting up a benchmark fixture that uses the system allocators * If you wish to do additional setup and tear down be sure to call the base class SetUp first and TearDown @@ -218,7 +236,7 @@ namespace UnitTest static constexpr bool sHasPadding = size < alignment; AZStd::enable_if mPadding; }; - + template int CreationCounter::s_count = 0; template diff --git a/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake b/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake index 2c4c53642c..a7a46ad62c 100644 --- a/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake +++ b/Code/Tools/AssetProcessor/assetprocessor_test_files.cmake @@ -48,6 +48,7 @@ set(FILES native/tests/InternalBuilders/SettingsRegistryBuilderTests.cpp native/tests/MissingDependencyScannerTests.cpp native/tests/SourceFileRelocatorTests.cpp + native/tests/PathDependencyManagerTests.cpp native/tests/AssetProcessorMessagesTests.cpp native/unittests/AssetProcessingStateDataUnitTests.cpp native/unittests/AssetProcessingStateDataUnitTests.h diff --git a/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp b/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp index cf33e559ac..5edf4e1d53 100644 --- a/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp +++ b/Code/Tools/AssetProcessor/native/AssetDatabase/AssetDatabase.cpp @@ -172,7 +172,7 @@ namespace AssetProcessor static const char* CREATEINDEX_BUILDERGUID_SOURCE_SOURCEDEPENDENCY_STATEMENT = "CREATE INDEX IF NOT EXISTS BuilderGuid_Source_SourceDependency ON SourceDependency (BuilderGuid, Source);"; static const char* CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY = "AssetProcessor::CreateIndexTypeOfDependency_SourceDependency"; - static const char* CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY_STATEMENT = + static const char* CREATEINDEX_TYPEOFDEPENDENCY_SOURCEDEPENDENCY_STATEMENT = "CREATE INDEX IF NOT EXISTS TypeOfDependency_SourceDependency ON SourceDependency (TypeOfDependency);"; static const char* CREATEINDEX_SCANFOLDERS_SOURCES_SCANFOLDER = "AssetProcesser::CreateIndexScanFoldersSourcesScanFolder"; @@ -611,7 +611,7 @@ namespace AssetProcessor SqlParam(":missingDependencyString"), SqlParam(":lastScanTime"), SqlParam(":scanTimeSecondsSinceEpoch")); - + static const auto s_DeleteMissingProductDependencyByProductIdQuery = MakeSqlQuery( DELETE_MISSING_PRODUCT_DEPENDENCY_BY_PRODUCTID, @@ -643,7 +643,7 @@ namespace AssetProcessor SqlParam(":analysisFingerprint")); static const char* INSERT_COLUMN_ANALYSISFINGERPRINT = "AssetProcessor::AddColumnAnalysisFingerprint"; - static const char* INSERT_COLUMN_ANALYSISFINGERPRINT_STATEMENT = + static const char* INSERT_COLUMN_ANALYSISFINGERPRINT_STATEMENT = "ALTER TABLE Sources " "ADD AnalysisFingerprint TEXT NOT NULL collate nocase default('');"; @@ -653,7 +653,7 @@ namespace AssetProcessor "ADD TypeOfDependency INTEGER NOT NULL DEFAULT 0;"; static const char* INSERT_COLUMN_FILE_MODTIME = "AssetProcessor::AddFiles_ModTime"; - static const char* INSERT_COLUMN_FILE_MODTIME_STATEMENT = + static const char* INSERT_COLUMN_FILE_MODTIME_STATEMENT = "ALTER TABLE Files " "ADD ModTime INTEGER NOT NULL DEFAULT 0;"; @@ -673,7 +673,7 @@ namespace AssetProcessor "ADD UnresolvedDependencyType INTEGER NOT NULL DEFAULT 0;"; static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM = "AssetProcessor::AddProductDependency_Platform"; - static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM_STATEMENT = + static const char* INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM_STATEMENT = "ALTER TABLE ProductDependencies " "ADD Platform TEXT NOT NULL collate nocase default('');"; @@ -721,7 +721,7 @@ namespace AssetProcessor SqlParam(":isfolder"), SqlParam(":modtime"), SqlParam(":hash")); - + static const char* UPDATE_FILE = "AssetProcessor::UpdateFile"; static const char* UPDATE_FILE_STATEMENT = "UPDATE Files SET " @@ -961,7 +961,7 @@ namespace AssetProcessor AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Upgraded Asset Database to version %i (AddedTypeOfDependencyIndex)\n", foundVersion) } } - + if (foundVersion == AssetDatabase::DatabaseVersion::AddedTypeOfDependencyIndex) { if (m_databaseConnection->ExecuteOneOffStatement(INSERT_COLUMN_PRODUCTDEPENDENCY_PLATFORM)) @@ -1178,7 +1178,7 @@ namespace AssetProcessor AddStatement(m_databaseConnection, s_InsertJobQuery); AddStatement(m_databaseConnection, s_UpdateJobQuery); AddStatement(m_databaseConnection, s_DeleteJobQuery); - + // --------------------------------------------------------------------------------------------- // Builder Info Table // --------------------------------------------------------------------------------------------- @@ -1207,7 +1207,7 @@ namespace AssetProcessor m_databaseConnection->AddStatement(CREATE_SOURCE_DEPENDENCY_TABLE, CREATE_SOURCE_DEPENDENCY_TABLE_STATEMENT); m_databaseConnection->AddStatement(INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY, INSERT_COLUMN_SOURCEDEPENDENCY_TYPEOFDEPENDENCY_STATEMENT); m_databaseConnection->AddStatement(INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID, INSERT_COLUMNS_SOURCEDEPENDENCY_FROM_ASSETID_STATEMENT); - + m_createStatements.push_back(CREATE_SOURCE_DEPENDENCY_TABLE); AddStatement(m_databaseConnection, s_InsertSourceDependencyQuery); @@ -1242,7 +1242,7 @@ namespace AssetProcessor AddStatement(m_databaseConnection, s_InsertProductDependencyQuery); AddStatement(m_databaseConnection, s_UpdateProductDependencyQuery); AddStatement(m_databaseConnection, s_DeleteProductDependencyByProductIdQuery); - + // --------------------------------------------------------------------------------------------- // Missing Product Dependency table // --------------------------------------------------------------------------------------------- @@ -1253,7 +1253,7 @@ namespace AssetProcessor AddStatement(m_databaseConnection, s_InsertMissingProductDependencyQuery); AddStatement(m_databaseConnection, s_UpdateMissingProductDependencyQuery); AddStatement(m_databaseConnection, s_DeleteMissingProductDependencyByProductIdQuery); - + // --------------------------------------------------------------------------------------------- // Files table // --------------------------------------------------------------------------------------------- @@ -1344,7 +1344,7 @@ namespace AssetProcessor bool AssetDatabaseConnection::GetScanFolderByScanFolderID(AZ::s64 scanfolderID, ScanFolderDatabaseEntry& entry) { bool found = false; - QueryScanFolderByScanFolderID( scanfolderID, + QueryScanFolderByScanFolderID( scanfolderID, [&](ScanFolderDatabaseEntry& scanFolderEntry) { entry = scanFolderEntry; @@ -1357,7 +1357,7 @@ namespace AssetProcessor bool AssetDatabaseConnection::GetScanFolderBySourceID(AZ::s64 sourceID, ScanFolderDatabaseEntry& entry) { bool found = false; - QueryScanFolderBySourceID( sourceID, + QueryScanFolderBySourceID( sourceID, [&](ScanFolderDatabaseEntry& scanFolderEntry) { entry = scanFolderEntry; @@ -1370,7 +1370,7 @@ namespace AssetProcessor bool AssetDatabaseConnection::GetScanFolderByJobID(AZ::s64 jobID, ScanFolderDatabaseEntry& entry) { bool found = false; - QueryScanFolderByJobID( jobID, + QueryScanFolderByJobID( jobID, [&](ScanFolderDatabaseEntry& scanFolderEntry) { entry = scanFolderEntry; @@ -1383,7 +1383,7 @@ namespace AssetProcessor bool AssetDatabaseConnection::GetScanFolderByProductID(AZ::s64 productID, ScanFolderDatabaseEntry& entry) { bool found = false; - QueryScanFolderByProductID( productID, + QueryScanFolderByProductID( productID, [&](ScanFolderDatabaseEntry& scanFolderEntry) { entry = scanFolderEntry; @@ -2105,7 +2105,7 @@ namespace AssetProcessor bool AssetDatabaseConnection::GetProductsLikeProductName(QString likeProductName, LikeType likeType, ProductDatabaseEntryContainer& container, AZ::Uuid builderGuid, QString jobKey, QString platform, JobStatus status) { bool found = false; - + if (likeProductName.isEmpty()) { return false; @@ -2198,7 +2198,7 @@ namespace AssetProcessor bool AssetDatabaseConnection::GetProductByJobIDSubId(AZ::s64 jobID, AZ::u32 subID, AzToolsFramework::AssetDatabase::ProductDatabaseEntry& result) { bool found = false; - QueryProductByJobIDSubID(jobID, subID, + QueryProductByJobIDSubID(jobID, subID, [&](ProductDatabaseEntry& resultFromDB) { found = true; @@ -2312,13 +2312,19 @@ namespace AssetProcessor { return false; } - - bool succeeded = true; + + ScopedTransaction transaction(m_databaseConnection); + for (auto& entry : container) { - succeeded &= SetProduct(entry); + if(!SetProduct(entry)) + { + return false; + } } - return succeeded; + + transaction.Commit(); + return true; } //! Clear the products for a given source. This removes the entry entirely, not just sets it to empty. @@ -2407,7 +2413,7 @@ namespace AssetProcessor if(!platform.isEmpty()) { AZStd::string platformStr = platform.toUtf8().constData(); - + if (!s_DeleteProductsBySourceidPlatformQuery.BindAndStep(*m_databaseConnection, sourceID, platformStr.c_str())) { return false; @@ -2521,7 +2527,7 @@ namespace AssetProcessor { succeeded = succeeded && RemoveSourceFileDependency(entry); } - + if (succeeded) { transaction.Commit(); @@ -2577,7 +2583,7 @@ namespace AssetProcessor } bool AssetDatabaseConnection::GetDependsOnSourceBySource( - const char* source, + const char* source, AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::TypeOfDependency typeOfDependency, AzToolsFramework::AssetDatabase::SourceFileDependencyEntryContainer& container) { @@ -2596,7 +2602,7 @@ namespace AssetProcessor bool AssetDatabaseConnection::GetSourceFileDependencyBySourceDependencyId(AZ::s64 sourceDependencyId, SourceFileDependencyEntry& sourceDependencyEntry) { bool found = false; - QuerySourceDependencyBySourceDependencyId(sourceDependencyId, + QuerySourceDependencyBySourceDependencyId(sourceDependencyId, [&](SourceFileDependencyEntry& entry) { found = true; @@ -2624,7 +2630,7 @@ namespace AssetProcessor return false; } - + if (creatingNew) { AZ::s64 rowID = m_databaseConnection->GetLastRowID(); @@ -2958,9 +2964,25 @@ namespace AssetProcessor for(auto& entry : container) { - if(!SetProductDependency(entry)) + if(entry.m_productDependencyID == InvalidEntryId) { - return false; + if (!s_InsertProductDependencyQuery.BindAndStep( + *m_databaseConnection, entry.m_productPK, entry.m_dependencySourceGuid, entry.m_dependencySubID, + entry.m_dependencyFlags.to_ullong(), entry.m_platform.c_str(), entry.m_unresolvedPath.c_str(), + entry.m_dependencyType, entry.m_fromAssetId)) + { + return false; + } + } + else + { + if(!s_UpdateProductDependencyQuery.BindAndStep( + *m_databaseConnection, entry.m_productPK, entry.m_dependencySourceGuid, entry.m_dependencySubID, + entry.m_dependencyFlags.to_ullong(), entry.m_platform.c_str(), entry.m_unresolvedPath.c_str(), + entry.m_productDependencyID, entry.m_dependencyType, entry.m_fromAssetId)) + { + return false; + } } } @@ -2989,7 +3011,7 @@ namespace AssetProcessor } // now insert the new ones since we know there's no collisions: - + for (auto& entry : container) { @@ -3109,7 +3131,7 @@ namespace AssetProcessor } Statement* statement = autoFinal.Get(); - + if (statement->Step() == Statement::SqlError) { AZ_Warning(LOG_NAME, false, "Failed to write the new source into the database. %s", entry.m_fileName.c_str()); @@ -3126,7 +3148,7 @@ namespace AssetProcessor return UpdateFile(entry, entryAlreadyExists); } - bool AssetDatabaseConnection::UpdateFile(FileDatabaseEntry& entry, bool& entryAlreadyExists) + bool AssetDatabaseConnection::UpdateFile(FileDatabaseEntry& entry, bool& entryAlreadyExists) { entryAlreadyExists = false; diff --git a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp index d7cdd30be8..bda5eb7842 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/AssetCatalog.cpp @@ -480,12 +480,12 @@ namespace AssetProcessor AZ::Data::AssetId assetId(combined.m_sourceGuid, combined.m_subID); // relative file path is gotten by removing the platform and game from the product name - QString relativeProductPath = AssetUtilities::StripAssetPlatform(combined.m_productName); + AZStd::string_view relativeProductPath = AssetUtilities::StripAssetPlatformNoCopy(combined.m_productName); QString fullProductPath = m_cacheRoot.absoluteFilePath(combined.m_productName.c_str()); AZ::Data::AssetInfo info; info.m_assetType = combined.m_assetType; - info.m_relativePath = relativeProductPath.toUtf8().data(); + info.m_relativePath = relativeProductPath; info.m_assetId = assetId; info.m_sizeBytes = AZ::IO::SystemFile::Length(fullProductPath.toUtf8().constData()); diff --git a/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.cpp b/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.cpp index dc10dc2237..6dddfd62d3 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.cpp @@ -9,18 +9,24 @@ #include "PathDependencyManager.h" #include #include +#include #include #include #include +#include namespace AssetProcessor { void SanitizeForDatabase(AZStd::string& str) { - // Not calling normalize because wildcards should be preserved. AZStd::to_lower(str.begin(), str.end()); - AZStd::replace(str.begin(), str.end(), AZ_WRONG_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR); - AzFramework::StringFunc::Replace(str, AZ_DOUBLE_CORRECT_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR_STRING); + + // Not calling normalize because wildcards should be preserved. + if (AZ::StringFunc::Contains(str, AZ_WRONG_DATABASE_SEPARATOR, true)) + { + AZStd::replace(str.begin(), str.end(), AZ_WRONG_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR); + AzFramework::StringFunc::Replace(str, AZ_DOUBLE_CORRECT_DATABASE_SEPARATOR, AZ_CORRECT_DATABASE_SEPARATOR_STRING); + } } PathDependencyManager::PathDependencyManager(AZStd::shared_ptr stateData, PlatformConfiguration* platformConfig) @@ -29,7 +35,97 @@ namespace AssetProcessor } - void PathDependencyManager::SaveUnresolvedDependenciesToDatabase(AssetBuilderSDK::ProductPathDependencySet& unresolvedDependencies, const AzToolsFramework::AssetDatabase::ProductDatabaseEntry& productEntry, const AZStd::string& platform) + void PathDependencyManager::QueueSourceForDependencyResolution(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry) + { + m_queuedForResolve.push_back(sourceEntry); + } + + void PathDependencyManager::ProcessQueuedDependencyResolves() + { + if (m_queuedForResolve.empty()) + { + return; + } + + auto queuedForResolve = m_queuedForResolve; + m_queuedForResolve.clear(); + + // Grab every product from the database and map to Source PK -> [products] + AZStd::unordered_map> productMap; + m_stateData->QueryCombined([&productMap](const AzToolsFramework::AssetDatabase::CombinedDatabaseEntry& entry) + { + productMap[entry.m_sourcePK].push_back(entry); + return true; + }); + + // Build up a list of all the paths we need to search for: products + 2 variations of the source path + AZStd::vector searches; + + for (const auto& entry : queuedForResolve) + { + // Search for each product + for (const auto& productEntry : productMap[entry.m_sourceID]) + { + const AZStd::string& productName = productEntry.m_productName; + + // strip path of the / + AZStd::string_view result = AssetUtilities::StripAssetPlatformNoCopy(productName); + searches.emplace_back(result, false, &entry, &productEntry); + } + + // Search for the source path + AZStd::string sourceNameWithScanFolder = + ToScanFolderPrefixedPath(aznumeric_cast(entry.m_scanFolderPK), entry.m_sourceName.c_str()); + AZStd::string sanitizedSourceName = entry.m_sourceName; + + SanitizeForDatabase(sourceNameWithScanFolder); + SanitizeForDatabase(sanitizedSourceName); + + searches.emplace_back(sourceNameWithScanFolder, true, &entry, nullptr); + searches.emplace_back(sanitizedSourceName, true, &entry, nullptr); + } + + AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer unresolvedDependencies; + m_stateData->GetUnresolvedProductDependencies(unresolvedDependencies); + + AZStd::recursive_mutex mapMutex; + // Map of Map of Product Dependency>> + AZStd::unordered_map>> sourceIdToMatchedSearchDependencies; + + // For every search path we created, we're going to see if it matches up against any of the unresolved dependencies + AZ::parallel_for_each( + searches.begin(), searches.end(), + [&sourceIdToMatchedSearchDependencies, &mapMutex, &unresolvedDependencies](const SearchEntry& search) + { + AZStd::unordered_set matches; + for (const auto& entry: unresolvedDependencies) + { + AZ::IO::PathView searchPath(search.m_path); + + if(((entry.m_dependencyType == AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry::ProductDep_SourceFile && search.m_isSourcePath) + || (entry.m_dependencyType == AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry::ProductDep_ProductFile && !search.m_isSourcePath)) + && searchPath.Match(entry.m_unresolvedPath)) + { + matches.insert(entry); + } + } + + if (!matches.empty()) + { + AZStd::scoped_lock lock(mapMutex); + auto& productDependencyDatabaseEntries = sourceIdToMatchedSearchDependencies[search.m_sourceEntry->m_sourceID][&search]; + productDependencyDatabaseEntries.insert(matches.begin(), matches.end()); + } + }); + + for (const auto& entry : queuedForResolve) + { + RetryDeferredDependencies(entry, sourceIdToMatchedSearchDependencies[entry.m_sourceID], productMap[entry.m_sourceID]); + } + } + + void PathDependencyManager::SaveUnresolvedDependenciesToDatabase(AssetBuilderSDK::ProductPathDependencySet& unresolvedDependencies, + const AzToolsFramework::AssetDatabase::ProductDatabaseEntry& productEntry, const AZStd::string& platform) { using namespace AzToolsFramework::AssetDatabase; @@ -206,9 +302,9 @@ namespace AssetProcessor } void PathDependencyManager::SaveResolvedDependencies(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry, const MapSet& exclusionMaps, const AZStd::string& sourceNameWithScanFolder, - const AZStd::vector& dependencyEntries, + const AZStd::unordered_set& dependencyEntries, AZStd::string_view matchedPath, bool isSourceDependency, const AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& matchedProducts, - AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencyContainer) const + AZStd::vector& dependencyContainer) const { for (const auto& productDependencyDatabaseEntry : dependencyEntries) { @@ -267,8 +363,7 @@ namespace AssetProcessor } // All checks passed, this is a valid dependency we need to save to the db - dependencyContainer.push_back(); - auto& entry = dependencyContainer.back(); + AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry entry; entry.m_productDependencyID = dependencyId; entry.m_productPK = productDependencyDatabaseEntry.m_productPK; @@ -276,62 +371,30 @@ namespace AssetProcessor entry.m_dependencySubID = matchedProduct.m_subID; entry.m_platform = productDependencyDatabaseEntry.m_platform; + dependencyContainer.push_back(AZStd::move(entry)); + // If there's more than 1 product, reset the ID so further products create new db entries dependencyId = AzToolsFramework::AssetDatabase::InvalidEntryId; } } } - void PathDependencyManager::RetryDeferredDependencies(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry) + void PathDependencyManager::RetryDeferredDependencies(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry, + const AZStd::unordered_map>& matches, + const AZStd::vector& products) { MapSet exclusionMaps = PopulateExclusionMaps(); - // Gather a list of all the products this source file produced - AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer products; - if (!m_stateData->GetProductsBySourceName(sourceEntry.m_sourceName.c_str(), products)) - { - AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Source %s did not have any products. Skipping dependency processing.\n", sourceEntry.m_sourceName.c_str()); - return; - } - - AZStd::unordered_map> map; - - // Build up a list of all the paths we need to search for: products + 2 variations of the source path - AZStd::vector searchPaths; - - for (const auto& productEntry : products) - { - const AZStd::string& productName = productEntry.m_productName; - - // strip path of the / - AZStd::string strippedPath = AssetUtilities::StripAssetPlatform(productName).toUtf8().constData(); - SanitizeForDatabase(strippedPath); - - searchPaths.push_back(strippedPath); - } - AZStd::string sourceNameWithScanFolder = ToScanFolderPrefixedPath(aznumeric_cast(sourceEntry.m_scanFolderPK), sourceEntry.m_sourceName.c_str()); - AZStd::string sanitizedSourceName = sourceEntry.m_sourceName; - SanitizeForDatabase(sourceNameWithScanFolder); - SanitizeForDatabase(sanitizedSourceName); - searchPaths.push_back(sourceNameWithScanFolder); - searchPaths.push_back(sanitizedSourceName); - - m_stateData->QueryProductDependenciesUnresolvedAdvanced(searchPaths, [&map](AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry& entry, const AZStd::string& matchedPath) - { - map[matchedPath].push_back(AZStd::move(entry)); - return true; - }); - - AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer; + AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyVector; // Go through all the matched dependencies - for (const auto& pair : map) + for (const auto& pair : matches) { - AZStd::string_view matchedPath = pair.first; - const bool isSourceDependency = matchedPath == sanitizedSourceName || matchedPath == sourceNameWithScanFolder; + const SearchEntry* searchEntry = pair.first; + const bool isSourceDependency = searchEntry->m_isSourcePath; AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer matchedProducts; @@ -342,34 +405,24 @@ namespace AssetProcessor } else { - for (const auto& productEntry : products) - { - const AZStd::string& productName = productEntry.m_productName; - - // strip path of the leading asset platform / - AZStd::string strippedPath = AssetUtilities::StripAssetPlatform(productName).toUtf8().constData(); - SanitizeForDatabase(strippedPath); - - if (strippedPath == matchedPath) - { - matchedProducts.push_back(productEntry); - } - } + matchedProducts.push_back(*searchEntry->m_productEntry); } // Go through each dependency we're resolving and create a db entry for each product that resolved it (wildcard/source dependencies will generally create more than 1) - SaveResolvedDependencies(sourceEntry, exclusionMaps, sourceNameWithScanFolder, pair.second, matchedPath, isSourceDependency, matchedProducts, dependencyContainer); + SaveResolvedDependencies( + sourceEntry, exclusionMaps, sourceNameWithScanFolder, pair.second, searchEntry->m_path, isSourceDependency, matchedProducts, + dependencyVector); } - // Save everything to the db - if (!m_stateData->UpdateProductDependencies(dependencyContainer)) + // Save everything to the db, this will update matched non-wildcard dependencies and add new records for wildcard matches + if (!m_stateData->UpdateProductDependencies(dependencyVector)) { AZ_Error("PathDependencyManager", false, "Failed to update product dependencies"); } else { // Send a notification for each dependency that has been resolved - NotifyResolvedDependencies(dependencyContainer); + NotifyResolvedDependencies(dependencyVector); } } @@ -460,7 +513,7 @@ namespace AssetProcessor if (isExactDependency) { // Search for products in the cache platform folder - // Example: If a path dependency is "test1.asset" in AutomatedTesting on PC, this would search + // Example: If a path dependency is "test1.asset" in AutomatedTesting on PC, this would search // "AutomatedTesting/Cache/pc/test1.asset" m_stateData->GetProductsByProductName(productNameWithPlatform, productInfoContainer); diff --git a/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.h b/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.h index 3a207ec6a9..763ee2cd74 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.h +++ b/Code/Tools/AssetProcessor/native/AssetManager/PathDependencyManager.h @@ -39,9 +39,27 @@ namespace AssetProcessor PathDependencyManager(AZStd::shared_ptr stateData, PlatformConfiguration* platformConfig); + void QueueSourceForDependencyResolution(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry); + + void ProcessQueuedDependencyResolves(); + + struct SearchEntry + { + SearchEntry(AZStd::string path, bool isSourcePath, const AzToolsFramework::AssetDatabase::SourceDatabaseEntry* sourceEntry, const AzToolsFramework::AssetDatabase::ProductDatabaseEntry* productEntry) + : m_path(std::move(path)), + m_isSourcePath(isSourcePath), + m_sourceEntry(sourceEntry), + m_productEntry(productEntry) {} + + AZStd::string m_path; + bool m_isSourcePath; + const AzToolsFramework::AssetDatabase::SourceDatabaseEntry* m_sourceEntry = nullptr; + const AzToolsFramework::AssetDatabase::ProductDatabaseEntry* m_productEntry = nullptr; + }; + /// This function is responsible for looking up existing, unresolved dependencies that the current asset satisfies. /// These can be dependencies on either the source asset or one of the product assets - void RetryDeferredDependencies(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry); + void RetryDeferredDependencies(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry, const AZStd::unordered_map>& matches, const AZStd::vector& products); /// This function is responsible for taking the path dependencies output by the current asset and trying to resolve them to AssetIds /// This does not look for dependencies that the current asset satisfies. @@ -66,7 +84,7 @@ namespace AssetProcessor MapSet PopulateExclusionMaps() const; void NotifyResolvedDependencies(const AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencyContainer) const; - void SaveResolvedDependencies(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry, const MapSet& exclusionMaps, const AZStd::string& sourceNameWithScanFolder, const AZStd::vector& dependencyEntries, AZStd::string_view matchedPath, bool isSourceDependency, const AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& matchedProducts, AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer& dependencyContainer) const; + void SaveResolvedDependencies(const AzToolsFramework::AssetDatabase::SourceDatabaseEntry& sourceEntry, const MapSet& exclusionMaps, const AZStd::string& sourceNameWithScanFolder, const AZStd::unordered_set& dependencyEntries, AZStd::string_view matchedPath, bool isSourceDependency, const AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer& matchedProducts, AZStd::vector& dependencyContainer) const; static DependencyProductMap& SelectMap(MapSet& mapSet, bool wildcard, AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry::DependencyType type); /// Returns false if a path contains wildcards, true otherwise @@ -93,5 +111,6 @@ namespace AssetProcessor AZStd::shared_ptr m_stateData; PlatformConfiguration* m_platformConfig{}; DependencyResolvedCallback m_dependencyResolvedCallback{}; + AZStd::vector m_queuedForResolve; }; } // namespace AssetProcessor diff --git a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp index 8867f2379f..beb82dfcab 100644 --- a/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp +++ b/Code/Tools/AssetProcessor/native/AssetManager/assetProcessorManager.cpp @@ -48,7 +48,7 @@ namespace AssetProcessor // note that this is not the first time we're opening the database - the main thread also opens it before this happens, // which allows it to upgrade it and check it for errors. If we get here, it means the database is already good to go. - m_stateData->OpenDatabase(); + m_stateData->OpenDatabase(); MigrateScanFolders(); @@ -70,7 +70,7 @@ namespace AssetProcessor m_excludedFolderCache = AZStd::make_unique(m_platformConfig); PopulateJobStateCache(); - + AssetProcessor::ProcessingJobInfoBus::Handler::BusConnect(); } @@ -126,7 +126,7 @@ namespace AssetProcessor { // capture scanning stats: AssetProcessor::StatsCapture::BeginCaptureStat("AssetScanning"); - + // Ensure that the source file list is populated before a scan begins m_sourceFilesInDatabase.clear(); m_fileModTimes.clear(); @@ -155,11 +155,11 @@ namespace AssetProcessor QString scanFolderPath; QString relativeToScanFolderPath = QString::fromUtf8(entry.m_fileName.c_str()); - + for (int i = 0; i < m_platformConfig->GetScanFolderCount(); ++i) { const auto& scanFolderInfo = m_platformConfig->GetScanFolderAt(i); - + if (scanFolderInfo.ScanFolderID() == entry.m_scanFolderPK) { scanFolderPath = scanFolderInfo.ScanPath(); @@ -181,7 +181,7 @@ namespace AssetProcessor { m_isCurrentlyScanning = false; AssetProcessor::StatsCapture::EndCaptureStat("AssetScanning"); - + // we cannot invoke this immediately - the scanner might be done, but we aren't actually ready until we've processed all remaining messages: QMetaObject::invokeMethod(this, "CheckMissingFiles", Qt::QueuedConnection); } @@ -216,7 +216,7 @@ namespace AssetProcessor else { QString statKey = QString("ProcessJob,%1,%2,%3").arg(jobEntry.m_databaseSourceName).arg(jobEntry.m_jobKey).arg(jobEntry.m_platformInfo.m_identifier.c_str()); - + if (status == JobStatus::InProgress) { //update to in progress status @@ -232,7 +232,7 @@ namespace AssetProcessor // without going thru the RC. // as such, all the code in this block should be crafted to work regardless of whether its double called. AssetProcessor::StatsCapture::EndCaptureStat(statKey.toUtf8().constData()); - + m_jobRunKeyToJobInfoMap.erase(jobEntry.m_jobRunKey); Q_EMIT SourceFinished(sourceUUID, legacySourceUUID); Q_EMIT JobComplete(jobEntry, status); @@ -308,7 +308,7 @@ namespace AssetProcessor //! A network request came in, Given a Job Run Key (from the above Job Request), asking for the actual log for that job. GetAbsoluteAssetDatabaseLocationResponse AssetProcessorManager::ProcessGetAbsoluteAssetDatabaseLocationRequest(MessageData messageData) - { + { GetAbsoluteAssetDatabaseLocationResponse response; AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Broadcast(&AzToolsFramework::AssetDatabase::AssetDatabaseRequests::GetAssetDatabaseLocation, response.m_absoluteAssetDatabaseLocation); @@ -525,7 +525,7 @@ namespace AssetProcessor { foundOne = true; return true; - }, + }, AZ::Uuid::CreateNull(), nullptr, platform.toUtf8().constData(), @@ -750,7 +750,7 @@ namespace AssetProcessor } OnJobStatusChanged(jobEntry, JobStatus::Failed); - + // note that we always print out the failed job status here in both batch and GUI mode. AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Failed %s, (%s)... \n", jobEntry.m_pathRelativeToWatchFolder.toUtf8().constData(), @@ -868,7 +868,7 @@ namespace AssetProcessor && AzFramework::StringFunc::Equal(job.m_platform.c_str(), itProcessedAsset->m_entry.m_platformInfo.m_identifier.c_str())) { // If we are here it implies that for the same source file we have another job that outputs the same product. - // This is usually the case when two builders process the same source file and outputs the same product file. + // This is usually the case when two builders process the same source file and outputs the same product file. remove = true; AZStd::string consoleMsg = AZStd::string::format("Failing Job (source : %s , jobkey %s) because another job (source : %s , jobkey : %s ) outputted the same product %s.\n", itProcessedAsset->m_entry.m_pathRelativeToWatchFolder.toUtf8().constData(), itProcessedAsset->m_entry.m_jobKey.toUtf8().data(), source.m_sourceName.c_str(), job.m_jobKey.c_str(), newProductName.toUtf8().constData()); @@ -1128,7 +1128,7 @@ namespace AssetProcessor QString fullProductPath = m_cacheRootDir.absoluteFilePath(productName); // Strip the from the front of a relative product path - QString relativeProductPath = AssetUtilities::StripAssetPlatform(priorProduct.m_productName); + AZStd::string_view relativeProductPath = AssetUtilities::StripAssetPlatformNoCopy(priorProduct.m_productName); AZ::Data::AssetId assetId(source.m_sourceGuid, priorProduct.m_subID); @@ -1137,7 +1137,7 @@ namespace AssetProcessor AZ::Data::AssetId legacyAssetId(priorProduct.m_legacyGuid, 0); AZ::Data::AssetId legacySourceAssetId(AssetUtilities::CreateSafeSourceUUIDFromName(source.m_sourceName.c_str(), false), priorProduct.m_subID); - AssetNotificationMessage message(relativeProductPath.toUtf8().constData(), AssetNotificationMessage::AssetRemoved, priorProduct.m_assetType, processedAsset.m_entry.m_platformInfo.m_identifier.c_str()); + AssetNotificationMessage message(relativeProductPath, AssetNotificationMessage::AssetRemoved, priorProduct.m_assetType, processedAsset.m_entry.m_platformInfo.m_identifier.c_str()); message.m_assetId = assetId; if (legacyAssetId != assetId) @@ -1271,7 +1271,7 @@ namespace AssetProcessor [&](AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntry& dependencyEntry) { return dependencyEntry.m_dependencySubID == pair.first.m_subID - && dependencyEntry.m_dependencySourceGuid == source.m_sourceGuid; + && dependencyEntry.m_dependencySourceGuid == source.m_sourceGuid; }); if (conflictItr != dependencySet.end()) @@ -1312,14 +1312,14 @@ namespace AssetProcessor // relative file path is gotten by removing the platform and game from the product name // Strip the from the front of a relative product path - QString relativeProductPath = AssetUtilities::StripAssetPlatform(productName.toUtf8().constData()); + AZStd::string relativeProductPath = AssetUtilities::StripAssetPlatform(productName.toUtf8().constData()).toUtf8().constData(); - AssetNotificationMessage message(relativeProductPath.toUtf8().constData(), AssetNotificationMessage::AssetChanged, newProduct.m_assetType, processedAsset.m_entry.m_platformInfo.m_identifier.c_str()); + AssetNotificationMessage message(relativeProductPath, AssetNotificationMessage::AssetChanged, newProduct.m_assetType, processedAsset.m_entry.m_platformInfo.m_identifier.c_str()); AZ::Data::AssetId assetId(source.m_sourceGuid, newProduct.m_subID); AZ::Data::AssetId legacyAssetId(newProduct.m_legacyGuid, 0); AZ::Data::AssetId legacySourceAssetId(AssetUtilities::CreateSafeSourceUUIDFromName(source.m_sourceName.c_str(), false), newProduct.m_subID); - message.m_data = relativeProductPath.toUtf8().data(); + message.m_data = relativeProductPath; message.m_sizeBytes = QFileInfo(fullProductPath).size(); message.m_assetId = assetId; @@ -1350,7 +1350,7 @@ namespace AssetProcessor } Q_EMIT AssetMessage( message); - + AddKnownFoldersRecursivelyForFile(fullProductPath, m_cacheRootDir.absolutePath()); } @@ -1497,7 +1497,7 @@ namespace AssetProcessor // Record the modtime for the metadata file so we don't re-analyze this change again next time AP starts up QFileInfo metadataFileInfo(originalName); auto* scanFolder = m_platformConfig->GetScanFolderForFile(originalName); - + if (scanFolder) { QString databaseName; @@ -1534,7 +1534,7 @@ namespace AssetProcessor for (const QString& absolutePath : absoluteSourcePathList) { // we need to check if its already in the "active files" (things that we are looking over) - // or if its in the "currently being examined" list. The latter is likely to be the smaller list, + // or if its in the "currently being examined" list. The latter is likely to be the smaller list, // so we check it first. Both of those are absolute paths, so we convert to absolute path before // searching those lists: if (m_filesToExamine.find(absolutePath) != m_filesToExamine.end()) @@ -1633,9 +1633,6 @@ namespace AssetProcessor } } - // Strip the from the front of a relative product path - QString relativePath = AssetUtilities::StripAssetPlatform(relativeProductFile.toUtf8().constData()); - //set the fingerprint on the job that made this product for (auto& job : jobs) { @@ -1678,7 +1675,7 @@ namespace AssetProcessor } QString fullProductPath = m_cacheRootDir.absoluteFilePath(product.m_productName.c_str()); - QString relativeProductPath(AssetUtilities::StripAssetPlatform(product.m_productName)); + AZStd::string_view relativeProductPath = AssetUtilities::StripAssetPlatformNoCopy(product.m_productName); QFileInfo productFileInfo(fullProductPath); if (productFileInfo.exists()) { @@ -1725,7 +1722,7 @@ namespace AssetProcessor AZ::Data::AssetId legacyAssetId(product.m_legacyGuid, 0); AZ::Data::AssetId legacySourceAssetId(AssetUtilities::CreateSafeSourceUUIDFromName(source.m_sourceName.c_str(), false), product.m_subID); - AssetNotificationMessage message(relativeProductPath.toUtf8().constData(), AssetNotificationMessage::AssetRemoved, product.m_assetType, job.m_platform.c_str()); + AssetNotificationMessage message(relativeProductPath, AssetNotificationMessage::AssetRemoved, product.m_assetType, job.m_platform.c_str()); message.m_assetId = assetId; if (legacyAssetId != assetId) @@ -1759,7 +1756,7 @@ namespace AssetProcessor // and no overrides exist for it. // we must delete its products. using namespace AzToolsFramework::AssetDatabase; - + // If we fail to delete a product, the deletion event gets requeued // To avoid retrying forever, we keep track of the time of the first deletion failure and only retry // if less than this amount of time has passed. @@ -1832,7 +1829,7 @@ namespace AssetProcessor { return; } - + // Check if this file causes any file types to be re-evaluated CheckMetaDataRealFiles(normalizedPath); @@ -2046,7 +2043,7 @@ namespace AssetProcessor AZ_TracePrintf(AssetProcessor::DebugChannel, "Non-processed file: %s\n", databaseSourceFile.toUtf8().constData()); ++m_numSourcesNotHandledByAnyBuilder; - + // Record the modtime for the file so we know we've already processed it QString absolutePath = QDir(scanFolder->ScanPath()).absoluteFilePath(normalizedPath); @@ -2114,7 +2111,7 @@ namespace AssetProcessor // Check whether another job emitted this job as a job dependency and if true, queue the dependent job source file also JobDesc jobDesc(jobDetails.m_jobEntry.m_databaseSourceName.toUtf8().data(), jobDetails.m_jobEntry.m_jobKey.toUtf8().data(), jobDetails.m_jobEntry.m_platformInfo.m_identifier); - + shouldProcessAsset = true; QFileInfo file(jobDetails.m_jobEntry.GetAbsoluteSourcePath()); QDateTime dateTime(file.lastModified()); @@ -2347,7 +2344,7 @@ namespace AssetProcessor } QString canonicalRootDir = AssetUtilities::NormalizeFilePath(m_cacheRootDir.canonicalPath()); - + FileExamineContainer swapped; m_filesToExamine.swap(swapped); // makes it okay to call CheckSource(...) @@ -2470,7 +2467,7 @@ namespace AssetProcessor AZ_TracePrintf(AssetProcessor::DebugChannel, "ProcessFilesToExamineQueue: Unable to find the relative path.\n"); continue; } - + const ScanFolderInfo* scanFolderInfo = m_platformConfig->GetScanFolderForFile(normalizedPath); relativePathToFile = databasePathToFile; @@ -2494,9 +2491,9 @@ namespace AssetProcessor QString::fromUtf8(jobInfo.m_watchFolder.c_str()), relativePathToFile, databasePathToFile, - jobInfo.m_builderGuid, - *platformFromInfo, - jobInfo.m_jobKey.c_str(), 0, GenerateNewJobRunKey(), + jobInfo.m_builderGuid, + *platformFromInfo, + jobInfo.m_jobKey.c_str(), 0, GenerateNewJobRunKey(), AZ::Uuid::CreateNull()); job.m_autoFail = true; @@ -2597,7 +2594,7 @@ namespace AssetProcessor { // on the other hand, if we found a file it means that a deleted file revealed a file that // was previously overridden by it. - // Because the deleted file may have "revealed" a file with different case, + // Because the deleted file may have "revealed" a file with different case, // we have to actually correct its case here. This is rare, so it should be reasonable // to call the expensive function to discover correct case. QString pathRelativeToScanFolder; @@ -2674,6 +2671,7 @@ namespace AssetProcessor AZ_TracePrintf(ConsoleChannel, "Builder optimization: %i / %i files required full analysis, %i sources found but not processed by anyone\n", m_numSourcesNeedingFullAnalysis, m_numTotalSourcesFound, m_numSourcesNotHandledByAnyBuilder); } + m_pathDependencyManager->ProcessQueuedDependencyResolves(); QTimer::singleShot(20, this, SLOT(RemoveEmptyFolders())); } else @@ -2739,7 +2737,7 @@ namespace AssetProcessor } // over here we also want to invalidate the metafiles on disk map if it COULD Be a metafile - // note that there is no reason to do an expensive exacting computation here, it will be + // note that there is no reason to do an expensive exacting computation here, it will be // done later and cached when m_cachedMetaFilesExistMap is set to false, we just need to // know if its POSSIBLE that its a metafile, cheaply. // if its a metafile match, then invalidate the metafile table. @@ -2752,7 +2750,7 @@ namespace AssetProcessor m_metaFilesWhichActuallyExistOnDisk.clear(); // invalidate the map, force a recompuation later. } } - + } m_AssetProcessorIsBusy = true; @@ -2927,7 +2925,7 @@ namespace AssetProcessor } AZ::u64 fileHash = AssetUtilities::GetFileHash(fileInfo.m_filePath.toUtf8().constData()); - + if(fileHash != databaseHashValue) { // File contents have changed @@ -3149,7 +3147,7 @@ namespace AssetProcessor { AddMetadataFilesForFingerprinting(kvp.first.c_str(), job.m_fingerprintFiles); } - + // Check the current builder jobs with the previous ones in the database: job.m_jobEntry.m_computedFingerprint = AssetUtilities::GenerateFingerprint(job); JobIndentifier jobIndentifier(JobDesc(job.m_jobEntry.m_databaseSourceName.toUtf8().data(), job.m_jobEntry.m_jobKey.toUtf8().data(), job.m_jobEntry.m_platformInfo.m_identifier), job.m_jobEntry.m_builderGuid); @@ -3208,7 +3206,7 @@ namespace AssetProcessor { // If the database knows about the job than it implies that AP has processed it sucessfully at least once // and therefore the dependent job should not cause the job which depends on it to be processed again. - // If however we find a dependent job which is not known to AP then we know this job needs to be processed + // If however we find a dependent job which is not known to AP then we know this job needs to be processed // after all the dependent jobs have completed at least once. AzToolsFramework::AssetDatabase::JobDatabaseEntryContainer jobs; @@ -3238,7 +3236,7 @@ namespace AssetProcessor } else if(sourceFileDependency.m_sourceDependencyType != AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards) { - AZ_TracePrintf(AssetProcessor::ConsoleChannel, "UpdateJobDependency: Failed to find builder dependency for %s job (%s, %s, %s)\n", + AZ_TracePrintf(AssetProcessor::ConsoleChannel, "UpdateJobDependency: Failed to find builder dependency for %s job (%s, %s, %s)\n", job.m_jobEntry.GetAbsoluteSourcePath().toUtf8().constData(), jobDependencyInternal->m_jobDependency.m_sourceFile.m_sourceFileDependencyPath.c_str(), jobDependencyInternal->m_jobDependency.m_jobKey.c_str(), @@ -3262,7 +3260,7 @@ namespace AssetProcessor ++jobDependencySlot; } - // sorting job dependencies as they can effect the fingerprint of the job + // sorting job dependencies as they can effect the fingerprint of the job AZStd::sort(job.m_jobDependencyList.begin(), job.m_jobDependencyList.end(), [](const AssetProcessor::JobDependencyInternal& lhs, const AssetProcessor::JobDependencyInternal& rhs) { @@ -3289,7 +3287,7 @@ namespace AssetProcessor for (const JobDependencyInternal& jobDependencyInternal : job.m_jobDependencyList) { // Loop over all the builderUuid and check whether the corresponding entry exists in the jobsFingerprint map. - // If an entry exists, it implies than we have already send the job over to the RCController + // If an entry exists, it implies than we have already send the job over to the RCController for (auto builderIter = jobDependencyInternal.m_builderUuidList.begin(); builderIter != jobDependencyInternal.m_builderUuidList.end(); ++builderIter) { JobIndentifier jobIdentifier(JobDesc(jobDependencyInternal.m_jobDependency.m_sourceFile.m_sourceFileDependencyPath, @@ -3299,7 +3297,7 @@ namespace AssetProcessor auto jobFound = m_jobFingerprintMap.find(jobIdentifier); if (jobFound == m_jobFingerprintMap.end()) { - // Job cannot be processed, since one of its dependent job hasn't been fingerprinted + // Job cannot be processed, since one of its dependent job hasn't been fingerprinted return false; } } @@ -3317,7 +3315,7 @@ namespace AssetProcessor // and call the CreateJobs function on the builder. // it bundles the results up in a JobToProcessEntry struct, while it is doing this: JobToProcessEntry entry; - + AZ::Uuid sourceUUID = AssetUtilities::CreateSafeSourceUUIDFromName(databasePathToFile.toUtf8().constData()); // first, we put the source UUID in the map so that its present for any other queries: @@ -3375,14 +3373,14 @@ namespace AssetProcessor builderInfo.m_createJobFunction(createJobsRequest, createJobsResponse); AssetProcessor::StatsCapture::EndCaptureStat(statKey.toUtf8().constData()); } - + AssetProcessor::SetThreadLocalJobId(0); bool isBuilderMissingFingerprint = (createJobsResponse.m_result == AssetBuilderSDK::CreateJobsResultCode::Success && !createJobsResponse.m_createJobOutputs.empty() && !createJobsResponse.m_createJobOutputs[0].m_additionalFingerprintInfo.empty() && builderInfo.m_analysisFingerprint.empty()); - + if (createJobsResponse.m_result == AssetBuilderSDK::CreateJobsResultCode::Failed || isBuilderMissingFingerprint) { AZ_TracePrintf(AssetProcessor::ConsoleChannel, "Createjobs Failed: %s.\n", normalizedPath.toUtf8().constData()); @@ -3393,7 +3391,7 @@ namespace AssetProcessor char resolvedBuffer[AZ_MAX_PATH_LEN] = { 0 }; AZ::IO::FileIOBase::GetInstance()->ResolvePath(fullPathToLogFile.c_str(), resolvedBuffer, AZ_MAX_PATH_LEN); - + JobDetails jobdetail; jobdetail.m_jobEntry = JobEntry( scanFolder->ScanPath(), @@ -3486,9 +3484,9 @@ namespace AssetProcessor scanFolder->ScanPath(), actualRelativePath, databasePathToFile, - builderInfo.m_busId, - *infoForPlatform, - jobDescriptor.m_jobKey.c_str(), 0, GenerateNewJobRunKey(), + builderInfo.m_busId, + *infoForPlatform, + jobDescriptor.m_jobKey.c_str(), 0, GenerateNewJobRunKey(), sourceUUID); newJob.m_jobEntry.m_checkExclusiveLock = jobDescriptor.m_checkExclusiveLock; newJob.m_jobParam = AZStd::move(jobDescriptor.m_jobParameters); @@ -3506,7 +3504,7 @@ namespace AssetProcessor newJob.m_jobDependencyList.push_back(JobDependencyInternal(jobDependency)); ++numJobDependencies; } - + // note that until analysis completes, the jobId is not set and neither is the destination pat JobDesc jobDesc(newJob.m_jobEntry.m_databaseSourceName.toUtf8().data(), newJob.m_jobEntry.m_jobKey.toUtf8().data(), newJob.m_jobEntry.m_platformInfo.m_identifier); m_jobDescToBuilderUuidMap[jobDesc].insert(builderInfo.m_busId); @@ -3515,7 +3513,7 @@ namespace AssetProcessor JobIndentifier jobIdentifier(jobDesc, builderInfo.m_busId); { AZStd::lock_guard lock(AssetProcessor::ProcessingJobInfoBus::GetOrCreateContext().m_contextMutex); - m_jobFingerprintMap.erase(jobIdentifier); + m_jobFingerprintMap.erase(jobIdentifier); } entry.m_jobsToAnalyze.push_back(AZStd::move(newJob)); @@ -3578,7 +3576,7 @@ namespace AssetProcessor // instead of a UUID, a path has been provided, prepare and use that. We need to turn it into a database path QString encodedFileData = QString::fromUtf8(sourceDependency.m_sourceFileDependencyPath.c_str()); encodedFileData = AssetUtilities::NormalizeFilePath(encodedFileData); - + if (sourceDependency.m_sourceDependencyType == AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards) { int wildcardIndex = encodedFileData.indexOf("*"); @@ -3653,7 +3651,7 @@ namespace AssetProcessor } // Convert to relative paths - for (auto dependencyItr = resolvedDependencyList.begin(); dependencyItr != resolvedDependencyList.end();) + for (auto dependencyItr = resolvedDependencyList.begin(); dependencyItr != resolvedDependencyList.end();) { QString relativePath, scanFolder; if (m_platformConfig->ConvertToRelativePath(*dependencyItr, relativePath, scanFolder)) @@ -3705,7 +3703,7 @@ namespace AssetProcessor return (!resultDatabaseSourceName.isEmpty()); } - + void AssetProcessorManager::UpdateSourceFileDependenciesDatabase(JobToProcessEntry& entry) { using namespace AzToolsFramework::AssetDatabase; @@ -3738,7 +3736,7 @@ namespace AssetProcessor QString resolvedDatabaseName; if (!ResolveSourceFileDependencyPath(sourceDependency.second, resolvedDatabaseName,resolvedDependencyList)) { - // ResolveDependencyPath should only fail in a data error, otherwise it always outputs something, + // ResolveDependencyPath should only fail in a data error, otherwise it always outputs something, // even if that something starts with the placeholder. continue; } @@ -3759,7 +3757,7 @@ namespace AssetProcessor SourceFileDependencyEntry newDependencyEntry( sourceDependency.first, entry.m_sourceFileInfo.m_databasePath.toUtf8().constData(), - resolvedDatabaseName.toUtf8().constData(), + resolvedDatabaseName.toUtf8().constData(), sourceDependency.second.m_sourceDependencyType == AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards ? SourceFileDependencyEntry::DEP_SourceLikeMatch : SourceFileDependencyEntry::DEP_SourceToSource, !sourceDependency.second.m_sourceFileDependencyUUID.IsNull()); // If the UUID is null, then record that this dependency came from a (resolved) path newDependencies.push_back(AZStd::move(newDependencyEntry)); @@ -3803,7 +3801,7 @@ namespace AssetProcessor } // get all the old dependencies and remove them. This function is comprehensive on all dependencies - // for a given source file so we can just eliminate all of them from that same source file and replace + // for a given source file so we can just eliminate all of them from that same source file and replace // them with all of the new ones for the given source file: AZStd::unordered_set oldDependencies; m_stateData->QueryDependsOnSourceBySourceDependency( @@ -4018,7 +4016,7 @@ namespace AssetProcessor result.m_watchFolder = QString::fromUtf8(scanFolder.m_scanFolder.c_str()); result.m_sourceRelativeToWatchFolder = result.m_sourceDatabaseName; - { + { // this scope exists to restrict the duration of the below lock. AZStd::lock_guard lock(m_sourceUUIDToSourceInfoMapMutex); m_sourceUUIDToSourceInfoMap.insert(AZStd::make_pair(sourceUuid, result)); @@ -4045,9 +4043,9 @@ namespace AssetProcessor auto jobPair = m_jobsToProcess.insert(AZStd::move(jobDetail)); if (!jobPair.second) { - // if we are here it means that this job was already found in the jobs to process list + // if we are here it means that this job was already found in the jobs to process list // and therefore insert failed, we will try to update the iterator manually here. - // Note that if insert fails the original object is not destroyed and therefore we can use move again. + // Note that if insert fails the original object is not destroyed and therefore we can use move again. // we just replaced a job, so we have to decrement its count. UpdateAnalysisTrackerForFile(jobPair.first->m_jobEntry, AnalysisTrackerUpdateType::JobFinished); @@ -4068,7 +4066,7 @@ namespace AssetProcessor QSet absoluteSourceFilePathQueue; QString databasePath; QString scanFolder; - + auto callbackFunction = [this, &absoluteSourceFilePathQueue](SourceFileDependencyEntry& entry) { QString relativeDatabaseName = QString::fromUtf8(entry.m_source.c_str()); @@ -4111,7 +4109,7 @@ namespace AssetProcessor sourceDatabaseEntry.m_sourceName = relativeSourceFilePath.toUtf8().constData(); sourceDatabaseEntry.m_sourceGuid = AssetUtilities::CreateSafeSourceUUIDFromName(sourceDatabaseEntry.m_sourceName.c_str()); - + if (!m_stateData->SetSource(sourceDatabaseEntry)) { AZ_Error(AssetProcessor::ConsoleChannel, false, "Failed to add source to the database!!!"); @@ -4260,7 +4258,7 @@ namespace AssetProcessor { AZ_TracePrintf(DebugChannel, "Builder %s analysis fingerprint changed. Files assigned to it will be re-analyzed.\n", priorBuilderUUID.ToString().c_str()); } - + if (builderIsDirty) { m_anyBuilderChange = true; @@ -4414,7 +4412,7 @@ namespace AssetProcessor source.m_analysisFingerprint.append(builderFP.ToString()); } - m_pathDependencyManager->RetryDeferredDependencies(source); + m_pathDependencyManager->QueueSourceForDependencyResolution(source); m_stateData->SetSource(source); databaseSourceName = source.m_sourceName.c_str(); @@ -4593,7 +4591,7 @@ namespace AssetProcessor { continue; } - + QString firstMatchingFile = m_platformConfig->FindFirstMatchingFile(dep); if (firstMatchingFile.isEmpty()) { @@ -4787,7 +4785,7 @@ namespace AssetProcessor assetIter->m_entry.m_sourceFileUUID); jobdetail.m_autoFail = true; jobdetail.m_critical = true; - jobdetail.m_priority = INT_MAX; // front of the queue. + jobdetail.m_priority = INT_MAX; // front of the queue. jobdetail.m_scanFolder = m_platformConfig->GetScanFolderForFile(assetIter->m_entry.GetAbsoluteSourcePath()); // the new lines make it easier to copy and paste the file names. jobdetail.m_jobParam[AZ_CRC(AutoFailReasonKey)] = autoFailReason; @@ -4859,6 +4857,6 @@ namespace AssetProcessor return filesFound; } - + } // namespace AssetProcessor diff --git a/Code/Tools/AssetProcessor/native/tests/BaseAssetProcessorTest.h b/Code/Tools/AssetProcessor/native/tests/BaseAssetProcessorTest.h index 71d3fa0f6d..be7e78d097 100644 --- a/Code/Tools/AssetProcessor/native/tests/BaseAssetProcessorTest.h +++ b/Code/Tools/AssetProcessor/native/tests/BaseAssetProcessorTest.h @@ -40,12 +40,14 @@ protected: void SetupEnvironment() override { // Setup code + AZ::Environment::Create(nullptr); qInstallMessageHandler(UnitTestMessageHandler); } void TeardownEnvironment() override { qInstallMessageHandler(nullptr); + AZ::Environment::Destroy(); } private: diff --git a/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp b/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp index b20d373307..1d6e92e47e 100644 --- a/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp +++ b/Code/Tools/AssetProcessor/native/tests/PathDependencyManagerTests.cpp @@ -12,13 +12,23 @@ #include "AzToolsFramework/API/AssetDatabaseBus.h" #include "AssetDatabase/AssetDatabase.h" #include +#include +#include +#include +#include namespace UnitTests { class MockDatabaseLocationListener : public AzToolsFramework::AssetDatabase::AssetDatabaseRequests::Bus::Handler { public: - MOCK_METHOD1(GetAssetDatabaseLocation, bool(AZStd::string&)); + bool GetAssetDatabaseLocation(AZStd::string& location) override + { + location = m_databaseLocation; + return true; + } + + AZStd::string m_databaseLocation; }; namespace Util @@ -38,25 +48,45 @@ namespace UnitTests } } - struct PathDependencyDeletionTest - : UnitTest::ScopedAllocatorSetupFixture - , UnitTest::TraceBusRedirector + struct PathDependencyBase + : UnitTest::TraceBusRedirector { - void SetUp() override; - void TearDown() override; + void Init(); + void Destroy(); QTemporaryDir m_tempDir; AZStd::string m_databaseLocation; - ::testing::NiceMock m_databaseLocationListener; + MockDatabaseLocationListener m_databaseLocationListener; AZStd::shared_ptr m_stateData; AZStd::unique_ptr m_platformConfig; + AZStd::unique_ptr m_serializeContext; + AZ::Entity* m_jobManagerEntity{}; + AZ::ComponentDescriptor* m_descriptor{}; }; - void PathDependencyDeletionTest::SetUp() + struct PathDependencyDeletionTest + : UnitTest::ScopedAllocatorSetupFixture + , PathDependencyBase + { + void SetUp() override + { + PathDependencyBase::Init(); + } + + void TearDown() override + { + PathDependencyBase::Destroy(); + } + }; + + void PathDependencyBase::Init() { using namespace ::testing; using namespace AzToolsFramework::AssetDatabase; + ::UnitTest::TestRunner::Instance().m_suppressAsserts = false; + ::UnitTest::TestRunner::Instance().m_suppressErrors = false; + BusConnect(); QDir tempPath(m_tempDir.path()); @@ -68,21 +98,39 @@ namespace UnitTests // ":memory:" databases are one-instance-only, and even if another connection is opened to ":memory:" it would // not share with others created using ":memory:" and get a unique database instead. m_databaseLocation = tempPath.absoluteFilePath("test_database.sqlite").toUtf8().constData(); - - ON_CALL(m_databaseLocationListener, GetAssetDatabaseLocation(_)) - .WillByDefault( - DoAll( // set the 0th argument ref (string) to the database location and return true. - SetArgReferee<0>(m_databaseLocation), - Return(true))); + m_databaseLocationListener.m_databaseLocation = m_databaseLocation; m_stateData = AZStd::shared_ptr(new AssetProcessor::AssetDatabaseConnection()); m_stateData->OpenDatabase(); m_platformConfig = AZStd::make_unique(); + + AZ::AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(); + + m_serializeContext = AZStd::make_unique(); + m_descriptor = AZ::JobManagerComponent::CreateDescriptor(); + m_descriptor->Reflect(m_serializeContext.get()); + + m_jobManagerEntity = aznew AZ::Entity{}; + m_jobManagerEntity->CreateComponent(); + m_jobManagerEntity->Init(); + m_jobManagerEntity->Activate(); } - void PathDependencyDeletionTest::TearDown() + void PathDependencyBase::Destroy() { + m_stateData = nullptr; + m_platformConfig = nullptr; + + m_jobManagerEntity->Deactivate(); + delete m_jobManagerEntity; + + delete m_descriptor; + + AZ::AllocatorInstance::Destroy(); + AZ::AllocatorInstance::Destroy(); + BusDisconnect(); } @@ -91,7 +139,7 @@ namespace UnitTests using namespace AzToolsFramework::AssetDatabase; // Add a product to the db with an unmet dependency - ScanFolderDatabaseEntry scanFolder("folder", "test", "test", ""); + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); m_stateData->SetScanFolder(scanFolder); SourceDatabaseEntry source1, source2; @@ -110,7 +158,8 @@ namespace UnitTests Util::CreateSourceJobAndProduct(m_stateData.get(), scanFolder.m_scanFolderID, source2, job2, product2, "source2.txt", "product2.jpg"); - manager.RetryDeferredDependencies(source2); + manager.QueueSourceForDependencyResolution(source2); + manager.ProcessQueuedDependencyResolves(); } TEST_F(PathDependencyDeletionTest, ExistingSourceWithUnmetDependency_RemovedFromDB_DependentProductCreatedWithoutError) @@ -118,7 +167,7 @@ namespace UnitTests using namespace AzToolsFramework::AssetDatabase; // Add a product to the db with an unmet dependency - ScanFolderDatabaseEntry scanFolder("folder", "test", "test", ""); + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); m_stateData->SetScanFolder(scanFolder); SourceDatabaseEntry source1, source2; @@ -137,7 +186,8 @@ namespace UnitTests Util::CreateSourceJobAndProduct(m_stateData.get(), scanFolder.m_scanFolderID, source2, job2, product2, "source2.txt", "product2.jpg"); - manager.RetryDeferredDependencies(source2); + manager.QueueSourceForDependencyResolution(source2); + manager.ProcessQueuedDependencyResolves(); } TEST_F(PathDependencyDeletionTest, NewSourceWithUnmetDependency_RemovedFromDB_DependentSourceCreatedWithoutError) @@ -147,7 +197,7 @@ namespace UnitTests AssetProcessor::PathDependencyManager manager(m_stateData, m_platformConfig.get()); // Add a product to the db with an unmet dependency - ScanFolderDatabaseEntry scanFolder("folder", "test", "test", ""); + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); m_stateData->SetScanFolder(scanFolder); SourceDatabaseEntry source1, source2; @@ -166,7 +216,8 @@ namespace UnitTests Util::CreateSourceJobAndProduct(m_stateData.get(), scanFolder.m_scanFolderID, source2, job2, product2, "source2.txt", "product2.jpg"); - manager.RetryDeferredDependencies(source2); + manager.QueueSourceForDependencyResolution(source2); + manager.ProcessQueuedDependencyResolves(); } TEST_F(PathDependencyDeletionTest, NewSourceWithUnmetDependency_RemovedFromDB_DependentProductCreatedWithoutError) @@ -176,7 +227,7 @@ namespace UnitTests AssetProcessor::PathDependencyManager manager(m_stateData, m_platformConfig.get()); // Add a product to the db with an unmet dependency - ScanFolderDatabaseEntry scanFolder("folder", "test", "test", ""); + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); m_stateData->SetScanFolder(scanFolder); SourceDatabaseEntry source1, source2; @@ -195,7 +246,8 @@ namespace UnitTests Util::CreateSourceJobAndProduct(m_stateData.get(), scanFolder.m_scanFolderID, source2, job2, product2, "source2.txt", "product2.jpg"); - manager.RetryDeferredDependencies(source2); + manager.QueueSourceForDependencyResolution(source2); + manager.ProcessQueuedDependencyResolves(); } TEST_F(PathDependencyDeletionTest, NewSourceWithUnmetDependency_Wildcard_RemovedFromDB_DependentSourceCreatedWithoutError) @@ -205,7 +257,7 @@ namespace UnitTests AssetProcessor::PathDependencyManager manager(m_stateData, m_platformConfig.get()); // Add a product to the db with an unmet dependency - ScanFolderDatabaseEntry scanFolder("folder", "test", "test", ""); + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); m_stateData->SetScanFolder(scanFolder); SourceDatabaseEntry source1, source2; @@ -224,6 +276,266 @@ namespace UnitTests Util::CreateSourceJobAndProduct(m_stateData.get(), scanFolder.m_scanFolderID, source2, job2, product2, "source2.txt", "product2.jpg"); - manager.RetryDeferredDependencies(source2); + manager.QueueSourceForDependencyResolution(source2); + manager.ProcessQueuedDependencyResolves(); } + + using PathDependencyTests = PathDependencyDeletionTest; + + TEST_F(PathDependencyTests, SourceAndProductHaveSameName_SourceFileDependency_MatchesSource) + { + using namespace AzToolsFramework::AssetDatabase; + + AssetProcessor::PathDependencyManager manager(m_stateData, m_platformConfig.get()); + + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); + m_stateData->SetScanFolder(scanFolder); + + SourceDatabaseEntry source1, source2; + JobDatabaseEntry job1, job2; + ProductDatabaseEntry product1, product2, product3; + + Util::CreateSourceJobAndProduct( + m_stateData.get(), scanFolder.m_scanFolderID, source1, job1, product1, "source1.txt", "product1.jpg"); + + AssetBuilderSDK::ProductPathDependencySet set; + set.insert(AssetBuilderSDK::ProductPathDependency("*.xml", AssetBuilderSDK::ProductPathDependencyType::SourceFile)); + + manager.SaveUnresolvedDependenciesToDatabase(set, product1, "pc"); + + Util::CreateSourceJobAndProduct( + m_stateData.get(), scanFolder.m_scanFolderID, source2, job2, product2, "source2.xml", "source2.xml"); + + // Create a 2nd product for this source + product3 = ProductDatabaseEntry{ job2.m_jobID, product2.m_subID + 1, "source2.txt", AZ::Data::AssetType::CreateRandom() }; + ASSERT_TRUE(m_stateData->SetProduct(product3)); + + manager.QueueSourceForDependencyResolution(source2); + manager.ProcessQueuedDependencyResolves(); + + ProductDependencyDatabaseEntryContainer productDependencies; + m_stateData->GetProductDependencies(productDependencies); + + EXPECT_EQ(productDependencies.size(), 3); + } + + TEST_F(PathDependencyTests, SourceAndProductHaveSameName_ProductFileDependency_MatchesProduct) + { + using namespace AzToolsFramework::AssetDatabase; + + AssetProcessor::PathDependencyManager manager(m_stateData, m_platformConfig.get()); + + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); + m_stateData->SetScanFolder(scanFolder); + + SourceDatabaseEntry source1, source2; + JobDatabaseEntry job1, job2; + ProductDatabaseEntry product1, product2, product3; + + Util::CreateSourceJobAndProduct( + m_stateData.get(), scanFolder.m_scanFolderID, source1, job1, product1, "source1.txt", "product1.jpg"); + + AssetBuilderSDK::ProductPathDependencySet set; + set.insert(AssetBuilderSDK::ProductPathDependency("*.xml", AssetBuilderSDK::ProductPathDependencyType::ProductFile)); + + manager.SaveUnresolvedDependenciesToDatabase(set, product1, "pc"); + + Util::CreateSourceJobAndProduct( + m_stateData.get(), scanFolder.m_scanFolderID, source2, job2, product2, "source2.xml", "source2.xml"); + + // Create a 2nd product for this source + product3 = ProductDatabaseEntry{job2.m_jobID, product2.m_subID + 1, "source2.txt", AZ::Data::AssetType::CreateRandom()}; + ASSERT_TRUE(m_stateData->SetProduct(product3)); + + manager.QueueSourceForDependencyResolution(source2); + manager.ProcessQueuedDependencyResolves(); + + ProductDependencyDatabaseEntryContainer productDependencies; + m_stateData->GetProductDependencies(productDependencies); + + EXPECT_EQ(productDependencies.size(), 2); + } + + struct PathDependencyBenchmarks + : UnitTest::ScopedAllocatorFixture + , PathDependencyBase + { + static inline constexpr int NumTestDependencies = 4; // Must be a multiple of 4 + static inline constexpr int NumTestProducts = 2; // Must be a multiple of 2 + + AzToolsFramework::AssetDatabase::ProductDatabaseEntryContainer m_products; + AzToolsFramework::AssetDatabase::SourceDatabaseEntry m_source1, m_source2, m_source4; + AzToolsFramework::AssetDatabase::JobDatabaseEntry m_job1, m_job2, m_job4; + AzToolsFramework::AssetDatabase::ProductDatabaseEntry m_product1, m_product2, m_product4; + AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer m_dependencies; + + void SetupTestData() + { + using namespace AzToolsFramework::AssetDatabase; + + ScanFolderDatabaseEntry scanFolder("folder", "test", "test", 0); + ASSERT_TRUE(m_stateData->SetScanFolder(scanFolder)); + + Util::CreateSourceJobAndProduct( + m_stateData.get(), scanFolder.m_scanFolderID, m_source1, m_job1, m_product1, "source1.txt", "product1.jpg"); + + Util::CreateSourceJobAndProduct( + m_stateData.get(), scanFolder.m_scanFolderID, m_source4, m_job4, m_product4, "source4.txt", "product4.jpg"); + + for (int i = 0; i < NumTestDependencies / 2; ++i) + { + m_dependencies.emplace_back( + m_product1.m_productID, AZ::Uuid::CreateNull(), 0, 0, "pc", 0, + AZStd::string::format("folder/folder2/%d_*2.jpg", i).c_str()); + ++i; + m_dependencies.emplace_back( + m_product1.m_productID, AZ::Uuid::CreateNull(), 0, 0, "mac", 0, + AZStd::string::format("folder/folder2/%d_*2.jpg", i).c_str()); + } + + for (int i = 0; i < NumTestDependencies / 2; ++i) + { + m_dependencies.emplace_back( + m_product4.m_productID, AZ::Uuid::CreateNull(), 0, 0, "pc", 0, + AZStd::string::format("folder/folder2/%d_*2.jpg", i).c_str()); + ++i; + m_dependencies.emplace_back( + m_product4.m_productID, AZ::Uuid::CreateNull(), 0, 0, "mac", 0, + AZStd::string::format("folder/folder2/%d_*2.jpg", i).c_str()); + } + + ASSERT_TRUE(m_stateData->SetProductDependencies(m_dependencies)); + + Util::CreateSourceJobAndProduct( + m_stateData.get(), scanFolder.m_scanFolderID, m_source2, m_job2, m_product2, "source2.txt", "product2.jpg"); + + auto job3 = JobDatabaseEntry( + m_source2.m_sourceID, "jobkey", 1111, "mac", AZ::Uuid::CreateRandom(), AzToolsFramework::AssetSystem::JobStatus::Completed, + 4444); + ASSERT_TRUE(m_stateData->SetJob(job3)); + + for (int i = 0; i < NumTestProducts; ++i) + { + m_products.emplace_back( + m_job2.m_jobID, i, AZStd::string::format("pc/folder/folder2/%d_product2.jpg", i).c_str(), + AZ::Data::AssetType::CreateRandom()); + ++i; + m_products.emplace_back( + job3.m_jobID, i, AZStd::string::format("mac/folder/folder2/%d_product2.jpg", i).c_str(), + AZ::Data::AssetType::CreateRandom()); + } + + ASSERT_TRUE(m_stateData->SetProducts(m_products)); + } + + void DoTest() + { + AssetProcessor::PathDependencyManager manager(m_stateData, m_platformConfig.get()); + + manager.QueueSourceForDependencyResolution(m_source2); + manager.ProcessQueuedDependencyResolves(); + } + + void VerifyResult() + { + using namespace AzToolsFramework::AssetDatabase; + + ProductDependencyDatabaseEntryContainer productDependencies; + m_stateData->GetProductDependencies(productDependencies); + + for (int i = 0; i < NumTestDependencies / 2 && i < NumTestProducts; ++i) + { + const auto& product = m_products[i]; + int found = 0; + + for (const auto& unresolvedProductDependency : productDependencies) + { + if (unresolvedProductDependency.m_dependencySourceGuid == m_source2.m_sourceGuid && + unresolvedProductDependency.m_dependencySubID == product.m_subID && + unresolvedProductDependency.m_productPK == m_product1.m_productID) + { + ++found; + } + + if (unresolvedProductDependency.m_dependencySourceGuid == m_source2.m_sourceGuid && + unresolvedProductDependency.m_dependencySubID == product.m_subID && + unresolvedProductDependency.m_productPK == m_product4.m_productID) + { + ++found; + } + + if (found == 2) + break; + } + + EXPECT_TRUE(found == 2) << product.m_productName.c_str() << " was not found"; + } + + EXPECT_EQ(productDependencies.size(), NumTestDependencies * 2); + } + }; + + // For some reason, BENCHMARK_F doesn't seem to call the destructor + // So we'll wrap the class and handle the new/delete ourselves + struct PathDependencyBenchmarksWrapperClass : public ::benchmark::Fixture + { + void SetUp([[maybe_unused]] const benchmark::State& st) override + { + m_benchmarks = new PathDependencyBenchmarks(); + m_benchmarks->Init(); + m_benchmarks->SetupTestData(); + } + + void SetUp([[maybe_unused]] benchmark::State& st) override + { + m_benchmarks = new PathDependencyBenchmarks(); + m_benchmarks->Init(); + m_benchmarks->SetupTestData(); + } + + void TearDown([[maybe_unused]] benchmark::State& st) override + { + m_benchmarks->Destroy(); + delete m_benchmarks; + } + + void TearDown([[maybe_unused]] const benchmark::State& st) override + { + m_benchmarks->Destroy(); + delete m_benchmarks; + } + + PathDependencyBenchmarks* m_benchmarks = {}; + }; + + struct PathDependencyTestValidation + : PathDependencyBenchmarks, ::testing::Test + { + void SetUp() override + { + PathDependencyBase::Init(); + } + void TearDown() override + { + PathDependencyBase::Destroy(); + } + }; + + TEST_F(PathDependencyTestValidation, DeferredWildcardDependencyResolution) + { + SetupTestData(); + DoTest(); + VerifyResult(); + } + + BENCHMARK_F(PathDependencyBenchmarksWrapperClass, BM_DeferredWildcardDependencyResolution)(benchmark::State& state) + { + for (auto _ : state) + { + m_benchmarks->m_stateData->SetProductDependencies(m_benchmarks->m_dependencies); + + m_benchmarks->DoTest(); + } + } + } diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp index 58f76f8da6..0908d0fdb9 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.cpp @@ -15,6 +15,10 @@ #include #include +#include +#include +#include +#include using namespace AssetProcessor; @@ -26,6 +30,7 @@ public: friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies); friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_DeferredResolution); + friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, SameFilenameForAllPlatforms); friend class GTEST_TEST_CLASS_NAME_(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath); @@ -176,8 +181,21 @@ void AssetProcessorManagerTest::SetUp() AssetProcessorTest::SetUp(); + AZ::AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(); + m_data = AZStd::make_unique(); + m_data->m_serializeContext = AZStd::make_unique(); + + m_data->m_descriptor = AZ::JobManagerComponent::CreateDescriptor(); + m_data->m_descriptor->Reflect(m_data->m_serializeContext.get()); + + m_data->m_jobManagerEntity = aznew AZ::Entity{}; + m_data->m_jobManagerEntity->CreateComponent(); + m_data->m_jobManagerEntity->Init(); + m_data->m_jobManagerEntity->Activate(); + m_config.reset(new AssetProcessor::PlatformConfiguration()); m_mockApplicationManager.reset(new AssetProcessor::MockApplicationManager()); @@ -256,6 +274,10 @@ void AssetProcessorManagerTest::SetUp() void AssetProcessorManagerTest::TearDown() { + m_data->m_jobManagerEntity->Deactivate(); + delete m_data->m_jobManagerEntity; + delete m_data->m_descriptor; + m_data = nullptr; QObject::disconnect(m_idleConnection); @@ -271,6 +293,9 @@ void AssetProcessorManagerTest::TearDown() m_qApp.reset(); m_scopeDir.reset(); + AZ::AllocatorInstance::Destroy(); + AZ::AllocatorInstance::Destroy(); + AssetProcessor::AssetProcessorTest::TearDown(); } @@ -1270,7 +1295,8 @@ TEST_F(AbsolutePathProductDependencyTest, AbsolutePathProductDependency_RetryDef AZ::Data::AssetType::CreateNull()); m_assetProcessorManager->m_stateData->SetProduct(matchingProductForDependency); - m_assetProcessorManager->m_pathDependencyManager->RetryDeferredDependencies(matchingSource); + m_assetProcessorManager->m_pathDependencyManager->QueueSourceForDependencyResolution(matchingSource); + m_assetProcessorManager->m_pathDependencyManager->ProcessQueuedDependencyResolves(); // The product dependency ID shouldn't change when it goes from unresolved to resolved. AZStd::vector resolvedProductDependencies; @@ -1405,6 +1431,7 @@ bool PathDependencyTest::ProcessAsset(TestAsset& asset, const OutputAssetSet& ou // tell the APM that the asset has been processed and allow it to bubble through its event queue: m_isIdling = false; m_assetProcessorManager->AssetProcessed(capturedDetails[jobSet].m_jobEntry, processJobResponse); + m_assetProcessorManager->CheckForIdle(); jobSet++; } @@ -2646,6 +2673,44 @@ TEST_F(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDepende ASSERT_NE(SearchDependencies(dependencyContainer, asset1.m_products[0]), SearchDependencies(dependencyContainer, asset1.m_products[1])); } +TEST_F(MultiplatformPathDependencyTest, SameFilenameForAllPlatforms) +{ + TestAsset asset2("asset2"); + bool result = ProcessAsset( + asset2, { { ".output" }, { ".output" } }, { { "*1.output", AssetBuilderSDK::ProductPathDependencyType::ProductFile } }, "subfolder1/", + ".txt"); + + ASSERT_TRUE(result); + + TestAsset asset1("asset1"); + result = ProcessAsset(asset1, { { ".output" }, { ".output" } }, {}); + + ASSERT_TRUE(result); + + AssetDatabaseConnection* sharedConnection = m_assetProcessorManager->m_stateData.get(); + ASSERT_TRUE(sharedConnection); + + AzToolsFramework::AssetDatabase::ProductDependencyDatabaseEntryContainer dependencyContainer; + + sharedConnection->GetProductDependencies(dependencyContainer); + int resolvedCount = 0; + int unresolvedCount = 0; + for (const auto& dep : dependencyContainer) + { + if (dep.m_unresolvedPath.empty()) + { + resolvedCount++; + } + else + { + unresolvedCount++; + } + } + ASSERT_EQ(resolvedCount, 2); + ASSERT_EQ(unresolvedCount, 2); + VerifyDependencies(dependencyContainer, { asset1.m_products[0], asset1.m_products[1] }, { "*1.output", "*1.output" }); +} + TEST_F(MultiplatformPathDependencyTest, AssetProcessed_Impl_MultiplatformDependencies_SourcePath) { // One product will be pc, one will be console (order is non-deterministic) @@ -4185,7 +4250,7 @@ TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeleteFails) auto theFile = m_data->m_absolutePath[1].toUtf8(); const char* theFileString = theFile.constData(); auto [sourcePath, productPath] = *m_data->m_productPaths.find(theFileString); - + { QFile file(theFileString); file.remove(); @@ -4257,7 +4322,7 @@ TEST_F(LockedFileTest, DeleteFile_LockedProduct_DeletesWhenReleased) EXPECT_FALSE(QFile::exists(productPath)); EXPECT_EQ(m_data->m_deletedSources.size(), 1); - + EXPECT_GT(m_deleteCounter, 1); // Make sure the AP tried more than once to delete the file m_errorAbsorber->ExpectAsserts(0); } @@ -5364,7 +5429,7 @@ AZStd::vector WildcardSourceDependencyTest::FileAddedTest(const Q void WildcardSourceDependencyTest::SetUp() { AssetProcessorManagerTest::SetUp(); - + QDir tempPath(m_tempDir.path()); // Add a non-recursive scan folder. Only files directly inside of this folder should be picked up, subfolders are ignored @@ -5454,7 +5519,7 @@ TEST_F(WildcardSourceDependencyTest, Relative_Broad) { // Expect all files except for the 2 invalid ones (e and f) AZStd::vector resolvedPaths; - + ASSERT_TRUE(Test("*.foo", resolvedPaths)); ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre("a.foo", "b.foo", "folder/one/c.foo", "folder/one/d.foo", "1a.foo", "1b.foo")); } @@ -5585,7 +5650,7 @@ TEST_F(WildcardSourceDependencyTest, Relative_CacheFolder) { AZStd::vector resolvedPaths; QDir tempPath(m_tempDir.path()); - + ASSERT_TRUE(Test("*cache.foo", resolvedPaths)); ASSERT_THAT(resolvedPaths, ::testing::UnorderedElementsAre()); } @@ -5635,7 +5700,7 @@ TEST_F(WildcardSourceDependencyTest, FilesRemovedAfterInitialCache) ASSERT_EQ(excludedFolders.size(), 3); } - + m_fileStateCache->SignalDeleteEvent(tempPath.absoluteFilePath("subfolder2/redirected/folder/two/ignored")); const auto& excludedFolders = excludedFolderCacheInterface->GetExcludedFolders(); diff --git a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h index 7bbef41f44..c532b08016 100644 --- a/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h +++ b/Code/Tools/AssetProcessor/native/tests/assetmanager/AssetProcessorManagerTest.h @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include #include "resourcecompiler/rccontroller.h" @@ -39,7 +41,7 @@ class AssetProcessorManagerTest : public AssetProcessor::AssetProcessorTest { public: - + AssetProcessorManagerTest(); virtual ~AssetProcessorManagerTest() @@ -67,16 +69,19 @@ protected: { AZStd::string m_databaseLocation; ::testing::NiceMock m_databaseLocationListener; + AZ::Entity* m_jobManagerEntity{}; + AZ::ComponentDescriptor* m_descriptor{}; + AZStd::unique_ptr m_serializeContext; }; AZStd::unique_ptr m_data; - + private: int m_argc; char** m_argv; AZStd::unique_ptr m_scopeDir; - AZStd::unique_ptr m_qApp; + AZStd::unique_ptr m_qApp; }; struct AbsolutePathProductDependencyTest diff --git a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp index 7543e9ec8b..c62d822171 100644 --- a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp @@ -51,7 +51,7 @@ namespace AssetProcessor case AZ::SettingsRegistryInterface::VisitAction::Begin: { // Only continue traversal if the path is exactly the AssetProcessorSettingsKey (which indicates the start of traversal) - // or if a "Platform *" object and it's children are being traversed + // or if a "Platform *" object and it's children are being traversed if (jsonPath == AssetProcessorSettingsKey) { return AZ::SettingsRegistryInterface::VisitResponse::Continue; @@ -631,7 +631,7 @@ namespace AssetProcessor for (const AssetBuilderSDK::PlatformInfo& platform : m_enabledPlatforms) { AZStd::string_view currentRCParams = assetRecognizer.m_defaultParams; - // The "/Amazon/AssetProcessor/Settings/RC */" entry will be queried + // The "/Amazon/AssetProcessor/Settings/RC */" entry will be queried AZ::IO::Path overrideParamsKey = AZ::IO::Path(AZ::IO::PosixPathSeparator); overrideParamsKey /= path; overrideParamsKey /= platform.m_identifier; @@ -644,7 +644,7 @@ namespace AssetProcessor } else { - // otherwise check for tags associated with the platform + // otherwise check for tags associated with the platform for (const AZStd::string& tag : platform.m_tags) { overrideParamsKey.ReplaceFilename(AZ::IO::PathView(tag)); @@ -1416,6 +1416,8 @@ namespace AssetProcessor return QString(); } + auto* fileStateInterface = AZ::Interface::Get(); + for (int pathIdx = 0; pathIdx < m_scanFolders.size(); ++pathIdx) { AssetProcessor::ScanFolderInfo scanFolderInfo = m_scanFolders[pathIdx]; @@ -1430,7 +1432,7 @@ namespace AssetProcessor QDir rooted(scanFolderInfo.ScanPath()); QString absolutePath = rooted.absoluteFilePath(tempRelativeName); AssetProcessor::FileStateInfo fileStateInfo; - auto* fileStateInterface = AZ::Interface::Get(); + if (fileStateInterface) { if (fileStateInterface->GetFileInfo(absolutePath, &fileStateInfo)) @@ -1499,7 +1501,7 @@ namespace AssetProcessor QRegExp nameMatch{ posixRelativeName, Qt::CaseInsensitive, QRegExp::Wildcard }; AZStd::stack dirs; dirs.push(sourceFolderDir.absolutePath()); - + while (!dirs.empty()) { QString absolutePath = dirs.top(); @@ -1528,7 +1530,7 @@ namespace AssetProcessor continue; } } - + QString pathMatch{ sourceFolderDir.relativeFilePath(dirIterator.filePath()) }; if (nameMatch.exactMatch(pathMatch)) { diff --git a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp index 6bcd0dec01..a6cbfd8077 100644 --- a/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/assetUtils.cpp @@ -131,7 +131,7 @@ namespace AssetUtilsInternal } } } while (!timer.hasExpired(waitTimeInSeconds * 1000)); //We will keep retrying until the timer has expired the inputted timeout - + // once we're done, regardless of success or failure, we 'unlock' those files for further process. // if we failed, also re-trigger them to rebuild (the bool param at the end of the ebus call) QString normalized = AssetUtilities::NormalizeFilePath(outputFile); @@ -870,23 +870,27 @@ namespace AssetUtilities return true; } - QString StripAssetPlatform(AZStd::string_view relativeProductPath) + AZStd::string_view StripAssetPlatformNoCopy(AZStd::string_view relativeProductPath) { // Skip over the assetPlatform path segment if it is matches one of the platform defaults // Otherwise return the path unchanged - AZStd::string_view strippedProductPath{ relativeProductPath }; - if (AZStd::optional pathSegment = AZ::StringFunc::TokenizeNext(strippedProductPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR); - pathSegment.has_value()) + + AZStd::string_view originalPath = relativeProductPath; + AZStd::optional firstPathSegment = AZ::StringFunc::TokenizeNext(relativeProductPath, AZ_CORRECT_AND_WRONG_FILESYSTEM_SEPARATOR); + + if (firstPathSegment && AzFramework::PlatformHelper::GetPlatformIdFromName(*firstPathSegment) != AzFramework::PlatformId::Invalid) { - AZ::IO::FixedMaxPathString assetPlatformSegmentLower{ *pathSegment }; - AZStd::to_lower(assetPlatformSegmentLower.begin(), assetPlatformSegmentLower.end()); - if (AzFramework::PlatformHelper::GetPlatformIdFromName(assetPlatformSegmentLower) != AzFramework::PlatformId::Invalid) - { - return QString::fromUtf8(strippedProductPath.data(), aznumeric_cast(strippedProductPath.size())); - } + return relativeProductPath; } - return QString::fromUtf8(relativeProductPath.data(), aznumeric_cast(relativeProductPath.size())); + return originalPath; + } + + QString StripAssetPlatform(AZStd::string_view relativeProductPath) + { + AZStd::string_view result = StripAssetPlatformNoCopy(relativeProductPath); + + return QString::fromUtf8(result.data(), aznumeric_cast(result.size())); } QString NormalizeFilePath(const QString& filePath) diff --git a/Code/Tools/AssetProcessor/native/utilities/assetUtils.h b/Code/Tools/AssetProcessor/native/utilities/assetUtils.h index 46ec5d6145..18cf5422de 100644 --- a/Code/Tools/AssetProcessor/native/utilities/assetUtils.h +++ b/Code/Tools/AssetProcessor/native/utilities/assetUtils.h @@ -145,7 +145,7 @@ namespace AssetUtilities //! Strips the first "asset platform" from the first path segment of a relative product path //! This is meant for removing the asset platform for paths such as "pc/MyAssetFolder/MyAsset.asset" //! Therefore the result here becomes "MyAssetFolder/MyAsset" - //! + //! //! Similarly invoking this function on relative path that begins with the "server" platform //! "server/AssetFolder/Server.asset2" -> "AssetFolder/Server.asset2" //! This function does not strip an asset platform from anywhere, but the first path segment @@ -153,6 +153,10 @@ namespace AssetUtilities //! would return a copy of the relative path QString StripAssetPlatform(AZStd::string_view relativeProductPath); + //! Same as StripAssetPlatform, but does not perform any string copies + //! The return result is only valid for as long as the original input is valid + AZStd::string_view StripAssetPlatformNoCopy(AZStd::string_view relativeProductPath); + //! Converts all slashes to forward slashes, removes double slashes, //! replaces all indirections such as '.' or '..' as appropriate. //! On windows, the drive letter (if present) is converted to uppercase. From 3f0bd9285372e41b3634b26aa9b342da9a527913 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 13 Jan 2022 10:28:58 -0600 Subject: [PATCH 073/108] Removed some unused EditorUtils functions Signed-off-by: Chris Galvan --- Code/Editor/Util/EditorUtils.cpp | 17 -- Code/Editor/Util/EditorUtils.h | 165 ------------------ .../Editor/Animation/Util/UiEditorUtils.cpp | 17 -- 3 files changed, 199 deletions(-) diff --git a/Code/Editor/Util/EditorUtils.cpp b/Code/Editor/Util/EditorUtils.cpp index adae34773a..47264a51ab 100644 --- a/Code/Editor/Util/EditorUtils.cpp +++ b/Code/Editor/Util/EditorUtils.cpp @@ -176,23 +176,6 @@ QString TrimTrailingZeros(QString str) return str; } -////////////////////////////////////////////////////////////////////////// -// This function is supposed to format float in user-friendly way, -// omitting the exponent notation. -// -// Why not using printf? Its formatting rules has following drawbacks: -// %g - will use exponent for small numbers; -// %.Nf - doesn't allow to control total amount of significant numbers, -// which exposes limited precision during binary-to-decimal fraction -// conversion. -////////////////////////////////////////////////////////////////////////// -void FormatFloatForUI(QString& str, int significantDigits, double value) -{ - str = TrimTrailingZeros(QString::number(value, 'f', significantDigits)); - return; -} -//////////////////////////////////////////////////////////////////////////- - ////////////////////////////////////////////////////////////////////////// QColor ColorLinearToGamma(ColorF col) { diff --git a/Code/Editor/Util/EditorUtils.h b/Code/Editor/Util/EditorUtils.h index e950d75012..5a69633d0f 100644 --- a/Code/Editor/Util/EditorUtils.h +++ b/Code/Editor/Util/EditorUtils.h @@ -212,22 +212,6 @@ namespace XmlHelpers ////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -// Drag Drop helper functions -////////////////////////////////////////////////////////////////////////// -namespace EditorDragDropHelpers -{ - inline QString GetAnimationNameClipboardFormat() - { - return QStringLiteral("application/x-animation-browser-copy"); - } - - inline QString GetFragmentClipboardFormat() - { - return QStringLiteral("application/x-preview-fragment-properties"); - } -} - ////////////////////////////////////////////////////////////////////////// /*! @@ -292,116 +276,6 @@ public: } }; - -////////////////////////////////////////////////////////////////////////// -// -// Convert String representation of color to RGB integer value. -// -////////////////////////////////////////////////////////////////////////// -inline QColor String2Color(const QString& val) -{ - unsigned int r = 0, g = 0, b = 0; - int res = 0; - res = azsscanf(val.toUtf8().data(), "R:%d,G:%d,B:%d", &r, &g, &b); - if (res != 3) - { - res = azsscanf(val.toUtf8().data(), "R:%d G:%d B:%d", &r, &g, &b); - } - if (res != 3) - { - res = azsscanf(val.toUtf8().data(), "%d,%d,%d", &r, &g, &b); - } - if (res != 3) - { - res = azsscanf(val.toUtf8().data(), "%d %d %d", &r, &g, &b); - } - if (res != 3) - { - azsscanf(val.toUtf8().data(), "%x", &r); - return r; - } - - return QColor(r, g, b); -} - -// Converts QColor to Vector. -inline Vec3 Rgb2Vec(const QColor& color) -{ - return Vec3(aznumeric_cast(color.redF()), aznumeric_cast(color.greenF()), aznumeric_cast(color.blueF())); -} - -// Converts QColor to ColorF. -inline ColorF Rgb2ColorF(const QColor& color) -{ - return ColorF(aznumeric_cast(color.redF()), aznumeric_cast(color.greenF()), aznumeric_cast(color.blueF()), 1.0f); -} - -// Converts QColor to Vector. -inline QColor Vec2Rgb(const Vec3& color) -{ - return QColor(aznumeric_cast(color.x * 255), aznumeric_cast(color.y * 255), aznumeric_cast(color.z * 255)); -} - -// Converts ColorF to QColor. -inline QColor ColorF2Rgb(const ColorF& color) -{ - return QColor(aznumeric_cast(color.r * 255), aznumeric_cast(color.g * 255), aznumeric_cast(color.b * 255)); -} - -////////////////////////////////////////////////////////////////////////// -// Tokenize string. -////////////////////////////////////////////////////////////////////////// -inline QString TokenizeString(const QString& s, LPCSTR pszTokens, int& iStart) -{ - assert(iStart >= 0); - - QByteArray str = s.toUtf8(); - - if (pszTokens == nullptr) - { - return str; - } - - auto pszPlace = str.begin() + iStart; - auto pszEnd = str.end(); - if (pszPlace < pszEnd) - { - int nIncluding = (int)strspn(pszPlace, pszTokens); - ; - - if ((pszPlace + nIncluding) < pszEnd) - { - pszPlace += nIncluding; - int nExcluding = (int)strcspn(pszPlace, pszTokens); - - int iFrom = iStart + nIncluding; - int nUntil = nExcluding; - iStart = iFrom + nUntil + 1; - - return (str.mid(iFrom, nUntil)); - } - } - - // return empty string, done tokenizing - iStart = -1; - return ""; -} - -// This template function will join strings from a vector into a single string, using a separator char -template -inline void JoinStrings(const QList& rStrings, QString& rDestStr, char aSeparator = ',') -{ - for (size_t i = 0, iCount = rStrings.size(); i < iCount; ++i) - { - rDestStr += rStrings[i]; - - if (i < iCount - 1) - { - rDestStr += aSeparator; - } - } -} - // This function will split a string containing separated strings, into a vector of strings // better version of TokenizeString inline void SplitString(const QString& rSrcStr, QStringList& rDestStrings, char aSeparator = ',') @@ -435,45 +309,6 @@ inline void SplitString(const QString& rSrcStr, QStringList& rDestStrings, char } } -// Format unsigned number to string with 1000s separator -inline QString FormatWithThousandsSeperator(const unsigned int number) -{ - QString string; - - string = QString::number(number); - - for (int p = string.length() - 3; p > 0; p -= 3) - { - string.insert(p, ','); - } - - return string; -} - - -void FormatFloatForUI(QString& str, int significantDigits, double value); - -////////////////////////////////////////////////////////////////////////// -// Simply sub string searching case insensitive. -////////////////////////////////////////////////////////////////////////// -inline const char* strstri(const char* pString, const char* pSubstring) -{ - int i, j, k; - for (i = 0; pString[i]; i++) - { - for (j = i, k = 0; tolower(pString[j]) == tolower(pSubstring[k]); j++, k++) - { - if (!pSubstring[k + 1]) - { - return (pString + i); - } - } - } - - return nullptr; -} - - inline bool CheckVirtualKey(Qt::MouseButton button) { return (qApp->property("pressedMouseButtons").toInt() & button) != 0; diff --git a/Gems/LyShine/Code/Editor/Animation/Util/UiEditorUtils.cpp b/Gems/LyShine/Code/Editor/Animation/Util/UiEditorUtils.cpp index 41f7300002..85270df355 100644 --- a/Gems/LyShine/Code/Editor/Animation/Util/UiEditorUtils.cpp +++ b/Gems/LyShine/Code/Editor/Animation/Util/UiEditorUtils.cpp @@ -92,23 +92,6 @@ QString TrimTrailingZeros(QString str) return str; } -////////////////////////////////////////////////////////////////////////// -// This function is supposed to format float in user-friendly way, -// omitting the exponent notation. -// -// Why not using printf? Its formatting rules has following drawbacks: -// %g - will use exponent for small numbers; -// %.Nf - doesn't allow to control total amount of significant numbers, -// which exposes limited precision during binary-to-decimal fraction -// conversion. -////////////////////////////////////////////////////////////////////////// -void FormatFloatForUI(QString& str, int significantDigits, double value) -{ - str = TrimTrailingZeros(QString::number(value, 'f', significantDigits)); - return; -} -//////////////////////////////////////////////////////////////////////////- - ////////////////////////////////////////////////////////////////////////// QColor ColorLinearToGamma(ColorF col) { From 62e7483b0e7a025369c09fcd92bcf326ea71a131 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Thu, 13 Jan 2022 14:44:59 -0600 Subject: [PATCH 074/108] Switched GradientSignal to use GemTestEnvironment. (#6886) This allows actual Shape components to be used instead of MockShapes, which is important for the benchmarks to get accurate results as Mocks are extremely expensive. It also removes a lot of unnecessary mock handling and test setup code. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../EditorGradientSignalPreviewTests.cpp | 38 +++-- .../Code/Tests/GradientSignalImageTests.cpp | 31 ++-- .../Tests/GradientSignalReferencesTests.cpp | 38 ++--- .../Tests/GradientSignalServicesTests.cpp | 10 +- .../Code/Tests/GradientSignalSurfaceTests.cpp | 10 +- .../Code/Tests/GradientSignalTest.cpp | 47 +++--- .../Code/Tests/GradientSignalTestFixtures.cpp | 134 ++++++++---------- .../Code/Tests/GradientSignalTestFixtures.h | 84 +++++------ .../Code/Tests/ImageAssetTests.cpp | 21 +-- 9 files changed, 193 insertions(+), 220 deletions(-) diff --git a/Gems/GradientSignal/Code/Tests/EditorGradientSignalPreviewTests.cpp b/Gems/GradientSignal/Code/Tests/EditorGradientSignalPreviewTests.cpp index e8bd9f2dff..83892f1c69 100644 --- a/Gems/GradientSignal/Code/Tests/EditorGradientSignalPreviewTests.cpp +++ b/Gems/GradientSignal/Code/Tests/EditorGradientSignalPreviewTests.cpp @@ -29,21 +29,34 @@ namespace UnitTest { GradientSignalTest::SetUp(); - // Set up job manager with two threads so that we can run and test the preview job logic. - AZ::JobManagerDesc desc; - AZ::JobManagerThreadDesc threadDesc; - desc.m_workerThreads.push_back(threadDesc); - desc.m_workerThreads.push_back(threadDesc); - m_jobManager = aznew AZ::JobManager(desc); - m_jobContext = aznew AZ::JobContext(*m_jobManager); - AZ::JobContext::SetGlobalContext(m_jobContext); + auto globalContext = AZ::JobContext::GetGlobalContext(); + if (globalContext) + { + AZ_Assert( + globalContext->GetJobManager().GetNumWorkerThreads() >= 2, + "Job Manager previously started by test environment with too few threads for this test."); + } + else + { + // Set up job manager with two threads so that we can run and test the preview job logic. + AZ::JobManagerDesc desc; + AZ::JobManagerThreadDesc threadDesc; + desc.m_workerThreads.push_back(threadDesc); + desc.m_workerThreads.push_back(threadDesc); + m_jobManager = aznew AZ::JobManager(desc); + m_jobContext = aznew AZ::JobContext(*m_jobManager); + AZ::JobContext::SetGlobalContext(m_jobContext); + } } void TearDown() override { - AZ::JobContext::SetGlobalContext(nullptr); - delete m_jobContext; - delete m_jobManager; + if (m_jobContext) + { + AZ::JobContext::SetGlobalContext(nullptr); + delete m_jobContext; + delete m_jobManager; + } GradientSignalTest::TearDown(); } @@ -180,4 +193,5 @@ namespace UnitTest } } -AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); +// This uses a custom test hook so that we can load LmbrCentral and use Shape components in our unit tests. +AZ_UNIT_TEST_HOOK(new UnitTest::GradientSignalTestEnvironment); diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp index 5cd3c7edf6..8ec190000d 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalImageTests.cpp @@ -14,10 +14,13 @@ #include #include #include +#include #include #include +#include + namespace UnitTest { struct GradientSignalImageTestsFixture @@ -89,23 +92,21 @@ namespace UnitTest test.m_imageSize, test.m_imageSize, static_cast(test.m_pixel.GetX()), static_cast(test.m_pixel.GetY())); config.m_tilingX = test.m_tiling; config.m_tilingY = test.m_tiling; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); // Create the Gradient Transform Component. GradientSignal::GradientTransformConfig gradientTransformConfig; gradientTransformConfig.m_wrappingType = test.m_wrappingType; - CreateComponent(entity.get(), gradientTransformConfig); + entity->CreateComponent(gradientTransformConfig); - // Create a mock Shape component that describes the bounds that we're using to map our ImageGradient into world space. - CreateComponent(entity.get()); - MockShapeComponentHandler mockShapeHandler(entity->GetId()); - mockShapeHandler.m_GetLocalBounds = AZ::Aabb::CreateCenterRadius(AZ::Vector3(shapeHalfBounds), shapeHalfBounds); + LmbrCentral::BoxShapeConfig boxConfig(AZ::Vector3(shapeHalfBounds * 2.0f)); + auto boxComponent = entity->CreateComponent(LmbrCentral::AxisAlignedBoxShapeComponentTypeId); + boxComponent->SetConfiguration(boxConfig); - // Create a mock Transform component that locates our ImageGradient in the center of our desired mock Shape. - MockTransformHandler mockTransformHandler; - mockTransformHandler.m_GetLocalTMOutput = AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds)); - mockTransformHandler.m_GetWorldTMOutput = AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds)); - mockTransformHandler.BusConnect(entity->GetId()); + // Create a transform that locates our gradient in the center of our desired mock Shape. + auto transform = entity->CreateComponent(); + transform->SetLocalTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds))); + transform->SetWorldTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds))); // All components are created, so activate the entity ActivateEntity(entity.get()); @@ -365,7 +366,7 @@ namespace UnitTest mockShapeTransformHandler.BusConnect(mockShape->GetId()); // Create the mock shape that maps our 3x3 image to a 3x3 sample space in the world. - CreateComponent(mockShape.get()); + mockShape->CreateComponent(); MockShapeComponentHandler mockShapeComponentHandler(mockShape->GetId()); // Create a 2x2 box shape (shapes are inclusive, so that's 3x3 sampling space), so that each pixel in the image directly maps to 1 meter in the box. mockShapeComponentHandler.m_GetEncompassingAabb = AZ::Aabb::CreateFromMinMax(AZ::Vector3(0.0f), AZ::Vector3(2.0f)); @@ -379,7 +380,7 @@ namespace UnitTest // Create an ImageGradient with a 3x3 asset with the center pixel set. GradientSignal::ImageGradientConfig gradientConfig; gradientConfig.m_imageAsset = ImageAssetMockAssetHandler::CreateSpecificPixelImageAsset(3, 3, 1, 1); - CreateComponent(entity.get(), gradientConfig); + entity->CreateComponent(gradientConfig); // Create the test GradientTransform GradientSignal::GradientTransformConfig config; @@ -400,7 +401,7 @@ namespace UnitTest config.m_overrideRotate = false; config.m_overrideScale = false; config.m_is3d = false; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); // Set up the transform on the gradient entity. MockTransformHandler mockTransformHandler; @@ -409,7 +410,7 @@ namespace UnitTest mockTransformHandler.BusConnect(entity->GetId()); // Put a default shape on our gradient entity. This is only used for previews, so it doesn't matter what it gets set to. - CreateComponent(entity.get()); + entity->CreateComponent(); MockShapeComponentHandler mockShapeHandler(entity->GetId()); ActivateEntity(entity.get()); diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp index cc91c58fce..72bdfa202e 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalReferencesTests.cpp @@ -55,7 +55,7 @@ namespace UnitTest config.m_layers.push_back(layer); auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -88,7 +88,7 @@ namespace UnitTest config.m_smoothStep.m_falloffStrength = falloffStrength; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -391,7 +391,7 @@ namespace UnitTest GradientSignal::ReferenceGradientConfig referenceGradientConfig1; referenceGradientConfig1.m_gradientSampler.m_ownerEntityId = referenceGradientEntity1->GetId(); referenceGradientConfig1.m_gradientSampler.m_gradientId = constantGradientEntity->GetId(); - CreateComponent(referenceGradientEntity1.get(), referenceGradientConfig1); + referenceGradientEntity1->CreateComponent(referenceGradientConfig1); ActivateEntity(referenceGradientEntity1.get()); EXPECT_TRUE(referenceGradientConfig1.m_gradientSampler.ValidateGradientEntityId()); @@ -400,7 +400,7 @@ namespace UnitTest GradientSignal::ReferenceGradientConfig referenceGradientConfig2; referenceGradientConfig2.m_gradientSampler.m_ownerEntityId = referenceGradientEntity2->GetId(); referenceGradientConfig2.m_gradientSampler.m_gradientId = referenceGradientEntity1->GetId(); - CreateComponent(referenceGradientEntity2.get(), referenceGradientConfig2); + referenceGradientEntity2->CreateComponent(referenceGradientConfig2); ActivateEntity(referenceGradientEntity2.get()); EXPECT_TRUE(referenceGradientConfig2.m_gradientSampler.ValidateGradientEntityId()); @@ -409,7 +409,7 @@ namespace UnitTest GradientSignal::ReferenceGradientConfig referenceGradientConfig3; referenceGradientConfig3.m_gradientSampler.m_ownerEntityId = referenceGradientEntity3->GetId(); referenceGradientConfig3.m_gradientSampler.m_gradientId = referenceGradientEntity3->GetId(); - CreateComponent(referenceGradientEntity3.get(), referenceGradientConfig3); + referenceGradientEntity3->CreateComponent(referenceGradientConfig3); ActivateEntity(referenceGradientEntity3.get()); EXPECT_FALSE(referenceGradientConfig3.m_gradientSampler.ValidateGradientEntityId()); EXPECT_EQ(referenceGradientConfig3.m_gradientSampler.m_gradientId, AZ::EntityId()); @@ -422,19 +422,19 @@ namespace UnitTest GradientSignal::ReferenceGradientConfig referenceGradientConfig4; referenceGradientConfig4.m_gradientSampler.m_ownerEntityId = referenceGradientEntity4->GetId(); referenceGradientConfig4.m_gradientSampler.m_gradientId = referenceGradientEntity5->GetId(); - CreateComponent(referenceGradientEntity4.get(), referenceGradientConfig4); + referenceGradientEntity4->CreateComponent(referenceGradientConfig4); ActivateEntity(referenceGradientEntity4.get()); GradientSignal::ReferenceGradientConfig referenceGradientConfig5; referenceGradientConfig5.m_gradientSampler.m_ownerEntityId = referenceGradientEntity5->GetId(); referenceGradientConfig5.m_gradientSampler.m_gradientId = referenceGradientEntity6->GetId(); - CreateComponent(referenceGradientEntity5.get(), referenceGradientConfig5); + referenceGradientEntity5->CreateComponent(referenceGradientConfig5); ActivateEntity(referenceGradientEntity5.get()); GradientSignal::ReferenceGradientConfig referenceGradientConfig6; referenceGradientConfig6.m_gradientSampler.m_ownerEntityId = referenceGradientEntity6->GetId(); referenceGradientConfig6.m_gradientSampler.m_gradientId = referenceGradientEntity4->GetId(); - CreateComponent(referenceGradientEntity6.get(), referenceGradientConfig6); + referenceGradientEntity6->CreateComponent(referenceGradientConfig6); ActivateEntity(referenceGradientEntity6.get()); EXPECT_FALSE(referenceGradientConfig6.m_gradientSampler.ValidateGradientEntityId()); @@ -456,7 +456,7 @@ namespace UnitTest // Create an AABB from -1 to 1, so points at coorindates 0 and 1 fall on it, but any points at coordinate 2 won't. auto entityShape = CreateEntity(); - CreateComponent(entityShape.get()); + entityShape->CreateComponent(); MockShapeComponentHandler mockShapeComponentHandler(entityShape->GetId()); mockShapeComponentHandler.m_GetEncompassingAabb = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-1.0f), AZ::Vector3(1.0f)); @@ -466,7 +466,7 @@ namespace UnitTest config.m_falloffType = GradientSignal::FalloffType::Outer; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -481,7 +481,7 @@ namespace UnitTest // Create our test shape from -1 to 0, so we have a corner directly on (0, 0). auto entityShape = CreateEntity(); - CreateComponent(entityShape.get()); + entityShape->CreateComponent(); MockShapeComponentHandler mockShapeComponentHandler(entityShape->GetId()); mockShapeComponentHandler.m_GetEncompassingAabb = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-1.0f), AZ::Vector3(0.0f)); @@ -512,7 +512,7 @@ namespace UnitTest } auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -533,7 +533,7 @@ namespace UnitTest // We're pinning a shape, so the bounding box of (0, 0, 0) - (10, 10, 10) will be the one that applies. auto entityShape = CreateEntity(); - CreateComponent(entityShape.get()); + entityShape->CreateComponent(); MockShapeComponentHandler mockShapeComponentHandler(entityShape->GetId()); mockShapeComponentHandler.m_GetEncompassingAabb = AZ::Aabb::CreateFromMinMax(AZ::Vector3::CreateZero(), AZ::Vector3(10.0f)); @@ -551,7 +551,7 @@ namespace UnitTest config.m_altitudeMax = 24.0f; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -584,7 +584,7 @@ namespace UnitTest config.m_altitudeMax = 10.0f; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -612,7 +612,7 @@ namespace UnitTest config.m_altitudeMax = 15.0f; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -649,7 +649,7 @@ namespace UnitTest config.m_altitudeMax = 15.0f; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -684,7 +684,7 @@ namespace UnitTest config.m_surfaceTagList.push_back(AZ_CRC("test_mask", 0x7a16e9ff)); auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -711,7 +711,7 @@ namespace UnitTest config.m_surfaceTagList.push_back(AZ_CRC("test_mask", 0x7a16e9ff)); auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp index ec770f038d..449719af67 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp @@ -31,7 +31,7 @@ namespace UnitTest config.m_value = expectedOutput; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); GradientSignal::GradientSampler gradientSampler; @@ -75,7 +75,7 @@ namespace UnitTest config.m_gradientSampler.m_gradientId = entityMock->GetId(); auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -109,7 +109,7 @@ namespace UnitTest config.m_gradientSampler.m_gradientId = entityMock->GetId(); auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -147,7 +147,7 @@ namespace UnitTest config.m_gradientSampler.m_gradientId = entityMock->GetId(); auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -185,7 +185,7 @@ namespace UnitTest config.m_gradientSampler.m_gradientId = entityMock->GetId(); auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp index 702965c0de..a716fc79b8 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalSurfaceTests.cpp @@ -44,11 +44,9 @@ namespace UnitTest // This lets our component register with surfaceData successfully. MockSurfaceDataSystem mockSurfaceDataSystem; - // Create a mock shape entity in case we want to use it. + // Create a mock shape entity in case our gradient test uses shape constraints. // The mock shape is a cube that goes from -0.5 to 0.5 in space. - auto mockShapeEntity = CreateEntity(); - CreateComponent(mockShapeEntity.get()); - MockShapeComponentHandler mockShapeHandler(mockShapeEntity->GetId()); + auto mockShapeEntity = CreateTestEntity(0.5f); ActivateEntity(mockShapeEntity.get()); // For ease of testing, use a constant gradient as our input gradient. @@ -76,8 +74,8 @@ namespace UnitTest // Create the test entity with the GradientSurfaceData component and the required gradient dependency auto entity = CreateEntity(); - CreateComponent(entity.get(), constantGradientConfig); - CreateComponent(entity.get(), config); + entity->CreateComponent(constantGradientConfig); + entity->CreateComponent(config); ActivateEntity(entity.get()); // Get our registered modifier handle (and verify that it's valid) diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTest.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalTest.cpp index adc35e6738..13e535e072 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTest.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTest.cpp @@ -27,14 +27,12 @@ namespace UnitTest void TestLevelsGradientComponent(int dataSize, const AZStd::vector& inputData, const AZStd::vector& expectedOutput, float inputMin, float inputMid, float inputMax, float outputMin, float outputMax) { - auto entityMock = CreateEntity(); + auto entityMock = CreateTestEntity(1.0f); const AZ::EntityId id = entityMock->GetId(); UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize); GradientSignal::GradientTransformConfig gradientTransformConfig; - CreateComponent(entityMock.get(), gradientTransformConfig); - CreateComponent(entityMock.get()); - MockShapeComponentHandler mockShapeHandler(entityMock->GetId()); + entityMock->CreateComponent(gradientTransformConfig); ActivateEntity(entityMock.get()); @@ -47,7 +45,7 @@ namespace UnitTest config.m_outputMax = outputMax; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -56,14 +54,12 @@ namespace UnitTest void TestPosterizeGradientComponent(int dataSize, const AZStd::vector& inputData, const AZStd::vector& expectedOutput, GradientSignal::PosterizeGradientConfig::ModeType posterizeMode, int bands) { - auto entityMock = CreateEntity(); + auto entityMock = CreateTestEntity(0.5f); const AZ::EntityId id = entityMock->GetId(); UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize); GradientSignal::GradientTransformConfig gradientTransformConfig; - CreateComponent(entityMock.get(), gradientTransformConfig); - CreateComponent(entityMock.get()); - MockShapeComponentHandler mockShapeHandler(entityMock->GetId()); + entityMock->CreateComponent(gradientTransformConfig); ActivateEntity(entityMock.get()); @@ -73,7 +69,7 @@ namespace UnitTest config.m_bands = bands; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -82,14 +78,12 @@ namespace UnitTest void TestSmoothStepGradientComponent(int dataSize, const AZStd::vector& inputData, const AZStd::vector& expectedOutput, float midpoint, float range, float softness) { - auto entityMock = CreateEntity(); + auto entityMock = CreateTestEntity(0.5f); const AZ::EntityId id = entityMock->GetId(); UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize); GradientSignal::GradientTransformConfig gradientTransformConfig; - CreateComponent(entityMock.get(), gradientTransformConfig); - CreateComponent(entityMock.get()); - MockShapeComponentHandler mockShapeHandler(entityMock->GetId()); + entityMock->CreateComponent(gradientTransformConfig); ActivateEntity(entityMock.get()); @@ -100,7 +94,7 @@ namespace UnitTest config.m_smoothStep.m_falloffStrength = softness; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -108,14 +102,12 @@ namespace UnitTest void TestThresholdGradientComponent(int dataSize, const AZStd::vector& inputData, const AZStd::vector& expectedOutput, float threshold) { - auto entityMock = CreateEntity(); + auto entityMock = CreateTestEntity(0.5f); const AZ::EntityId id = entityMock->GetId(); UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize); GradientSignal::GradientTransformConfig gradientTransformConfig; - CreateComponent(entityMock.get(), gradientTransformConfig); - CreateComponent(entityMock.get()); - MockShapeComponentHandler mockShapeHandler(entityMock->GetId()); + entityMock->CreateComponent(gradientTransformConfig); ActivateEntity(entityMock.get()); @@ -124,7 +116,7 @@ namespace UnitTest config.m_threshold = threshold; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); @@ -167,11 +159,11 @@ namespace UnitTest AZStd::vector expectedOutput = { AZ_TRAIT_UNIT_TEST_PERLINE_GRADIANT_GOLDEN_VALUES_7878 }; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); GradientSignal::GradientTransformConfig gradientTransformConfig; - CreateComponent(entity.get(), gradientTransformConfig); - CreateComponent(entity.get()); + entity->CreateComponent(gradientTransformConfig); + entity->CreateComponent(); MockShapeComponentHandler mockShapeHandler(entity->GetId()); ActivateEntity(entity.get()); @@ -197,11 +189,11 @@ namespace UnitTest config.m_randomSeed = 5656; auto entity = CreateEntity(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); GradientSignal::GradientTransformConfig gradientTransformConfig; - CreateComponent(entity.get(), gradientTransformConfig); - CreateComponent(entity.get()); + entity->CreateComponent(gradientTransformConfig); + entity->CreateComponent(); MockShapeComponentHandler mockShapeHandler(entity->GetId()); ActivateEntity(entity.get()); @@ -546,4 +538,5 @@ namespace UnitTest } } -AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV); +// This uses custom test / benchmark hooks so that we can load LmbrCentral and use Shape components in our unit tests and benchmarks. +AZ_UNIT_TEST_HOOK(new UnitTest::GradientSignalTestEnvironment, UnitTest::GradientSignalBenchmarkEnvironment); diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp index 154e9032b2..d81370f6a8 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.cpp @@ -10,7 +10,9 @@ #include #include +#include #include +#include // Base gradient components #include @@ -36,65 +38,48 @@ namespace UnitTest { + void GradientSignalTestEnvironment::AddGemsAndComponents() + { + AddDynamicModulePaths({ "LmbrCentral" }); + + AddComponentDescriptors({ + AzFramework::TransformComponent::CreateDescriptor(), + + GradientSignal::ConstantGradientComponent::CreateDescriptor(), + GradientSignal::DitherGradientComponent::CreateDescriptor(), + GradientSignal::GradientSurfaceDataComponent::CreateDescriptor(), + GradientSignal::GradientTransformComponent::CreateDescriptor(), + GradientSignal::ImageGradientComponent::CreateDescriptor(), + GradientSignal::InvertGradientComponent::CreateDescriptor(), + GradientSignal::LevelsGradientComponent::CreateDescriptor(), + GradientSignal::MixedGradientComponent::CreateDescriptor(), + GradientSignal::PerlinGradientComponent::CreateDescriptor(), + GradientSignal::PosterizeGradientComponent::CreateDescriptor(), + GradientSignal::RandomGradientComponent::CreateDescriptor(), + GradientSignal::ReferenceGradientComponent::CreateDescriptor(), + GradientSignal::ShapeAreaFalloffGradientComponent::CreateDescriptor(), + GradientSignal::SmoothStepGradientComponent::CreateDescriptor(), + GradientSignal::SurfaceAltitudeGradientComponent::CreateDescriptor(), + GradientSignal::SurfaceMaskGradientComponent::CreateDescriptor(), + GradientSignal::SurfaceSlopeGradientComponent::CreateDescriptor(), + GradientSignal::ThresholdGradientComponent::CreateDescriptor(), + + MockShapeComponent::CreateDescriptor(), + }); + } + void GradientSignalBaseFixture::SetupCoreSystems() { - m_app = AZStd::make_unique(); - ASSERT_TRUE(m_app != nullptr); - - AZ::ComponentApplication::Descriptor componentAppDesc; - - m_systemEntity = m_app->Create(componentAppDesc); - ASSERT_TRUE(m_systemEntity != nullptr); - m_app->AddEntity(m_systemEntity); - - AZ::AllocatorInstance::Create(); - AZ::Data::AssetManager::Descriptor desc; - AZ::Data::AssetManager::Create(desc); - m_mockHandler = new ImageAssetMockAssetHandler(); + m_mockHandler = new UnitTest::ImageAssetMockAssetHandler(); AZ::Data::AssetManager::Instance().RegisterHandler(m_mockHandler, azrtti_typeid()); - - m_mockShapeHandlers = new AZStd::vector>>(); } void GradientSignalBaseFixture::TearDownCoreSystems() { - // Clear any mock shape handlers that we've created for our test entities. - delete m_mockShapeHandlers; - AZ::Data::AssetManager::Instance().UnregisterHandler(m_mockHandler); delete m_mockHandler; // delete after removing from the asset manager AzFramework::LegacyAssetEventBus::ClearQueuedEvents(); - AZ::Data::AssetManager::Destroy(); - AZ::AllocatorInstance::Destroy(); - - m_app->Destroy(); - m_app.reset(); - m_systemEntity = nullptr; - } - - AZStd::unique_ptr> GradientSignalBaseFixture::CreateMockShape( - const AZ::Aabb& spawnerBox, const AZ::EntityId& shapeEntityId) - { - AZStd::unique_ptr> mockShape = - AZStd::make_unique>(shapeEntityId); - - ON_CALL(*mockShape, GetEncompassingAabb).WillByDefault(testing::Return(spawnerBox)); - ON_CALL(*mockShape, GetTransformAndLocalBounds) - .WillByDefault( - [spawnerBox](AZ::Transform& transform, AZ::Aabb& bounds) - { - transform = AZ::Transform::CreateTranslation(spawnerBox.GetCenter()); - bounds = spawnerBox.GetTranslated(-spawnerBox.GetCenter()); - }); - ON_CALL(*mockShape, IsPointInside) - .WillByDefault( - [spawnerBox](const AZ::Vector3& point) -> bool - { - return spawnerBox.Contains(point); - }); - - return mockShape; } AZStd::unique_ptr GradientSignalBaseFixture::CreateMockSurfaceDataSystem(const AZ::Aabb& spawnerBox) @@ -130,16 +115,12 @@ namespace UnitTest // Create the base entity AZStd::unique_ptr testEntity = CreateEntity(); - // Create a mock Shape component that describes the bounds that we're using to map our gradient into world space. - CreateComponent(testEntity.get()); - - // Create and keep a reference to a mock shape handler that will respond to shape requests for the mock shape. - auto mockShapeHandler = - CreateMockShape(AZ::Aabb::CreateCenterRadius(AZ::Vector3(shapeHalfBounds), shapeHalfBounds), testEntity->GetId()); - m_mockShapeHandlers->push_back(AZStd::move(mockShapeHandler)); + LmbrCentral::BoxShapeConfig boxConfig(AZ::Vector3(shapeHalfBounds * 2.0f)); + auto boxComponent = testEntity->CreateComponent(LmbrCentral::AxisAlignedBoxShapeComponentTypeId); + boxComponent->SetConfiguration(boxConfig); // Create a transform that locates our gradient in the center of our desired mock Shape. - auto transform = CreateComponent(testEntity.get()); + auto transform = testEntity->CreateComponent(); transform->SetLocalTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds))); transform->SetWorldTM(AZ::Transform::CreateTranslation(AZ::Vector3(shapeHalfBounds))); @@ -152,7 +133,7 @@ namespace UnitTest auto entity = CreateTestEntity(shapeHalfBounds); GradientSignal::ConstantGradientConfig config; config.m_value = 0.75f; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -168,12 +149,12 @@ namespace UnitTest config.m_imageAsset = ImageAssetMockAssetHandler::CreateImageAsset(imageSize, imageSize, imageSeed); config.m_tilingX = 1.0f; config.m_tilingY = 1.0f; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); // Create a Gradient Transform Component with arbitrary parameters. GradientSignal::GradientTransformConfig gradientTransformConfig; gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; - CreateComponent(entity.get(), gradientTransformConfig); + entity->CreateComponent(gradientTransformConfig); ActivateEntity(entity.get()); return entity; @@ -188,12 +169,12 @@ namespace UnitTest config.m_frequency = 1.1f; config.m_octave = 4; config.m_randomSeed = 12345; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); // Create a Gradient Transform Component with arbitrary parameters. GradientSignal::GradientTransformConfig gradientTransformConfig; gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; - CreateComponent(entity.get(), gradientTransformConfig); + entity->CreateComponent(gradientTransformConfig); ActivateEntity(entity.get()); return entity; @@ -205,12 +186,12 @@ namespace UnitTest auto entity = CreateTestEntity(shapeHalfBounds); GradientSignal::RandomGradientConfig config; config.m_randomSeed = 12345; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); // Create a Gradient Transform Component with arbitrary parameters. GradientSignal::GradientTransformConfig gradientTransformConfig; gradientTransformConfig.m_wrappingType = GradientSignal::WrappingType::None; - CreateComponent(entity.get(), gradientTransformConfig); + entity->CreateComponent(gradientTransformConfig); ActivateEntity(entity.get()); return entity; @@ -224,7 +205,7 @@ namespace UnitTest config.m_shapeEntityId = entity->GetId(); config.m_falloffWidth = 16.0f; config.m_falloffType = GradientSignal::FalloffType::InnerOuter; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -238,10 +219,11 @@ namespace UnitTest GradientSignal::DitherGradientConfig config; config.m_gradientSampler.m_gradientId = inputGradientId; config.m_useSystemPointsPerUnit = false; - config.m_pointsPerUnit = 1.0f; + // Use a number other than 1.0f for pointsPerUnit to ensure the dither math is getting exercised properly. + config.m_pointsPerUnit = 0.25f; config.m_patternOffset = AZ::Vector3::CreateZero(); config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -254,7 +236,7 @@ namespace UnitTest auto entity = CreateTestEntity(shapeHalfBounds); GradientSignal::InvertGradientConfig config; config.m_gradientSampler.m_gradientId = inputGradientId; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -272,7 +254,7 @@ namespace UnitTest config.m_inputMax = 0.9f; config.m_outputMin = 0.0f; config.m_outputMax = 1.0f; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -298,7 +280,7 @@ namespace UnitTest layer.m_gradientSampler.m_opacity = 0.75f; config.m_layers.push_back(layer); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -313,7 +295,7 @@ namespace UnitTest config.m_gradientSampler.m_gradientId = inputGradientId; config.m_mode = GradientSignal::PosterizeGradientConfig::ModeType::Ps; config.m_bands = 5; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -327,7 +309,7 @@ namespace UnitTest GradientSignal::ReferenceGradientConfig config; config.m_gradientSampler.m_gradientId = inputGradientId; config.m_gradientSampler.m_ownerEntityId = entity->GetId(); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -343,7 +325,7 @@ namespace UnitTest config.m_smoothStep.m_falloffMidpoint = 0.75f; config.m_smoothStep.m_falloffRange = 0.125f; config.m_smoothStep.m_falloffStrength = 0.25f; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -357,7 +339,7 @@ namespace UnitTest GradientSignal::ThresholdGradientConfig config; config.m_gradientSampler.m_gradientId = inputGradientId; config.m_threshold = 0.75f; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -370,7 +352,7 @@ namespace UnitTest GradientSignal::SurfaceAltitudeGradientConfig config; config.m_altitudeMin = -5.0f; config.m_altitudeMax = 15.0f; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -382,7 +364,7 @@ namespace UnitTest auto entity = CreateTestEntity(shapeHalfBounds); GradientSignal::SurfaceMaskGradientConfig config; config.m_surfaceTagList.push_back(AZ_CRC_CE("test_mask")); - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; @@ -399,7 +381,7 @@ namespace UnitTest config.m_smoothStep.m_falloffMidpoint = 0.75f; config.m_smoothStep.m_falloffRange = 0.125f; config.m_smoothStep.m_falloffStrength = 0.25f; - CreateComponent(entity.get(), config); + entity->CreateComponent(config); ActivateEntity(entity.get()); return entity; diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h index 478f1c1d92..5fda88ea27 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h @@ -9,9 +9,39 @@ #include #include +#include namespace UnitTest { + // The GradientSignal unit tests need to use the GemTestEnvironment to load the LmbrCentral Gem so that Shape components can be used + // in the unit tests and benchmarks. + class GradientSignalTestEnvironment + : public AZ::Test::GemTestEnvironment + { + public: + void AddGemsAndComponents() override; + }; + +#ifdef HAVE_BENCHMARK + //! The Benchmark environment is used for one time setup and tear down of shared resources + class GradientSignalBenchmarkEnvironment + : public AZ::Test::BenchmarkEnvironmentBase + , public GradientSignalTestEnvironment + + { + protected: + void SetUpBenchmark() override + { + SetupEnvironment(); + } + + void TearDownBenchmark() override + { + TeardownEnvironment(); + } + }; +#endif + // Base test fixture used for GradientSignal unit tests and benchmark tests class GradientSignalBaseFixture { @@ -30,24 +60,6 @@ namespace UnitTest entity->Activate(); } - template - Component* CreateComponent(AZ::Entity* entity, const Configuration& config) - { - m_app->RegisterComponentDescriptor(Component::CreateDescriptor()); - return entity->CreateComponent(config); - } - - template - Component* CreateComponent(AZ::Entity* entity) - { - m_app->RegisterComponentDescriptor(Component::CreateDescriptor()); - return entity->CreateComponent(); - } - - // Create a mock shape that will respond to the shape bus with proper responses for the given input box. - AZStd::unique_ptr> CreateMockShape( - const AZ::Aabb& spawnerBox, const AZ::EntityId& shapeEntityId); - // Create a mock SurfaceDataSystem that will respond to requests for surface points with mock responses for points inside // the given input box. AZStd::unique_ptr CreateMockSurfaceDataSystem(const AZ::Aabb& spawnerBox); @@ -77,27 +89,22 @@ namespace UnitTest AZStd::unique_ptr BuildTestSurfaceMaskGradient(float shapeHalfBounds); AZStd::unique_ptr BuildTestSurfaceSlopeGradient(float shapeHalfBounds); - AZStd::unique_ptr m_app; - AZ::Entity* m_systemEntity = nullptr; - ImageAssetMockAssetHandler* m_mockHandler = nullptr; - AZStd::vector>>* m_mockShapeHandlers = nullptr; + UnitTest::ImageAssetMockAssetHandler* m_mockHandler = nullptr; }; struct GradientSignalTest : public GradientSignalBaseFixture - , public UnitTest::AllocatorsTestFixture + , public ::testing::Test { protected: void SetUp() override { - UnitTest::AllocatorsTestFixture::SetUp(); SetupCoreSystems(); } void TearDown() override { TearDownCoreSystems(); - UnitTest::AllocatorsTestFixture::TearDown(); } void TestFixedDataSampler(const AZStd::vector& expectedOutput, int size, AZ::EntityId gradientEntityId); @@ -106,41 +113,36 @@ namespace UnitTest #ifdef HAVE_BENCHMARK class GradientSignalBenchmarkFixture : public GradientSignalBaseFixture - , public UnitTest::AllocatorsBenchmarkFixture - , public UnitTest::TraceBusRedirector + , public ::benchmark::Fixture { public: - void internalSetUp(const benchmark::State& state) + void internalSetUp() { - AZ::Debug::TraceMessageBus::Handler::BusConnect(); - UnitTest::AllocatorsBenchmarkFixture::SetUp(state); SetupCoreSystems(); } - void internalTearDown(const benchmark::State& state) + void internalTearDown() { TearDownCoreSystems(); - UnitTest::AllocatorsBenchmarkFixture::TearDown(state); - AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); } protected: - void SetUp(const benchmark::State& state) override + void SetUp([[maybe_unused]] const benchmark::State& state) override { - internalSetUp(state); + internalSetUp(); } - void SetUp(benchmark::State& state) override + void SetUp([[maybe_unused]] benchmark::State& state) override { - internalSetUp(state); + internalSetUp(); } - void TearDown(const benchmark::State& state) override + void TearDown([[maybe_unused]] const benchmark::State& state) override { - internalTearDown(state); + internalTearDown(); } - void TearDown(benchmark::State& state) override + void TearDown([[maybe_unused]] benchmark::State& state) override { - internalTearDown(state); + internalTearDown(); } }; #endif diff --git a/Gems/GradientSignal/Code/Tests/ImageAssetTests.cpp b/Gems/GradientSignal/Code/Tests/ImageAssetTests.cpp index 0111f10c3a..7b1c260d45 100644 --- a/Gems/GradientSignal/Code/Tests/ImageAssetTests.cpp +++ b/Gems/GradientSignal/Code/Tests/ImageAssetTests.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -64,26 +65,8 @@ namespace } } - class ImageAssetTest - : public ::testing::Test + class ImageAssetTest : public ::testing::Test { - protected: - AZ::ComponentApplication m_app; - AZ::Entity* m_systemEntity = nullptr; - - void SetUp() override - { - AZ::ComponentApplication::Descriptor appDesc; - appDesc.m_memoryBlocksByteSize = 128 * 1024 * 1024; - m_systemEntity = m_app.Create(appDesc); - m_app.AddEntity(m_systemEntity); - } - - void TearDown() override - { - m_app.Destroy(); - m_systemEntity = nullptr; - } }; #if AZ_TRAIT_DISABLE_FAILED_GRADIENT_SIGNAL_TESTS From 79431f5e5fbec10608e0de865c6474b0bead2c32 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Thu, 13 Jan 2022 14:50:54 -0600 Subject: [PATCH 075/108] First batch of GetValues() overrides (#6852) * Benchmarks and tests for Image and Constant GetValues Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Verify GetValues for Perlin and Random Gradients Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Standardized the assert format for GetValues(). Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * More GetValues unit tests and test cleanup Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed typos Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * GetValues() unit tests for surface gradients. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Benchmarks for ShapeAreaFalloff Gradient Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added benchmarks for all remaining gradients and cleaned up the helper methods. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Renamed class for better report formatting. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added missing Mocks dependencies for the Editor tests. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * First batch of specific GetValues() overrides. Each one is measurably faster than the generic version. Also, in ShapeAreaFalloffGradient, I optimized and simplified the logic a bit, so GetValue() is marginally faster too. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../Components/ConstantGradientComponent.h | 1 + .../Components/ImageGradientComponent.h | 1 + .../Components/PerlinGradientComponent.h | 1 + .../Components/RandomGradientComponent.h | 3 + .../ShapeAreaFalloffGradientComponent.h | 1 + .../Components/ConstantGradientComponent.cpp | 16 +++++ .../Components/ImageGradientComponent.cpp | 33 ++++++++++ .../Components/PerlinGradientComponent.cpp | 34 ++++++++++ .../Components/RandomGradientComponent.cpp | 65 +++++++++++++++---- .../ShapeAreaFalloffGradientComponent.cpp | 59 ++++++++++++++--- 10 files changed, 194 insertions(+), 20 deletions(-) diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h index cb27914b8a..af896f0933 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h @@ -62,6 +62,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; protected: ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h index 8214436f83..9fc98124cb 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h @@ -69,6 +69,7 @@ namespace GradientSignal // GradientRequestBus overrides... float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; // AZ::Data::AssetBus overrides... void OnAssetReady(AZ::Data::Asset asset) override; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h index ef171f5319..1b39f7f17b 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h @@ -70,6 +70,7 @@ namespace GradientSignal // GradientRequestBus overrides... float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; private: PerlinGradientConfig m_configuration; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h index b0dbd964a0..274442a2c0 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h @@ -61,6 +61,7 @@ namespace GradientSignal // GradientRequestBus overrides... float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; private: RandomGradientConfig m_configuration; @@ -73,5 +74,7 @@ namespace GradientSignal // RandomGradientRequestBus overrides... int GetRandomSeed() const override; void SetRandomSeed(int seed) override; + + float GetRandomValue(const AZ::Vector3& position, AZStd::size_t seed) const; }; } diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h index d7c2344fd2..df86c38069 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h @@ -69,6 +69,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; protected: ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp index 86e8a5abc6..2b1487f75e 100644 --- a/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp @@ -134,6 +134,22 @@ namespace GradientSignal return m_configuration.m_value; } + void ConstantGradientComponent::GetValues( + [[maybe_unused]] AZStd::array_view positions, AZStd::array_view outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + for (auto& outValue : outValues) + { + float& writableOutValue = const_cast(outValue); + writableOutValue = m_configuration.m_value; + } + } + float ConstantGradientComponent::GetConstantValue() const { return m_configuration.m_value; diff --git a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp index 269bfbc2df..06a3674188 100644 --- a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp @@ -219,6 +219,39 @@ namespace GradientSignal return 0.0f; } + void ImageGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + AZ::Vector3 uvw; + bool wasPointRejected = false; + + AZStd::shared_lock imageLock(m_imageMutex); + + for (size_t index = 0; index < positions.size(); index++) + { + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + + m_gradientTransform.TransformPositionToUVWNormalized(positions[index], uvw, wasPointRejected); + + if (!wasPointRejected) + { + outValue = GetValueFromImageAsset( + m_configuration.m_imageAsset, uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); + } + else + { + outValue = 0.0f; + } + } + } + AZStd::string ImageGradientComponent::GetImageAssetPath() const { AZStd::string assetPathString; diff --git a/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp index 3096afa3dc..667d8c30a7 100644 --- a/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp @@ -203,6 +203,40 @@ namespace GradientSignal return 0.0f; } + void PerlinGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + AZ::Vector3 uvw; + bool wasPointRejected = false; + + AZStd::shared_lock lock(m_transformMutex); + + for (size_t index = 0; index < positions.size(); index++) + { + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + + m_gradientTransform.TransformPositionToUVW(positions[index], uvw, wasPointRejected); + + if (!wasPointRejected) + { + outValue = m_perlinImprovedNoise->GenerateOctaveNoise( + uvw.GetX(), uvw.GetY(), uvw.GetZ(), m_configuration.m_octave, m_configuration.m_amplitude, + m_configuration.m_frequency); + } + else + { + outValue = 0.0f; + } + } + } + int PerlinGradientComponent::GetRandomSeed() const { return m_configuration.m_randomSeed; diff --git a/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp index 1b6753560c..ae51bdd4ac 100644 --- a/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp @@ -145,6 +145,22 @@ namespace GradientSignal m_gradientTransform = newTransform; } + float RandomGradientComponent::GetRandomValue(const AZ::Vector3& position, AZStd::size_t seed) const + { + // generating stable pseudo-random noise from a position based hash + float x = position.GetX(); + float y = position.GetY(); + AZStd::size_t result = 0; + + AZStd::hash_combine(result, x * seed + y); + AZStd::hash_combine(result, y * seed + x); + AZStd::hash_combine(result, x * y * seed); + + // always returns [0.0,1.0] + return static_cast(result % std::numeric_limits::max()) / static_cast(std::numeric_limits::max()); + } + + float RandomGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { @@ -158,23 +174,50 @@ namespace GradientSignal if (!wasPointRejected) { - //generating stable pseudo-random noise from a position based hash - float x = uvw.GetX(); - float y = uvw.GetY(); - AZStd::size_t result = 0; - const AZStd::size_t seed = m_configuration.m_randomSeed + AZStd::size_t(2); // Add 2 to avoid seeds 0 and 1, which can create strange patterns with this particular algorithm + const AZStd::size_t seed = m_configuration.m_randomSeed + + AZStd::size_t(2); // Add 2 to avoid seeds 0 and 1, which can create strange patterns with this particular algorithm - AZStd::hash_combine(result, x * seed + y); - AZStd::hash_combine(result, y * seed + x); - AZStd::hash_combine(result, x * y * seed); - - //always returns [0.0,1.0] - return static_cast(result % std::numeric_limits::max()) / static_cast(std::numeric_limits::max()); + return GetRandomValue(uvw, seed); } return 0.0f; } + void RandomGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + AZ::Vector3 uvw; + bool wasPointRejected = false; + const AZStd::size_t seed = m_configuration.m_randomSeed + + AZStd::size_t(2); // Add 2 to avoid seeds 0 and 1, which can create strange patterns with this particular algorithm + + AZStd::shared_lock lock(m_transformMutex); + + for (size_t index = 0; index < positions.size(); index++) + { + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + + m_gradientTransform.TransformPositionToUVW(positions[index], uvw, wasPointRejected); + + if (!wasPointRejected) + { + outValue = GetRandomValue(uvw, seed); + } + else + { + outValue = 0.0f; + } + } + } + + int RandomGradientComponent::GetRandomSeed() const { return m_configuration.m_randomSeed; diff --git a/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp index 9e1a250900..f2416f4fb6 100644 --- a/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp @@ -157,21 +157,62 @@ namespace GradientSignal float ShapeAreaFalloffGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { - AZ_PROFILE_FUNCTION(Entity); - float distance = 0.0f; LmbrCentral::ShapeComponentRequestsBus::EventResult(distance, m_configuration.m_shapeEntityId, &LmbrCentral::ShapeComponentRequestsBus::Events::DistanceFromPoint, sampleParams.m_position); - // In the special case of 0 falloff, make sure that all points inside the shape (0 distance) return - // 1.0, and all points outside the shape return 0. - if (m_configuration.m_falloffWidth == 0.0f) + // Since this is outer falloff, distance should give us values from 1.0 at the minimum distance to 0.0 at the maximum distance. + // The statement is written specifically to handle the 0 falloff case as well. For 0 falloff, all points inside the shape + // (0 distance) return 1.0, and all points outside the shape return 0. This works because division by 0 gives infinity, which gets + // clamped by the GetMax() to 0. However, if distance == 0, it would give us NaN, so we have the separate conditional check to + // handle that case and clamp to 1.0. + return (distance <= 0.0f) ? 1.0f : AZ::GetMax(1.0f - (distance / m_configuration.m_falloffWidth), 0.0f); + } + + void ShapeAreaFalloffGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + { + if (positions.size() != outValues.size()) { - return (distance > 0.0f) ? 0.0f : 1.0f; + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; } - // Since this is outer falloff, distance should give us values from 1.0 at the minimum distance - // to 0.0 at the maximum distance. - return GetRatio(m_configuration.m_falloffWidth, 0.0f, distance); + bool shapeConnected = false; + const float falloffWidth = m_configuration.m_falloffWidth; + + LmbrCentral::ShapeComponentRequestsBus::Event( + m_configuration.m_shapeEntityId, + [falloffWidth, positions, &outValues, &shapeConnected](LmbrCentral::ShapeComponentRequestsBus::Events* shapeRequests) + { + shapeConnected = true; + + for (size_t index = 0; index < positions.size(); index++) + { + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + + float distance = shapeRequests->DistanceFromPoint(positions[index]); + + // Since this is outer falloff, distance should give us values from 1.0 at the minimum distance to 0.0 at the maximum + // distance. The statement is written specifically to handle the 0 falloff case as well. For 0 falloff, all points + // inside the shape (0 distance) return 1.0, and all points outside the shape return 0. This works because division by 0 + // gives infinity, which gets clamped by the GetMax() to 0. However, if distance == 0, it would give us NaN, so we have + // the separate conditional check to handle that case and clamp to 1.0. + outValue = (distance <= 0.0f) ? 1.0f : AZ::GetMax(1.0f - (distance / falloffWidth), 0.0f); + } + }); + + // If there's no shape, there's no falloff. + if (!shapeConnected) + { + for (size_t index = 0; index < positions.size(); index++) + { + // The const_cast is necessary for now since array_view currently only supports const entries. + // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. + auto& outValue = const_cast(outValues[index]); + outValue = 1.0f; + } + } } AZ::EntityId ShapeAreaFalloffGradientComponent::GetShapeEntityId() const From 34d74857f5e940b8e18a971e7b053fb6805c48b2 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 13 Jan 2022 12:55:36 -0800 Subject: [PATCH 076/108] [development] fix for a possible MSVC compiler bug (#6870) Replaced a variable with the name "interface" to avoid conflict with MSVC keyword Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com> --- .../AssetProcessor/native/tests/SourceFileRelocatorTests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp b/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp index d7801abb3d..8d52ba23bd 100644 --- a/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp +++ b/Code/Tools/AssetProcessor/native/tests/SourceFileRelocatorTests.cpp @@ -793,9 +793,9 @@ namespace UnitTests TEST_F(SourceFileRelocatorTest, TestInterface) { - auto* interface = AZ::Interface::Get(); + auto* sourceFileRelocator = AZ::Interface::Get(); - ASSERT_NE(interface, nullptr); + ASSERT_NE(sourceFileRelocator, nullptr); } TEST_F(SourceFileRelocatorTest, Move_Real_Succeeds) From 193f529b9c8469930252b20d9fd15bd2bbc9bf60 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Thu, 13 Jan 2022 12:56:34 -0800 Subject: [PATCH 077/108] Add an LyShine client API target (#6829) * Reduce the need to link with LyShine static lib in other gems Signed-off-by: abrmich * Add UiBasics.Builders to VirtualGamepad.Builders alias Signed-off-by: abrmich * Add UiBasics to LyShine gem's metadata Signed-off-by: abrmich * Change include to a forward declaration Signed-off-by: abrmich --- Gems/GameStateSamples/Code/CMakeLists.txt | 2 +- Gems/LyShine/Code/CMakeLists.txt | 19 ++++---- Gems/LyShine/Code/Editor/GuideHelpers.cpp | 2 +- .../Code/Editor/ViewportCanvasBackground.cpp | 2 +- .../Code/Editor/ViewportDragInteraction.h | 2 +- Gems/LyShine/Code/Editor/ViewportHelpers.h | 2 +- Gems/LyShine/Code/Editor/ViewportIcon.cpp | 12 ++--- Gems/LyShine/Code/Editor/ViewportIcon.h | 2 +- Gems/LyShine/Code/Editor/ViewportWidget.cpp | 2 +- Gems/LyShine/Code/Include/LyShine/IDraw2d.h | 44 +++++++++++++++++++ Gems/LyShine/Code/Include/LyShine/ILyShine.h | 9 ++++ Gems/LyShine/Code/Source/Draw2d.cpp | 38 +--------------- .../Code/{Include/LyShine => Source}/Draw2d.h | 3 -- Gems/LyShine/Code/Source/LyShine.cpp | 10 ++++- Gems/LyShine/Code/Source/LyShine.h | 1 + Gems/LyShine/Code/Source/LyShineDebug.cpp | 22 +++++----- .../LyShine/Code/Source/UiCanvasComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiCanvasManager.cpp | 6 +-- Gems/LyShine/Code/Source/UiFaderComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiImageComponent.cpp | 2 +- .../Code/Source/UiImageSequenceComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiMaskComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiRenderer.cpp | 4 +- Gems/LyShine/Code/Source/UiTextComponent.cpp | 10 ++--- Gems/LyShine/Code/lyshine_static_files.cmake | 4 +- Gems/LyShine/gem.json | 3 +- Gems/LyShineExamples/Code/CMakeLists.txt | 4 +- .../Code/Source/UiCustomImageComponent.cpp | 2 +- Gems/MessagePopup/Code/CMakeLists.txt | 4 +- Gems/UiBasics/CMakeLists.txt | 1 + Gems/VirtualGamepad/Code/CMakeLists.txt | 4 +- 31 files changed, 125 insertions(+), 99 deletions(-) rename Gems/LyShine/Code/{Include/LyShine => Source}/Draw2d.h (98%) diff --git a/Gems/GameStateSamples/Code/CMakeLists.txt b/Gems/GameStateSamples/Code/CMakeLists.txt index 5d1d180de0..a07bef6a06 100644 --- a/Gems/GameStateSamples/Code/CMakeLists.txt +++ b/Gems/GameStateSamples/Code/CMakeLists.txt @@ -21,7 +21,7 @@ ly_add_target( INTERFACE Gem::GameState Gem::LocalUser - Gem::LyShine.Static + Gem::LyShine.Clients.API Gem::SaveData.Static Gem::MessagePopup.Static Legacy::CryCommon diff --git a/Gems/LyShine/Code/CMakeLists.txt b/Gems/LyShine/Code/CMakeLists.txt index 4f2c4e90a7..2b550b0e36 100644 --- a/Gems/LyShine/Code/CMakeLists.txt +++ b/Gems/LyShine/Code/CMakeLists.txt @@ -58,10 +58,13 @@ ly_add_target( # by default, load the above "Gem::LyShine" module in Client and Server applications: ly_create_alias(NAME LyShine.Clients NAMESPACE Gem TARGETS Gem::LyShine) ly_create_alias(NAME LyShine.Servers NAMESPACE Gem TARGETS Gem::LyShine) +# create an alias for other gems to depend on an LyShine public API (may be converted to a target in the future): +ly_create_alias(NAME LyShine.Clients.API NAMESPACE Gem TARGETS Gem::LyShine.Clients) +ly_create_alias(NAME LyShine.Servers.API NAMESPACE Gem TARGETS Gem::LyShine.Servers) if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( - NAME LyShine.Editor.Static STATIC + NAME LyShine.Tools.Static STATIC NAMESPACE Gem AUTOMOC AUTOUIC @@ -73,7 +76,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) . Source Editor - PUBLIC Include BUILD_DEPENDENCIES PRIVATE @@ -100,7 +102,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_target( - NAME LyShine.Editor GEM_MODULE + NAME LyShine.Tools GEM_MODULE NAMESPACE Gem FILES_CMAKE lyshine_common_module_files.cmake @@ -112,18 +114,18 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) . Source Editor - PUBLIC Include BUILD_DEPENDENCIES PRIVATE Legacy::CryCommon AZ::AzToolsFramework - Gem::LyShine.Editor.Static + Gem::LyShine.Tools.Static Gem::LmbrCentral.Editor Gem::TextureAtlas.Editor RUNTIME_DEPENDENCIES Gem::LmbrCentral.Editor Gem::TextureAtlas.Editor + Gem::UiBasics.Tools ) # by naming this target LyShine.Builders it ensures that it is loaded @@ -179,10 +181,9 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) Gem::LyShine.Builders.Static Gem::LmbrCentral.Editor Gem::TextureAtlas.Editor + RUNTIME_DEPENDENCIES + Gem::UiBasics.Builders ) - - # by default, load the above "Gem::LyShine.Editor" module in dev tools: - ly_create_alias(NAME LyShine.Tools NAMESPACE Gem TARGETS Gem::LyShine.Editor) endif() ################################################################################ @@ -241,7 +242,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) AZ::AzTest Legacy::CryCommon AZ::AssetBuilderSDK - Gem::LyShine.Editor.Static + Gem::LyShine.Tools.Static Gem::LyShine.Builders.Static Gem::LmbrCentral.Editor Gem::TextureAtlas diff --git a/Gems/LyShine/Code/Editor/GuideHelpers.cpp b/Gems/LyShine/Code/Editor/GuideHelpers.cpp index eb5966568e..b6d7acc57a 100644 --- a/Gems/LyShine/Code/Editor/GuideHelpers.cpp +++ b/Gems/LyShine/Code/Editor/GuideHelpers.cpp @@ -173,7 +173,7 @@ namespace GuideHelpers // the line is drawn as the inverse of the background color AZ::Color guideColor(1.0f, 1.0f, 1.0f, 1.0f); - CDraw2d::RenderState renderState; + IDraw2d::RenderState renderState; renderState.m_blendState.m_blendSource = AZ::RHI::BlendFactor::ColorDestInverse; renderState.m_blendState.m_blendDest = AZ::RHI::BlendFactor::Zero; diff --git a/Gems/LyShine/Code/Editor/ViewportCanvasBackground.cpp b/Gems/LyShine/Code/Editor/ViewportCanvasBackground.cpp index 668c4e8024..b1961de0a1 100644 --- a/Gems/LyShine/Code/Editor/ViewportCanvasBackground.cpp +++ b/Gems/LyShine/Code/Editor/ViewportCanvasBackground.cpp @@ -50,7 +50,7 @@ void ViewportCanvasBackground::Draw(Draw2dHelper& draw2d, const AZ::Vector2& can // now draw the same as Stretched but with UV's adjusted const AZ::Vector2 uvs[4] = { AZ::Vector2(0, 0), AZ::Vector2(uvScale.GetX(), 0), AZ::Vector2(uvScale.GetX(), uvScale.GetY()), AZ::Vector2(0, uvScale.GetY()) }; AZ::Color colorWhite(1.0f, 1.0f, 1.0f, 1.0f); - CDraw2d::VertexPosColUV verts[4]; + IDraw2d::VertexPosColUV verts[4]; for (int i = 0; i < 4; ++i) { verts[i].position = positions[i]; diff --git a/Gems/LyShine/Code/Editor/ViewportDragInteraction.h b/Gems/LyShine/Code/Editor/ViewportDragInteraction.h index 3b26b66308..6b48fc0133 100644 --- a/Gems/LyShine/Code/Editor/ViewportDragInteraction.h +++ b/Gems/LyShine/Code/Editor/ViewportDragInteraction.h @@ -8,7 +8,7 @@ #pragma once #include -#include +#include //! Abstract base class for drag interactions in the UI Editor viewport window. class ViewportDragInteraction diff --git a/Gems/LyShine/Code/Editor/ViewportHelpers.h b/Gems/LyShine/Code/Editor/ViewportHelpers.h index 8068f4af65..f2722fb6b8 100644 --- a/Gems/LyShine/Code/Editor/ViewportHelpers.h +++ b/Gems/LyShine/Code/Editor/ViewportHelpers.h @@ -7,7 +7,7 @@ */ #pragma once -#include +#include namespace ViewportHelpers { diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.cpp b/Gems/LyShine/Code/Editor/ViewportIcon.cpp index 3f0fdfaba0..33f2f40ffe 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.cpp +++ b/Gems/LyShine/Code/Editor/ViewportIcon.cpp @@ -6,7 +6,7 @@ * */ #include "EditorCommon.h" -#include +#include #include #include @@ -15,7 +15,7 @@ float ViewportIcon::m_dpiScaleFactor = 1.0f; ViewportIcon::ViewportIcon(const char* textureFilename) { - m_image = CDraw2d::LoadTexture(textureFilename); + m_image = Draw2dHelper::LoadTexture(textureFilename); } ViewportIcon::~ViewportIcon() @@ -48,7 +48,7 @@ void ViewportIcon::DrawImageAligned(Draw2dHelper& draw2d, AZ::Vector2& pivot, fl opacity); } -void ViewportIcon::DrawImageTiled(Draw2dHelper& draw2d, CDraw2d::VertexPosColUV* verts) +void ViewportIcon::DrawImageTiled(Draw2dHelper& draw2d, IDraw2d::VertexPosColUV* verts) { // Use default blending and rounding modes IDraw2d::Rounding rounding = IDraw2d::Rounding::Nearest; @@ -63,7 +63,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2 float endTexCoordU = fabsf((bound1.GetX() - bound0.GetX()) * pixelLengthForDottedLineTexture); float endTexCoordV = fabsf((bound1.GetY() - bound0.GetY()) * pixelLengthForDottedLineTexture); - CDraw2d::VertexPosColUV verts[2]; + IDraw2d::VertexPosColUV verts[2]; { verts[0].color = dottedColor; verts[1].color = dottedColor; @@ -158,7 +158,7 @@ void ViewportIcon::Draw(Draw2dHelper& draw2d, AZ::Vector2 anchorPos, const AZ::M AZ::Matrix4x4 moveFromPivotSpaceMat = AZ::Matrix4x4::CreateTranslation(pivot3); AZ::Matrix4x4 newTransform = transform * moveFromPivotSpaceMat * rotMat * moveToPivotSpaceMat; - CDraw2d::VertexPosColUV verts[4]; + IDraw2d::VertexPosColUV verts[4]; // points are a clockwise quad static const AZ::Vector2 uvs[4] = { AZ::Vector2(0.0f, 0.0f), AZ::Vector2(1.0f, 0.0f), AZ::Vector2(1.0f, 1.0f), AZ::Vector2(0.0f, 1.0f) @@ -251,7 +251,7 @@ void ViewportIcon::DrawDistanceLine(Draw2dHelper& draw2d, AZ::Vector2 start, AZ: const float pixelLengthForDottedLineTexture = 8.0f; float endTexCoordU = length / pixelLengthForDottedLineTexture; - CDraw2d::VertexPosColUV verts[2]; + IDraw2d::VertexPosColUV verts[2]; verts[0].position = start; verts[0].color = dottedColor; diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.h b/Gems/LyShine/Code/Editor/ViewportIcon.h index f815b244e9..fadd829bcf 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.h +++ b/Gems/LyShine/Code/Editor/ViewportIcon.h @@ -20,7 +20,7 @@ public: void DrawImageAligned(Draw2dHelper& draw2d, AZ::Vector2& pivot, float opacity); - void DrawImageTiled(Draw2dHelper& draw2d, CDraw2d::VertexPosColUV* verts); + void DrawImageTiled(Draw2dHelper& draw2d, IDraw2d::VertexPosColUV* verts); void Draw(Draw2dHelper& draw2d, AZ::Vector2 anchorPos, const AZ::Matrix4x4& transform, float iconRot = 0.0f, AZ::Color color = AZ::Color(1.0f, 1.0f, 1.0f, 1.0f)) const; diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.cpp b/Gems/LyShine/Code/Editor/ViewportWidget.cpp index 993f57aeeb..b481e9cbf1 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.cpp +++ b/Gems/LyShine/Code/Editor/ViewportWidget.cpp @@ -16,7 +16,6 @@ #include #include -#include #include "LyShine.h" #include "UiRenderer.h" @@ -27,6 +26,7 @@ #include "RulerWidget.h" #include "CanvasHelpers.h" #include "AssetDropHelpers.h" +#include "Draw2d.h" #include "QtHelpers.h" #include diff --git a/Gems/LyShine/Code/Include/LyShine/IDraw2d.h b/Gems/LyShine/Code/Include/LyShine/IDraw2d.h index 620b8c23c9..77dc5ac601 100644 --- a/Gems/LyShine/Code/Include/LyShine/IDraw2d.h +++ b/Gems/LyShine/Code/Include/LyShine/IDraw2d.h @@ -482,6 +482,50 @@ public: // static member functions return nullptr; } + //! Helper to load a texture + static AZ::Data::Instance LoadTexture(const AZStd::string& pathName) + { + if (gEnv && gEnv->pLyShine) // [LYSHINE_ATOM_TODO][GHI #3569] Remove LyShine global interface pointer from legacy global environment + { + return gEnv->pLyShine->LoadTexture(pathName); + } + + return nullptr; + } + + //! Given a position and size and an alignment return the top left corner of the aligned quad + static AZ::Vector2 Align(AZ::Vector2 position, AZ::Vector2 size, IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment) + { + AZ::Vector2 result = AZ::Vector2::CreateZero(); + switch (horizontalAlignment) + { + case IDraw2d::HAlign::Left: + result.SetX(position.GetX()); + break; + case IDraw2d::HAlign::Center: + result.SetX(position.GetX() - size.GetX() * 0.5f); + break; + case IDraw2d::HAlign::Right: + result.SetX(position.GetX() - size.GetX()); + break; + } + + switch (verticalAlignment) + { + case IDraw2d::VAlign::Top: + result.SetY(position.GetY()); + break; + case IDraw2d::VAlign::Center: + result.SetY(position.GetY() - size.GetY() * 0.5f); + break; + case IDraw2d::VAlign::Bottom: + result.SetY(position.GetY() - size.GetY()); + break; + } + + return result; + } + //! Round the X and Y coordinates of a point using the given rounding policy template static T RoundXY(T value, IDraw2d::Rounding roundingType) diff --git a/Gems/LyShine/Code/Include/LyShine/ILyShine.h b/Gems/LyShine/Code/Include/LyShine/ILyShine.h index 7832497d8c..71ca6ec074 100644 --- a/Gems/LyShine/Code/Include/LyShine/ILyShine.h +++ b/Gems/LyShine/Code/Include/LyShine/ILyShine.h @@ -9,12 +9,18 @@ #include #include +#include class IDraw2d; class ISprite; struct IUiAnimationSystem; class UiEntityContext; +namespace AZ::RPI +{ + class Image; +} + // The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the LYSHINE_EXPORTS // symbol defined in the StdAfx.h. this symbol should not be defined on any project @@ -82,6 +88,9 @@ public: //! Check if a sprite's texture asset exists. The .sprite sidecar file is optional and is not checked virtual bool DoesSpriteTextureAssetExist(const AZStd::string& pathname) = 0; + //! Load an image asset by texture pathname + virtual AZ::Data::Instance LoadTexture(const AZStd::string& pathName) = 0; + //! Perform post-initialization (script system will be available) virtual void PostInit() = 0; diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 2838ed4877..ff8c7f1c6d 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -6,7 +6,7 @@ * */ -#include +#include "Draw2d.h" #include #include "LyShinePassDataBus.h" @@ -215,7 +215,7 @@ void CDraw2d::DrawImageAligned(AZ::Data::Instance image, AZ::Vec HAlign horizontalAlignment, VAlign verticalAlignment, float opacity, float rotation, const AZ::Vector2* minMaxTexCoords, ImageOptions* imageOptions) { - AZ::Vector2 alignedPosition = Align(position, size, horizontalAlignment, verticalAlignment); + AZ::Vector2 alignedPosition = Draw2dHelper::Align(position, size, horizontalAlignment, verticalAlignment); DrawImage(image, alignedPosition, size, opacity, rotation, &position, minMaxTexCoords, imageOptions); } @@ -524,40 +524,6 @@ void CDraw2d::SetSortKey(int64_t key) // PUBLIC STATIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////// -AZ::Vector2 CDraw2d::Align(AZ::Vector2 position, AZ::Vector2 size, - HAlign horizontalAlignment, VAlign verticalAlignment) -{ - AZ::Vector2 result = AZ::Vector2::CreateZero(); - switch (horizontalAlignment) - { - case HAlign::Left: - result.SetX(position.GetX()); - break; - case HAlign::Center: - result.SetX(position.GetX() - size.GetX() * 0.5f); - break; - case HAlign::Right: - result.SetX(position.GetX() - size.GetX()); - break; - } - - switch (verticalAlignment) - { - case VAlign::Top: - result.SetY(position.GetY()); - break; - case VAlign::Center: - result.SetY(position.GetY() - size.GetY() * 0.5f); - break; - case VAlign::Bottom: - result.SetY(position.GetY() - size.GetY()); - break; - } - - return result; -} - //////////////////////////////////////////////////////////////////////////////////////////////////// AZ::Data::Instance CDraw2d::LoadTexture(const AZStd::string& pathName) { diff --git a/Gems/LyShine/Code/Include/LyShine/Draw2d.h b/Gems/LyShine/Code/Source/Draw2d.h similarity index 98% rename from Gems/LyShine/Code/Include/LyShine/Draw2d.h rename to Gems/LyShine/Code/Source/Draw2d.h index d138f41b03..6d400c6b55 100644 --- a/Gems/LyShine/Code/Include/LyShine/Draw2d.h +++ b/Gems/LyShine/Code/Source/Draw2d.h @@ -180,9 +180,6 @@ private: public: // static member functions - //! Given a position and size and an alignment return the top left corner of the aligned quad - static AZ::Vector2 Align(AZ::Vector2 position, AZ::Vector2 size, HAlign horizontalAlignment, VAlign verticalAlignment); - //! Helper to load a texture static AZ::Data::Instance LoadTexture(const AZStd::string& pathName); diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index 683d72f4ab..5a704329ef 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -43,11 +43,11 @@ #include "Sprite.h" #include "UiSerialize.h" #include "UiRenderer.h" +#include "Draw2d.h" #include #include #include -#include #if defined(LYSHINE_INTERNAL_UNIT_TEST) #include "TextMarkup.h" @@ -355,6 +355,12 @@ bool CLyShine::DoesSpriteTextureAssetExist(const AZStd::string& pathname) return CSprite::DoesSpriteTextureAssetExist(pathname); } +//////////////////////////////////////////////////////////////////////////////////////////////////// +AZ::Data::Instance CLyShine::LoadTexture(const AZStd::string& pathname) +{ + return CDraw2d::LoadTexture(pathname); +} + //////////////////////////////////////////////////////////////////////////////////////////////////// void CLyShine::PostInit() { @@ -691,7 +697,7 @@ void CLyShine::RenderUiCursor() AZ::RHI::Size cursorSize = m_uiCursorTexture->GetDescriptor().m_size; const AZ::Vector2 dimensions(aznumeric_cast(cursorSize.m_width), aznumeric_cast(cursorSize.m_height)); - CDraw2d::ImageOptions imageOptions; + IDraw2d::ImageOptions imageOptions; imageOptions.m_clamp = true; const float opacity = 1.0f; const float rotation = 0.0f; diff --git a/Gems/LyShine/Code/Source/LyShine.h b/Gems/LyShine/Code/Source/LyShine.h index 82f902a9f8..eab52258c1 100644 --- a/Gems/LyShine/Code/Source/LyShine.h +++ b/Gems/LyShine/Code/Source/LyShine.h @@ -72,6 +72,7 @@ public: ISprite* LoadSprite(const AZStd::string& pathname) override; ISprite* CreateSprite(const AZStd::string& renderTargetName) override; bool DoesSpriteTextureAssetExist(const AZStd::string& pathname) override; + AZ::Data::Instance LoadTexture(const AZStd::string& pathname) override; void PostInit() override; diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index bb57e70857..7e99652f45 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -7,7 +7,7 @@ */ #include "LyShineDebug.h" #include "IConsole.h" -#include +#include #include @@ -377,7 +377,7 @@ static void DebugDrawColoredBox(AZ::Vector2 pos, AZ::Vector2 size, AZ::Color col { IDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - CDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); + IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); imageOptions.color = color.GetAsVector3(); auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); draw2d->DrawImageAligned(whiteTexture, pos, size, horizontalAlignment, verticalAlignment, @@ -392,7 +392,7 @@ static void DebugDrawStringWithSizeBox(AZStd::string_view font, unsigned int eff { IDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - CDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); + IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); if (!font.empty()) { textOptions.fontName = font; @@ -618,7 +618,7 @@ static AZ::Vector2 DebugDrawFontColorTestBox(AZ::Vector2 pos, const char* string float pointSize = 32.0f; const float spacing = 6.0f; - CDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); + IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); textOptions.effectIndex = 1; // no drop shadow baked in textOptions.color = color; @@ -742,7 +742,7 @@ static void DebugDraw2dImageColor() AZ::Data::Instance texture = GetMonoAlphaTestTexture(); - CDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); + IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); draw2d->DrawText( "Testing image colors, image is black and white, top row is opacity=1, bottom row is opacity = 0.5", @@ -780,7 +780,7 @@ static void DebugDraw2dImageBlendMode() AZ::Data::Instance texture = GetColorAlphaTestTexture(); - CDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); + IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); draw2d->DrawText("Testing blend modes, src blend changes across x-axis, dst blend changes across y axis", AZ::Vector2(20, 20), 16); @@ -801,7 +801,7 @@ static void DebugDraw2dImageBlendMode() AZ::Vector2 pos(xStart + xSpacing * srcIndex, yStart + ySpacing * dstIndex); // first draw a background with varying color and alpha - CDraw2d::VertexPosColUV verts[4] = + IDraw2d::VertexPosColUV verts[4] = { { // top left AZ::Vector2(pos.GetX(), pos.GetY()), @@ -828,7 +828,7 @@ static void DebugDraw2dImageBlendMode() // Draw the image with this color - CDraw2d::RenderState renderState; + IDraw2d::RenderState renderState; renderState.m_blendState.m_blendSource = g_srcBlendModes[srcIndex]; renderState.m_blendState.m_blendDest = g_dstBlendModes[dstIndex]; draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions); @@ -845,7 +845,7 @@ static void DebugDraw2dImageUVs() AZ::Data::Instance texture = GetColorTestTexture(); - CDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); + IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); draw2d->DrawText( "Testing DrawImage with minMaxTexCoords. Full image, top left quadrant, middle section, full flipped", @@ -894,7 +894,7 @@ static void DebugDraw2dImagePixelRounding() AZ::Data::Instance texture = GetColorTestTexture(); - CDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); + IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); draw2d->DrawText("Testing DrawImage pixel rounding options", AZ::Vector2(20, 20), 16); @@ -933,7 +933,7 @@ static void DebugDraw2dLineBasic() { IDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - CDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); + IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); draw2d->DrawText("Testing DrawLine", AZ::Vector2(20, 20), 16); diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp index 0a21f92119..ea6e3681a3 100644 --- a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.cpp b/Gems/LyShine/Code/Source/UiCanvasManager.cpp index 70646246f0..fc373f17f6 100644 --- a/Gems/LyShine/Code/Source/UiCanvasManager.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasManager.cpp @@ -6,7 +6,7 @@ * */ #include "UiCanvasManager.h" -#include +#include #include "UiCanvasFileObject.h" #include "UiCanvasComponent.h" @@ -1020,7 +1020,7 @@ void UiCanvasManager::DebugDisplayCanvasData(int setting) const // local function to write a line of text (with a background rect) and increment Y offset AZStd::function WriteLine = [&](const char* buffer, const AZ::Vector3& color) { - CDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); + IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); textOptions.color = color; AZ::Vector2 textSize = draw2d->GetTextSize(buffer, fontSize, &textOptions); AZ::Vector2 rectTopLeft = AZ::Vector2(xOffset - 2, yOffset); @@ -1174,7 +1174,7 @@ void UiCanvasManager::DebugDisplayDrawCallData() const // local function to write a line of text (with a background rect) and increment Y offset AZStd::function WriteLine = [&](const char* buffer, const AZ::Vector3& color) { - CDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); + IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); textOptions.color = color; AZ::Vector2 textSize = draw2d->GetTextSize(buffer, fontSize, &textOptions); AZ::Vector2 rectTopLeft = AZ::Vector2(xOffset - 2, yOffset); diff --git a/Gems/LyShine/Code/Source/UiFaderComponent.cpp b/Gems/LyShine/Code/Source/UiFaderComponent.cpp index e1f5153e99..e84e5162b5 100644 --- a/Gems/LyShine/Code/Source/UiFaderComponent.cpp +++ b/Gems/LyShine/Code/Source/UiFaderComponent.cpp @@ -7,7 +7,7 @@ */ #include "UiFaderComponent.h" #include "RenderGraph.h" -#include +#include #include #include diff --git a/Gems/LyShine/Code/Source/UiImageComponent.cpp b/Gems/LyShine/Code/Source/UiImageComponent.cpp index baf210a629..a8b4210d6b 100644 --- a/Gems/LyShine/Code/Source/UiImageComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageComponent.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include diff --git a/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp b/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp index 4e7d22d96a..3559dc6306 100644 --- a/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp @@ -9,7 +9,7 @@ #include "Sprite.h" #include "RenderGraph.h" -#include +#include #include #include #include diff --git a/Gems/LyShine/Code/Source/UiMaskComponent.cpp b/Gems/LyShine/Code/Source/UiMaskComponent.cpp index 09975d1351..67ba8ee0fb 100644 --- a/Gems/LyShine/Code/Source/UiMaskComponent.cpp +++ b/Gems/LyShine/Code/Source/UiMaskComponent.cpp @@ -6,7 +6,7 @@ * */ #include "UiMaskComponent.h" -#include +#include #include #include diff --git a/Gems/LyShine/Code/Source/UiRenderer.cpp b/Gems/LyShine/Code/Source/UiRenderer.cpp index 3b835dec92..a9c56ece90 100644 --- a/Gems/LyShine/Code/Source/UiRenderer.cpp +++ b/Gems/LyShine/Code/Source/UiRenderer.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC MEMBER FUNCTIONS @@ -449,7 +449,7 @@ void UiRenderer::DebugDisplayTextureData(int recordingOption) // local function to write a line of text (with a background rect) and increment Y offset AZStd::function WriteLine = [&](const char* buffer, const AZ::Vector3& color) { - CDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); + IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); textOptions.color = color; AZ::Vector2 textSize = draw2d->GetTextSize(buffer, fontSize, &textOptions); AZ::Vector2 rectTopLeft = AZ::Vector2(xOffset - 2, yOffset); diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index 01cfd49e99..aa0235470a 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include @@ -1105,7 +1105,7 @@ UiTextComponent::InlineImage::InlineImage(const AZStd::string& texturePathname, else { // Load the texture - m_texture = CDraw2d::LoadTexture(m_filepath); + m_texture = Draw2dHelper::LoadTexture(m_filepath); if (m_texture) { AZ::RHI::Size size = m_texture->GetDescriptor().m_size; @@ -1157,7 +1157,7 @@ bool UiTextComponent::InlineImage::OnAtlasUnloaded(const TextureAtlasNamespace:: else { // Load the texture - m_texture = CDraw2d::LoadTexture(m_filepath); + m_texture = Draw2dHelper::LoadTexture(m_filepath); } return true; } @@ -2675,7 +2675,7 @@ void UiTextComponent::GetClickableTextRects(UiClickableTextInterface::ClickableT } else { - alignedPosition = CDraw2d::Align(pos, drawBatchLine.lineSize, m_textHAlignment, IDraw2d::VAlign::Top); // y is already aligned + alignedPosition = Draw2dHelper::Align(pos, drawBatchLine.lineSize, m_textHAlignment, IDraw2d::VAlign::Top); // y is already aligned } alignedPosition.SetY(alignedPosition.GetY() + newlinePosYIncrement); @@ -4043,7 +4043,7 @@ void UiTextComponent::RenderDrawBatchLines( } else { - alignedPosition = CDraw2d::Align(pos, drawBatchLine.lineSize, m_textHAlignment, IDraw2d::VAlign::Top); // y is already aligned + alignedPosition = Draw2dHelper::Align(pos, drawBatchLine.lineSize, m_textHAlignment, IDraw2d::VAlign::Top); // y is already aligned } alignedPosition.SetY(alignedPosition.GetY() + newlinePosYIncrement); diff --git a/Gems/LyShine/Code/lyshine_static_files.cmake b/Gems/LyShine/Code/lyshine_static_files.cmake index 1adbe1b796..925658e756 100644 --- a/Gems/LyShine/Code/lyshine_static_files.cmake +++ b/Gems/LyShine/Code/lyshine_static_files.cmake @@ -7,8 +7,6 @@ # set(FILES - Source/Draw2d.cpp - Include/LyShine/Draw2d.h Include/LyShine/IDraw2d.h Include/LyShine/IRenderGraph.h Include/LyShine/ISprite.h @@ -88,6 +86,8 @@ set(FILES Include/LyShine/Bus/World/UiCanvasOnMeshBus.h Include/LyShine/Bus/World/UiCanvasRefBus.h Include/LyShine/Bus/Tools/UiSystemToolsBus.h + Source/Draw2d.cpp + Source/Draw2d.h Source/LyShine.cpp Source/LyShine.h Source/LyShinePassDataBus.h diff --git a/Gems/LyShine/gem.json b/Gems/LyShine/gem.json index f3c3fc2c67..8dcac6404a 100644 --- a/Gems/LyShine/gem.json +++ b/Gems/LyShine/gem.json @@ -24,6 +24,7 @@ "Atom_Bootstrap", "AtomFont", "TextureAtlas", - "AtomToolsFramework" + "AtomToolsFramework", + "UiBasics" ] } diff --git a/Gems/LyShineExamples/Code/CMakeLists.txt b/Gems/LyShineExamples/Code/CMakeLists.txt index 6e8f53d5cd..40032d6342 100644 --- a/Gems/LyShineExamples/Code/CMakeLists.txt +++ b/Gems/LyShineExamples/Code/CMakeLists.txt @@ -21,7 +21,7 @@ ly_add_target( Gem::LmbrCentral PUBLIC Legacy::CryCommon - Gem::LyShine.Static + Gem::LyShine.Clients.API ) ly_add_target( @@ -42,7 +42,7 @@ ly_add_target( # if enabled, LyShineExamples is used by all kinds of applications, however, the dependency to LmbrCentral is different # per application type -ly_create_alias(NAME LyShineExamples.Builders NAMESPACE Gem TARGETS Gem::LyShineExamples Gem::LmbrCentral.Editor) +ly_create_alias(NAME LyShineExamples.Builders NAMESPACE Gem TARGETS Gem::LyShineExamples Gem::UiBasics.Builders Gem::LmbrCentral.Editor) ly_create_alias(NAME LyShineExamples.Tools NAMESPACE Gem TARGETS Gem::LyShineExamples Gem::LmbrCentral.Editor) ly_create_alias(NAME LyShineExamples.Clients NAMESPACE Gem TARGETS Gem::LyShineExamples Gem::LmbrCentral) ly_create_alias(NAME LyShineExamples.Servers NAMESPACE Gem TARGETS Gem::LyShineExamples Gem::LmbrCentral) diff --git a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp index 542e18b98c..e8b0e4370a 100644 --- a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp +++ b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include diff --git a/Gems/MessagePopup/Code/CMakeLists.txt b/Gems/MessagePopup/Code/CMakeLists.txt index 51ec1a3bd1..2ed9c71632 100644 --- a/Gems/MessagePopup/Code/CMakeLists.txt +++ b/Gems/MessagePopup/Code/CMakeLists.txt @@ -19,7 +19,7 @@ ly_add_target( BUILD_DEPENDENCIES PUBLIC Legacy::CryCommon - Gem::LyShine + Gem::LyShine.Clients.API ) ly_add_target( @@ -39,4 +39,4 @@ ly_add_target( # MessagePopup is used only in client applications ly_create_alias(NAME MessagePopup.Clients NAMESPACE Gem TARGETS Gem::MessagePopup) - +ly_create_alias(NAME MessagePopup.Builders NAMESPACE Gem TARGETS Gem::UiBasics.Builders) diff --git a/Gems/UiBasics/CMakeLists.txt b/Gems/UiBasics/CMakeLists.txt index 8d71bd08c7..9c3cf01d26 100644 --- a/Gems/UiBasics/CMakeLists.txt +++ b/Gems/UiBasics/CMakeLists.txt @@ -9,4 +9,5 @@ # This will export its "SourcePaths" to the generated "cmake_dependencies..assetbuilder.setreg" if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_create_alias(NAME UiBasics.Builders NAMESPACE Gem) + ly_create_alias(NAME UiBasics.Tools NAMESPACE Gem) endif() diff --git a/Gems/VirtualGamepad/Code/CMakeLists.txt b/Gems/VirtualGamepad/Code/CMakeLists.txt index d32834633f..6700004a30 100644 --- a/Gems/VirtualGamepad/Code/CMakeLists.txt +++ b/Gems/VirtualGamepad/Code/CMakeLists.txt @@ -21,7 +21,7 @@ ly_add_target( AZ::AzCore AZ::AzFramework Legacy::CryCommon - Gem::LyShine + Gem::LyShine.Clients.API ) ly_add_target( @@ -42,4 +42,4 @@ ly_add_target( # the virtual gamepad is needed everywhere except servers: ly_create_alias(NAME VirtualGamepad.Clients NAMESPACE Gem TARGETS Gem::VirtualGamepad) ly_create_alias(NAME VirtualGamepad.Tools NAMESPACE Gem TARGETS Gem::VirtualGamepad) -ly_create_alias(NAME VirtualGamepad.Builders NAMESPACE Gem TARGETS Gem::VirtualGamepad) +ly_create_alias(NAME VirtualGamepad.Builders NAMESPACE Gem TARGETS Gem::VirtualGamepad Gem::UiBasics.Builders) From 13d6451b6a806e23aa00e664a90d5c7a4d272381 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Thu, 13 Jan 2022 13:24:48 -0800 Subject: [PATCH 078/108] update parser and unit tests to respect the new way slots are added to user function nodes Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Grammar/AbstractCodeModel.cpp | 70 +- ...nitTest_PromotedUserVariables.scriptcanvas | 858 +++++++++++++ ...PromotedUserVariablesFunction.scriptcanvas | 1100 +++++++++++++++++ .../Tests/ScriptCanvas_RuntimeInterpreted.cpp | 5 + 4 files changed, 2012 insertions(+), 21 deletions(-) create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariables.scriptcanvas create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariablesFunction.scriptcanvas diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 299718fd0f..b2194e1bd0 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -240,7 +240,6 @@ namespace ScriptCanvas // #sc_user_slot_variable_ux consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering m_sourceVariableByDatum.insert(AZStd::make_pair(datum, &variablePair.second)); } - } for (auto& sourceVariable : sortedVariables) @@ -1714,6 +1713,7 @@ namespace ScriptCanvas auto iter = m_inputVariableByNodelingInSlot.find(input); if (iter != m_inputVariableByNodelingInSlot.end()) { + // #sc_user_slot_variable_ux don't add variable name if not necessary VariablePtr variable = iter->second; const Slot* slot = iter->first; variable->m_name = call->ModScope()->AddVariableName(slot->GetName()); @@ -4644,35 +4644,59 @@ namespace ScriptCanvas void AbstractCodeModel::ParseNodelingVariables(const Node& node, NodelingType nodelingType) { - // #sc_user_slot_variable_ux adjust once datums are more coordinated - auto createVariablesSlots = [&](AZStd::unordered_map& variablesBySlots, const AZStd::vector& slots, bool slotHasDatum) + // This function accounts for all the ways users have been able to introduce input/output data in their SC function definitions. + // They have been able to create slots, variables, or both. This function reads the datums to create the correct ACM + // variable per required SC user variable. It uses slots as the key, and checks datums in the SC variable list for possible + // matches. + auto createVariablesSlots = [&](AZStd::unordered_map& variablesBySlots, const AZStd::vector& slots, bool errorOnMissingDatum) { for (const auto& slot : slots) { auto variable = AZStd::make_shared(); + auto variableDatum = slot->FindDatum(); + bool initializeDatum = true; - if (slotHasDatum) + if (variableDatum) { - auto variableDatum = slot->FindDatum(); - if (!variableDatum) - { - AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("Datum missing from Slot %s on Node %s", slot->GetName().data(), node.GetNodeName().c_str()))); - return; - } + initializeDatum = false; + } + else if (errorOnMissingDatum) + { + AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("Datum missing from Slot %s on Node %s", slot->GetName().data(), node.GetNodeName().c_str()))); + return; + } - // #sc_user_slot_variable_ux consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering -// auto iter = m_sourceVariableByDatum.find(variableDatum); -// if (iter == m_sourceVariableByDatum.end()) -// { -// AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("Datum missing from Slot %s on Node %s", slot->GetName().data(), node.GetNodeName().c_str()))); -// return; -// } -// variable->m_sourceVariableId = iter->second->GetVariableId(); + // find the other variable + auto iter = m_sourceVariableByDatum.find(variableDatum); + if (iter != m_sourceVariableByDatum.end()) + { + initializeDatum = false; + } + else if (!variableDatum && errorOnMissingDatum) + { + AddError(nullptr, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("Datum missing from Slot %s on Node %s", slot->GetName().data(), node.GetNodeName().c_str()))); + return; + } + + VariablePtr premadeVariable = iter != m_sourceVariableByDatum.end() + ? AZStd::const_pointer_cast(FindVariable(iter->second->GetVariableId())) + : VariablePtr(); + + if (premadeVariable) + { + initializeDatum = false; + variable = premadeVariable; + } + + variable->m_sourceSlotId = slot->GetId(); + + if (!premadeVariable && variableDatum) + { variable->m_datum = *variableDatum; } - else + + if (initializeDatum) { - // make a new datum and a source slot id and all that variable->m_datum.SetType(slot->GetDataType()); } @@ -4680,7 +4704,11 @@ namespace ScriptCanvas variable->m_sourceSlotId = slot->GetId(); variable->m_isFromFunctionDefinitionSlot = true; variablesBySlots.insert({ slot, variable }); - m_variables.push_back(variable); + + if (!premadeVariable) + { + m_variables.push_back(variable); + } } }; diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariables.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariables.scriptcanvas new file mode 100644 index 0000000000..6ac83f4b62 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariables.scriptcanvas @@ -0,0 +1,858 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "ScriptCanvasData", + "ClassData": { + "m_scriptCanvas": { + "Id": { + "id": 8475300026301128284 + }, + "Name": "Script Canvas Graph", + "Components": { + "Component_[11907165653188402756]": { + "$type": "EditorGraphVariableManagerComponent", + "Id": 11907165653188402756 + }, + "Component_[3578973614457412392]": { + "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph", + "Id": 3578973614457412392, + "m_graphData": { + "m_nodes": [ + { + "Id": { + "id": 16019084446641 + }, + "Name": "SC-Node(Start)", + "Components": { + "Component_[1767232296153779726]": { + "$type": "Start", + "Id": 1767232296153779726, + "Slots": [ + { + "id": { + "m_id": "{635D7286-4B19-44D4-8F5E-1B4A0CF85C9E}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled when the entity that owns this graph is fully activated.", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ] + } + } + }, + { + "Id": { + "id": 7910364941488 + }, + "Name": "SC-Node(Mark Complete)", + "Components": { + "Component_[1885955816756801547]": { + "$type": "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF} Method", + "Id": 1885955816756801547, + "Slots": [ + { + "isVisibile": false, + "id": { + "m_id": "{31ABE549-E2E3-440E-884C-9F7FD4185C1D}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityId: 0", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{4FFA1776-D933-4475-BB3C-5BD7FAD47E2B}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Report", + "toolTip": "additional notes for the test report", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{F8687B16-9C64-4B5E-B000-035D9B3712EF}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{0E8012D1-A36B-4BCC-86C9-7D4F93816923}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 4276206253 + } + }, + { + "isOverloadedStorage": false, + "scriptCanvasType": { + "m_type": 5 + }, + "isNullPointer": false, + "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string", + "value": "", + "label": "Report" + } + ], + "methodType": 2, + "methodName": "Mark Complete", + "className": "Unit Testing", + "inputSlots": [ + { + "m_id": "{31ABE549-E2E3-440E-884C-9F7FD4185C1D}" + }, + { + "m_id": "{4FFA1776-D933-4475-BB3C-5BD7FAD47E2B}" + } + ], + "prettyClassName": "Unit Testing" + } + } + }, + { + "Id": { + "id": 16611789933489 + }, + "Name": "SC-Node(Expect Equal)", + "Components": { + "Component_[6935885723653735789]": { + "$type": "MethodOverloaded", + "Id": 6935885723653735789, + "Slots": [ + { + "isVisibile": false, + "id": { + "m_id": "{E2AB1183-3D7C-479C-88D5-8C90042F9D3F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "EntityId: 0", + "DisplayDataType": { + "m_type": 1 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{8D954D4E-D65E-47E4-8979-BAE900582B38}" + }, + "DynamicTypeOverride": 1, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "OverloadContract" + } + ], + "slotName": "Candidate", + "toolTip": "left of ==", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{17DA7626-AA06-4574-8F27-9DE230F03639}" + }, + "DynamicTypeOverride": 1, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "OverloadContract" + } + ], + "slotName": "Reference", + "toolTip": "right of ==", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{B442C3D0-F6F5-4689-982B-67CDF723D505}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Report", + "toolTip": "additional notes for the test report", + "DisplayDataType": { + "m_type": 5 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{33531BA3-2152-4F66-BFDA-CEAC2EB631C7}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{A8A9AB24-E5B2-4947-85CC-F87AD9F97FEB}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 1 + }, + "isNullPointer": false, + "$type": "EntityId", + "value": { + "id": 4276206253 + } + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Candidate" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 7.0, + "label": "Reference" + }, + { + "scriptCanvasType": { + "m_type": 5 + }, + "isNullPointer": false, + "$type": "{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9} AZStd::string", + "value": "", + "label": "Report" + } + ], + "methodType": 2, + "methodName": "Expect Equal", + "className": "Unit Testing", + "inputSlots": [ + { + "m_id": "{E2AB1183-3D7C-479C-88D5-8C90042F9D3F}" + }, + { + "m_id": "{8D954D4E-D65E-47E4-8979-BAE900582B38}" + }, + { + "m_id": "{17DA7626-AA06-4574-8F27-9DE230F03639}" + }, + { + "m_id": "{B442C3D0-F6F5-4689-982B-67CDF723D505}" + } + ], + "orderedInputSlotIds": [ + { + "m_id": "{E2AB1183-3D7C-479C-88D5-8C90042F9D3F}" + }, + { + "m_id": "{8D954D4E-D65E-47E4-8979-BAE900582B38}" + }, + { + "m_id": "{17DA7626-AA06-4574-8F27-9DE230F03639}" + }, + { + "m_id": "{B442C3D0-F6F5-4689-982B-67CDF723D505}" + } + ], + "outputSlotIds": [ + {} + ] + } + } + }, + { + "Id": { + "id": 15443558828977 + }, + "Name": "FunctionCallNode", + "Components": { + "Component_[9383725529787702808]": { + "$type": "FunctionCallNode", + "Id": 9383725529787702808, + "Slots": [ + { + "id": { + "m_id": "{32BD3CC0-AA44-4B1F-966D-4FF1561E4BC5}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "IncrementNumber", + "DisplayGroup": { + "Value": 921414446 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{EBE31443-CFB9-41B1-8DBA-127DB07A405A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "IncrementMe", + "DisplayGroup": { + "Value": 921414446 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{7FDF8233-D26E-4EBE-9D68-1074FD9B9999}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "DisplayGroup": { + "Value": 921414446 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{3A29CBC7-A727-4DBD-8319-0D31D299A9F0}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Incremented", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 2732307328 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 6.0, + "label": "IncrementMe" + } + ], + "m_sourceId": "{5F36B80D-9546-478E-AD33-BF4AFEC8FF01}", + "m_asset": { + "assetId": { + "guid": "{35A24A1D-57B7-5B0A-89C9-8BBA7657ECA5}", + "subId": 3756448882 + }, + "assetHint": "scriptcanvas/unittests/ly_sc_unittest_promoteduservariablesfunction.scriptcanvas_fn_compiled" + }, + "m_slotExecutionMap": { + "ins": [ + { + "_slotId": { + "m_id": "{32BD3CC0-AA44-4B1F-966D-4FF1561E4BC5}" + }, + "_inputs": [ + { + "_slotId": { + "m_id": "{EBE31443-CFB9-41B1-8DBA-127DB07A405A}" + }, + "_interfaceSourceId": { + "m_id": "{55F1434B-40C1-40AA-91C8-A65D6F2AFDC3}" + } + } + ], + "_outs": [ + { + "_slotId": { + "m_id": "{7FDF8233-D26E-4EBE-9D68-1074FD9B9999}" + }, + "_name": "Out", + "_outputs": [ + { + "_slotId": { + "m_id": "{3A29CBC7-A727-4DBD-8319-0D31D299A9F0}" + }, + "_interfaceSourceId": { + "m_id": "{81088CD0-BC45-4EB8-A823-DE442BF0541C}" + } + } + ], + "_interfaceSourceId": "{E9A0BF28-5910-4B0B-B82F-6519BCC1A33A}" + } + ], + "_parsedName": "IncrementNumber_scvm", + "_interfaceSourceId": "{5F36B80D-9546-478E-AD33-BF4AFEC8FF01}" + } + ] + }, + "m_slotExecutionMapSourceInterface": { + "ins": [ + { + "displayName": "IncrementNumber", + "parsedName": "IncrementNumber_scvm", + "inputs": [ + { + "displayName": "IncrementMe", + "parsedName": "IncrementMe_scvm_1", + "datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "sourceID": { + "m_id": "{55F1434B-40C1-40AA-91C8-A65D6F2AFDC3}" + } + } + ], + "outs": [ + { + "displayName": "Out", + "parsedName": "Out", + "outputs": [ + { + "displayName": "Incremented", + "parsedName": "Incremented_scvm_1", + "type": { + "m_type": 3 + }, + "sourceID": { + "m_id": "{81088CD0-BC45-4EB8-A823-DE442BF0541C}" + } + } + ], + "sourceID": "{E9A0BF28-5910-4B0B-B82F-6519BCC1A33A}" + } + ], + "isPure": true, + "sourceID": "{5F36B80D-9546-478E-AD33-BF4AFEC8FF01}" + } + ], + "outKeys": [ + { + "Value": 3119148441 + } + ], + "namespacePath": [ + "scriptcanvas", + "unittests", + "ly_sc_unittest_promoteduservariablesfunction_vm" + ] + } + } + } + } + ], + "m_connections": [ + { + "Id": { + "id": 16482940914609 + }, + "Name": "srcEndpoint=(On Graph Start: Out), destEndpoint=(Function Call Node: IncrementNumber)", + "Components": { + "Component_[1325606044371455697]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 1325606044371455697, + "sourceEndpoint": { + "nodeId": { + "id": 16019084446641 + }, + "slotId": { + "m_id": "{635D7286-4B19-44D4-8F5E-1B4A0CF85C9E}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 15443558828977 + }, + "slotId": { + "m_id": "{32BD3CC0-AA44-4B1F-966D-4FF1561E4BC5}" + } + } + } + } + }, + { + "Id": { + "id": 17672646855601 + }, + "Name": "srcEndpoint=(Function Call Node: Out), destEndpoint=(Expect Equal: In)", + "Components": { + "Component_[553888750995224414]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 553888750995224414, + "sourceEndpoint": { + "nodeId": { + "id": 15443558828977 + }, + "slotId": { + "m_id": "{7FDF8233-D26E-4EBE-9D68-1074FD9B9999}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 16611789933489 + }, + "slotId": { + "m_id": "{33531BA3-2152-4F66-BFDA-CEAC2EB631C7}" + } + } + } + } + }, + { + "Id": { + "id": 18003359337393 + }, + "Name": "srcEndpoint=(Function Call Node: Incremented), destEndpoint=(Expect Equal: Candidate)", + "Components": { + "Component_[6929789752232921563]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 6929789752232921563, + "sourceEndpoint": { + "nodeId": { + "id": 15443558828977 + }, + "slotId": { + "m_id": "{3A29CBC7-A727-4DBD-8319-0D31D299A9F0}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 16611789933489 + }, + "slotId": { + "m_id": "{8D954D4E-D65E-47E4-8979-BAE900582B38}" + } + } + } + } + }, + { + "Id": { + "id": 8902502386864 + }, + "Name": "srcEndpoint=(Expect Equal: Out), destEndpoint=(Mark Complete: In)", + "Components": { + "Component_[11962156650601495433]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 11962156650601495433, + "sourceEndpoint": { + "nodeId": { + "id": 16611789933489 + }, + "slotId": { + "m_id": "{A8A9AB24-E5B2-4947-85CC-F87AD9F97FEB}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7910364941488 + }, + "slotId": { + "m_id": "{F8687B16-9C64-4B5E-B000-035D9B3712EF}" + } + } + } + } + } + ] + }, + "m_assetType": "{1D497BC7-F97F-0000-80C2-359B6A010000}", + "versionData": { + "_grammarVersion": 1, + "_runtimeVersion": 1, + "_fileVersion": 1 + }, + "GraphCanvasData": [ + { + "Key": { + "id": 7910364941488 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 620.0, + 320.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{69405A2B-8669-41A0-9660-74C8ECCE8B84}" + } + } + } + }, + { + "Key": { + "id": 15443558828977 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 100.0, + 100.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{61B5E23D-2C56-4183-9606-AC0A4B788B7E}" + } + } + } + }, + { + "Key": { + "id": 16019084446641 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "TimeNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -80.0, + 60.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{A7B4E93B-07A1-43DC-BE07-4DC5A1D64352}" + } + } + } + }, + { + "Key": { + "id": 16611789933489 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MethodNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 300.0, + 300.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".method" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{5EDF60ED-BF05-4AC4-85D9-5988FFE7C2A7}" + } + } + } + }, + { + "Key": { + "id": 8475300026301128284 + }, + "Value": { + "ComponentData": { + "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { + "$type": "SceneComponentSaveData" + } + } + } + } + ], + "StatisticsHelper": { + "InstanceCounter": [ + { + "Key": 4053150093067829293, + "Value": 1 + }, + { + "Key": 4199610336680704683, + "Value": 1 + }, + { + "Key": 6740857896271713458, + "Value": 1 + }, + { + "Key": 10204019744198319120, + "Value": 1 + } + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariablesFunction.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariablesFunction.scriptcanvas new file mode 100644 index 0000000000..0fe5b1a730 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_PromotedUserVariablesFunction.scriptcanvas @@ -0,0 +1,1100 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "ScriptCanvasData", + "ClassData": { + "m_scriptCanvas": { + "Id": { + "id": 8918912361393065975 + }, + "Name": "Script Canvas Graph", + "Components": { + "Component_[14098532328271403379]": { + "$type": "EditorGraphVariableManagerComponent", + "Id": 14098532328271403379, + "m_variableData": { + "m_nameVariableMap": [ + { + "Key": { + "m_id": "{55F1434B-40C1-40AA-91C8-A65D6F2AFDC3}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0 + }, + "VariableId": { + "m_id": "{55F1434B-40C1-40AA-91C8-A65D6F2AFDC3}" + }, + "VariableName": "IncrementMe", + "Scope": 1 + } + }, + { + "Key": { + "m_id": "{71AAA826-F605-4EA7-8445-76CBCE253BE0}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 0 + }, + "isNullPointer": false, + "$type": "bool", + "value": false + }, + "VariableId": { + "m_id": "{71AAA826-F605-4EA7-8445-76CBCE253BE0}" + }, + "VariableName": "OnlyOne", + "Scope": 1 + } + }, + { + "Key": { + "m_id": "{793CF8BD-AF82-484E-AFD3-54EA328D9663}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 0 + }, + "isNullPointer": false, + "$type": "bool", + "value": false, + "label": "alsoTwo" + }, + "VariableId": { + "m_id": "{793CF8BD-AF82-484E-AFD3-54EA328D9663}" + }, + "VariableName": "alsoTwo", + "Scope": 1 + } + }, + { + "Key": { + "m_id": "{81088CD0-BC45-4EB8-A823-DE442BF0541C}" + }, + "Value": { + "Datum": { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Incremented" + }, + "VariableId": { + "m_id": "{81088CD0-BC45-4EB8-A823-DE442BF0541C}" + }, + "VariableName": "Incremented", + "Scope": 1 + } + } + ] + } + }, + "Component_[2840022707551160176]": { + "$type": "{4D755CA9-AB92-462C-B24F-0B3376F19967} Graph", + "Id": 2840022707551160176, + "m_graphData": { + "m_nodes": [ + { + "Id": { + "id": 7454919658417 + }, + "Name": "SC Node(SetVariable)", + "Components": { + "Component_[13386694676262750118]": { + "$type": "SetVariableNode", + "Id": 13386694676262750118, + "Slots": [ + { + "id": { + "m_id": "{22483279-E500-40D5-A61B-2C78DAC3319A}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the variable referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{17296A41-81F9-444D-BA2E-B8DAD7C62B10}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced variable has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{8D9CBBAD-5F75-4397-8139-B7FE79C48DFD}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A21214FF-8D17-48B1-9A29-E805230F8942}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number" + } + ], + "m_variableId": { + "m_id": "{81088CD0-BC45-4EB8-A823-DE442BF0541C}" + }, + "m_variableDataInSlotId": { + "m_id": "{8D9CBBAD-5F75-4397-8139-B7FE79C48DFD}" + }, + "m_variableDataOutSlotId": { + "m_id": "{A21214FF-8D17-48B1-9A29-E805230F8942}" + } + } + } + }, + { + "Id": { + "id": 3946110127280 + }, + "Name": "SC Node(GetVariable)", + "Components": { + "Component_[14162979093169706711]": { + "$type": "GetVariableNode", + "Id": 14162979093169706711, + "Slots": [ + { + "id": { + "m_id": "{D0D0EC9C-927F-42DB-AD22-412F374326CD}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "toolTip": "When signaled sends the property referenced by this node to a Data Output slot", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{484C5712-DB44-4A98-8199-11E47AC3D837}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "toolTip": "Signaled after the referenced property has been pushed to the Data Output slot", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{71712AB8-E5BC-42EC-A07E-733D0D36F830}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Number", + "DisplayDataType": { + "m_type": 3 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1 + } + ], + "m_variableId": { + "m_id": "{55F1434B-40C1-40AA-91C8-A65D6F2AFDC3}" + }, + "m_variableDataOutSlotId": { + "m_id": "{71712AB8-E5BC-42EC-A07E-733D0D36F830}" + } + } + } + }, + { + "Id": { + "id": 5620968623025 + }, + "Name": "SC-Node(FunctionDefinitionNode)", + "Components": { + "Component_[15563419574622171620]": { + "$type": "FunctionDefinitionNode", + "Id": 15563419574622171620, + "Slots": [ + { + "id": { + "m_id": "{8362D954-5F68-4DAB-94B3-1EFA2B2774FB}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "DisplayGroupConnectedSlotLimitContract", + "limit": 1, + "displayGroup": "NodelingSlotDisplayGroup", + "errorMessage": "Execution nodes can only be connected to either the Input or Output, and not both at the same time." + }, + { + "$type": "DisallowReentrantExecutionContract" + } + ], + "slotName": " ", + "DisplayGroup": { + "Value": 3992535411 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "isVisibile": false, + "id": { + "m_id": "{8F6E144D-A6A4-4A5D-8D47-D4FB5E165EAC}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "DisplayGroupConnectedSlotLimitContract", + "limit": 1, + "displayGroup": "NodelingSlotDisplayGroup", + "errorMessage": "Execution nodes can only be connected to either the Input or Output, and not both at the same time." + } + ], + "slotName": " ", + "DisplayGroup": { + "Value": 3992535411 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{67EC591D-BB4D-4D92-8FBE-617561EFD79D}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Incremented", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 452080683 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DataType": 1, + "IsReference": true, + "VariableReference": { + "m_id": "{81088CD0-BC45-4EB8-A823-DE442BF0541C}" + }, + "IsUserAdded": true + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Incremented" + } + ], + "m_displayName": "Out", + "m_identifier": "{E9A0BF28-5910-4B0B-B82F-6519BCC1A33A}", + "m_isExecutionEntry": false + } + } + }, + { + "Id": { + "id": 4731910392753 + }, + "Name": "SC-Node(FunctionDefinitionNode)", + "Components": { + "Component_[18278450953448842587]": { + "$type": "FunctionDefinitionNode", + "Id": 18278450953448842587, + "Slots": [ + { + "isVisibile": false, + "id": { + "m_id": "{52C8B76A-CC38-4358-9971-02B6F7E05030}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "DisplayGroupConnectedSlotLimitContract", + "limit": 1, + "displayGroup": "NodelingSlotDisplayGroup", + "errorMessage": "Execution nodes can only be connected to either the Input or Output, and not both at the same time." + }, + { + "$type": "DisallowReentrantExecutionContract" + } + ], + "slotName": " ", + "DisplayGroup": { + "Value": 3992535411 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{4C0849D0-627F-41BA-A8EE-A201074D5E52}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "DisplayGroupConnectedSlotLimitContract", + "limit": 1, + "displayGroup": "NodelingSlotDisplayGroup", + "errorMessage": "Execution nodes can only be connected to either the Input or Output, and not both at the same time." + } + ], + "slotName": " ", + "DisplayGroup": { + "Value": 3992535411 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{CFDCE169-7DE0-4DD9-A599-F0EA7360CF8A}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "IncrementMe", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 452080683 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DataType": 1, + "IsReference": true, + "VariableReference": { + "m_id": "{55F1434B-40C1-40AA-91C8-A65D6F2AFDC3}" + }, + "IsUserAdded": true + } + ], + "m_displayName": "IncrementNumber", + "m_identifier": "{5F36B80D-9546-478E-AD33-BF4AFEC8FF01}" + } + } + }, + { + "Id": { + "id": 8502891678641 + }, + "Name": "SC-Node(OperatorAdd)", + "Components": { + "Component_[6948954108967528756]": { + "$type": "OperatorAdd", + "Id": 6948954108967528756, + "Slots": [ + { + "id": { + "m_id": "{4546CCB4-B493-435F-BAEC-B76996DBDC8F}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "In", + "Descriptor": { + "ConnectionType": 1, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{52C93C3F-A8DC-47E5-98A6-5B6A15C83F92}" + }, + "contracts": [ + { + "$type": "SlotTypeContract" + } + ], + "slotName": "Out", + "Descriptor": { + "ConnectionType": 2, + "SlotType": 1 + } + }, + { + "id": { + "m_id": "{9D5A6AF3-99FE-4449-83DD-261AF2107F36}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{440FC98B-34B5-418A-9000-6E8B6BFBFDC7}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Number", + "toolTip": "An operand to use in performing the specified Operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 1, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + }, + { + "id": { + "m_id": "{A0113449-B8EA-441F-871E-A34F10A281AF}" + }, + "DynamicTypeOverride": 3, + "contracts": [ + { + "$type": "SlotTypeContract" + }, + { + "$type": "MathOperatorContract", + "NativeTypes": [ + { + "m_type": 3 + }, + { + "m_type": 6 + }, + { + "m_type": 8 + }, + { + "m_type": 9 + }, + { + "m_type": 10 + }, + { + "m_type": 11 + }, + { + "m_type": 12 + }, + { + "m_type": 14 + }, + { + "m_type": 15 + } + ] + } + ], + "slotName": "Result", + "toolTip": "The result of the specified operation", + "DisplayDataType": { + "m_type": 3 + }, + "DisplayGroup": { + "Value": 1114760223 + }, + "Descriptor": { + "ConnectionType": 2, + "SlotType": 2 + }, + "DynamicGroup": { + "Value": 1114760223 + }, + "DataType": 1 + } + ], + "Datums": [ + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 0.0, + "label": "Number" + }, + { + "scriptCanvasType": { + "m_type": 3 + }, + "isNullPointer": false, + "$type": "double", + "value": 1.0, + "label": "Number" + } + ] + } + } + } + ], + "m_connections": [ + { + "Id": { + "id": 11118526761905 + }, + "Name": "srcEndpoint=(Add (+): Result), destEndpoint=(Set Variable: Number)", + "Components": { + "Component_[4894099700298815938]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 4894099700298815938, + "sourceEndpoint": { + "nodeId": { + "id": 8502891678641 + }, + "slotId": { + "m_id": "{A0113449-B8EA-441F-871E-A34F10A281AF}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7454919658417 + }, + "slotId": { + "m_id": "{8D9CBBAD-5F75-4397-8139-B7FE79C48DFD}" + } + } + } + } + }, + { + "Id": { + "id": 11466419112881 + }, + "Name": "srcEndpoint=(Add (+): Out), destEndpoint=(Set Variable: In)", + "Components": { + "Component_[17374411643043616824]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 17374411643043616824, + "sourceEndpoint": { + "nodeId": { + "id": 8502891678641 + }, + "slotId": { + "m_id": "{52C93C3F-A8DC-47E5-98A6-5B6A15C83F92}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 7454919658417 + }, + "slotId": { + "m_id": "{22483279-E500-40D5-A61B-2C78DAC3319A}" + } + } + } + } + }, + { + "Id": { + "id": 11857261136817 + }, + "Name": "srcEndpoint=(Set Variable: Out), destEndpoint=(New Output: )", + "Components": { + "Component_[13113299305621275439]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 13113299305621275439, + "sourceEndpoint": { + "nodeId": { + "id": 7454919658417 + }, + "slotId": { + "m_id": "{17296A41-81F9-444D-BA2E-B8DAD7C62B10}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 5620968623025 + }, + "slotId": { + "m_id": "{8362D954-5F68-4DAB-94B3-1EFA2B2774FB}" + } + } + } + } + }, + { + "Id": { + "id": 4817988488368 + }, + "Name": "srcEndpoint=(IncrementNumber: ), destEndpoint=(Get Variable: In)", + "Components": { + "Component_[2259136399829712910]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 2259136399829712910, + "sourceEndpoint": { + "nodeId": { + "id": 4731910392753 + }, + "slotId": { + "m_id": "{4C0849D0-627F-41BA-A8EE-A201074D5E52}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 3946110127280 + }, + "slotId": { + "m_id": "{D0D0EC9C-927F-42DB-AD22-412F374326CD}" + } + } + } + } + }, + { + "Id": { + "id": 5084276460720 + }, + "Name": "srcEndpoint=(Get Variable: Number), destEndpoint=(Add (+): Number)", + "Components": { + "Component_[10085458428308435370]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 10085458428308435370, + "sourceEndpoint": { + "nodeId": { + "id": 3946110127280 + }, + "slotId": { + "m_id": "{71712AB8-E5BC-42EC-A07E-733D0D36F830}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 8502891678641 + }, + "slotId": { + "m_id": "{9D5A6AF3-99FE-4449-83DD-261AF2107F36}" + } + } + } + } + }, + { + "Id": { + "id": 5423578877104 + }, + "Name": "srcEndpoint=(Get Variable: Out), destEndpoint=(Add (+): In)", + "Components": { + "Component_[4574112699302556330]": { + "$type": "{64CA5016-E803-4AC4-9A36-BDA2C890C6EB} Connection", + "Id": 4574112699302556330, + "sourceEndpoint": { + "nodeId": { + "id": 3946110127280 + }, + "slotId": { + "m_id": "{484C5712-DB44-4A98-8199-11E47AC3D837}" + } + }, + "targetEndpoint": { + "nodeId": { + "id": 8502891678641 + }, + "slotId": { + "m_id": "{4546CCB4-B493-435F-BAEC-B76996DBDC8F}" + } + } + } + } + } + ] + }, + "m_assetType": "{003738F8-FA01-0000-7300-000000000000}", + "versionData": { + "_grammarVersion": 1, + "_runtimeVersion": 1, + "_fileVersion": 1 + }, + "m_variableCounter": 4, + "GraphCanvasData": [ + { + "Key": { + "id": 3946110127280 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "GetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 140.0, + -140.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".getVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{D085EC42-2893-4FFF-BF65-5A7BDBAA7CC7}" + } + } + } + }, + { + "Key": { + "id": 4731910392753 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "NodelingTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + -260.0, + -240.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".nodeling" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{DF821D33-9967-4B89-BA06-C2B8116DF1AB}" + } + } + } + }, + { + "Key": { + "id": 5620968623025 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "NodelingTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 640.0, + 160.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".nodeling" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{462CEE46-FA16-4DE3-B00C-236F49976D74}" + } + } + } + }, + { + "Key": { + "id": 7454919658417 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "SetVariableNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 660.0, + -160.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData", + "SubStyle": ".setVariable" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{54BBBFA0-B4C7-4FA4-BE92-51E9FA1A422B}" + } + } + } + }, + { + "Key": { + "id": 8502891678641 + }, + "Value": { + "ComponentData": { + "{24CB38BB-1705-4EC5-8F63-B574571B4DCD}": { + "$type": "NodeSaveData" + }, + "{328FF15C-C302-458F-A43D-E1794DE0904E}": { + "$type": "GeneralNodeTitleComponentSaveData", + "PaletteOverride": "MathNodeTitlePalette" + }, + "{7CC444B1-F9B3-41B5-841B-0C4F2179F111}": { + "$type": "GeometrySaveData", + "Position": [ + 320.0, + 60.0 + ] + }, + "{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}": { + "$type": "StylingComponentSaveData" + }, + "{B1F49A35-8408-40DA-B79E-F1E3B64322CE}": { + "$type": "PersistentIdComponentSaveData", + "PersistentId": "{AE983459-5498-46B7-A50B-7DF0A9D9886D}" + } + } + } + }, + { + "Key": { + "id": 8918912361393065975 + }, + "Value": { + "ComponentData": { + "{5F84B500-8C45-40D1-8EFC-A5306B241444}": { + "$type": "SceneComponentSaveData", + "ViewParams": { + "Scale": 0.85, + "AnchorX": -196.4705810546875, + "AnchorY": -303.5294189453125 + } + } + } + } + } + ], + "StatisticsHelper": { + "InstanceCounter": [ + { + "Key": 1244476766431948410, + "Value": 1 + }, + { + "Key": 7011818094993955847, + "Value": 2 + }, + { + "Key": 8876278780785933991, + "Value": 1 + }, + { + "Key": 11663418749378679464, + "Value": 1 + } + ] + } + } + } + } + } +} \ No newline at end of file diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index 9d75d3ed9d..3d88f014ff 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -935,3 +935,8 @@ TEST_F(ScriptCanvasTestFixture, InterpretedExecutionOutPerformance) { RunUnitTestGraph("LY_SC_UnitTest_ExecutionOutPerformance", ExecutionMode::Interpreted); } + +TEST_F(ScriptCanvasTestFixture, PromotedUserVariables) +{ + RunUnitTestGraph("LY_SC_UnitTest_PromotedUserVariables", ExecutionMode::Interpreted); +} From 42c523b27512f3697be50be637b18c400d9cec57 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Thu, 13 Jan 2022 16:07:44 -0800 Subject: [PATCH 079/108] Add SetEnv and UnSetEnv for environment variable to util (#6884) * Add SetEnv and UnSetEnv for environment variable to util * Move utils to AzTest * enable for ios and android * fix wrong file path --- .../Android/platform_android_files.cmake | 1 + .../AzTest/Utils_Unimplemented.cpp | 25 +++++++++++++++++++ .../Common/UnixLike/AzTest/Utils_UnixLike.cpp | 25 +++++++++++++++++++ .../Common/WinAPI/AzTest/Utils_WinAPI.cpp | 25 +++++++++++++++++++ .../Platform/Linux/platform_linux_files.cmake | 1 + .../Platform/Mac/platform_mac_files.cmake | 1 + .../Windows/platform_windows_files.cmake | 1 + .../Platform/iOS/platform_ios_files.cmake | 1 + Code/Framework/AzTest/AzTest/Utils.h | 13 ++++++++++ 9 files changed, 93 insertions(+) create mode 100644 Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/AzTest/Utils_Unimplemented.cpp create mode 100644 Code/Framework/AzTest/AzTest/Platform/Common/UnixLike/AzTest/Utils_UnixLike.cpp create mode 100644 Code/Framework/AzTest/AzTest/Platform/Common/WinAPI/AzTest/Utils_WinAPI.cpp diff --git a/Code/Framework/AzTest/AzTest/Platform/Android/platform_android_files.cmake b/Code/Framework/AzTest/AzTest/Platform/Android/platform_android_files.cmake index e0f47c8fa6..83ae97fa20 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Android/platform_android_files.cmake +++ b/Code/Framework/AzTest/AzTest/Platform/Android/platform_android_files.cmake @@ -8,6 +8,7 @@ set(FILES ../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp + ../Common/UnixLike/AzTest/Utils_UnixLike.cpp ScopedAutoTempDirectory_Android.cpp Platform_Android.cpp AzTest_Traits_Platform.h diff --git a/Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/AzTest/Utils_Unimplemented.cpp b/Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/AzTest/Utils_Unimplemented.cpp new file mode 100644 index 0000000000..0f91ea1020 --- /dev/null +++ b/Code/Framework/AzTest/AzTest/Platform/Common/Unimplemented/AzTest/Utils_Unimplemented.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +namespace AZ +{ + namespace Test + { + bool SetEnv([[maybe_unused]] const char* envname, [[maybe_unused]] const char* envvalue, [[maybe_unused]] bool overwrite) + { + return false; + } + + bool UnsetEnv([[maybe_unused]] const char* envname) + { + return false; + } + } // namespace Test +} // namespace AZ diff --git a/Code/Framework/AzTest/AzTest/Platform/Common/UnixLike/AzTest/Utils_UnixLike.cpp b/Code/Framework/AzTest/AzTest/Platform/Common/UnixLike/AzTest/Utils_UnixLike.cpp new file mode 100644 index 0000000000..8efdb5d082 --- /dev/null +++ b/Code/Framework/AzTest/AzTest/Platform/Common/UnixLike/AzTest/Utils_UnixLike.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +namespace AZ +{ + namespace Test + { + bool SetEnv(const char* envname, const char* envvalue, bool overwrite) + { + return setenv(envname, envvalue, overwrite) != -1; + } + + bool UnsetEnv(const char* envname) + { + return unsetenv(envname) != -1; + } + } +} diff --git a/Code/Framework/AzTest/AzTest/Platform/Common/WinAPI/AzTest/Utils_WinAPI.cpp b/Code/Framework/AzTest/AzTest/Platform/Common/WinAPI/AzTest/Utils_WinAPI.cpp new file mode 100644 index 0000000000..a06cbf7ffe --- /dev/null +++ b/Code/Framework/AzTest/AzTest/Platform/Common/WinAPI/AzTest/Utils_WinAPI.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +namespace AZ +{ + namespace Test + { + bool SetEnv(const char* envname, const char* envvalue, [[maybe_unused]] bool overwrite) + { + return _putenv_s(envname, envvalue); + } + + bool UnsetEnv(const char* envname) + { + return SetEnv(envname, "", 1); + } + } +} diff --git a/Code/Framework/AzTest/AzTest/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzTest/AzTest/Platform/Linux/platform_linux_files.cmake index 68ca9332c7..9c6692b409 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Linux/platform_linux_files.cmake +++ b/Code/Framework/AzTest/AzTest/Platform/Linux/platform_linux_files.cmake @@ -9,6 +9,7 @@ set(FILES ../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp ../Common/UnixLike/AzTest/ScopedAutoTempDirectory_UnixLike.cpp + ../Common/UnixLike/AzTest/Utils_UnixLike.cpp Platform_Linux.cpp AzTest_Traits_Platform.h AzTest_Traits_Linux.h diff --git a/Code/Framework/AzTest/AzTest/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzTest/AzTest/Platform/Mac/platform_mac_files.cmake index 3cbe35792c..cb641e2113 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Mac/platform_mac_files.cmake +++ b/Code/Framework/AzTest/AzTest/Platform/Mac/platform_mac_files.cmake @@ -9,6 +9,7 @@ set(FILES ../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp ../Common/UnixLike/AzTest/ScopedAutoTempDirectory_UnixLike.cpp + ../Common/UnixLike/AzTest/Utils_UnixLike.cpp Platform_Mac.cpp AzTest_Traits_Platform.h AzTest_Traits_Mac.h diff --git a/Code/Framework/AzTest/AzTest/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzTest/AzTest/Platform/Windows/platform_windows_files.cmake index 656b28a373..4730b383a2 100644 --- a/Code/Framework/AzTest/AzTest/Platform/Windows/platform_windows_files.cmake +++ b/Code/Framework/AzTest/AzTest/Platform/Windows/platform_windows_files.cmake @@ -8,6 +8,7 @@ set(FILES ../Common/WinAPI/AzTest/ColorizedOutput_WinAPI.cpp + ../Common/WinAPI/AzTest/Utils_WinAPI.cpp Platform_Windows.cpp ScopedAutoTempDirectory_Windows.cpp AzTest_Traits_Platform.h diff --git a/Code/Framework/AzTest/AzTest/Platform/iOS/platform_ios_files.cmake b/Code/Framework/AzTest/AzTest/Platform/iOS/platform_ios_files.cmake index 64bbc27bc1..81875f71e5 100644 --- a/Code/Framework/AzTest/AzTest/Platform/iOS/platform_ios_files.cmake +++ b/Code/Framework/AzTest/AzTest/Platform/iOS/platform_ios_files.cmake @@ -9,6 +9,7 @@ set(FILES ../Common/UnixLike/AzTest/ColorizedOutput_UnixLike.cpp ../Common/Unimplemented/AzTest/ScopedAutoTempDirectory_Unimplemented.cpp + ../Common/UnixLike/AzTest/Utils_UnixLike.cpp Platform_iOS.cpp AzTest_Traits_Platform.h AzTest_Traits_iOS.h diff --git a/Code/Framework/AzTest/AzTest/Utils.h b/Code/Framework/AzTest/AzTest/Utils.h index 2778e163b3..e3b45e97f2 100644 --- a/Code/Framework/AzTest/AzTest/Utils.h +++ b/Code/Framework/AzTest/AzTest/Utils.h @@ -55,6 +55,19 @@ namespace AZ // Returns the path to the engine's root by cdup from the current execution path until engine.txt is found AZStd::string GetEngineRootPath(); + //! Create or modify environment variable. + //! @param envname The environment variable name + //! @param envvalue The environment variable name + //! @param overwrite If name does exist in the environment, then its value is changed to value if overwrite is nonzero; + //! if overwrite is zero, then the value of name is not changed + //! @returns Return true if successful, otherwise false + bool SetEnv(const char* envname, const char* envvalue, bool overwrite); + + //! Remove environment variable. + //! @param envname The environment variable name + //! @returns Return true if successful, otherwise false + bool UnsetEnv(const char* envname); + //! Provides a scoped object that will create a temporary operating-system specific folder on creation, and delete it and //! its contents on destruction. This class is only available on host platforms (Windows, Mac, and Linux) class ScopedAutoTempDirectory From 22cee244c19d2cb721840128cb11a64451d58800 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Thu, 13 Jan 2022 17:30:02 -0800 Subject: [PATCH 080/108] remove a ability to reset reference, do not display reference box on user added data slots Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index 342273cb2e..0e158d3e08 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -1142,7 +1142,7 @@ namespace ScriptCanvasEditor { if (slot->IsVariableReference()) { - return true; + return !slot->IsUserAdded(); } else { @@ -1254,7 +1254,7 @@ namespace ScriptCanvasEditor return nullptr; } - if (slot->IsVariableReference()) + if (slot->IsVariableReference() && !slot->IsUserAdded()) { ScriptCanvasVariableReferenceDataInterface* dataInterface = aznew ScriptCanvasVariableReferenceDataInterface(&m_variableDataModel, GetScriptCanvasId(), scriptCanvasNodeId, scriptCanvasSlotId); GraphCanvas::NodePropertyDisplay* dataDisplay = nullptr; From 1431afb51a08535a0ceabc22f11a55c0e5f5bb93 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Thu, 13 Jan 2022 18:26:39 -0800 Subject: [PATCH 081/108] remove a ability to change type on user added slots Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 1176df61dc..573a3f6e57 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -3873,7 +3873,9 @@ namespace ScriptCanvasEditor contextMenu.AddMenuAction(aznew ConvertReferenceToVariableNodeAction(&contextMenu)); contextMenu.AddMenuAction(aznew ExposeSlotMenuAction(&contextMenu)); contextMenu.AddMenuAction(aznew CreateAzEventHandlerSlotMenuAction(&contextMenu)); - contextMenu.AddMenuAction(aznew SetDataSlotTypeMenuAction(&contextMenu)); + + // disabling until references can be changed + // contextMenu.AddMenuAction(aznew SetDataSlotTypeMenuAction(&contextMenu)); return HandleContextMenu(contextMenu, slotId, screenPoint, scenePoint); } From 5c603882b348bdf220eda73e90c2491217744079 Mon Sep 17 00:00:00 2001 From: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> Date: Thu, 13 Jan 2022 19:57:22 -0700 Subject: [PATCH 082/108] Changed the Shader instanceId to the combined assetId and supervariant index Signed-off-by: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> --- .../Include/Atom/RPI.Public/Shader/Shader.h | 5 --- .../Code/Source/RPI.Public/Shader/Shader.cpp | 44 ++++++++++--------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h index 92b67c3a7a..be20d89d65 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/Shader.h @@ -136,11 +136,6 @@ namespace AZ //! This tag corresponds to the ShaderAsset object's DrawListName. RHI::DrawListTag GetDrawListTag() const; - //! Changes the supervariant of the shader to the specified supervariantIndex. - //! [GFX TODO][ATOM-15813]: this can be removed when the shader InstanceDatabase can support multiple shader - //! instances with different supervariants. - void ChangeSupervariant(SupervariantIndex supervariantIndex); - private: explicit Shader(const SupervariantIndex& supervariantIndex) : m_supervariantIndex(supervariantIndex){}; Shader() = delete; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp index b1ae460af6..3830d8ee42 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp @@ -25,21 +25,34 @@ namespace AZ Data::Instance Shader::FindOrCreate(const Data::Asset& shaderAsset, const Name& supervariantName) { auto anySupervariantName = AZStd::any(supervariantName); - Data::Instance shaderInstance = Data::InstanceDatabase::Instance().FindOrCreate( - Data::InstanceId::CreateFromAssetId(shaderAsset.GetId()), shaderAsset, &anySupervariantName); - if (shaderInstance) + // retrieve the supervariant index from the shader asset + SupervariantIndex supervariantIndex = shaderAsset->GetSupervariantIndex(supervariantName); + if (!supervariantIndex.IsValid()) { - // [GFX TODO][ATOM-15813] Change InstanceDatabase to support multiple instances with different supervariants. - // At this time we do not support multiple supervariants loaded for a shader asset simultaneously, so if this shader - // is referring to the wrong supervariant we need to change it to the correct one. - SupervariantIndex supervariantIndex = shaderAsset->GetSupervariantIndex(supervariantName); - if (supervariantIndex.IsValid() && shaderInstance->GetSupervariantIndex() != supervariantIndex) - { - shaderInstance->ChangeSupervariant(supervariantIndex); - } + AZ_Error("Shader", false, "Supervariant with name %s, was not found in shader %s", supervariantName.GetCStr(), shaderAsset->GetName().GetCStr()); + return nullptr; } + // create the InstanceId from the combined assetId and supervariantIndex + const Data::AssetId& assetId = shaderAsset.GetId(); + uint32_t shaderSupervariantIndex = supervariantIndex.GetIndex(); + + const uint32_t instanceIdDataSize = sizeof(assetId.m_guid) + sizeof(assetId.m_subId) + sizeof(shaderSupervariantIndex); + uint8_t instanceIdData[instanceIdDataSize]; + uint8_t* instanceIdDataPtr = instanceIdData; + + memcpy(instanceIdDataPtr, &assetId.m_guid, sizeof(assetId.m_guid)); + instanceIdDataPtr += sizeof(assetId.m_guid); + memcpy(instanceIdDataPtr, &assetId.m_subId, sizeof(assetId.m_subId)); + instanceIdDataPtr += sizeof(assetId.m_subId); + memcpy(instanceIdDataPtr, &shaderSupervariantIndex, sizeof(shaderSupervariantIndex)); + + Data::InstanceId instanceId = Data::InstanceId::CreateData(instanceIdData, instanceIdDataSize); + + // retrieve the shader instance from the Instance database + Data::Instance shaderInstance = Data::InstanceDatabase::Instance().FindOrCreate(instanceId, shaderAsset, &anySupervariantName); + return shaderInstance; } @@ -478,14 +491,5 @@ namespace AZ return m_drawListTag; } - void Shader::ChangeSupervariant(SupervariantIndex supervariantIndex) - { - if (supervariantIndex != m_supervariantIndex) - { - m_supervariantIndex = supervariantIndex; - Init(*m_asset); - } - } - } // namespace RPI } // namespace AZ From a43cd9531328d006f8487f449555318750712115 Mon Sep 17 00:00:00 2001 From: moraaar Date: Fri, 14 Jan 2022 10:01:38 +0000 Subject: [PATCH 083/108] Fixed physics periodic tests on linux platform (#6881) - Fixed path separators, now levels will be correctly opened in linux. - Fixed casing of physics paths. - Fixed casing of files inside levels Joints_HingeNoLimitsConstrained and RigidBody_KinematicModeWorks. - Resaved a level that still used old test ids in its name but the python tests didn't match. Linux: Start 21: AutomatedTesting::PhysicsTests_Periodic.periodic::TEST_RUN 8/11 Test #21: AutomatedTesting::PhysicsTests_Periodic.periodic::TEST_RUN .................. Passed 609.87 sec Windows: Start 21: AutomatedTesting::PhysicsTests_Periodic.periodic::TEST_RUN 8/13 Test #21: AutomatedTesting::PhysicsTests_Periodic.periodic::TEST_RUN ....................... Passed 810.59 sec Signed-off-by: moraaar --- ...ameCollisionGroupSameCustomLayerCollide.py | 2 +- ...tipleForcesInSameComponentCombineForces.py | 2 +- ...DefaultLibraryUpdatedAcrossLevels_after.py | 4 +- ...efaultLibraryUpdatedAcrossLevels_before.py | 2 +- .../Material_LibraryUpdatedAcrossLevels.py | 6 +- ...iptCanvas_SpawnEntityWithPhysComponents.py | 2 +- .../Joints_HingeNoLimitsConstrained.ly | 4 +- .../0/0.ly | 3 + .../0/filelist.xml | 6 + .../0/level.pak | 3 + .../tags.txt | 0 .../terraintexture.pak | 0 .../1/1.ly | 3 + .../1/filelist.xml | 6 + .../1/level.pak | 3 + .../tags.txt | 0 .../terraintexture.pak | 0 ...5_Material_LibraryUpdatedAcrossLevels_0.ly | 3 - .../filelist.xml | 6 - .../level.pak | 3 - .../leveldata/Environment.xml | 14 - .../leveldata/GameTokens.xml | 5 - .../leveldata/TerrainTexture.xml | 7 - .../leveldata/TimeOfDay.xml | 356 ------------------ .../leveldata/VegetationMap.dat | 3 - .../terrain/terrain.pxheightfield | 3 - ...5_Material_LibraryUpdatedAcrossLevels_1.ly | 3 - .../filelist.xml | 6 - .../level.pak | 3 - .../leveldata/Environment.xml | 14 - .../leveldata/GameTokens.xml | 5 - .../leveldata/TerrainTexture.xml | 7 - .../leveldata/TimeOfDay.xml | 356 ------------------ .../leveldata/VegetationMap.dat | 3 - .../terrain/terrain.pxheightfield | 3 - .../RigidBody_KinematicModeWorks.ly | 4 +- 36 files changed, 36 insertions(+), 814 deletions(-) create mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/0.ly create mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/filelist.xml create mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/level.pak rename AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/{C15425935_Material_LibraryUpdatedAcrossLevels_0 => 0}/tags.txt (100%) rename AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/{C15425935_Material_LibraryUpdatedAcrossLevels_0 => 0}/terraintexture.pak (100%) create mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/1.ly create mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/filelist.xml create mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/level.pak rename AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/{C15425935_Material_LibraryUpdatedAcrossLevels_1 => 1}/tags.txt (100%) rename AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/{C15425935_Material_LibraryUpdatedAcrossLevels_1 => 1}/terraintexture.pak (100%) delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/C15425935_Material_LibraryUpdatedAcrossLevels_0.ly delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/filelist.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/level.pak delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/Environment.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/GameTokens.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TerrainTexture.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TimeOfDay.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/VegetationMap.dat delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/terrain/terrain.pxheightfield delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/C15425935_Material_LibraryUpdatedAcrossLevels_1.ly delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/filelist.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/level.pak delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/Environment.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/GameTokens.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TerrainTexture.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TimeOfDay.xml delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/VegetationMap.dat delete mode 100644 AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/terrain/terrain.pxheightfield diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py index 2e40c0b557..8e8fccd725 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/collider/Collider_SameCollisionGroupSameCustomLayerCollide.py @@ -127,7 +127,7 @@ def Collider_SameCollisionGroupSameCustomLayerCollide(): # Main Script # 1) Load the level helper.init_idle() - helper.open_level("physics", "Collider_SameCollisionGroupSameCustomLayerCollide") + helper.open_level("Physics", "Collider_SameCollisionGroupSameCustomLayerCollide") # 2) Enter Game Mode helper.enter_game_mode(Tests.enter_game_mode) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py index 7307f3a2fb..e5f6e236cf 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_MultipleForcesInSameComponentCombineForces.py @@ -162,7 +162,7 @@ def ForceRegion_MultipleForcesInSameComponentCombineForces(): helper.init_idle() # 1) Load Level - helper.open_level("physics", "ForceRegion_MultipleForcesInSameComponentCombineForces") + helper.open_level("Physics", "ForceRegion_MultipleForcesInSameComponentCombineForces") # 2) Enter Game Mode helper.enter_game_mode(Tests.enter_game_mode) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py index 1f8cfae498..41ccc8f2dd 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_after.py @@ -229,8 +229,8 @@ def Material_DefaultLibraryUpdatedAcrossLevels_after(): for test in test_list: # 1) Open the correct level is open helper.open_level( - "physics", - f"Material_DefaultLibraryUpdatedAcrossLevels\\{test.level}" + "Physics", + os.path.join("Material_DefaultLibraryUpdatedAcrossLevels", str(test.level)) ) # 2) Enter Game Mode diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py index 15db5808e2..d86a016be1 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_DefaultLibraryUpdatedAcrossLevels_before.py @@ -189,7 +189,7 @@ def Material_DefaultLibraryUpdatedAcrossLevels_before(): # 1) Open the correct level is open helper.open_level( "Physics", - f"Material_DefaultLibraryUpdatedAcrossLevels\\{test.level}" + os.path.join("Material_DefaultLibraryUpdatedAcrossLevels", str(test.level)) ) # 2) Enter Game Mode diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryUpdatedAcrossLevels.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryUpdatedAcrossLevels.py index 0b647361f6..6eebfe60bc 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryUpdatedAcrossLevels.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/material/Material_LibraryUpdatedAcrossLevels.py @@ -252,10 +252,8 @@ def Material_LibraryUpdatedAcrossLevels(): for test in test_list: # 1) Open the correct level for the test helper.open_level( - "physics", - "Material_LibraryUpdatedAcrossLevels\\Material_LibraryUpdatedAcrossLevels_{}".format( - test.level_index - ), + "Physics", + os.path.join("Material_LibraryUpdatedAcrossLevels", str(test.level_index)) ) # 2) Open Game Mode diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py index 5862b7586b..e6e29063d6 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/script_canvas/ScriptCanvas_SpawnEntityWithPhysComponents.py @@ -106,7 +106,7 @@ def ScriptCanvas_SpawnEntityWithPhysComponents(): # Main Script helper.init_idle() # 1) Open Level - helper.open_level("physics", "ScriptCanvas_SpawnEntityWithPhysComponents") + helper.open_level("Physics", "ScriptCanvas_SpawnEntityWithPhysComponents") # 2) Enter Game Mode helper.enter_game_mode(Tests.enter_game_mode) diff --git a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly index 9babf84ba4..18b503bab5 100644 --- a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly +++ b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60276c07b45a734e4f71d695278167ea61e884f8b513906168c9642078ad5954 -size 6045 +oid sha256:0d004c329a7c5044a8fe05b6dbbf9b19de29c60acec75f13fdbc344a55aab8c7 +size 6404 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/0.ly b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/0.ly new file mode 100644 index 0000000000..b908d29eab --- /dev/null +++ b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/0.ly @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e89946c224d2e765931e8ba8e33133ac24651af321a404016d9a9ea8c323db6c +size 8563 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/filelist.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/filelist.xml new file mode 100644 index 0000000000..bb94b733b3 --- /dev/null +++ b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/filelist.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/level.pak b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/level.pak new file mode 100644 index 0000000000..614e41c4b2 --- /dev/null +++ b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/level.pak @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a46437ba86135567d87d43af0c4d499bf3cfe321721dbaf6e3cda8e49427ee1 +size 40212 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/tags.txt b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/tags.txt similarity index 100% rename from AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/tags.txt rename to AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/tags.txt diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/terraintexture.pak b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/terraintexture.pak similarity index 100% rename from AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/terraintexture.pak rename to AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/0/terraintexture.pak diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/1.ly b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/1.ly new file mode 100644 index 0000000000..216426fc2a --- /dev/null +++ b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/1.ly @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95996da3902d885060e700c573d13144bab246b930dfeedaed6066c13c879b11 +size 8737 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/filelist.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/filelist.xml new file mode 100644 index 0000000000..5f5b4928fc --- /dev/null +++ b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/filelist.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/level.pak b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/level.pak new file mode 100644 index 0000000000..d920770374 --- /dev/null +++ b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/level.pak @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:894dfd4ab92aa4d1d6003aebf82cf7ff854a8b3684e010234e073879f88b64e5 +size 40210 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/tags.txt b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/tags.txt similarity index 100% rename from AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/tags.txt rename to AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/tags.txt diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/terraintexture.pak b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/terraintexture.pak similarity index 100% rename from AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/terraintexture.pak rename to AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/1/terraintexture.pak diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/C15425935_Material_LibraryUpdatedAcrossLevels_0.ly b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/C15425935_Material_LibraryUpdatedAcrossLevels_0.ly deleted file mode 100644 index a5953fc44b..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/C15425935_Material_LibraryUpdatedAcrossLevels_0.ly +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:969b77ee335d2a04524a27c765dd2f2bdee048661f3ff7be0766ba69d18d5842 -size 10409 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/filelist.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/filelist.xml deleted file mode 100644 index 9a78b1bfd5..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/filelist.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/level.pak b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/level.pak deleted file mode 100644 index 8e6b3b29cb..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/level.pak +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:547d7fdfcd959569b69d78eb6f63c7c19fc90840d69ca2d46eca8a3e82b8db75 -size 39337 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/Environment.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/Environment.xml deleted file mode 100644 index 4ba36f66ae..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/Environment.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/GameTokens.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/GameTokens.xml deleted file mode 100644 index 668a4583bd..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/GameTokens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TerrainTexture.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TerrainTexture.xml deleted file mode 100644 index f43df05b22..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TerrainTexture.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TimeOfDay.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TimeOfDay.xml deleted file mode 100644 index 456d609b8a..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/TimeOfDay.xml +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/VegetationMap.dat b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/VegetationMap.dat deleted file mode 100644 index dce5631cd0..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/leveldata/VegetationMap.dat +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0e6a5435c928079b27796f6b202bbc2623e7e454244ddc099a3cadf33b7cb9e9 -size 63 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/terrain/terrain.pxheightfield b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/terrain/terrain.pxheightfield deleted file mode 100644 index 011356e521..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_0/terrain/terrain.pxheightfield +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:19096597087688692a225c1955f73d22c46354995fca1df8dff107a90c2f17a2 -size 4202594 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/C15425935_Material_LibraryUpdatedAcrossLevels_1.ly b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/C15425935_Material_LibraryUpdatedAcrossLevels_1.ly deleted file mode 100644 index 9f48f08a1b..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/C15425935_Material_LibraryUpdatedAcrossLevels_1.ly +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:29f752c141514cb4b50aea07e6b63de5c8f43149ddac37722e9ddb8b5f4a667d -size 9495 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/filelist.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/filelist.xml deleted file mode 100644 index 9a78b1bfd5..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/filelist.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/level.pak b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/level.pak deleted file mode 100644 index 8e6b3b29cb..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/level.pak +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:547d7fdfcd959569b69d78eb6f63c7c19fc90840d69ca2d46eca8a3e82b8db75 -size 39337 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/Environment.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/Environment.xml deleted file mode 100644 index 4ba36f66ae..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/Environment.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/GameTokens.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/GameTokens.xml deleted file mode 100644 index 668a4583bd..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/GameTokens.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TerrainTexture.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TerrainTexture.xml deleted file mode 100644 index f43df05b22..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TerrainTexture.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TimeOfDay.xml b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TimeOfDay.xml deleted file mode 100644 index 456d609b8a..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/TimeOfDay.xml +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/VegetationMap.dat b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/VegetationMap.dat deleted file mode 100644 index dce5631cd0..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/leveldata/VegetationMap.dat +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0e6a5435c928079b27796f6b202bbc2623e7e454244ddc099a3cadf33b7cb9e9 -size 63 diff --git a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/terrain/terrain.pxheightfield b/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/terrain/terrain.pxheightfield deleted file mode 100644 index 011356e521..0000000000 --- a/AutomatedTesting/Levels/Physics/Material_LibraryUpdatedAcrossLevels/C15425935_Material_LibraryUpdatedAcrossLevels_1/terrain/terrain.pxheightfield +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:19096597087688692a225c1955f73d22c46354995fca1df8dff107a90c2f17a2 -size 4202594 diff --git a/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly b/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly index d6052ffa7c..a4b28a9e96 100644 --- a/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly +++ b/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cb97ada674d123c67d7a32eb65e81fa66472cf51f748054c4a4297649f2a0f40 -size 5568 +oid sha256:0f645243fb623258ed4b063c5a18ea414560496f97d7234782ca97884e0ed8f0 +size 5961 From e1572ce5c9615d8b4ecaa5ee8b8409f2fcb7944b Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> Date: Fri, 14 Jan 2022 08:49:42 -0800 Subject: [PATCH 084/108] Updating assimp to the v12 packages (#6861) Signed-off-by: AMZN-stankowi <4838196+AMZN-stankowi@users.noreply.github.com> --- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index f7bc2721ae..f1e8fdc950 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -8,7 +8,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) @@ -21,6 +20,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) # platform-specific: +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev12-linux TARGETS assimplib PACKAGE_HASH 49d32e11c594e58a9079972ad63570dd895ac61e6148e428b9c39a62feb676ee) ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-linux TARGETS TIFF PACKAGE_HASH 2377f48b2ebc2d1628d9f65186c881544c92891312abe478a20d10b85877409a) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux TARGETS freetype PACKAGE_HASH 3f10c703d9001ecd2bb51a3bd003d3237c02d8f947ad0161c0252fdc54cbcf97) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index ea324a5cb7..575a2dd70e 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -8,7 +8,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) @@ -21,6 +20,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) # platform-specific: +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev12-mac TARGETS assimplib PACKAGE_HASH 12db03817553f607bee0d65b690bcaae748014f3ed9266b70384f463bc98c9d1) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-mac TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 3f77367dbb0342136ec4ebbd44bc1fedf7198089a0f83c5631248530769b2be6) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-mac TARGETS TIFF PACKAGE_HASH c2615ccdadcc0e1d6c5ed61e5965c4d3a82193d206591b79b805c3b3ff35a4bf) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 5441bcd76f..7fd07927cc 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -8,7 +8,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) -ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev11-multiplatform TARGETS assimplib PACKAGE_HASH 1a9113788b893ef4a2ee63ac01eb71b981a92894a5a51175703fa225f5804dec) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) @@ -21,6 +20,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) # platform-specific: +ly_associate_package(PACKAGE_NAME assimp-5.0.1-rev12-windows TARGETS assimplib PACKAGE_HASH 5273b7661a7a247bb18e8bc928d25c9cd1bd8ce9dfcc56c50742bac8fa02f0f2) ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows TARGETS AWSGameLiftServerSDK PACKAGE_HASH a0586b006e4def65cc25f388de17dc475e417dc1e6f9d96749777c88aa8271b0) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-windows TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 803e10b94006b834cbbdd30f562a8ddf04174c2cb6956c8399ec164ef8418d1f) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows TARGETS SPIRVCross PACKAGE_HASH 7d601ea9d625b1d509d38bd132a1f433d7e895b16adab76bac6103567a7a6817) From 4392c8963c66786d9db2164fb3d7384dc2e7a6f9 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Fri, 14 Jan 2022 09:00:26 -0800 Subject: [PATCH 085/108] [Linux] Prefer higher versioned clang compilers to lower versions (#6824) If the user does not specify which compiler to use via cache variables in the CMake invocation, we perform a search for which version to use. Previously this was done using a glob search on some pre-defined paths, and then sorting the results using `list(SORT ... COMPARE NATURAL)`. Sorting in this manner results in lower versions being moved to the head of the list. The first result in the list was then used. Consequently, if the user has `clang-11` and `clang-12` installed, `clang-11` was chosen. This reverses the sort order so that the highest installed version is chosen. Signed-off-by: Chris Burel --- cmake/Platform/Linux/CompilerSettings_linux.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Linux/CompilerSettings_linux.cmake b/cmake/Platform/Linux/CompilerSettings_linux.cmake index 9bb629c53b..a1a632e957 100644 --- a/cmake/Platform/Linux/CompilerSettings_linux.cmake +++ b/cmake/Platform/Linux/CompilerSettings_linux.cmake @@ -19,7 +19,7 @@ if(NOT CMAKE_C_COMPILER AND NOT CMAKE_CXX_COMPILER AND NOT "$ENV{CC}" AND NOT "$ file(GLOB clang_versions ${path_search}) if(clang_versions) # Find and pick the highest installed version - list(SORT clang_versions COMPARE NATURAL) + list(SORT clang_versions COMPARE NATURAL ORDER DESCENDING) list(GET clang_versions 0 clang_higher_version_path) string(REGEX MATCH "clang-([0-9.]*)" clang_higher_version ${clang_higher_version_path}) if(CMAKE_MATCH_1) From b62d130475b81e9936f89c5123d1436b4c3dfb1a Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 14 Jan 2022 11:32:29 -0600 Subject: [PATCH 086/108] Updated AnimNode registration in LyShine and Maestro to register to a member variable map (#6786) * Updated the Maestro MovieSystem and LyShine AnimationSystem to register Anim Nodes and Anim Params into a member variable map Previously the registration was occuring in a global variable map inside of Movie.cpp and UiAnimationSystem.cpp Rolled back the changes to update the CUiAnimNode and CAnimParamType to use the stateless allocator in their m_name string member. This was only needed because those types were used in global memory. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the AZStd::hash specializations for basic_string and basic_fixed_string to be transparent. This allows hashing of types that aren't basic_string or basic_fixed_string using the hash specializations for those types without needing to create an instance of those types. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Adding call to disable saving of the UserSettings.xml in the DisplaySettingsPythonBindingsFixture to avoid race condition running the test in parallel Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../test_DisplaySettingsPythonBindings.cpp | 5 + .../AzCore/AzCore/std/string/fixed_string.inl | 3 +- .../AzCore/AzCore/std/string/string.h | 5 +- Code/Legacy/CryCommon/IMovieSystem.h | 5 +- .../Styling/SelectorImplementations.h | 2 +- Gems/LyShine/Code/Source/Animation/AnimNode.h | 3 +- .../Source/Animation/UiAnimationSystem.cpp | 133 ++++----- .../Code/Source/Animation/UiAnimationSystem.h | 22 +- Gems/LyShine/Code/Source/LyShine.cpp | 2 - .../Code/Source/Cinematics/AnimPostFXNode.cpp | 3 +- Gems/Maestro/Code/Source/Cinematics/Movie.cpp | 259 ++++++++---------- Gems/Maestro/Code/Source/Cinematics/Movie.h | 20 +- .../Code/Source/TextureAtlasImpl.h | 2 +- 13 files changed, 227 insertions(+), 237 deletions(-) diff --git a/Code/Editor/Lib/Tests/test_DisplaySettingsPythonBindings.cpp b/Code/Editor/Lib/Tests/test_DisplaySettingsPythonBindings.cpp index fd65634d4e..b73cb039ea 100644 --- a/Code/Editor/Lib/Tests/test_DisplaySettingsPythonBindings.cpp +++ b/Code/Editor/Lib/Tests/test_DisplaySettingsPythonBindings.cpp @@ -35,6 +35,11 @@ namespace DisplaySettingsPythonBindingsUnitTests m_app.Start(appDesc); m_app.RegisterComponentDescriptor(AzToolsFramework::DisplaySettingsPythonFuncsHandler::CreateDescriptor()); + + // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is + // shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash + // in the unit tests. + AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); } void TearDown() override diff --git a/Code/Framework/AzCore/AzCore/std/string/fixed_string.inl b/Code/Framework/AzCore/AzCore/std/string/fixed_string.inl index 15d2acf7a1..a1c95b7ba2 100644 --- a/Code/Framework/AzCore/AzCore/std/string/fixed_string.inl +++ b/Code/Framework/AzCore/AzCore/std/string/fixed_string.inl @@ -1760,7 +1760,8 @@ namespace AZStd template struct hash> { - inline constexpr size_t operator()(const basic_fixed_string& value) const + using is_transparent = void; + inline constexpr size_t operator()(const basic_string_view& value) const { return hash_string(value.begin(), value.length()); } diff --git a/Code/Framework/AzCore/AzCore/std/string/string.h b/Code/Framework/AzCore/AzCore/std/string/string.h index 7dd6dd7065..56afd16226 100644 --- a/Code/Framework/AzCore/AzCore/std/string/string.h +++ b/Code/Framework/AzCore/AzCore/std/string/string.h @@ -2071,9 +2071,8 @@ namespace AZStd template struct hash< basic_string< Element, Traits, Allocator> > { - typedef basic_string< Element, Traits, Allocator> argument_type; - typedef AZStd::size_t result_type; - inline result_type operator()(const argument_type& value) const + using is_transparent = void; + inline constexpr size_t operator()(const basic_string_view& value) const { return hash_string(value.begin(), value.length()); } diff --git a/Code/Legacy/CryCommon/IMovieSystem.h b/Code/Legacy/CryCommon/IMovieSystem.h index 79c000bfca..a55d764afa 100644 --- a/Code/Legacy/CryCommon/IMovieSystem.h +++ b/Code/Legacy/CryCommon/IMovieSystem.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -184,7 +183,7 @@ public: private: AnimParamType m_type; - AZStd::basic_string, AZStd::stateless_allocator> m_name; + AZStd::string m_name; }; namespace AZStd @@ -620,7 +619,7 @@ public: , valueType(_valueType) , flags(_flags) {}; - AZStd::basic_string, AZStd::stateless_allocator> name; // parameter name. + AZStd::string name; // parameter name. CAnimParamType paramType; // parameter id. AnimValueType valueType; // value type, defines type of track to use for animating this parameter. ESupportedParamFlags flags; // combination of flags from ESupportedParamFlags. diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h index 1c65bf1915..eac9abdec8 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/SelectorImplementations.h @@ -79,7 +79,7 @@ namespace GraphCanvas private: AZStd::string m_value; - AZStd::hash::result_type m_hash; + size_t m_hash; friend class BasicSelectorEventHandler; }; diff --git a/Gems/LyShine/Code/Source/Animation/AnimNode.h b/Gems/LyShine/Code/Source/Animation/AnimNode.h index 4d139e99ca..0076276204 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimNode.h +++ b/Gems/LyShine/Code/Source/Animation/AnimNode.h @@ -13,7 +13,6 @@ #include #include "UiAnimationSystem.h" -#include /*! @@ -40,7 +39,7 @@ public: , valueType(_valueType) , flags(_flags) {}; - AZStd::basic_string, AZStd::stateless_allocator> name; // parameter name. + AZStd::string name; // parameter name. CUiAnimParamType paramType; // parameter id. EUiAnimValue valueType; // value type, defines type of track to use for animating this parameter. ESupportedParamFlags flags; // combination of flags from ESupportedParamFlags. diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp index c8818836d6..06e7110fe2 100644 --- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp +++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp @@ -14,77 +14,59 @@ #include "UiAnimSerialize.h" #include -#include #include #include -#include #include #include #include ////////////////////////////////////////////////////////////////////////// -namespace -{ - using UiAnimParamSystemString = AZStd::basic_string, AZStd::stateless_allocator>; - template > - using UiAnimSystemOrderedMap = AZStd::map; - template , typename EqualKey = AZStd::equal_to> - using UiAnimSystemUnorderedMap = AZStd::unordered_map; -} // Serialization for anim nodes & param types -#define REGISTER_NODE_TYPE(name) assert(!g_animNodeEnumToStringMap.contains(eUiAnimNodeType_ ## name)); \ - g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \ - g_animNodeStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name; +#define REGISTER_NODE_TYPE(name) assert(!m_animNodeEnumToStringMap.contains(eUiAnimNodeType_ ## name)); \ + m_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \ + m_animNodeStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name; -#define REGISTER_PARAM_TYPE(name) assert(!g_animParamEnumToStringMap.contains(eUiAnimParamType_ ## name)); \ - g_animParamEnumToStringMap[eUiAnimParamType_ ## name] = AZ_STRINGIZE(name); \ - g_animParamStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name; +#define REGISTER_PARAM_TYPE(name) assert(!m_animParamEnumToStringMap.contains(eUiAnimParamType_ ## name)); \ + m_animParamEnumToStringMap[eUiAnimParamType_ ## name] = AZ_STRINGIZE(name); \ + m_animParamStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name; -namespace + +// If you get an assert in this function, it means two node types have the same enum value. +void UiAnimationSystem::RegisterNodeTypes() { - UiAnimSystemUnorderedMap g_animNodeEnumToStringMap; - UiAnimSystemOrderedMap> g_animNodeStringToEnumMap; + REGISTER_NODE_TYPE(Entity) + REGISTER_NODE_TYPE(Director) + REGISTER_NODE_TYPE(Camera) + REGISTER_NODE_TYPE(CVar) + REGISTER_NODE_TYPE(ScriptVar) + REGISTER_NODE_TYPE(Material) + REGISTER_NODE_TYPE(Event) + REGISTER_NODE_TYPE(Group) + REGISTER_NODE_TYPE(Layer) + REGISTER_NODE_TYPE(Comment) + REGISTER_NODE_TYPE(RadialBlur) + REGISTER_NODE_TYPE(ColorCorrection) + REGISTER_NODE_TYPE(DepthOfField) + REGISTER_NODE_TYPE(ScreenFader) + REGISTER_NODE_TYPE(Light) + REGISTER_NODE_TYPE(HDRSetup) + REGISTER_NODE_TYPE(ShadowSetup) + REGISTER_NODE_TYPE(Alembic) + REGISTER_NODE_TYPE(GeomCache) + REGISTER_NODE_TYPE(Environment) + REGISTER_NODE_TYPE(ScreenDropsSetup) + REGISTER_NODE_TYPE(AzEntity) +} - UiAnimSystemUnorderedMap g_animParamEnumToStringMap; - UiAnimSystemOrderedMap> g_animParamStringToEnumMap; - - // If you get an assert in this function, it means two node types have the same enum value. - void RegisterNodeTypes() - { - REGISTER_NODE_TYPE(Entity) - REGISTER_NODE_TYPE(Director) - REGISTER_NODE_TYPE(Camera) - REGISTER_NODE_TYPE(CVar) - REGISTER_NODE_TYPE(ScriptVar) - REGISTER_NODE_TYPE(Material) - REGISTER_NODE_TYPE(Event) - REGISTER_NODE_TYPE(Group) - REGISTER_NODE_TYPE(Layer) - REGISTER_NODE_TYPE(Comment) - REGISTER_NODE_TYPE(RadialBlur) - REGISTER_NODE_TYPE(ColorCorrection) - REGISTER_NODE_TYPE(DepthOfField) - REGISTER_NODE_TYPE(ScreenFader) - REGISTER_NODE_TYPE(Light) - REGISTER_NODE_TYPE(HDRSetup) - REGISTER_NODE_TYPE(ShadowSetup) - REGISTER_NODE_TYPE(Alembic) - REGISTER_NODE_TYPE(GeomCache) - REGISTER_NODE_TYPE(Environment) - REGISTER_NODE_TYPE(ScreenDropsSetup) - REGISTER_NODE_TYPE(AzEntity) - } - - // If you get an assert in this function, it means two param types have the same enum value. - void RegisterParamTypes() - { - REGISTER_PARAM_TYPE(Event) - REGISTER_PARAM_TYPE(Float) - REGISTER_PARAM_TYPE(TrackEvent) - REGISTER_PARAM_TYPE(AzComponentField) - } +// If you get an assert in this function, it means two param types have the same enum value. +void UiAnimationSystem::RegisterParamTypes() +{ + REGISTER_PARAM_TYPE(Event) + REGISTER_PARAM_TYPE(Float) + REGISTER_PARAM_TYPE(TrackEvent) + REGISTER_PARAM_TYPE(AzComponentField) } ////////////////////////////////////////////////////////////////////////// @@ -98,6 +80,10 @@ UiAnimationSystem::UiAnimationSystem() m_lastUpdateTime = AZ::Time::ZeroTimeUs; m_nextSequenceId = 1; + + DoNodeStaticInitialisation(); + RegisterNodeTypes(); + RegisterParamTypes(); } ////////////////////////////////////////////////////////////////////////// @@ -1173,16 +1159,16 @@ void UiAnimationSystem::SerializeNodeType(EUiAnimNodeType& animNodeType, XmlNode XmlString nodeTypeString; if (xmlNode->getAttr(kType, nodeTypeString)) { - assert(g_animNodeStringToEnumMap.find(nodeTypeString.c_str()) != g_animNodeStringToEnumMap.end()); - animNodeType = stl::find_in_map(g_animNodeStringToEnumMap, nodeTypeString.c_str(), eUiAnimNodeType_Invalid); + assert(m_animNodeStringToEnumMap.contains(nodeTypeString.c_str())); + animNodeType = stl::find_in_map(m_animNodeStringToEnumMap, nodeTypeString.c_str(), eUiAnimNodeType_Invalid); } } } else { const char* pTypeString = "Invalid"; - assert(g_animNodeEnumToStringMap.find(animNodeType) != g_animNodeEnumToStringMap.end()); - pTypeString = g_animNodeEnumToStringMap[animNodeType].c_str(); + assert(m_animNodeEnumToStringMap.find(animNodeType) != m_animNodeEnumToStringMap.end()); + pTypeString = m_animNodeEnumToStringMap[animNodeType].c_str(); xmlNode->setAttr(kType, pTypeString); } } @@ -1242,8 +1228,8 @@ void UiAnimationSystem::SerializeParamType(CUiAnimParamType& animParamType, XmlN } else { - assert(g_animParamStringToEnumMap.find(paramTypeString.c_str()) != g_animParamStringToEnumMap.end()); - animParamType.m_type = stl::find_in_map(g_animParamStringToEnumMap, paramTypeString.c_str(), eUiAnimParamType_Invalid); + assert(m_animParamStringToEnumMap.contains(paramTypeString.c_str())); + animParamType.m_type = stl::find_in_map(m_animParamStringToEnumMap, paramTypeString.c_str(), eUiAnimParamType_Invalid); } } } @@ -1265,8 +1251,8 @@ void UiAnimationSystem::SerializeParamType(CUiAnimParamType& animParamType, XmlN } else { - assert(g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end()); - pTypeString = g_animParamEnumToStringMap[animParamType.m_type].c_str(); + assert(m_animParamEnumToStringMap.find(animParamType.m_type) != m_animParamEnumToStringMap.end()); + pTypeString = m_animParamEnumToStringMap[animParamType.m_type].c_str(); } xmlNode->setAttr(kParamType, pTypeString); @@ -1332,9 +1318,9 @@ const char* UiAnimationSystem::GetParamTypeName(const CUiAnimParamType& animPara } else { - if (g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end()) + if (m_animParamEnumToStringMap.find(animParamType.m_type) != m_animParamEnumToStringMap.end()) { - return g_animParamEnumToStringMap[animParamType.m_type].c_str(); + return m_animParamEnumToStringMap[animParamType.m_type].c_str(); } } @@ -1346,15 +1332,6 @@ void UiAnimationSystem::OnCameraCut() { } -////////////////////////////////////////////////////////////////////////// -void UiAnimationSystem::StaticInitialize() -{ - DoNodeStaticInitialisation(); - - RegisterNodeTypes(); - RegisterParamTypes(); -} - ////////////////////////////////////////////////////////////////////////// void UiAnimationSystem::Reflect(AZ::SerializeContext* serializeContext) { @@ -1380,13 +1357,13 @@ void UiAnimationSystem::Reflect(AZ::SerializeContext* serializeContext) ////////////////////////////////////////////////////////////////////////// EUiAnimNodeType UiAnimationSystem::GetNodeTypeFromString(const char* pString) const { - return stl::find_in_map(g_animNodeStringToEnumMap, pString, eUiAnimNodeType_Invalid); + return stl::find_in_map(m_animNodeStringToEnumMap, pString, eUiAnimNodeType_Invalid); } ////////////////////////////////////////////////////////////////////////// CUiAnimParamType UiAnimationSystem::GetParamTypeFromString(const char* pString) const { - const EUiAnimParamType paramType = stl::find_in_map(g_animParamStringToEnumMap, pString, eUiAnimParamType_Invalid); + const EUiAnimParamType paramType = stl::find_in_map(m_animParamStringToEnumMap, pString, eUiAnimParamType_Invalid); if (paramType != eUiAnimParamType_Invalid) { diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h index cd51cd51d0..6c710205fa 100644 --- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h +++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.h @@ -14,6 +14,8 @@ #include #include +#include + struct PlayingUIAnimSequence { //! Sequence playing @@ -134,12 +136,10 @@ public: void SerializeParamType(CUiAnimParamType& animParamType, XmlNodeRef& xmlNode, bool bLoading, const uint version) override; void SerializeParamData(UiAnimParamData& animParamData, XmlNodeRef& xmlNode, bool bLoading) override; - static const char* GetParamTypeName(const CUiAnimParamType& animParamType); + const char* GetParamTypeName(const CUiAnimParamType& animParamType); void OnCameraCut(); - static void StaticInitialize(); - static void Reflect(AZ::SerializeContext* serializeContext); void NotifyTrackEventListeners(const char* eventName, const char* valueName, IUiAnimSequence* pSequence) override; @@ -187,5 +187,21 @@ private: // A sequence which turned on the early animation update last time uint32 m_nextSequenceId; + + using UiAnimParamSystemString = AZStd::string; + template > + using UiAnimSystemOrderedMap = AZStd::map; + template , typename EqualKey = AZStd::equal_to<>> + using UiAnimSystemUnorderedMap = AZStd::unordered_map; + + UiAnimSystemUnorderedMap m_animNodeEnumToStringMap; + UiAnimSystemOrderedMap m_animNodeStringToEnumMap; + + UiAnimSystemUnorderedMap m_animParamEnumToStringMap; + UiAnimSystemOrderedMap m_animParamStringToEnumMap; + + void RegisterNodeTypes(); + void RegisterParamTypes(); + void ShowPlayedSequencesDebug(); }; diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index 5a704329ef..b362ed2106 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -156,8 +156,6 @@ CLyShine::CLyShine([[maybe_unused]] ISystem* system) UiElementComponent::Initialize(); UiCanvasComponent::Initialize(); - UiAnimationSystem::StaticInitialize(); - AzFramework::InputChannelEventListener::Connect(); AzFramework::InputTextEventListener::Connect(); UiCursorBus::Handler::BusConnect(); diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp index b535033351..7e32301b71 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp @@ -8,7 +8,6 @@ #include -#include #include "AnimPostFXNode.h" #include "AnimSplineTrack.h" #include "CompoundSplineTrack.h" @@ -39,7 +38,7 @@ public: virtual void GetDefault(bool& val) const = 0; virtual void GetDefault(Vec4& val) const = 0; - AZStd::basic_string, AZStd::stateless_allocator> m_name; + AZStd::string m_name; protected: virtual ~CControlParamBase(){} diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp index dc0782f982..51be8a4c24 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -28,7 +27,6 @@ #include "LayerNode.h" #include "ShadowsSetupNode.h" -#include #include #include @@ -74,136 +72,117 @@ static SMovieSequenceAutoComplete s_movieSequenceAutoComplete; #endif ////////////////////////////////////////////////////////////////////////// -namespace -{ - using AnimParamSystemString = AZStd::basic_string, AZStd::stateless_allocator>; +// Serialization for anim nodes & param types +#define REGISTER_NODE_TYPE(name) assert(!m_animNodeEnumToStringMap.contains(AnimNodeType::name)); \ + m_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ + m_animNodeStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimNodeType::name; - template > - using AnimSystemOrderedMap = AZStd::map; - template , typename EqualKey = AZStd::equal_to> - using AnimSystemUnorderedMap = AZStd::unordered_map; +#define REGISTER_PARAM_TYPE(name) assert(!m_animParamEnumToStringMap.contains(AnimParamType::name)); \ + m_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ + m_animParamStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimParamType::name; + +// If you get an assert in this function, it means two node types have the same enum value. +void CMovieSystem::RegisterNodeTypes() +{ + REGISTER_NODE_TYPE(Entity) + REGISTER_NODE_TYPE(Director) + REGISTER_NODE_TYPE(Camera) + REGISTER_NODE_TYPE(CVar) + REGISTER_NODE_TYPE(ScriptVar) + REGISTER_NODE_TYPE(Material) + REGISTER_NODE_TYPE(Event) + REGISTER_NODE_TYPE(Group) + REGISTER_NODE_TYPE(Layer) + REGISTER_NODE_TYPE(Comment) + REGISTER_NODE_TYPE(RadialBlur) + REGISTER_NODE_TYPE(ColorCorrection) + REGISTER_NODE_TYPE(DepthOfField) + REGISTER_NODE_TYPE(ScreenFader) + REGISTER_NODE_TYPE(Light) + REGISTER_NODE_TYPE(ShadowSetup) + REGISTER_NODE_TYPE(Alembic) + REGISTER_NODE_TYPE(GeomCache) + REGISTER_NODE_TYPE(Environment) + REGISTER_NODE_TYPE(AzEntity) + REGISTER_NODE_TYPE(Component) } -// Serialization for anim nodes & param types -#define REGISTER_NODE_TYPE(name) assert(!g_animNodeEnumToStringMap.contains(AnimNodeType::name)); \ - g_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ - g_animNodeStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimNodeType::name; - -#define REGISTER_PARAM_TYPE(name) assert(!g_animParamEnumToStringMap.contains(AnimParamType::name)); \ - g_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ - g_animParamStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimParamType::name; - -namespace +// If you get an assert in this function, it means two param types have the same enum value. +void CMovieSystem::RegisterParamTypes() { - AnimSystemUnorderedMap g_animNodeEnumToStringMap; - AnimSystemOrderedMap> g_animNodeStringToEnumMap; - - AnimSystemUnorderedMap g_animParamEnumToStringMap; - AnimSystemOrderedMap> g_animParamStringToEnumMap; - - // If you get an assert in this function, it means two node types have the same enum value. - void RegisterNodeTypes() - { - REGISTER_NODE_TYPE(Entity) - REGISTER_NODE_TYPE(Director) - REGISTER_NODE_TYPE(Camera) - REGISTER_NODE_TYPE(CVar) - REGISTER_NODE_TYPE(ScriptVar) - REGISTER_NODE_TYPE(Material) - REGISTER_NODE_TYPE(Event) - REGISTER_NODE_TYPE(Group) - REGISTER_NODE_TYPE(Layer) - REGISTER_NODE_TYPE(Comment) - REGISTER_NODE_TYPE(RadialBlur) - REGISTER_NODE_TYPE(ColorCorrection) - REGISTER_NODE_TYPE(DepthOfField) - REGISTER_NODE_TYPE(ScreenFader) - REGISTER_NODE_TYPE(Light) - REGISTER_NODE_TYPE(ShadowSetup) - REGISTER_NODE_TYPE(Alembic) - REGISTER_NODE_TYPE(GeomCache) - REGISTER_NODE_TYPE(Environment) - REGISTER_NODE_TYPE(AzEntity) - REGISTER_NODE_TYPE(Component) - } - - // If you get an assert in this function, it means two param types have the same enum value. - void RegisterParamTypes() - { - REGISTER_PARAM_TYPE(FOV) - REGISTER_PARAM_TYPE(Position) - REGISTER_PARAM_TYPE(Rotation) - REGISTER_PARAM_TYPE(Scale) - REGISTER_PARAM_TYPE(Event) - REGISTER_PARAM_TYPE(Visibility) - REGISTER_PARAM_TYPE(Camera) - REGISTER_PARAM_TYPE(Animation) - REGISTER_PARAM_TYPE(Sound) - REGISTER_PARAM_TYPE(Sequence) - REGISTER_PARAM_TYPE(Console) - REGISTER_PARAM_TYPE(Music) ///@deprecated in 1.11, left in for legacy serialization - REGISTER_PARAM_TYPE(Float) - REGISTER_PARAM_TYPE(LookAt) - REGISTER_PARAM_TYPE(TrackEvent) - REGISTER_PARAM_TYPE(ShakeAmplitudeA) - REGISTER_PARAM_TYPE(ShakeAmplitudeB) - REGISTER_PARAM_TYPE(ShakeFrequencyA) - REGISTER_PARAM_TYPE(ShakeFrequencyB) - REGISTER_PARAM_TYPE(ShakeMultiplier) - REGISTER_PARAM_TYPE(ShakeNoise) - REGISTER_PARAM_TYPE(ShakeWorking) - REGISTER_PARAM_TYPE(ShakeAmpAMult) - REGISTER_PARAM_TYPE(ShakeAmpBMult) - REGISTER_PARAM_TYPE(ShakeFreqAMult) - REGISTER_PARAM_TYPE(ShakeFreqBMult) - REGISTER_PARAM_TYPE(DepthOfField) - REGISTER_PARAM_TYPE(FocusDistance) - REGISTER_PARAM_TYPE(FocusRange) - REGISTER_PARAM_TYPE(BlurAmount) - REGISTER_PARAM_TYPE(Capture) - REGISTER_PARAM_TYPE(TransformNoise) - REGISTER_PARAM_TYPE(TimeWarp) - REGISTER_PARAM_TYPE(FixedTimeStep) - REGISTER_PARAM_TYPE(NearZ) - REGISTER_PARAM_TYPE(Goto) - REGISTER_PARAM_TYPE(PositionX) - REGISTER_PARAM_TYPE(PositionY) - REGISTER_PARAM_TYPE(PositionZ) - REGISTER_PARAM_TYPE(RotationX) - REGISTER_PARAM_TYPE(RotationY) - REGISTER_PARAM_TYPE(RotationZ) - REGISTER_PARAM_TYPE(ScaleX) - REGISTER_PARAM_TYPE(ScaleY) - REGISTER_PARAM_TYPE(ScaleZ) - REGISTER_PARAM_TYPE(ColorR) - REGISTER_PARAM_TYPE(ColorG) - REGISTER_PARAM_TYPE(ColorB) - REGISTER_PARAM_TYPE(CommentText) - REGISTER_PARAM_TYPE(ScreenFader) - REGISTER_PARAM_TYPE(LightDiffuse) - REGISTER_PARAM_TYPE(LightRadius) - REGISTER_PARAM_TYPE(LightDiffuseMult) - REGISTER_PARAM_TYPE(LightHDRDynamic) - REGISTER_PARAM_TYPE(LightSpecularMult) - REGISTER_PARAM_TYPE(LightSpecPercentage) - REGISTER_PARAM_TYPE(MaterialDiffuse) - REGISTER_PARAM_TYPE(MaterialSpecular) - REGISTER_PARAM_TYPE(MaterialEmissive) - REGISTER_PARAM_TYPE(MaterialEmissiveIntensity) - REGISTER_PARAM_TYPE(MaterialOpacity) - REGISTER_PARAM_TYPE(MaterialSmoothness) - REGISTER_PARAM_TYPE(TimeRanges) - REGISTER_PARAM_TYPE(Physics) - REGISTER_PARAM_TYPE(GSMCache) - REGISTER_PARAM_TYPE(ShutterSpeed) - REGISTER_PARAM_TYPE(Physicalize) - REGISTER_PARAM_TYPE(PhysicsDriven) - REGISTER_PARAM_TYPE(SunLongitude) - REGISTER_PARAM_TYPE(SunLatitude) - REGISTER_PARAM_TYPE(MoonLongitude) - REGISTER_PARAM_TYPE(MoonLatitude) - REGISTER_PARAM_TYPE(ProceduralEyes) - } + REGISTER_PARAM_TYPE(FOV) + REGISTER_PARAM_TYPE(Position) + REGISTER_PARAM_TYPE(Rotation) + REGISTER_PARAM_TYPE(Scale) + REGISTER_PARAM_TYPE(Event) + REGISTER_PARAM_TYPE(Visibility) + REGISTER_PARAM_TYPE(Camera) + REGISTER_PARAM_TYPE(Animation) + REGISTER_PARAM_TYPE(Sound) + REGISTER_PARAM_TYPE(Sequence) + REGISTER_PARAM_TYPE(Console) + REGISTER_PARAM_TYPE(Music) ///@deprecated in 1.11, left in for legacy serialization + REGISTER_PARAM_TYPE(Float) + REGISTER_PARAM_TYPE(LookAt) + REGISTER_PARAM_TYPE(TrackEvent) + REGISTER_PARAM_TYPE(ShakeAmplitudeA) + REGISTER_PARAM_TYPE(ShakeAmplitudeB) + REGISTER_PARAM_TYPE(ShakeFrequencyA) + REGISTER_PARAM_TYPE(ShakeFrequencyB) + REGISTER_PARAM_TYPE(ShakeMultiplier) + REGISTER_PARAM_TYPE(ShakeNoise) + REGISTER_PARAM_TYPE(ShakeWorking) + REGISTER_PARAM_TYPE(ShakeAmpAMult) + REGISTER_PARAM_TYPE(ShakeAmpBMult) + REGISTER_PARAM_TYPE(ShakeFreqAMult) + REGISTER_PARAM_TYPE(ShakeFreqBMult) + REGISTER_PARAM_TYPE(DepthOfField) + REGISTER_PARAM_TYPE(FocusDistance) + REGISTER_PARAM_TYPE(FocusRange) + REGISTER_PARAM_TYPE(BlurAmount) + REGISTER_PARAM_TYPE(Capture) + REGISTER_PARAM_TYPE(TransformNoise) + REGISTER_PARAM_TYPE(TimeWarp) + REGISTER_PARAM_TYPE(FixedTimeStep) + REGISTER_PARAM_TYPE(NearZ) + REGISTER_PARAM_TYPE(Goto) + REGISTER_PARAM_TYPE(PositionX) + REGISTER_PARAM_TYPE(PositionY) + REGISTER_PARAM_TYPE(PositionZ) + REGISTER_PARAM_TYPE(RotationX) + REGISTER_PARAM_TYPE(RotationY) + REGISTER_PARAM_TYPE(RotationZ) + REGISTER_PARAM_TYPE(ScaleX) + REGISTER_PARAM_TYPE(ScaleY) + REGISTER_PARAM_TYPE(ScaleZ) + REGISTER_PARAM_TYPE(ColorR) + REGISTER_PARAM_TYPE(ColorG) + REGISTER_PARAM_TYPE(ColorB) + REGISTER_PARAM_TYPE(CommentText) + REGISTER_PARAM_TYPE(ScreenFader) + REGISTER_PARAM_TYPE(LightDiffuse) + REGISTER_PARAM_TYPE(LightRadius) + REGISTER_PARAM_TYPE(LightDiffuseMult) + REGISTER_PARAM_TYPE(LightHDRDynamic) + REGISTER_PARAM_TYPE(LightSpecularMult) + REGISTER_PARAM_TYPE(LightSpecPercentage) + REGISTER_PARAM_TYPE(MaterialDiffuse) + REGISTER_PARAM_TYPE(MaterialSpecular) + REGISTER_PARAM_TYPE(MaterialEmissive) + REGISTER_PARAM_TYPE(MaterialEmissiveIntensity) + REGISTER_PARAM_TYPE(MaterialOpacity) + REGISTER_PARAM_TYPE(MaterialSmoothness) + REGISTER_PARAM_TYPE(TimeRanges) + REGISTER_PARAM_TYPE(Physics) + REGISTER_PARAM_TYPE(GSMCache) + REGISTER_PARAM_TYPE(ShutterSpeed) + REGISTER_PARAM_TYPE(Physicalize) + REGISTER_PARAM_TYPE(PhysicsDriven) + REGISTER_PARAM_TYPE(SunLongitude) + REGISTER_PARAM_TYPE(SunLatitude) + REGISTER_PARAM_TYPE(MoonLongitude) + REGISTER_PARAM_TYPE(MoonLatitude) + REGISTER_PARAM_TYPE(ProceduralEyes) } namespace Internal @@ -1666,16 +1645,16 @@ void CMovieSystem::SerializeNodeType(AnimNodeType& animNodeType, XmlNodeRef& xml XmlString nodeTypeString; if (xmlNode->getAttr(kType, nodeTypeString)) { - assert(g_animNodeStringToEnumMap.find(nodeTypeString.c_str()) != g_animNodeStringToEnumMap.end()); - animNodeType = stl::find_in_map(g_animNodeStringToEnumMap, nodeTypeString.c_str(), AnimNodeType::Invalid); + assert(m_animNodeStringToEnumMap.find(nodeTypeString.c_str()) != m_animNodeStringToEnumMap.end()); + animNodeType = stl::find_in_map(m_animNodeStringToEnumMap, nodeTypeString.c_str(), AnimNodeType::Invalid); } } } else { const char* pTypeString = "Invalid"; - assert(g_animNodeEnumToStringMap.find(animNodeType) != g_animNodeEnumToStringMap.end()); - pTypeString = g_animNodeEnumToStringMap[animNodeType].c_str(); + assert(m_animNodeEnumToStringMap.find(animNodeType) != m_animNodeEnumToStringMap.end()); + pTypeString = m_animNodeEnumToStringMap[animNodeType].c_str(); xmlNode->setAttr(kType, pTypeString); } } @@ -1744,8 +1723,8 @@ void CMovieSystem::LoadParamTypeFromXml(CAnimParamType& animParamType, const Xml animParamType.m_name = virtualPropertyValue; } - assert(g_animParamStringToEnumMap.find(paramTypeString.c_str()) != g_animParamStringToEnumMap.end()); - animParamType.m_type = stl::find_in_map(g_animParamStringToEnumMap, paramTypeString.c_str(), AnimParamType::Invalid); + assert(m_animParamStringToEnumMap.find(paramTypeString.c_str()) != m_animParamStringToEnumMap.end()); + animParamType.m_type = stl::find_in_map(m_animParamStringToEnumMap, paramTypeString.c_str(), AnimParamType::Invalid); } } } @@ -1775,8 +1754,8 @@ void CMovieSystem::SaveParamTypeToXml(const CAnimParamType& animParamType, XmlNo xmlNode->setAttr(CAnimParamTypeXmlNames::kVirtualPropertyName, animParamType.m_name.c_str()); } - assert(g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end()); - pTypeString = g_animParamEnumToStringMap[animParamType.m_type].c_str(); + assert(m_animParamEnumToStringMap.find(animParamType.m_type) != m_animParamEnumToStringMap.end()); + pTypeString = m_animParamEnumToStringMap[animParamType.m_type].c_str(); } xmlNode->setAttr(kParamType, pTypeString); @@ -1809,9 +1788,9 @@ const char* CMovieSystem::GetParamTypeName(const CAnimParamType& animParamType) } else { - if (g_animParamEnumToStringMap.find(animParamType.m_type) != g_animParamEnumToStringMap.end()) + if (m_animParamEnumToStringMap.contains(animParamType.m_type)) { - return g_animParamEnumToStringMap[animParamType.m_type].c_str(); + return m_animParamEnumToStringMap[animParamType.m_type].c_str(); } } @@ -1973,13 +1952,13 @@ void CLightAnimWrapper::RemoveCachedLightAnim(const char* name) ////////////////////////////////////////////////////////////////////////// AnimNodeType CMovieSystem::GetNodeTypeFromString(const char* pString) const { - return stl::find_in_map(g_animNodeStringToEnumMap, pString, AnimNodeType::Invalid); + return stl::find_in_map(m_animNodeStringToEnumMap, pString, AnimNodeType::Invalid); } ////////////////////////////////////////////////////////////////////////// CAnimParamType CMovieSystem::GetParamTypeFromString(const char* pString) const { - const AnimParamType paramType = stl::find_in_map(g_animParamStringToEnumMap, pString, AnimParamType::Invalid); + const AnimParamType paramType = stl::find_in_map(m_animParamStringToEnumMap, pString, AnimParamType::Invalid); if (paramType != AnimParamType::Invalid) { diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.h b/Gems/Maestro/Code/Source/Cinematics/Movie.h index ab2c2e649b..4af2b55ced 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.h +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.h @@ -18,6 +18,7 @@ #include #include +#include #include "IMovieSystem.h" #include "IShader.h" @@ -192,7 +193,7 @@ public: void SaveParamTypeToXml(const CAnimParamType& animParamType, XmlNodeRef& xmlNode) override; void SerializeParamType(CAnimParamType& animParamType, XmlNodeRef& xmlNode, bool bLoading, const uint version) override; - static const char* GetParamTypeName(const CAnimParamType& animParamType); + const char* GetParamTypeName(const CAnimParamType& animParamType); void OnCameraCut(); @@ -290,6 +291,23 @@ private: void ShowPlayedSequencesDebug(); + + using AnimParamSystemString = AZStd::string; + + template > + using AnimSystemOrderedMap = AZStd::map; + template , typename EqualKey = AZStd::equal_to<>> + using AnimSystemUnorderedMap = AZStd::unordered_map; + + AnimSystemUnorderedMap m_animNodeEnumToStringMap; + AnimSystemOrderedMap m_animNodeStringToEnumMap; + + AnimSystemUnorderedMap m_animParamEnumToStringMap; + AnimSystemOrderedMap m_animParamStringToEnumMap; + + void RegisterNodeTypes(); + void RegisterParamTypes(); + public: static float m_mov_cameraPrecacheTime; #if !defined(_RELEASE) diff --git a/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h b/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h index ce2f4826da..bb0ed650e5 100644 --- a/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h +++ b/Gems/TextureAtlas/Code/Source/TextureAtlasImpl.h @@ -33,7 +33,7 @@ namespace TextureAtlasNamespace struct hash_case_insensitive : public AZStd::hash { AZ_TYPE_INFO(hash_case_insensitive, "{FE0F4349-D80D-4286-8874-733966A32B29}"); - inline result_type operator()(const AZStd::string& value) const + inline size_t operator()(const AZStd::string& value) const { AZStd::string lowerStr = value; AZStd::to_lower(lowerStr.begin(), lowerStr.end()); From f87e1f6906d1ccdb4485d6e6e1237101128b68fd Mon Sep 17 00:00:00 2001 From: LesaelR <89800757+LesaelR@users.noreply.github.com> Date: Fri, 14 Jan 2022 09:48:46 -0800 Subject: [PATCH 087/108] Disabling BundleMode, AssetBundler, and MissingDependency tests on Linux. (#6888) Signed-off-by: Rosario Cox --- .../asset_processor_tests/CMakeLists.txt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt index e37a5ed99b..5839093473 100644 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/CMakeLists.txt @@ -93,15 +93,19 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_pytest( - NAME AssetPipelineTests.AssetBundler - PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py + NAME AssetPipelineTests.AssetBuilder + PATH ${CMAKE_CURRENT_LIST_DIR}/asset_builder_tests.py EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL TEST_SUITE periodic RUNTIME_DEPENDENCIES AZ::AssetProcessor - AZ::AssetBundlerBatch ) + + set(SUPPORTED_PLATFORMS "Windows" "Mac") + if (NOT "${PAL_PLATFORM_NAME}" IN_LIST SUPPORTED_PLATFORMS) + return() + endif() ly_add_pytest( NAME AssetPipelineTests.BundleMode @@ -117,16 +121,16 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ) ly_add_pytest( - NAME AssetPipelineTests.AssetBuilder - PATH ${CMAKE_CURRENT_LIST_DIR}/asset_builder_tests.py + NAME AssetPipelineTests.AssetBundler + PATH ${CMAKE_CURRENT_LIST_DIR}/asset_bundler_batch_tests.py EXCLUDE_TEST_RUN_TARGET_FROM_IDE TEST_SERIAL TEST_SUITE periodic RUNTIME_DEPENDENCIES AZ::AssetProcessor + AZ::AssetBundlerBatch ) - ly_add_pytest( NAME AssetPipelineTests.MissingDependency PATH ${CMAKE_CURRENT_LIST_DIR}/missing_dependency_tests.py @@ -136,5 +140,5 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) RUNTIME_DEPENDENCIES AZ::AssetProcessorBatch ) - + endif() From 02ce4659c4312c11c6210f5745b2a592650012c0 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Fri, 14 Jan 2022 09:58:54 -0800 Subject: [PATCH 088/108] remove comment Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index 0e158d3e08..92045b505f 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -674,7 +674,6 @@ namespace ScriptCanvasEditor if (variable) { - // functions 2.0 set variable scope to function if (variable->GetScope() != ScriptCanvas::VariableFlags::Scope::Function) { variable->SetScope(ScriptCanvas::VariableFlags::Scope::Function); From c778606c89e795ff885f5a732eaecd3b8946ba98 Mon Sep 17 00:00:00 2001 From: AMZN-byrcolin <68035668+byrcolin@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:27:20 -0800 Subject: [PATCH 089/108] Templates restricted (#6498) * Templates/Restricted upgrade/fixes: Fixed template storage format: templates now only store true relative paths and no longer save "origin" paths and "optional" has been removed, it was never used. Upgraded all templates to new standard Template system now correctly handles child objects: Child objects no longer have to specify restricted they inherit from parent Restricted now operates at the object level and makes no assumptions about parent Restricted templates can now be combined and seperated on creation ly_get_list_relative_filename has been deprecated for o3de_pal_dir All Gems/Projects/Templates updated to use new code Signed-off-by: byrcolin --- AutomatedTesting/CMakeLists.txt | 1 - AutomatedTesting/Gem/CMakeLists.txt | 7 +- AutomatedTesting/Gem/Code/CMakeLists.txt | 2 +- .../Gem/PythonCoverage/CMakeLists.txt | 4 + .../Gem/PythonCoverage/Code/CMakeLists.txt | 2 +- AutomatedTesting/Gem/PythonCoverage/gem.json | 6 +- .../Gem/PythonTests/Blast/CMakeLists.txt | 2 +- .../Gem/PythonTests/CMakeLists.txt | 2 +- .../Gem/PythonTests/WhiteBox/CMakeLists.txt | 2 +- AutomatedTesting/Gem/Sponza/gem.json | 11 +- AutomatedTesting/Gem/gem.json | 14 +- AutomatedTesting/project.json | 9 +- CMakeLists.txt | 73 +- Code/Editor/CMakeLists.txt | 2 +- Code/Framework/AzCore/CMakeLists.txt | 10 +- Code/Framework/AzFramework/CMakeLists.txt | 12 +- Code/Framework/AzNetworking/CMakeLists.txt | 4 +- Code/Framework/AzQtComponents/CMakeLists.txt | 2 +- Code/Framework/AzTest/CMakeLists.txt | 8 +- Code/Framework/GridMate/CMakeLists.txt | 6 +- Code/LauncherUnified/CMakeLists.txt | 2 +- Code/LauncherUnified/launcher_generator.cmake | 2 +- Code/Legacy/CryCommon/CMakeLists.txt | 2 +- Code/Legacy/CrySystem/CMakeLists.txt | 2 +- Code/Tools/AWSNativeSDKInit/CMakeLists.txt | 4 +- .../AssetBuilderSDK/CMakeLists.txt | 2 +- Code/Tools/AzTestRunner/CMakeLists.txt | 2 +- Code/Tools/CrashHandler/CMakeLists.txt | 2 +- Code/Tools/LuaIDE/CMakeLists.txt | 4 +- .../ProjectManager/Source/PythonBindings.cpp | 2 +- Code/Tools/RemoteConsole/CMakeLists.txt | 2 +- Code/Tools/SceneAPI/SceneData/CMakeLists.txt | 2 +- Code/Tools/TestImpactFramework/CMakeLists.txt | 4 +- .../Runtime/Code/CMakeLists.txt | 4 +- Gems/AWSClientAuth/CMakeLists.txt | 4 + Gems/AWSClientAuth/Code/CMakeLists.txt | 2 +- Gems/AWSClientAuth/gem.json | 4 +- Gems/AWSCore/CMakeLists.txt | 4 + Gems/AWSCore/Code/CMakeLists.txt | 4 +- Gems/AWSCore/gem.json | 8 +- Gems/AWSGameLift/gem.json | 5 +- Gems/AWSMetrics/gem.json | 4 +- Gems/Achievements/CMakeLists.txt | 4 + Gems/Achievements/Code/CMakeLists.txt | 6 +- Gems/Achievements/gem.json | 1 + Gems/AssetValidation/gem.json | 1 + Gems/Atom/Asset/CMakeLists.txt | 10 - .../Asset/ImageProcessingAtom/CMakeLists.txt | 4 + .../ImageProcessingAtom/Code/CMakeLists.txt | 6 +- Gems/Atom/Asset/ImageProcessingAtom/gem.json | 2 + Gems/Atom/Asset/Shader/CMakeLists.txt | 4 + Gems/Atom/Asset/Shader/Code/CMakeLists.txt | 6 +- Gems/Atom/Asset/Shader/gem.json | 8 +- Gems/Atom/Bootstrap/CMakeLists.txt | 4 + Gems/Atom/Bootstrap/Code/CMakeLists.txt | 2 +- Gems/Atom/Bootstrap/gem.json | 2 + Gems/Atom/CMakeLists.txt | 10 +- Gems/Atom/Component/CMakeLists.txt | 9 - .../Atom/Component/DebugCamera/CMakeLists.txt | 4 + Gems/Atom/Component/DebugCamera/gem.json | 2 + Gems/Atom/Feature/CMakeLists.txt | 9 - Gems/Atom/Feature/Common/CMakeLists.txt | 4 + Gems/Atom/Feature/Common/Code/CMakeLists.txt | 4 +- Gems/Atom/Feature/Common/gem.json | 2 + Gems/Atom/RHI/CMakeLists.txt | 8 +- Gems/Atom/RHI/Code/CMakeLists.txt | 4 +- Gems/Atom/RHI/DX12/CMakeLists.txt | 4 + Gems/Atom/RHI/DX12/Code/CMakeLists.txt | 6 +- Gems/Atom/RHI/DX12/gem.json | 2 + Gems/Atom/RHI/Metal/CMakeLists.txt | 4 + Gems/Atom/RHI/Metal/Code/CMakeLists.txt | 4 +- Gems/Atom/RHI/Metal/gem.json | 2 + Gems/Atom/RHI/Null/CMakeLists.txt | 4 + Gems/Atom/RHI/Null/Code/CMakeLists.txt | 4 +- Gems/Atom/RHI/Null/gem.json | 2 + Gems/Atom/RHI/Vulkan/CMakeLists.txt | 4 + Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt | 4 +- Gems/Atom/RHI/Vulkan/gem.json | 2 + Gems/Atom/RHI/gem.json | 7 + Gems/Atom/RPI/CMakeLists.txt | 4 + Gems/Atom/RPI/Code/CMakeLists.txt | 6 +- Gems/Atom/RPI/gem.json | 4 +- .../Tools/AtomToolsFramework/CMakeLists.txt | 4 + .../AtomToolsFramework/Code/CMakeLists.txt | 2 +- Gems/Atom/Tools/AtomToolsFramework/gem.json | 2 + Gems/Atom/Tools/CMakeLists.txt | 2 - Gems/Atom/Tools/MaterialEditor/CMakeLists.txt | 4 + .../Tools/MaterialEditor/Code/CMakeLists.txt | 2 +- Gems/Atom/Tools/MaterialEditor/gem.json | 2 + .../Code/CMakeLists.txt | 2 +- Gems/Atom/Utils/Code/CMakeLists.txt | 5 +- Gems/Atom/gem.json | 12 + Gems/AtomContent/CMakeLists.txt | 2 - Gems/AtomContent/ReferenceMaterials/gem.json | 10 +- Gems/AtomContent/Sponza/gem.json | 5 +- Gems/AtomContent/gem.json | 9 +- .../AtomBridge/CMakeLists.txt | 4 + .../AtomBridge/Code/CMakeLists.txt | 2 +- Gems/AtomLyIntegration/AtomBridge/gem.json | 2 + .../AtomLyIntegration/AtomFont/CMakeLists.txt | 4 + .../AtomFont/Code/CMakeLists.txt | 2 +- Gems/AtomLyIntegration/AtomFont/gem.json | 2 + .../AtomLyIntegration/AtomImGuiTools/gem.json | 2 + .../AtomViewportDisplayIcons/gem.json | 2 + .../AtomViewportDisplayInfo/gem.json | 2 + Gems/AtomLyIntegration/CMakeLists.txt | 9 - .../CommonFeatures/CMakeLists.txt | 4 + .../CommonFeatures/Code/CMakeLists.txt | 4 +- .../AtomLyIntegration/CommonFeatures/gem.json | 2 + Gems/AtomLyIntegration/EMotionFXAtom/gem.json | 2 + Gems/AtomLyIntegration/ImguiAtom/gem.json | 2 + .../TechnicalArt/CMakeLists.txt | 9 - .../DccScriptingInterface/CMakeLists.txt | 1 - .../DccScriptingInterface/gem.json | 4 +- Gems/AtomLyIntegration/gem.json | 12 + Gems/AtomTressFX/gem.json | 5 +- Gems/AudioEngineWwise/CMakeLists.txt | 4 + Gems/AudioEngineWwise/Code/CMakeLists.txt | 4 +- Gems/AudioEngineWwise/gem.json | 1 + Gems/AudioSystem/CMakeLists.txt | 4 + Gems/AudioSystem/Code/CMakeLists.txt | 4 +- Gems/AudioSystem/gem.json | 1 + Gems/BarrierInput/gem.json | 2 + Gems/Blast/CMakeLists.txt | 4 + Gems/Blast/Code/CMakeLists.txt | 2 +- Gems/Blast/gem.json | 1 + Gems/Camera/gem.json | 1 + Gems/CameraFramework/gem.json | 1 + Gems/CertificateManager/gem.json | 1 + Gems/CrashReporting/CMakeLists.txt | 4 + Gems/CrashReporting/Code/CMakeLists.txt | 2 +- Gems/CrashReporting/gem.json | 1 + Gems/CustomAssetExample/gem.json | 1 + Gems/DebugDraw/gem.json | 1 + Gems/DevTextures/gem.json | 1 + Gems/EMotionFX/CMakeLists.txt | 4 + Gems/EMotionFX/Code/CMakeLists.txt | 7 +- Gems/EMotionFX/gem.json | 1 + Gems/EditorPythonBindings/gem.json | 1 + Gems/ExpressionEvaluation/gem.json | 1 + Gems/FastNoise/gem.json | 1 + Gems/GameState/gem.json | 1 + Gems/GameStateSamples/CMakeLists.txt | 4 + Gems/GameStateSamples/Code/CMakeLists.txt | 2 +- Gems/GameStateSamples/gem.json | 1 + Gems/Gestures/gem.json | 1 + Gems/GradientSignal/gem.json | 1 + Gems/GraphCanvas/gem.json | 1 + Gems/GraphModel/gem.json | 1 + Gems/HttpRequestor/CMakeLists.txt | 4 + Gems/HttpRequestor/Code/CMakeLists.txt | 2 +- Gems/HttpRequestor/gem.json | 1 + Gems/ImGui/CMakeLists.txt | 4 + Gems/ImGui/Code/CMakeLists.txt | 2 +- Gems/ImGui/gem.json | 1 + Gems/InAppPurchases/CMakeLists.txt | 4 + Gems/InAppPurchases/Code/CMakeLists.txt | 2 +- Gems/InAppPurchases/gem.json | 1 + Gems/LandscapeCanvas/gem.json | 1 + Gems/LmbrCentral/CMakeLists.txt | 4 + Gems/LmbrCentral/Code/CMakeLists.txt | 4 +- Gems/LmbrCentral/gem.json | 1 + Gems/LocalUser/CMakeLists.txt | 4 + Gems/LocalUser/Code/CMakeLists.txt | 2 +- Gems/LocalUser/gem.json | 1 + Gems/LyShine/CMakeLists.txt | 4 + Gems/LyShine/Code/CMakeLists.txt | 4 +- Gems/LyShine/gem.json | 1 + Gems/LyShineExamples/gem.json | 1 + Gems/Maestro/gem.json | 1 + Gems/MessagePopup/gem.json | 1 + Gems/Metastream/CMakeLists.txt | 4 + Gems/Metastream/Code/CMakeLists.txt | 4 +- Gems/Metastream/gem.json | 1 + Gems/Microphone/CMakeLists.txt | 4 + Gems/Microphone/Code/CMakeLists.txt | 2 +- Gems/Microphone/gem.json | 1 + Gems/Multiplayer/CMakeLists.txt | 4 + Gems/Multiplayer/Code/CMakeLists.txt | 2 + Gems/Multiplayer/gem.json | 2 + Gems/MultiplayerCompression/gem.json | 1 + Gems/NvCloth/CMakeLists.txt | 4 + Gems/NvCloth/Code/CMakeLists.txt | 2 +- Gems/NvCloth/gem.json | 3 +- Gems/PhysX/CMakeLists.txt | 4 + Gems/PhysX/Code/CMakeLists.txt | 2 +- Gems/PhysXDebug/CMakeLists.txt | 4 + Gems/PhysXDebug/Code/CMakeLists.txt | 6 +- Gems/PhysXDebug/gem.json | 1 + Gems/Prefab/PrefabBuilder/gem.json | 1 + Gems/Presence/CMakeLists.txt | 4 + Gems/Presence/Code/CMakeLists.txt | 2 +- Gems/Presence/gem.json | 1 + Gems/PrimitiveAssets/gem.json | 1 + Gems/Profiler/gem.json | 1 + Gems/PythonAssetBuilder/gem.json | 1 + Gems/QtForPython/Code/CMakeLists.txt | 2 +- Gems/QtForPython/gem.json | 1 + Gems/SaveData/CMakeLists.txt | 4 + Gems/SaveData/Code/CMakeLists.txt | 2 +- Gems/SaveData/gem.json | 1 + Gems/SceneLoggingExample/gem.json | 1 + Gems/SceneProcessing/gem.json | 1 + Gems/ScriptCanvas/gem.json | 1 + Gems/ScriptCanvasDeveloper/gem.json | 1 + Gems/ScriptCanvasPhysics/gem.json | 1 + Gems/ScriptCanvasTesting/gem.json | 1 + Gems/ScriptEvents/gem.json | 1 + Gems/ScriptedEntityTweener/gem.json | 1 + Gems/SliceFavorites/gem.json | 5 + Gems/StartingPointCamera/gem.json | 1 + Gems/StartingPointInput/gem.json | 1 + Gems/StartingPointMovement/gem.json | 1 + Gems/SurfaceData/gem.json | 1 + Gems/Terrain/gem.json | 1 + Gems/TestAssetBuilder/gem.json | 1 + Gems/TextureAtlas/gem.json | 1 + Gems/TickBusOrderViewer/gem.json | 1 + Gems/Twitch/CMakeLists.txt | 4 + Gems/Twitch/Code/CMakeLists.txt | 4 +- Gems/Twitch/gem.json | 4 +- Gems/UiBasics/gem.json | 1 + Gems/Vegetation/gem.json | 1 + Gems/VideoPlaybackFramework/gem.json | 1 + Gems/VirtualGamepad/gem.json | 1 + Gems/WhiteBox/CMakeLists.txt | 4 + Gems/WhiteBox/Code/CMakeLists.txt | 4 +- Gems/WhiteBox/gem.json | 1 + Templates/AssetGem/Template/gem.json | 15 +- Templates/AssetGem/template.json | 32 +- Templates/CppToolGem/Template/gem.json | 15 +- Templates/CppToolGem/template.json | 262 ++---- Templates/DefaultGem/Template/CMakeLists.txt | 9 +- .../DefaultGem/Template/Code/CMakeLists.txt | 4 +- Templates/DefaultGem/Template/gem.json | 14 +- Templates/DefaultGem/template.json | 250 ++---- .../DefaultProject/Template/CMakeLists.txt | 1 - .../{Code => Gem}/${NameLower}_files.cmake | 0 .../${NameLower}_shared_files.cmake | 0 .../Template/Gem}/CMakeLists.txt | 11 +- .../Include/${Name}/${Name}Bus.h | 2 +- .../Android/${NameLower}_android_files.cmake | 0 .../${NameLower}_shared_android_files.cmake | 0 .../Platform/Android/PAL_android.cmake | 0 .../Linux/${NameLower}_linux_files.cmake | 0 .../${NameLower}_shared_linux_files.cmake | 0 .../Platform/Linux/PAL_linux.cmake | 0 .../Platform/Mac/${NameLower}_mac_files.cmake | 0 .../Mac/${NameLower}_shared_mac_files.cmake | 0 .../{Code => Gem}/Platform/Mac/PAL_mac.cmake | 0 .../${NameLower}_shared_windows_files.cmake | 0 .../Windows/${NameLower}_windows_files.cmake | 0 .../Platform/Windows/PAL_windows.cmake | 0 .../Platform/iOS/${NameLower}_ios_files.cmake | 0 .../iOS/${NameLower}_shared_ios_files.cmake | 0 .../{Code => Gem}/Platform/iOS/PAL_ios.cmake | 0 .../{Code => Gem}/Source/${Name}Module.cpp | 0 .../Source/${Name}SystemComponent.cpp | 2 +- .../Source/${Name}SystemComponent.h | 0 .../Template/{Code => Gem}/enabled_gems.cmake | 0 .../DefaultProject/Template/Gem/gem.json | 21 + .../DefaultProject/Template/project.json | 7 +- Templates/DefaultProject/template.json | 646 +++++--------- Templates/GemRepo/Template/gem.json | 22 +- Templates/GemRepo/template.json | 18 +- .../MinimalProject/Template/CMakeLists.txt | 1 - .../{Code => Gem}/${NameLower}_files.cmake | 0 .../${NameLower}_shared_files.cmake | 0 .../Template/Gem}/CMakeLists.txt | 11 +- .../Include/${Name}/${Name}Bus.h | 0 .../Android/${NameLower}_android_files.cmake | 0 .../${NameLower}_shared_android_files.cmake | 0 .../Platform/Android/PAL_android.cmake | 0 .../Linux/${NameLower}_linux_files.cmake | 0 .../${NameLower}_shared_linux_files.cmake | 0 .../Platform/Linux/PAL_linux.cmake | 0 .../Platform/Mac/${NameLower}_mac_files.cmake | 0 .../Mac/${NameLower}_shared_mac_files.cmake | 0 .../{Code => Gem}/Platform/Mac/PAL_mac.cmake | 0 .../${NameLower}_shared_windows_files.cmake | 0 .../Windows/${NameLower}_windows_files.cmake | 0 .../Platform/Windows/PAL_windows.cmake | 0 .../Platform/iOS/${NameLower}_ios_files.cmake | 0 .../iOS/${NameLower}_shared_ios_files.cmake | 0 .../{Code => Gem}/Platform/iOS/PAL_ios.cmake | 0 .../{Code => Gem}/Source/${Name}Module.cpp | 0 .../Source/${Name}SystemComponent.cpp | 0 .../Source/${Name}SystemComponent.h | 0 .../Template/{Code => Gem}/enabled_gems.cmake | 0 .../MinimalProject/Template/Gem/gem.json | 21 + .../Template/cmake/CompilerSettings.cmake | 4 +- .../Linux/CompilerSettings_linux.cmake | 4 +- .../MinimalProject/Template/project.json | 6 +- Templates/MinimalProject/template.json | 617 +++++-------- Templates/PythonToolGem/Template/gem.json | 6 +- Templates/PythonToolGem/template.json | 162 ++-- cmake/3rdParty.cmake | 6 +- cmake/3rdParty/BuiltInPackages.cmake | 4 +- cmake/3rdPartyPackages.cmake | 3 +- cmake/Configurations.cmake | 2 +- cmake/FileUtil.cmake | 21 +- cmake/Install.cmake | 4 +- cmake/LYTestWrappers.cmake | 2 +- cmake/LYWrappers.cmake | 2 +- cmake/PAL.cmake | 335 +++++-- cmake/PALTools.cmake | 4 +- cmake/Packaging.cmake | 2 +- cmake/Projects.cmake | 22 +- cmake/RuntimeDependencies.cmake | 2 +- engine.json | 2 +- scripts/o3de/CMakeLists.txt | 2 +- scripts/o3de/o3de/disable_gem.py | 6 - scripts/o3de/o3de/download.py | 5 - scripts/o3de/o3de/enable_gem.py | 6 - scripts/o3de/o3de/engine_template.py | 835 ++++++++++-------- scripts/o3de/o3de/get_registration.py | 6 - scripts/o3de/o3de/manifest.py | 481 +++++----- scripts/o3de/o3de/print_registration.py | 135 +-- scripts/o3de/o3de/register.py | 7 +- scripts/o3de/tests/unit_test_enable_gem.py | 11 +- .../o3de/tests/unit_test_engine_template.py | 56 +- .../o3de/tests/unit_test_gem_properties.py | 9 +- scripts/o3de/tests/unit_test_manifest.py | 64 +- .../tests/unit_test_print_registration.py | 19 +- 324 files changed, 2471 insertions(+), 2548 deletions(-) delete mode 100644 Gems/Atom/Asset/CMakeLists.txt delete mode 100644 Gems/Atom/Component/CMakeLists.txt delete mode 100644 Gems/Atom/Feature/CMakeLists.txt delete mode 100644 Gems/AtomLyIntegration/TechnicalArt/CMakeLists.txt rename Templates/DefaultProject/Template/{Code => Gem}/${NameLower}_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/${NameLower}_shared_files.cmake (100%) rename Templates/{MinimalProject/Template/Code => DefaultProject/Template/Gem}/CMakeLists.txt (87%) rename Templates/DefaultProject/Template/{Code => Gem}/Include/${Name}/${Name}Bus.h (99%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Android/${NameLower}_android_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Android/${NameLower}_shared_android_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Android/PAL_android.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Linux/${NameLower}_linux_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Linux/${NameLower}_shared_linux_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Linux/PAL_linux.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Mac/${NameLower}_mac_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Mac/${NameLower}_shared_mac_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Mac/PAL_mac.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Windows/${NameLower}_shared_windows_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Windows/${NameLower}_windows_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/Windows/PAL_windows.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/iOS/${NameLower}_ios_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/iOS/${NameLower}_shared_ios_files.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Platform/iOS/PAL_ios.cmake (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Source/${Name}Module.cpp (100%) rename Templates/DefaultProject/Template/{Code => Gem}/Source/${Name}SystemComponent.cpp (99%) rename Templates/DefaultProject/Template/{Code => Gem}/Source/${Name}SystemComponent.h (100%) rename Templates/DefaultProject/Template/{Code => Gem}/enabled_gems.cmake (100%) create mode 100644 Templates/DefaultProject/Template/Gem/gem.json rename Templates/MinimalProject/Template/{Code => Gem}/${NameLower}_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/${NameLower}_shared_files.cmake (100%) rename Templates/{DefaultProject/Template/Code => MinimalProject/Template/Gem}/CMakeLists.txt (87%) rename Templates/MinimalProject/Template/{Code => Gem}/Include/${Name}/${Name}Bus.h (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Android/${NameLower}_android_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Android/${NameLower}_shared_android_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Android/PAL_android.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Linux/${NameLower}_linux_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Linux/${NameLower}_shared_linux_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Linux/PAL_linux.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Mac/${NameLower}_mac_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Mac/${NameLower}_shared_mac_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Mac/PAL_mac.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Windows/${NameLower}_shared_windows_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Windows/${NameLower}_windows_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/Windows/PAL_windows.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/iOS/${NameLower}_ios_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/iOS/${NameLower}_shared_ios_files.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Platform/iOS/PAL_ios.cmake (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Source/${Name}Module.cpp (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Source/${Name}SystemComponent.cpp (100%) rename Templates/MinimalProject/Template/{Code => Gem}/Source/${Name}SystemComponent.h (100%) rename Templates/MinimalProject/Template/{Code => Gem}/enabled_gems.cmake (100%) create mode 100644 Templates/MinimalProject/Template/Gem/gem.json diff --git a/AutomatedTesting/CMakeLists.txt b/AutomatedTesting/CMakeLists.txt index 1c5382ba4b..9621c0accb 100644 --- a/AutomatedTesting/CMakeLists.txt +++ b/AutomatedTesting/CMakeLists.txt @@ -27,5 +27,4 @@ else() set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name}) - add_subdirectory(Gem) endif() \ No newline at end of file diff --git a/AutomatedTesting/Gem/CMakeLists.txt b/AutomatedTesting/Gem/CMakeLists.txt index 7a411544ec..e3d8a4087a 100644 --- a/AutomatedTesting/Gem/CMakeLists.txt +++ b/AutomatedTesting/Gem/CMakeLists.txt @@ -6,6 +6,9 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) -add_subdirectory(PythonTests) -add_subdirectory(PythonCoverage) +add_subdirectory(PythonTests) \ No newline at end of file diff --git a/AutomatedTesting/Gem/Code/CMakeLists.txt b/AutomatedTesting/Gem/Code/CMakeLists.txt index 8808507765..1a88d6e69a 100644 --- a/AutomatedTesting/Gem/Code/CMakeLists.txt +++ b/AutomatedTesting/Gem/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME AutomatedTesting ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} diff --git a/AutomatedTesting/Gem/PythonCoverage/CMakeLists.txt b/AutomatedTesting/Gem/PythonCoverage/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/AutomatedTesting/Gem/PythonCoverage/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonCoverage/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/AutomatedTesting/Gem/PythonCoverage/Code/CMakeLists.txt b/AutomatedTesting/Gem/PythonCoverage/Code/CMakeLists.txt index a865ccc49f..ea6db88c1c 100644 --- a/AutomatedTesting/Gem/PythonCoverage/Code/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonCoverage/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${o3de_gem_restricted_path} ${o3de_gem_path} ${o3de_gem_name}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) if(PAL_TRAIT_PYTHONCOVERAGE_SUPPORTED) diff --git a/AutomatedTesting/Gem/PythonCoverage/gem.json b/AutomatedTesting/Gem/PythonCoverage/gem.json index b99ce0daad..681696d78e 100644 --- a/AutomatedTesting/Gem/PythonCoverage/gem.json +++ b/AutomatedTesting/Gem/PythonCoverage/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "A tool for generating gem coverage for Python tests.", "canonical_tags": [ @@ -13,5 +14,8 @@ "PythonCoverage" ], "icon_path": "preview.png", - "requirements": "" + "requirements": "", + "documentation_url": "", + "dependencies": [ + ] } diff --git a/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt index aea2562e0b..64effb5b4c 100644 --- a/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/Blast/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # for PAL_TRAIT_BLAST Traits diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index 800f347359..26c03e78c2 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -10,7 +10,7 @@ # Automated Tests ################################################################################ -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/PAL_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt index 733e8edf29..d4554ee84b 100644 --- a/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/WhiteBox/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # for PAL_TRAIT_WHITEBOX Traits diff --git a/AutomatedTesting/Gem/Sponza/gem.json b/AutomatedTesting/Gem/Sponza/gem.json index 68749cd5f4..f36b22a805 100644 --- a/AutomatedTesting/Gem/Sponza/gem.json +++ b/AutomatedTesting/Gem/Sponza/gem.json @@ -4,14 +4,19 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "A standard test scene for Global Illumination (forked from crytek sponza scene)", "canonical_tags": [ - "Gem" + "Gem", + "Asset" ], "user_tags": [ - "Assets" + "Sponza" ], + "icon_path": "preview.png", "requirements": "", - "dependencies": [] + "documentation_url": "", + "dependencies": [ + ] } diff --git a/AutomatedTesting/Gem/gem.json b/AutomatedTesting/Gem/gem.json index df197df09d..90a0c8cb01 100644 --- a/AutomatedTesting/Gem/gem.json +++ b/AutomatedTesting/Gem/gem.json @@ -3,13 +3,21 @@ "display_name": "AutomatedTesting", "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", - "origin": "Amazon Web Services, Inc.", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "Project Gem for customizing the AutomatedTesting project functionality.", "canonical_tags": [ "Gem" ], - "user_tags": [], + "user_tags": [ + "AutomatedTesting" + ], "icon_path": "preview.png", - "requirements": "" + "requirements": "", + "documentation_url": "", + "dependencies": [], + "external_subdirectories": [ + "PythonCoverage" + ] } diff --git a/AutomatedTesting/project.json b/AutomatedTesting/project.json index fc14645d2b..5a4b303570 100644 --- a/AutomatedTesting/project.json +++ b/AutomatedTesting/project.json @@ -5,12 +5,15 @@ "modules": [], "project_id": "{D816AFAE-4BB7-4FEF-88F4-E2B786DCF29D}", "android_settings": { - "package_name": "com.lumberyard.yourgame", + "package_name": "org.o3de.automatedtesting", "version_number": 1, "version_name": "1.0.0", "orientation": "landscape" }, "engine": "o3de", "display_name": "AutomatedTesting", - "icon_path": "preview.png" -} + "icon_path": "preview.png", + "external_subdirectories": [ + "Gem" + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f61a9561e8..c81581fe0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,21 +49,56 @@ include(cmake/O3DEJson.cmake) # Subdirectory processing ################################################################################ -function(add_engine_json_external_subdirectories) - read_json_external_subdirs(external_subdis ${LY_ROOT_FOLDER}/engine.json) - foreach(external_subdir ${external_subdis}) - file(REAL_PATH ${external_subdir} real_external_subdir BASE_DIRECTORY ${LY_ROOT_FOLDER}) - list(APPEND engine_external_subdirs ${real_external_subdir}) - endforeach() +# this function is building up the LY_EXTERNAL_SUBDIRS global property +function(add_engine_gem_json_external_subdirectories gem_path) + set(gem_json_path ${gem_path}/gem.json) + if(EXISTS ${gem_json_path}) + read_json_external_subdirs(gem_external_subdirs ${gem_path}/gem.json) + foreach(gem_external_subdir ${gem_external_subdirs}) + file(REAL_PATH ${gem_external_subdir} real_external_subdir BASE_DIRECTORY ${gem_path}) + set_property(GLOBAL APPEND PROPERTY LY_EXTERNAL_SUBDIRS ${real_external_subdir}) + add_engine_gem_json_external_subdirectories(${real_external_subdir}) + endforeach() + endif() +endfunction() - set_property(GLOBAL APPEND PROPERTY LY_EXTERNAL_SUBDIRS ${engine_external_subdirs}) +function(add_engine_json_external_subdirectories) + read_json_external_subdirs(engine_external_subdirs ${LY_ROOT_FOLDER}/engine.json) + foreach(engine_external_subdir ${engine_external_subdirs}) + file(REAL_PATH ${engine_external_subdir} real_external_subdir BASE_DIRECTORY ${LY_ROOT_FOLDER}) + set_property(GLOBAL APPEND PROPERTY LY_EXTERNAL_SUBDIRS ${real_external_subdir}) + add_engine_gem_json_external_subdirectories(${real_external_subdir}) + endforeach() +endfunction() + +function(add_subdirectory_on_externalsubdirs) + get_property(external_subdirs GLOBAL PROPERTY LY_EXTERNAL_SUBDIRS) + list(APPEND LY_EXTERNAL_SUBDIRS ${external_subdirs}) + # Loop over the additional external subdirectories and invoke add_subdirectory on them + foreach(external_directory ${LY_EXTERNAL_SUBDIRS}) + # Hash the external_directory name and append it to the Binary Directory section of add_subdirectory + # This is to deal with potential situations where multiple external directories has the same last directory name + # For example if D:/Company1/RayTracingGem and F:/Company2/Path/RayTracingGem were both added as a subdirectory + file(REAL_PATH ${external_directory} full_directory_path) + string(SHA256 full_directory_hash ${full_directory_path}) + # Truncate the full_directory_hash down to 8 characters to avoid hitting the Windows 260 character path limit + # when the external subdirectory contains relative paths of significant length + string(SUBSTRING ${full_directory_hash} 0 8 full_directory_hash) + # Use the last directory as the suffix path to use for the Binary Directory + get_filename_component(directory_name ${external_directory} NAME) + add_subdirectory(${external_directory} ${CMAKE_BINARY_DIR}/External/${directory_name}-${full_directory_hash}) + endforeach() endfunction() # Add the projects first so the Launcher can find them include(cmake/Projects.cmake) if(NOT INSTALLED_ENGINE) - + # Add external subdirectories listed in the engine.json. LY_EXTERNAL_SUBDIRS is a cache variable so the user can add extra + # external subdirectories. This should go before adding the rest of the targets so the targets are availbe to the launcher. + add_engine_json_external_subdirectories() + add_subdirectory_on_externalsubdirs() + # Add the rest of the targets add_subdirectory(Assets) add_subdirectory(Code) @@ -73,31 +108,11 @@ if(NOT INSTALLED_ENGINE) add_subdirectory(Templates) add_subdirectory(Tools) - # Add external subdirectories listed in the engine.json. LY_EXTERNAL_SUBDIRS is a cache variable so the user can add extra - # external subdirectories - add_engine_json_external_subdirectories() else() ly_find_o3de_packages() + add_subdirectory_on_externalsubdirs() endif() -get_property(external_subdirs GLOBAL PROPERTY LY_EXTERNAL_SUBDIRS) -list(APPEND LY_EXTERNAL_SUBDIRS ${external_subdirs}) - -# Loop over the additional external subdirectories and invoke add_subdirectory on them -foreach(external_directory ${LY_EXTERNAL_SUBDIRS}) - # Hash the extenal_directory name and append it to the Binary Directory section of add_subdirectory - # This is to deal with potential situations where multiple external directories has the same last directory name - # For example if D:/Company1/RayTracingGem and F:/Company2/Path/RayTracingGem were both added as a subdirectory - file(REAL_PATH ${external_directory} full_directory_path) - string(SHA256 full_directory_hash ${full_directory_path}) - # Truncate the full_directory_hash down to 8 characters to avoid hitting the Windows 260 character path limit - # when the external subdirectory contains relative paths of significant length - string(SUBSTRING ${full_directory_hash} 0 8 full_directory_hash) - # Use the last directory as the suffix path to use for the Binary Directory - get_filename_component(directory_name ${external_directory} NAME) - add_subdirectory(${external_directory} ${CMAKE_BINARY_DIR}/External/${directory_name}-${full_directory_hash}) -endforeach() - ################################################################################ # Post-processing ################################################################################ diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt index 3358b49dce..9d74f8e3a2 100644 --- a/Code/Editor/CMakeLists.txt +++ b/Code/Editor/CMakeLists.txt @@ -63,7 +63,7 @@ ly_add_target( set(pal_cmake_files "") foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_list_relative_pal_filename(pal_cmake_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${enabled_platform}) + o3de_pal_dir(pal_cmake_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${enabled_platform} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) list(APPEND pal_cmake_files ${pal_cmake_dir}/editor_lib_${enabled_platform_lowercase}_files.cmake) endforeach() diff --git a/Code/Framework/AzCore/CMakeLists.txt b/Code/Framework/AzCore/CMakeLists.txt index 838142f0df..01f4086a18 100644 --- a/Code/Framework/AzCore/CMakeLists.txt +++ b/Code/Framework/AzCore/CMakeLists.txt @@ -9,8 +9,8 @@ # TODO: would like to be able to build from this path, however, the whole setup is done at the workspace's root # we also dont want to drop cmake output files everywhere. -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) if(PAL_TRAIT_PROF_PIX_SUPPORTED) set(LY_PIX_ENABLED OFF CACHE BOOL "Enables PIX profiler integration.") @@ -110,15 +110,15 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) AZ::AzTest ) - ly_get_list_relative_pal_filename(pal_test_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME}) + o3de_pal_dir(pal_tests_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME AzCore.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE AZ FILES_CMAKE Tests/azcoretests_files.cmake - ${pal_test_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + ${pal_tests_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake PLATFORM_INCLUDE_FILES - ${pal_test_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + ${pal_tests_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake INCLUDE_DIRECTORIES PRIVATE Tests diff --git a/Code/Framework/AzFramework/CMakeLists.txt b/Code/Framework/AzFramework/CMakeLists.txt index 9f30d23a19..bd7af2724e 100644 --- a/Code/Framework/AzFramework/CMakeLists.txt +++ b/Code/Framework/AzFramework/CMakeLists.txt @@ -8,8 +8,8 @@ include(AzFramework/feature_options.cmake) -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) ly_add_target( NAME AzFramework STATIC @@ -44,7 +44,7 @@ ly_add_source_properties( if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) - ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME}) + o3de_pal_dir(test_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME AzFrameworkTestShared STATIC @@ -86,11 +86,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) NAMESPACE AZ FILES_CMAKE Tests/frameworktests_files.cmake - ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + ${test_pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake INCLUDE_DIRECTORIES PRIVATE Tests - ${pal_dir} + ${test_pal_dir} BUILD_DEPENDENCIES PRIVATE AZ::AzFramework @@ -104,7 +104,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) NAME AZ::AzFramework.Tests ) - include(${pal_dir}/platform_specific_test_targets.cmake) + include(${test_pal_dir}/platform_specific_test_targets.cmake) endif() diff --git a/Code/Framework/AzNetworking/CMakeLists.txt b/Code/Framework/AzNetworking/CMakeLists.txt index a0a3871201..ba2eecd023 100644 --- a/Code/Framework/AzNetworking/CMakeLists.txt +++ b/Code/Framework/AzNetworking/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) ly_add_target( NAME AzNetworking STATIC diff --git a/Code/Framework/AzQtComponents/CMakeLists.txt b/Code/Framework/AzQtComponents/CMakeLists.txt index a24b68bcd7..76850e196b 100644 --- a/Code/Framework/AzQtComponents/CMakeLists.txt +++ b/Code/Framework/AzQtComponents/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME AzQtComponents SHARED diff --git a/Code/Framework/AzTest/CMakeLists.txt b/Code/Framework/AzTest/CMakeLists.txt index 95e444a1e9..2edc80f893 100644 --- a/Code/Framework/AzTest/CMakeLists.txt +++ b/Code/Framework/AzTest/CMakeLists.txt @@ -7,18 +7,18 @@ # if(NOT LY_MONOLITHIC_GAME) - ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AzTest/Platform/${PAL_PLATFORM_NAME}) + o3de_pal_dir(pal_aztest_dir ${CMAKE_CURRENT_LIST_DIR}/AzTest/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME AzTest STATIC NAMESPACE AZ FILES_CMAKE AzTest/aztest_files.cmake - ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + ${pal_aztest_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake INCLUDE_DIRECTORIES PUBLIC . - ${pal_dir} + ${pal_aztest_dir} BUILD_DEPENDENCIES PUBLIC 3rdParty::googletest::GMock @@ -26,6 +26,6 @@ if(NOT LY_MONOLITHIC_GAME) 3rdParty::GoogleBenchmark AZ::AzCore PLATFORM_INCLUDE_FILES - ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + ${pal_aztest_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake ) endif() diff --git a/Code/Framework/GridMate/CMakeLists.txt b/Code/Framework/GridMate/CMakeLists.txt index 0da878081d..07c2f8b4a8 100644 --- a/Code/Framework/GridMate/CMakeLists.txt +++ b/Code/Framework/GridMate/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) ly_add_target( NAME GridMate STATIC @@ -41,7 +41,7 @@ ly_add_source_properties( ################################################################################ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) - ly_get_list_relative_pal_filename(pal_test_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME}) + o3de_pal_dir(pal_test_dir ${CMAKE_CURRENT_LIST_DIR}/Tests/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME GridMate.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE AZ diff --git a/Code/LauncherUnified/CMakeLists.txt b/Code/LauncherUnified/CMakeLists.txt index 845c2cd6c7..8097570462 100644 --- a/Code/LauncherUnified/CMakeLists.txt +++ b/Code/LauncherUnified/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/LauncherUnified_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Code/LauncherUnified/launcher_generator.cmake b/Code/LauncherUnified/launcher_generator.cmake index 550a67bc49..70bcf776af 100644 --- a/Code/LauncherUnified/launcher_generator.cmake +++ b/Code/LauncherUnified/launcher_generator.cmake @@ -201,7 +201,7 @@ function(ly_delayed_generate_static_modules_inl) foreach(game_gem_dependency ${all_game_gem_dependencies}) # Sometimes, a gem's Client variant may be an interface library - # which dependes on multiple gem targets. The interface libraries + # which depends on multiple gem targets. The interface libraries # should be skipped; the real dependencies of the interface will be processed if(TARGET ${game_gem_dependency}) get_target_property(target_type ${game_gem_dependency} TYPE) diff --git a/Code/Legacy/CryCommon/CMakeLists.txt b/Code/Legacy/CryCommon/CMakeLists.txt index 1556c6a099..629f26d217 100644 --- a/Code/Legacy/CryCommon/CMakeLists.txt +++ b/Code/Legacy/CryCommon/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME CryCommon STATIC diff --git a/Code/Legacy/CrySystem/CMakeLists.txt b/Code/Legacy/CrySystem/CMakeLists.txt index ebfc866f4a..3153205b69 100644 --- a/Code/Legacy/CrySystem/CMakeLists.txt +++ b/Code/Legacy/CrySystem/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) add_subdirectory(XML) diff --git a/Code/Tools/AWSNativeSDKInit/CMakeLists.txt b/Code/Tools/AWSNativeSDKInit/CMakeLists.txt index 57ee31d30d..04f61eb924 100644 --- a/Code/Tools/AWSNativeSDKInit/CMakeLists.txt +++ b/Code/Tools/AWSNativeSDKInit/CMakeLists.txt @@ -6,14 +6,14 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/source/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME AWSNativeSDKInit STATIC NAMESPACE AZ FILES_CMAKE aws_native_sdk_init_files.cmake - ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake INCLUDE_DIRECTORIES PUBLIC include diff --git a/Code/Tools/AssetProcessor/AssetBuilderSDK/CMakeLists.txt b/Code/Tools/AssetProcessor/AssetBuilderSDK/CMakeLists.txt index bfbcc35663..f32d55844e 100644 --- a/Code/Tools/AssetProcessor/AssetBuilderSDK/CMakeLists.txt +++ b/Code/Tools/AssetProcessor/AssetBuilderSDK/CMakeLists.txt @@ -11,7 +11,7 @@ ly_get_pal_tool_dirs(pal_tool_dirs ${CMAKE_CURRENT_LIST_DIR}/AssetBuilderSDK/Pla set(pal_files "") foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AssetBuilderSDK/Platform/${enabled_platform}) + o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/AssetBuilderSDK/Platform/${enabled_platform} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) list(APPEND pal_files ${pal_dir}/assetbuildersdk_${enabled_platform_lowercase}_files.cmake) endforeach() diff --git a/Code/Tools/AzTestRunner/CMakeLists.txt b/Code/Tools/AzTestRunner/CMakeLists.txt index 5f3bb829a8..2bd74fa1a1 100644 --- a/Code/Tools/AzTestRunner/CMakeLists.txt +++ b/Code/Tools/AzTestRunner/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/platform_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Code/Tools/CrashHandler/CMakeLists.txt b/Code/Tools/CrashHandler/CMakeLists.txt index 259a7d2891..db50741326 100644 --- a/Code/Tools/CrashHandler/CMakeLists.txt +++ b/Code/Tools/CrashHandler/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Code/Tools/LuaIDE/CMakeLists.txt b/Code/Tools/LuaIDE/CMakeLists.txt index 98c8d7f04b..58e0fe505a 100644 --- a/Code/Tools/LuaIDE/CMakeLists.txt +++ b/Code/Tools/LuaIDE/CMakeLists.txt @@ -10,6 +10,8 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) + ly_add_target( NAME LuaIDE APPLICATION NAMESPACE AZ @@ -18,7 +20,7 @@ ly_add_target( AUTORCC FILES_CMAKE lua_ide_files.cmake - Platform/${PAL_PLATFORM_NAME}/lua_ide_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + ${pal_dir}/lua_ide_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake INCLUDE_DIRECTORIES PRIVATE . diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 35bdfe0031..7c436a3a70 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -1221,7 +1221,7 @@ namespace O3DE::ProjectManager auto result = ExecuteWithLockErrorHandling( [&] { - for (auto repoUri : m_manifest.attr("get_repos")()) + for (auto repoUri : m_manifest.attr("get_manifest_repos")()) { gemRepos.push_back(GetGemRepoInfo(repoUri)); } diff --git a/Code/Tools/RemoteConsole/CMakeLists.txt b/Code/Tools/RemoteConsole/CMakeLists.txt index d2685b2aea..b9a08650b6 100644 --- a/Code/Tools/RemoteConsole/CMakeLists.txt +++ b/Code/Tools/RemoteConsole/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME RemoteConsoleCore STATIC diff --git a/Code/Tools/SceneAPI/SceneData/CMakeLists.txt b/Code/Tools/SceneAPI/SceneData/CMakeLists.txt index 5507ada2b9..0d4ef4a5df 100644 --- a/Code/Tools/SceneAPI/SceneData/CMakeLists.txt +++ b/Code/Tools/SceneAPI/SceneData/CMakeLists.txt @@ -10,7 +10,7 @@ if (NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_add_target( NAME SceneData SHARED diff --git a/Code/Tools/TestImpactFramework/CMakeLists.txt b/Code/Tools/TestImpactFramework/CMakeLists.txt index 1cdf02d101..15d93b1a70 100644 --- a/Code/Tools/TestImpactFramework/CMakeLists.txt +++ b/Code/Tools/TestImpactFramework/CMakeLists.txt @@ -6,9 +6,9 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) -include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) if(PAL_TRAIT_TEST_IMPACT_FRAMEWORK_SUPPORTED) add_subdirectory(Runtime) diff --git a/Code/Tools/TestImpactFramework/Runtime/Code/CMakeLists.txt b/Code/Tools/TestImpactFramework/Runtime/Code/CMakeLists.txt index 0b8432642a..f3262a26af 100644 --- a/Code/Tools/TestImpactFramework/Runtime/Code/CMakeLists.txt +++ b/Code/Tools/TestImpactFramework/Runtime/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) ly_add_target( NAME TestImpact.Runtime.Static STATIC diff --git a/Gems/AWSClientAuth/CMakeLists.txt b/Gems/AWSClientAuth/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/AWSClientAuth/CMakeLists.txt +++ b/Gems/AWSClientAuth/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/AWSClientAuth/Code/CMakeLists.txt b/Gems/AWSClientAuth/Code/CMakeLists.txt index 1f0c119f5a..ac9d221f07 100644 --- a/Gems/AWSClientAuth/Code/CMakeLists.txt +++ b/Gems/AWSClientAuth/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME AWSClientAuth.Static STATIC diff --git a/Gems/AWSClientAuth/gem.json b/Gems/AWSClientAuth/gem.json index 9c7188f103..d6729cee99 100644 --- a/Gems/AWSClientAuth/gem.json +++ b/Gems/AWSClientAuth/gem.json @@ -3,7 +3,8 @@ "display_name": "AWS Client Authorization", "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", - "origin": "Amazon Web Services, Inc.", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "AWS Client Auth provides client authentication and AWS authorization solution.", "canonical_tags": [ @@ -15,6 +16,7 @@ "SDK" ], "icon_path": "preview.png", + "requirements": "", "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/", "dependencies": [ "AWSCore", diff --git a/Gems/AWSCore/CMakeLists.txt b/Gems/AWSCore/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/AWSCore/CMakeLists.txt +++ b/Gems/AWSCore/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/AWSCore/Code/CMakeLists.txt b/Gems/AWSCore/Code/CMakeLists.txt index 877696e26c..3911aefce6 100644 --- a/Gems/AWSCore/Code/CMakeLists.txt +++ b/Gems/AWSCore/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME AWSCore.Static STATIC @@ -61,7 +61,7 @@ ly_create_alias( if (PAL_TRAIT_BUILD_HOST_TOOLS) - include(${CMAKE_CURRENT_SOURCE_DIR}/Platform/${PAL_PLATFORM_NAME}/PAL_traits_editor_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) + include(${pal_dir}/PAL_traits_editor_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) ly_add_target( NAME AWSCore.Editor.Static STATIC diff --git a/Gems/AWSCore/gem.json b/Gems/AWSCore/gem.json index 3bced07e8d..3bc8e6f77c 100644 --- a/Gems/AWSCore/gem.json +++ b/Gems/AWSCore/gem.json @@ -3,7 +3,8 @@ "display_name": "AWS Core", "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", - "origin": "Amazon Web Services, Inc.", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The AWS Core Gem provides basic shared AWS functionality such as AWS SDK initialization and client configuration, and is automatically added when selecting any AWS feature Gem.", "canonical_tags": [ @@ -15,5 +16,8 @@ "SDK" ], "icon_path": "preview.png", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-core/" + "requirements": "", + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-core/", + "dependencies": [ + ] } diff --git a/Gems/AWSGameLift/gem.json b/Gems/AWSGameLift/gem.json index 1ac65c4526..e1b80cb9fe 100644 --- a/Gems/AWSGameLift/gem.json +++ b/Gems/AWSGameLift/gem.json @@ -3,7 +3,8 @@ "display_name": "AWS GameLift", "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", - "origin": "Amazon Web Services, Inc.", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The AWS GameLift Gem provides a framework to extend O3DE networking layer to work with GameLift resources via GameLift server and client SDK.", "canonical_tags": [ @@ -12,7 +13,7 @@ "user_tags": [ "AWS", "Framework", - "Network", + "Network", "SDK" ], "icon_path": "preview.png", diff --git a/Gems/AWSMetrics/gem.json b/Gems/AWSMetrics/gem.json index 054c3624c4..bd462edec3 100644 --- a/Gems/AWSMetrics/gem.json +++ b/Gems/AWSMetrics/gem.json @@ -3,7 +3,8 @@ "display_name": "AWS Metrics", "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", - "origin": "Amazon Web Services, Inc.", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The AWS Metrics Gem provides a solution for AWS metrics submission and analytics.", "canonical_tags": [ @@ -15,6 +16,7 @@ "SDK" ], "icon_path": "preview.png", + "requirements": "", "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/", "dependencies": [ "AWSCore" diff --git a/Gems/Achievements/CMakeLists.txt b/Gems/Achievements/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Achievements/CMakeLists.txt +++ b/Gems/Achievements/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Achievements/Code/CMakeLists.txt b/Gems/Achievements/Code/CMakeLists.txt index 2d00ac2fb2..5ac43e9736 100644 --- a/Gems/Achievements/Code/CMakeLists.txt +++ b/Gems/Achievements/Code/CMakeLists.txt @@ -6,16 +6,16 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME Achievements.Static STATIC NAMESPACE Gem PLATFORM_INCLUDE_FILES - ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake FILES_CMAKE achievements_files.cmake - ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake INCLUDE_DIRECTORIES PUBLIC Include diff --git a/Gems/Achievements/gem.json b/Gems/Achievements/gem.json index 8180584500..5fc83aefe2 100644 --- a/Gems/Achievements/gem.json +++ b/Gems/Achievements/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Achievements Gem provides a target platform agnostic interface for retrieving achievement details and unlocking achievements.", "canonical_tags": [ diff --git a/Gems/AssetValidation/gem.json b/Gems/AssetValidation/gem.json index 55cdffb9f3..de1d36ffb4 100644 --- a/Gems/AssetValidation/gem.json +++ b/Gems/AssetValidation/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Asset Validation Gem provides seed-related commands to ensure assets have valid seeds for asset bundling.", "canonical_tags": [ diff --git a/Gems/Atom/Asset/CMakeLists.txt b/Gems/Atom/Asset/CMakeLists.txt deleted file mode 100644 index 3ed20148a2..0000000000 --- a/Gems/Atom/Asset/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -add_subdirectory(ImageProcessingAtom) -add_subdirectory(Shader) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt b/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt index 54543a000a..92079d35be 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt +++ b/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt @@ -7,4 +7,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt index 982ec43715..74876994f6 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt @@ -26,15 +26,15 @@ set(pal_tools_include_dirs) foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_list_relative_pal_filename(pal_tools_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${enabled_platform}) + o3de_pal_dir(pal_tools_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${enabled_platform} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) list(APPEND pal_tools_include_dirs ${pal_tools_source_dir}) list(APPEND platform_tools_files ${pal_tools_source_dir}/pal_tools_${enabled_platform_lowercase}.cmake) list(APPEND pal_tools_include_files ${pal_tools_source_dir}/pal_tools_${enabled_platform_lowercase}_files.cmake) endforeach() -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) ly_add_target( NAME ImageProcessingAtom.Editor.Static STATIC diff --git a/Gems/Atom/Asset/ImageProcessingAtom/gem.json b/Gems/Atom/Asset/ImageProcessingAtom/gem.json index 4fd437d298..c2af4b7e7e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/gem.json +++ b/Gems/Atom/Asset/ImageProcessingAtom/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RPI", "Atom_RHI", diff --git a/Gems/Atom/Asset/Shader/CMakeLists.txt b/Gems/Atom/Asset/Shader/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/Asset/Shader/CMakeLists.txt +++ b/Gems/Atom/Asset/Shader/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt index ed5aa45bbf..9ebd5e6d2d 100644 --- a/Gems/Atom/Asset/Shader/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/Shader/Code/CMakeLists.txt @@ -10,8 +10,8 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) #for PAL_TRAIT_BUILD_ATOM_ASSET_SHADER_SUPPORTED @@ -71,7 +71,7 @@ ly_add_target( set(builder_tools_include_files) foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_list_relative_pal_filename(builder_tools_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${enabled_platform}) + o3de_pal_dir(builder_tools_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${enabled_platform} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) list(APPEND builder_tools_include_files ${builder_tools_source_dir}/platform_builders_${enabled_platform_lowercase}.cmake) endforeach() diff --git a/Gems/Atom/Asset/Shader/gem.json b/Gems/Atom/Asset/Shader/gem.json index 9f59c65f78..8b4ba4fb0d 100644 --- a/Gems/Atom/Asset/Shader/gem.json +++ b/Gems/Atom/Asset/Shader/gem.json @@ -4,13 +4,17 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", - "summary": "", + "summary": "Atom Shader Builder", "canonical_tags": [ "Gem" ], - "user_tags": [], + "user_tags": [ + "AtomShader" + ], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI", "Atom_RPI" diff --git a/Gems/Atom/Bootstrap/CMakeLists.txt b/Gems/Atom/Bootstrap/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/Bootstrap/CMakeLists.txt +++ b/Gems/Atom/Bootstrap/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/Bootstrap/Code/CMakeLists.txt b/Gems/Atom/Bootstrap/Code/CMakeLists.txt index fd9df96124..0ba8d17865 100644 --- a/Gems/Atom/Bootstrap/Code/CMakeLists.txt +++ b/Gems/Atom/Bootstrap/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME Atom_Bootstrap.Headers HEADERONLY diff --git a/Gems/Atom/Bootstrap/gem.json b/Gems/Atom/Bootstrap/gem.json index df615366da..543efe0f34 100644 --- a/Gems/Atom/Bootstrap/gem.json +++ b/Gems/Atom/Bootstrap/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RPI" ] diff --git a/Gems/Atom/CMakeLists.txt b/Gems/Atom/CMakeLists.txt index a71afa64e0..b5dd311e5a 100644 --- a/Gems/Atom/CMakeLists.txt +++ b/Gems/Atom/CMakeLists.txt @@ -6,12 +6,10 @@ # # -add_subdirectory(Asset) -add_subdirectory(Bootstrap) -add_subdirectory(Component) -add_subdirectory(Feature) -add_subdirectory(RHI) -add_subdirectory(RPI) +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Tools) add_subdirectory(Utils) diff --git a/Gems/Atom/Component/CMakeLists.txt b/Gems/Atom/Component/CMakeLists.txt deleted file mode 100644 index 8b867b8c67..0000000000 --- a/Gems/Atom/Component/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -add_subdirectory(DebugCamera) diff --git a/Gems/Atom/Component/DebugCamera/CMakeLists.txt b/Gems/Atom/Component/DebugCamera/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/Component/DebugCamera/CMakeLists.txt +++ b/Gems/Atom/Component/DebugCamera/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/Component/DebugCamera/gem.json b/Gems/Atom/Component/DebugCamera/gem.json index 8eab74f41d..74d88a21b6 100644 --- a/Gems/Atom/Component/DebugCamera/gem.json +++ b/Gems/Atom/Component/DebugCamera/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RPI" ] diff --git a/Gems/Atom/Feature/CMakeLists.txt b/Gems/Atom/Feature/CMakeLists.txt deleted file mode 100644 index 32d654d5c4..0000000000 --- a/Gems/Atom/Feature/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -add_subdirectory(Common) diff --git a/Gems/Atom/Feature/Common/CMakeLists.txt b/Gems/Atom/Feature/Common/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/Feature/Common/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/Feature/Common/Code/CMakeLists.txt b/Gems/Atom/Feature/Common/Code/CMakeLists.txt index db9ac8560f..a832c46539 100644 --- a/Gems/Atom/Feature/Common/Code/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) ly_add_target( NAME Atom_Feature_Common.Static STATIC diff --git a/Gems/Atom/Feature/Common/gem.json b/Gems/Atom/Feature/Common/gem.json index 84ab07a9f9..f4c936dc4a 100644 --- a/Gems/Atom/Feature/Common/gem.json +++ b/Gems/Atom/Feature/Common/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RPI", "Atom", diff --git a/Gems/Atom/RHI/CMakeLists.txt b/Gems/Atom/RHI/CMakeLists.txt index 074f6acfd7..5812828c1a 100644 --- a/Gems/Atom/RHI/CMakeLists.txt +++ b/Gems/Atom/RHI/CMakeLists.txt @@ -6,10 +6,10 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) add_subdirectory(Code) -add_subdirectory(DX12) -add_subdirectory(Metal) -add_subdirectory(Vulkan) -add_subdirectory(Null) diff --git a/Gems/Atom/RHI/Code/CMakeLists.txt b/Gems/Atom/RHI/Code/CMakeLists.txt index 5238985feb..fe9db107a8 100644 --- a/Gems/Atom/RHI/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/AtomRHITests_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Gems/Atom/RHI/DX12/CMakeLists.txt b/Gems/Atom/RHI/DX12/CMakeLists.txt index 51912a5ff0..5812828c1a 100644 --- a/Gems/Atom/RHI/DX12/CMakeLists.txt +++ b/Gems/Atom/RHI/DX12/CMakeLists.txt @@ -6,6 +6,10 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) add_subdirectory(Code) diff --git a/Gems/Atom/RHI/DX12/Code/CMakeLists.txt b/Gems/Atom/RHI/DX12/Code/CMakeLists.txt index 975b838ffa..95118c60a7 100644 --- a/Gems/Atom/RHI/DX12/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/DX12/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # PAL_TRAIT_ATOM_RHI_DX12_SUPPORTED @@ -23,7 +23,7 @@ set(pal_builder_tools_files) set(pal_builder_tools_includes) foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_list_relative_pal_filename(pal_builder_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${enabled_platform}) + o3de_pal_dir(pal_builder_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${enabled_platform} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) list(APPEND pal_builder_tools_includes ${pal_builder_source_dir}) list(APPEND pal_builder_tools_files ${pal_builder_source_dir}/platform_builders_${enabled_platform_lowercase}_tools_files.cmake) endforeach() diff --git a/Gems/Atom/RHI/DX12/gem.json b/Gems/Atom/RHI/DX12/gem.json index 868acd43db..803ae4f4d0 100644 --- a/Gems/Atom/RHI/DX12/gem.json +++ b/Gems/Atom/RHI/DX12/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI" ] diff --git a/Gems/Atom/RHI/Metal/CMakeLists.txt b/Gems/Atom/RHI/Metal/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/RHI/Metal/CMakeLists.txt +++ b/Gems/Atom/RHI/Metal/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/RHI/Metal/Code/CMakeLists.txt b/Gems/Atom/RHI/Metal/Code/CMakeLists.txt index 11876e0a30..3df00a30e0 100644 --- a/Gems/Atom/RHI/Metal/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Metal/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_source_dir}/PAL2_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Gems/Atom/RHI/Metal/gem.json b/Gems/Atom/RHI/Metal/gem.json index 6e983ba505..0257048bd3 100644 --- a/Gems/Atom/RHI/Metal/gem.json +++ b/Gems/Atom/RHI/Metal/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI" ] diff --git a/Gems/Atom/RHI/Null/CMakeLists.txt b/Gems/Atom/RHI/Null/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/RHI/Null/CMakeLists.txt +++ b/Gems/Atom/RHI/Null/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/RHI/Null/Code/CMakeLists.txt b/Gems/Atom/RHI/Null/Code/CMakeLists.txt index 71df9f696f..081edd4c44 100644 --- a/Gems/Atom/RHI/Null/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Null/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( diff --git a/Gems/Atom/RHI/Null/gem.json b/Gems/Atom/RHI/Null/gem.json index e9f22c5fcb..1ea2eb4cb0 100644 --- a/Gems/Atom/RHI/Null/gem.json +++ b/Gems/Atom/RHI/Null/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI" ] diff --git a/Gems/Atom/RHI/Vulkan/CMakeLists.txt b/Gems/Atom/RHI/Vulkan/CMakeLists.txt index 51912a5ff0..5812828c1a 100644 --- a/Gems/Atom/RHI/Vulkan/CMakeLists.txt +++ b/Gems/Atom/RHI/Vulkan/CMakeLists.txt @@ -6,6 +6,10 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) add_subdirectory(Code) diff --git a/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt b/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt index fb13d1fddb..674e5aff9e 100644 --- a/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt +++ b/Gems/Atom/RHI/Vulkan/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_include_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # PAL_TRAIT_ATOM_RHI_VULKAN_SUPPORTED / PAL_TRAIT_ATOM_RHI_VULKAN_TARGETS_ALREADY_DEFINED diff --git a/Gems/Atom/RHI/Vulkan/gem.json b/Gems/Atom/RHI/Vulkan/gem.json index 1dfeb9eafa..508ad85c75 100644 --- a/Gems/Atom/RHI/Vulkan/gem.json +++ b/Gems/Atom/RHI/Vulkan/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI" ] diff --git a/Gems/Atom/RHI/gem.json b/Gems/Atom/RHI/gem.json index de46c312ad..858a64fc17 100644 --- a/Gems/Atom/RHI/gem.json +++ b/Gems/Atom/RHI/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,12 @@ ], "user_tags": [], "requirements": "", + "external_subdirectories": [ + "DX12", + "Metal", + "Null", + "Vulkan" + ], "dependencies": [ "Atom_RHI_DX12", "Atom_RHI_Metal", diff --git a/Gems/Atom/RPI/CMakeLists.txt b/Gems/Atom/RPI/CMakeLists.txt index 6d148328ec..2c2cee5804 100644 --- a/Gems/Atom/RPI/CMakeLists.txt +++ b/Gems/Atom/RPI/CMakeLists.txt @@ -6,6 +6,10 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) add_subdirectory(Tools) diff --git a/Gems/Atom/RPI/Code/CMakeLists.txt b/Gems/Atom/RPI/Code/CMakeLists.txt index f0459a23c2..dcdad13c10 100644 --- a/Gems/Atom/RPI/Code/CMakeLists.txt +++ b/Gems/Atom/RPI/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) #for PAL_TRAIT_BUILD_ATOM_RPI_ASSETS_SUPPORTED and PAL_TRAIT_BUILD_ATOM_RPI_MASKED_OCCLUSION_CULLING_SUPPORTED include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) @@ -176,8 +176,8 @@ endif() if(PAL_TRAIT_BUILD_HOST_TOOLS) - ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) - ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) + o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) + set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) if(NOT PAL_TRAIT_BUILD_ATOM_RPI_ASSETS_SUPPORTED) diff --git a/Gems/Atom/RPI/gem.json b/Gems/Atom/RPI/gem.json index 885f150508..0acef5179b 100644 --- a/Gems/Atom/RPI/gem.json +++ b/Gems/Atom/RPI/gem.json @@ -1,16 +1,18 @@ { "gem_name": "Atom_RPI", "display_name": "Atom API", - "summary": "", "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", + "summary": "", "canonical_tags": [ "Gem" ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI" ] diff --git a/Gems/Atom/Tools/AtomToolsFramework/CMakeLists.txt b/Gems/Atom/Tools/AtomToolsFramework/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/CMakeLists.txt +++ b/Gems/Atom/Tools/AtomToolsFramework/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt index e7e8208722..0fc896e88a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME AtomToolsFramework.Static STATIC diff --git a/Gems/Atom/Tools/AtomToolsFramework/gem.json b/Gems/Atom/Tools/AtomToolsFramework/gem.json index de2a9e06f2..6e5a7b311a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/gem.json +++ b/Gems/Atom/Tools/AtomToolsFramework/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RPI", "Atom_RHI", diff --git a/Gems/Atom/Tools/CMakeLists.txt b/Gems/Atom/Tools/CMakeLists.txt index 653babd0b3..82a803bdef 100644 --- a/Gems/Atom/Tools/CMakeLists.txt +++ b/Gems/Atom/Tools/CMakeLists.txt @@ -6,6 +6,4 @@ # # -add_subdirectory(AtomToolsFramework) -add_subdirectory(MaterialEditor) add_subdirectory(ShaderManagementConsole) diff --git a/Gems/Atom/Tools/MaterialEditor/CMakeLists.txt b/Gems/Atom/Tools/MaterialEditor/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Atom/Tools/MaterialEditor/CMakeLists.txt +++ b/Gems/Atom/Tools/MaterialEditor/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt index 99beb721d6..1d9295f9b3 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # PAL_TRAIT_ATOM_MATERIAL_EDITOR_APPLICATION_SUPPORTED diff --git a/Gems/Atom/Tools/MaterialEditor/gem.json b/Gems/Atom/Tools/MaterialEditor/gem.json index 807e3fa65f..463553c27d 100644 --- a/Gems/Atom/Tools/MaterialEditor/gem.json +++ b/Gems/Atom/Tools/MaterialEditor/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "Editor for creating, modifying, and previewing materials", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "AtomToolsFramework", "Atom_RPI", diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt index d384378b09..3f7788418a 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # PAL_TRAIT_ATOM_SHADER_MANAGEMENT_CONSOLE_APPLICATION_SUPPORTED diff --git a/Gems/Atom/Utils/Code/CMakeLists.txt b/Gems/Atom/Utils/Code/CMakeLists.txt index 90d7ce501b..a657262f2d 100644 --- a/Gems/Atom/Utils/Code/CMakeLists.txt +++ b/Gems/Atom/Utils/Code/CMakeLists.txt @@ -6,8 +6,6 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) - ly_add_target( NAME Atom_Utils.Static STATIC NAMESPACE Gem @@ -52,6 +50,9 @@ endif() # Tests ################################################################################ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + + o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) + ly_add_target( NAME Atom_Utils.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem diff --git a/Gems/Atom/gem.json b/Gems/Atom/gem.json index 0f409ad993..ee6a617ee7 100644 --- a/Gems/Atom/gem.json +++ b/Gems/Atom/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Atom Renderer Gem provides Atom Renderer and its associated tools (such as Material Editor), utilites, libraries, and interfaces.", "canonical_tags": [ @@ -15,6 +16,17 @@ ], "requirements": "", "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom/", + "external_subdirectories": [ + "Asset/ImageProcessingAtom", + "Asset/Shader", + "Bootstrap", + "Component/DebugCamera", + "Feature/Common", + "RHI", + "RPI", + "Tools/AtomToolsFramework", + "Tools/MaterialEditor" + ], "dependencies": [ "Atom_Feature_Common", "AtomShader", diff --git a/Gems/AtomContent/CMakeLists.txt b/Gems/AtomContent/CMakeLists.txt index ee06f07bc3..29477608b9 100644 --- a/Gems/AtomContent/CMakeLists.txt +++ b/Gems/AtomContent/CMakeLists.txt @@ -5,8 +5,6 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # -add_subdirectory(ReferenceMaterials) -add_subdirectory(Sponza) if(PAL_TRAIT_BUILD_HOST_TOOLS) ly_create_alias(NAME AtomContent.Builders NAMESPACE Gem TARGETS Gem::AtomContent_ReferenceMaterials.Builders Gem::AtomContent_Sponza.Builders) diff --git a/Gems/AtomContent/ReferenceMaterials/gem.json b/Gems/AtomContent/ReferenceMaterials/gem.json index b75b01e1ae..49a488b9d3 100644 --- a/Gems/AtomContent/ReferenceMaterials/gem.json +++ b/Gems/AtomContent/ReferenceMaterials/gem.json @@ -2,7 +2,9 @@ "gem_name": "ReferenceMaterials", "display_name": "PBR Reference Materials", "license": "Code, text, data files: Apache-2.0 Or MIT, assets/content/images: CC BY 4.0", - "origin": "https://github.com/aws-lumberyard-dev/o3de.git", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "Atom Asset Gem with a library of reference materials for StandardPBR (and others in the future)", "canonical_tags": [ @@ -14,6 +16,8 @@ "Materials" ], "icon_path": "preview.png", - "dependencies": [], - "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt" + "requirements": "", + "documentation_url": "", + "dependencies": [ + ] } diff --git a/Gems/AtomContent/Sponza/gem.json b/Gems/AtomContent/Sponza/gem.json index 68749cd5f4..f15d57a4d1 100644 --- a/Gems/AtomContent/Sponza/gem.json +++ b/Gems/AtomContent/Sponza/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "A standard test scene for Global Illumination (forked from crytek sponza scene)", "canonical_tags": [ @@ -13,5 +14,7 @@ "Assets" ], "requirements": "", - "dependencies": [] + "documentation_url": "", + "dependencies": [ + ] } diff --git a/Gems/AtomContent/gem.json b/Gems/AtomContent/gem.json index 400e897a3b..9be15f7da8 100644 --- a/Gems/AtomContent/gem.json +++ b/Gems/AtomContent/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "The Atom Content Gem provides assets for Atom Renderer and a modified version of the Pixar Look Development Studio.", "canonical_tags": [ @@ -17,7 +18,11 @@ "requirements": "", "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom-content/", "dependencies": [ - "ReferenceMaterials", - "Sponza" + "Sponza", + "ReferenceMaterials" + ], + "external_subdirectories": [ + "Sponza", + "ReferenceMaterials" ] } diff --git a/Gems/AtomLyIntegration/AtomBridge/CMakeLists.txt b/Gems/AtomLyIntegration/AtomBridge/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/AtomLyIntegration/AtomBridge/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomBridge/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt index 67f28767e0..fa3669d7c2 100644 --- a/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomBridge/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME Atom_AtomBridge.Static STATIC diff --git a/Gems/AtomLyIntegration/AtomBridge/gem.json b/Gems/AtomLyIntegration/AtomBridge/gem.json index e8ca413023..5a8512c90d 100644 --- a/Gems/AtomLyIntegration/AtomBridge/gem.json +++ b/Gems/AtomLyIntegration/AtomBridge/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RPI", "Atom_Bootstrap", diff --git a/Gems/AtomLyIntegration/AtomFont/CMakeLists.txt b/Gems/AtomLyIntegration/AtomFont/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/AtomLyIntegration/AtomFont/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomFont/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/AtomLyIntegration/AtomFont/Code/CMakeLists.txt b/Gems/AtomLyIntegration/AtomFont/Code/CMakeLists.txt index 6567736f02..79d97e797d 100644 --- a/Gems/AtomLyIntegration/AtomFont/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/AtomFont/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME AtomFont ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} diff --git a/Gems/AtomLyIntegration/AtomFont/gem.json b/Gems/AtomLyIntegration/AtomFont/gem.json index 8907ec0979..d979509059 100644 --- a/Gems/AtomLyIntegration/AtomFont/gem.json +++ b/Gems/AtomLyIntegration/AtomFont/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI", "Atom_RPI", diff --git a/Gems/AtomLyIntegration/AtomImGuiTools/gem.json b/Gems/AtomLyIntegration/AtomImGuiTools/gem.json index e188ba0cb8..205120f6f0 100644 --- a/Gems/AtomLyIntegration/AtomImGuiTools/gem.json +++ b/Gems/AtomLyIntegration/AtomImGuiTools/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "", "canonical_tags": [ @@ -14,6 +15,7 @@ "Rendering" ], "requirements": "", + "documentation_url": "", "dependencies": [ "ImguiAtom", "Atom" diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json index 5a0763e0da..cff957c1f1 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI", "Atom_RPI", diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json index 639d93d301..a2bc92c76d 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RHI", "Atom_RPI" diff --git a/Gems/AtomLyIntegration/CMakeLists.txt b/Gems/AtomLyIntegration/CMakeLists.txt index 4ab976d68f..25d7356b01 100644 --- a/Gems/AtomLyIntegration/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CMakeLists.txt @@ -6,13 +6,4 @@ # # -add_subdirectory(CommonFeatures) -add_subdirectory(ImguiAtom) -add_subdirectory(AtomImGuiTools) -add_subdirectory(EMotionFXAtom) -add_subdirectory(AtomFont) -add_subdirectory(TechnicalArt) -add_subdirectory(AtomBridge) -add_subdirectory(AtomViewportDisplayInfo) -add_subdirectory(AtomViewportDisplayIcons) diff --git a/Gems/AtomLyIntegration/CommonFeatures/CMakeLists.txt b/Gems/AtomLyIntegration/CommonFeatures/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CommonFeatures/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt index 7b685ece13..3234db2292 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) ly_add_target( NAME AtomLyIntegration_CommonFeatures.Public HEADERONLY diff --git a/Gems/AtomLyIntegration/CommonFeatures/gem.json b/Gems/AtomLyIntegration/CommonFeatures/gem.json index 6fa8938332..a06f607fab 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/gem.json +++ b/Gems/AtomLyIntegration/CommonFeatures/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_Feature_Common", "LmbrCentral", diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/gem.json b/Gems/AtomLyIntegration/EMotionFXAtom/gem.json index 3514d4c1b9..8bea93da91 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/gem.json +++ b/Gems/AtomLyIntegration/EMotionFXAtom/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "EMotionFX", "Atom", diff --git a/Gems/AtomLyIntegration/ImguiAtom/gem.json b/Gems/AtomLyIntegration/ImguiAtom/gem.json index fa611d8224..4c65d80e33 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/gem.json +++ b/Gems/AtomLyIntegration/ImguiAtom/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "", "canonical_tags": [ @@ -11,6 +12,7 @@ ], "user_tags": [], "requirements": "", + "documentation_url": "", "dependencies": [ "ImGui", "Atom_Feature_Common" diff --git a/Gems/AtomLyIntegration/TechnicalArt/CMakeLists.txt b/Gems/AtomLyIntegration/TechnicalArt/CMakeLists.txt deleted file mode 100644 index 4fc1e5241d..0000000000 --- a/Gems/AtomLyIntegration/TechnicalArt/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# -# Copyright (c) Contributors to the Open 3D Engine Project. -# For complete copyright and license terms please see the LICENSE at the root of this distribution. -# -# SPDX-License-Identifier: Apache-2.0 OR MIT -# -# - -add_subdirectory(DccScriptingInterface) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/CMakeLists.txt b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/CMakeLists.txt index 5780172755..f26d18b90e 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/CMakeLists.txt +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/CMakeLists.txt @@ -6,5 +6,4 @@ # # -add_subdirectory(Code) update_pip_requirements(${CMAKE_CURRENT_LIST_DIR}/requirements.txt DccScriptingInterface) diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json index 4cc6fff169..7786a8adf4 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json @@ -1,11 +1,12 @@ { "gem_name": "DccScriptingInterface", "display_name": "Atom DccScriptingInterface (DCCsi)", - "summary": "A python framework for working with various DCC tools and workflows.", "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", + "summary": "A python framework for working with various DCC tools and workflows.", "canonical_tags": [ "Gem" ], @@ -16,5 +17,6 @@ "Creation" ], "requirements": "", + "documentation_url": "", "dependencies": [] } diff --git a/Gems/AtomLyIntegration/gem.json b/Gems/AtomLyIntegration/gem.json index d9e526aee0..c491126269 100644 --- a/Gems/AtomLyIntegration/gem.json +++ b/Gems/AtomLyIntegration/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Atom O3DE Integration Gem provides components, libraries, and functionality to support and integrate Atom Renderer in Open 3D Engine.", "canonical_tags": [ @@ -25,5 +26,16 @@ "CommonFeaturesAtom", "EMotionFX_Atom", "ImguiAtom" + ], + "external_subdirectories": [ + "AtomBridge", + "AtomFont", + "AtomImGuiTools", + "AtomViewportDisplayIcons", + "AtomViewportDisplayInfo", + "CommonFeatures", + "EMotionFXAtom", + "ImguiAtom", + "TechnicalArt/DccScriptingInterface" ] } diff --git a/Gems/AtomTressFX/gem.json b/Gems/AtomTressFX/gem.json index b7588ea374..1bd619a418 100644 --- a/Gems/AtomTressFX/gem.json +++ b/Gems/AtomTressFX/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "Atom TressFX Gem provides a cutting edge hair and fur simulation and rendering in Atom enhancing the AMD TressFX 4.1. The open source TressFX can be found here: https://github.com/GPUOpen-Effects/TressFX", "canonical_tags": [ @@ -15,5 +16,7 @@ "Animation" ], "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/amd/atom-tressfx/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/amd/atom-tressfx/", + "dependencies": [ + ] } diff --git a/Gems/AudioEngineWwise/CMakeLists.txt b/Gems/AudioEngineWwise/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/AudioEngineWwise/CMakeLists.txt +++ b/Gems/AudioEngineWwise/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/AudioEngineWwise/Code/CMakeLists.txt b/Gems/AudioEngineWwise/Code/CMakeLists.txt index 33c80bc31c..02d4f1e6c8 100644 --- a/Gems/AudioEngineWwise/Code/CMakeLists.txt +++ b/Gems/AudioEngineWwise/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) #for PAL_TRAIT_AUDIO_ENGINE_WWISE Traits diff --git a/Gems/AudioEngineWwise/gem.json b/Gems/AudioEngineWwise/gem.json index 2b0af30d40..f0d8c73be2 100644 --- a/Gems/AudioEngineWwise/gem.json +++ b/Gems/AudioEngineWwise/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Wwise Audio Engine Gem provides support for Audiokinetic Wave Works Interactive Sound Engine (Wwise).", "canonical_tags": [ diff --git a/Gems/AudioSystem/CMakeLists.txt b/Gems/AudioSystem/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/AudioSystem/CMakeLists.txt +++ b/Gems/AudioSystem/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/AudioSystem/Code/CMakeLists.txt b/Gems/AudioSystem/Code/CMakeLists.txt index 17dbd91878..e5778e9152 100644 --- a/Gems/AudioSystem/Code/CMakeLists.txt +++ b/Gems/AudioSystem/Code/CMakeLists.txt @@ -10,7 +10,7 @@ set(AUDIOSYSTEM_COMPILEDEFINITIONS $,AUDIO_RELEASE,ENABLE_AUDIO_LOGGING> ) -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME AudioSystem.Static STATIC @@ -65,7 +65,7 @@ ly_create_alias(NAME AudioSystem.Clients NAMESPACE Gem TARGETS Gem::AudioSystem # Tests ################################################################################ if (PAL_TRAIT_BUILD_TESTS_SUPPORTED) - ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) + set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) ly_add_target( NAME AudioSystem.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem diff --git a/Gems/AudioSystem/gem.json b/Gems/AudioSystem/gem.json index ed028068a1..be618ee44e 100644 --- a/Gems/AudioSystem/gem.json +++ b/Gems/AudioSystem/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Audio System Gem provides the Audio Translation Layer (ATL) and Audio Controls Editor, which add support for audio in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/BarrierInput/gem.json b/Gems/BarrierInput/gem.json index 72d6398550..e8dcf0d93c 100644 --- a/Gems/BarrierInput/gem.json +++ b/Gems/BarrierInput/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Barrier Input Gem allows the Open 3D Engine to function as a Barrier client so that it can receive input from a remote Barrier server.", "canonical_tags": [ @@ -16,6 +17,7 @@ ], "icon_path": "preview.png", "requirements": "", + "documentation_url": "", "dependencies": [ "Atom_RPI" ] diff --git a/Gems/Blast/CMakeLists.txt b/Gems/Blast/CMakeLists.txt index 7c478ef2b2..e2fe57d8cc 100644 --- a/Gems/Blast/CMakeLists.txt +++ b/Gems/Blast/CMakeLists.txt @@ -6,5 +6,9 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Blast/Code/CMakeLists.txt b/Gems/Blast/Code/CMakeLists.txt index d3555b2855..7f478054b8 100644 --- a/Gems/Blast/Code/CMakeLists.txt +++ b/Gems/Blast/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # for PAL_TRAIT_BLAST Traits diff --git a/Gems/Blast/gem.json b/Gems/Blast/gem.json index 761eb04761..dc90c587d7 100644 --- a/Gems/Blast/gem.json +++ b/Gems/Blast/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The NVIDIA Blast Gem provides tools to author fractured mesh assets in Houdini, and functionality to create realistic destruction simulations in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/Camera/gem.json b/Gems/Camera/gem.json index 4cf0747c7b..c6367d4663 100644 --- a/Gems/Camera/gem.json +++ b/Gems/Camera/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Camera Gem provides a basic camera component that defines a frustum for runtime rendering.", "canonical_tags": [ diff --git a/Gems/CameraFramework/gem.json b/Gems/CameraFramework/gem.json index d24014be61..0803fd7522 100644 --- a/Gems/CameraFramework/gem.json +++ b/Gems/CameraFramework/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Camera Framework Gem provides a base for implementing more complex camera systems.", "canonical_tags": [ diff --git a/Gems/CertificateManager/gem.json b/Gems/CertificateManager/gem.json index 11ea14ea5e..c582e932be 100644 --- a/Gems/CertificateManager/gem.json +++ b/Gems/CertificateManager/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Certificate Manager Gem provides access to authentication files for secure game connections from Amazon S3, files on disk, and other 3rd party sources.", "canonical_tags": [ diff --git a/Gems/CrashReporting/CMakeLists.txt b/Gems/CrashReporting/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/CrashReporting/CMakeLists.txt +++ b/Gems/CrashReporting/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/CrashReporting/Code/CMakeLists.txt b/Gems/CrashReporting/Code/CMakeLists.txt index 8bcb143d1c..7d7b2c76da 100644 --- a/Gems/CrashReporting/Code/CMakeLists.txt +++ b/Gems/CrashReporting/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Gems/CrashReporting/gem.json b/Gems/CrashReporting/gem.json index b8c75548a4..1651bad7b8 100644 --- a/Gems/CrashReporting/gem.json +++ b/Gems/CrashReporting/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Crash Reporting Gem provides support for external crash reporting for Open 3D Engine projects.", "canonical_tags": [ diff --git a/Gems/CustomAssetExample/gem.json b/Gems/CustomAssetExample/gem.json index 89492ee6ea..ba1030b280 100644 --- a/Gems/CustomAssetExample/gem.json +++ b/Gems/CustomAssetExample/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Custom Asset Example Gem provides example code for creating a custom asset for Open 3D Engine's asset pipeline.", "canonical_tags": [ diff --git a/Gems/DebugDraw/gem.json b/Gems/DebugDraw/gem.json index 58eff5f87a..e140d642b8 100644 --- a/Gems/DebugDraw/gem.json +++ b/Gems/DebugDraw/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Debug Draw Gem provides Editor and runtime debug visualization features for Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/DevTextures/gem.json b/Gems/DevTextures/gem.json index 00cafbd6fb..f8c436887d 100644 --- a/Gems/DevTextures/gem.json +++ b/Gems/DevTextures/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "The Dev Textures Gem provides a collection of general purpose texture assets useful for prototypes and preproduction.", "canonical_tags": [ diff --git a/Gems/EMotionFX/CMakeLists.txt b/Gems/EMotionFX/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/EMotionFX/CMakeLists.txt +++ b/Gems/EMotionFX/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/EMotionFX/Code/CMakeLists.txt b/Gems/EMotionFX/Code/CMakeLists.txt index 67d0ba6d85..bd90e589c9 100644 --- a/Gems/EMotionFX/Code/CMakeLists.txt +++ b/Gems/EMotionFX/Code/CMakeLists.txt @@ -6,10 +6,9 @@ # # -ly_get_list_relative_pal_filename(core_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) - -ly_get_list_relative_pal_filename(editor_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Editor/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(editor_common_dir ${CMAKE_CURRENT_LIST_DIR}/Editor/Platform/Common) +o3de_pal_dir(core_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +o3de_pal_dir(editor_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Editor/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(editor_common_dir ${CMAKE_CURRENT_LIST_DIR}/Editor/Platform/Common) ly_add_target( NAME EMotionFXStaticLib STATIC diff --git a/Gems/EMotionFX/gem.json b/Gems/EMotionFX/gem.json index ed80517af1..c07c8368c2 100644 --- a/Gems/EMotionFX/gem.json +++ b/Gems/EMotionFX/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The EMotion FX Animation Gem provides Open 3D Engine's animation system for rigged actors and includes Animation Editor, a tool for creating animated behaviors, simulated objects, and colliders for rigged actors.", "canonical_tags": [ diff --git a/Gems/EditorPythonBindings/gem.json b/Gems/EditorPythonBindings/gem.json index 475483f13b..a5ee9f5631 100644 --- a/Gems/EditorPythonBindings/gem.json +++ b/Gems/EditorPythonBindings/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Editor Python Bindings Gem provides Python commands for Open 3D Engine Editor functions.", "canonical_tags": [ diff --git a/Gems/ExpressionEvaluation/gem.json b/Gems/ExpressionEvaluation/gem.json index cd712f4da9..667eebbcb5 100644 --- a/Gems/ExpressionEvaluation/gem.json +++ b/Gems/ExpressionEvaluation/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Expression Evaluation Gem provides a method for parsing and executing string expressions in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/FastNoise/gem.json b/Gems/FastNoise/gem.json index d8dfb878b4..a9c0f1f42d 100644 --- a/Gems/FastNoise/gem.json +++ b/Gems/FastNoise/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The FastNoise Gradient Gem uses the third-party, open source FastNoise library to provide a variety of high-performance noise generation algorithms.", "canonical_tags": [ diff --git a/Gems/GameState/gem.json b/Gems/GameState/gem.json index fe3a338997..d3e2d76c5a 100644 --- a/Gems/GameState/gem.json +++ b/Gems/GameState/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Game State Gem provides a generic framework to determine and manage game states and game state transitions in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/GameStateSamples/CMakeLists.txt b/Gems/GameStateSamples/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/GameStateSamples/CMakeLists.txt +++ b/Gems/GameStateSamples/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/GameStateSamples/Code/CMakeLists.txt b/Gems/GameStateSamples/Code/CMakeLists.txt index a07bef6a06..939b2ce1bd 100644 --- a/Gems/GameStateSamples/Code/CMakeLists.txt +++ b/Gems/GameStateSamples/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(include_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(include_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Include/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME GameStateSamples.Headers HEADERONLY diff --git a/Gems/GameStateSamples/gem.json b/Gems/GameStateSamples/gem.json index 80018ff1a8..94556ee677 100644 --- a/Gems/GameStateSamples/gem.json +++ b/Gems/GameStateSamples/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Game State Samples Gem provides a set of sample game states (built on top of the Game State Gem), including primary user selection, main menu, level loading, level running, and level paused.", "canonical_tags": [ diff --git a/Gems/Gestures/gem.json b/Gems/Gestures/gem.json index 8efd389d53..c0609c8d54 100644 --- a/Gems/Gestures/gem.json +++ b/Gems/Gestures/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Gestures Gem provides detection for common gesture-based input actions on iOS and Android devices.", "canonical_tags": [ diff --git a/Gems/GradientSignal/gem.json b/Gems/GradientSignal/gem.json index aac4c652c5..f0136ef104 100644 --- a/Gems/GradientSignal/gem.json +++ b/Gems/GradientSignal/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Gradient Signal Gem provides a number of components for generating, modifying, and mixing gradient signals.", "canonical_tags": [ diff --git a/Gems/GraphCanvas/gem.json b/Gems/GraphCanvas/gem.json index 4762cfef35..c2038f4645 100644 --- a/Gems/GraphCanvas/gem.json +++ b/Gems/GraphCanvas/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Graph Canvas Gem provides a C++ framework for creating custom graphical node based editors for Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/GraphModel/gem.json b/Gems/GraphModel/gem.json index ad6b592430..ece520278b 100644 --- a/Gems/GraphModel/gem.json +++ b/Gems/GraphModel/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Graph Model Gem provides a generic node graph data model framework for Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/HttpRequestor/CMakeLists.txt b/Gems/HttpRequestor/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/HttpRequestor/CMakeLists.txt +++ b/Gems/HttpRequestor/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/HttpRequestor/Code/CMakeLists.txt b/Gems/HttpRequestor/Code/CMakeLists.txt index 831eb52231..4ebca5518c 100644 --- a/Gems/HttpRequestor/Code/CMakeLists.txt +++ b/Gems/HttpRequestor/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(source_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(source_pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME HttpRequestor.Static STATIC diff --git a/Gems/HttpRequestor/gem.json b/Gems/HttpRequestor/gem.json index 582bfa0071..a8e111ac63 100644 --- a/Gems/HttpRequestor/gem.json +++ b/Gems/HttpRequestor/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The HTTP Requestor Gem provides functionality to make asynchronous HTTP/HTTPS requests and return data through a user-provided call back function.", "canonical_tags": [ diff --git a/Gems/ImGui/CMakeLists.txt b/Gems/ImGui/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/ImGui/CMakeLists.txt +++ b/Gems/ImGui/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/ImGui/Code/CMakeLists.txt b/Gems/ImGui/Code/CMakeLists.txt index e345e3d546..c293065636 100644 --- a/Gems/ImGui/Code/CMakeLists.txt +++ b/Gems/ImGui/Code/CMakeLists.txt @@ -8,7 +8,7 @@ set(config_base_defines $,IMGUI_DISABLED,IMGUI_ENABLED>) -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) # This library is the 3rdParty imgui that is in the Gem's External ly_add_target( diff --git a/Gems/ImGui/gem.json b/Gems/ImGui/gem.json index dfc12f64b4..0ed889f693 100644 --- a/Gems/ImGui/gem.json +++ b/Gems/ImGui/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Immediate Mode GUI Gem provides the 3rdParty library IMGUI which can be used to create run time immediate mode overlays for debugging and profiling information in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/InAppPurchases/CMakeLists.txt b/Gems/InAppPurchases/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/InAppPurchases/CMakeLists.txt +++ b/Gems/InAppPurchases/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/InAppPurchases/Code/CMakeLists.txt b/Gems/InAppPurchases/Code/CMakeLists.txt index 99fc937919..e7b34296d1 100644 --- a/Gems/InAppPurchases/Code/CMakeLists.txt +++ b/Gems/InAppPurchases/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME InAppPurchases.Static STATIC diff --git a/Gems/InAppPurchases/gem.json b/Gems/InAppPurchases/gem.json index 21febbfeca..0b3d2e65e4 100644 --- a/Gems/InAppPurchases/gem.json +++ b/Gems/InAppPurchases/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The In-App Purchases Gem provides functionality for in app purchases for iOS and Android.", "canonical_tags": [ diff --git a/Gems/LandscapeCanvas/gem.json b/Gems/LandscapeCanvas/gem.json index 8653da40e1..f1e326efce 100644 --- a/Gems/LandscapeCanvas/gem.json +++ b/Gems/LandscapeCanvas/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Landscape Canvas Gem provides the Landscape Canvas editor, a node-based graph tool for authoring workflows to populate landscape with dynamic vegetation.", "canonical_tags": [ diff --git a/Gems/LmbrCentral/CMakeLists.txt b/Gems/LmbrCentral/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/LmbrCentral/CMakeLists.txt +++ b/Gems/LmbrCentral/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/LmbrCentral/Code/CMakeLists.txt b/Gems/LmbrCentral/Code/CMakeLists.txt index 4401d3b752..a4c94a7b40 100644 --- a/Gems/LmbrCentral/Code/CMakeLists.txt +++ b/Gems/LmbrCentral/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) ly_add_target( NAME LmbrCentral.Static STATIC diff --git a/Gems/LmbrCentral/gem.json b/Gems/LmbrCentral/gem.json index a0a6ea813f..4eea28d26e 100644 --- a/Gems/LmbrCentral/gem.json +++ b/Gems/LmbrCentral/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The O3DE Core (LmbrCentral) Gem provides required code and assets for running Open 3D Engine Editor.", "canonical_tags": [ diff --git a/Gems/LocalUser/CMakeLists.txt b/Gems/LocalUser/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/LocalUser/CMakeLists.txt +++ b/Gems/LocalUser/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/LocalUser/Code/CMakeLists.txt b/Gems/LocalUser/Code/CMakeLists.txt index 055cfe6c7c..ce937e9dc5 100644 --- a/Gems/LocalUser/Code/CMakeLists.txt +++ b/Gems/LocalUser/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME LocalUser.Static STATIC diff --git a/Gems/LocalUser/gem.json b/Gems/LocalUser/gem.json index 5199b4f777..04f2145956 100644 --- a/Gems/LocalUser/gem.json +++ b/Gems/LocalUser/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Local User Gem provides functionality for mapping local user ids to local player slots and managing local user profiles.", "canonical_tags": [ diff --git a/Gems/LyShine/CMakeLists.txt b/Gems/LyShine/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/LyShine/CMakeLists.txt +++ b/Gems/LyShine/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/LyShine/Code/CMakeLists.txt b/Gems/LyShine/Code/CMakeLists.txt index 2b550b0e36..76d7742ddf 100644 --- a/Gems/LyShine/Code/CMakeLists.txt +++ b/Gems/LyShine/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) ly_add_target( NAME LyShine.Static STATIC diff --git a/Gems/LyShine/gem.json b/Gems/LyShine/gem.json index 8dcac6404a..7ebb733b0f 100644 --- a/Gems/LyShine/gem.json +++ b/Gems/LyShine/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The LyShine Gem provides the runtime UI system and creation tools for Open 3D Engine projects.", "canonical_tags": [ diff --git a/Gems/LyShineExamples/gem.json b/Gems/LyShineExamples/gem.json index 74d2b6fe51..c91e9b819e 100644 --- a/Gems/LyShineExamples/gem.json +++ b/Gems/LyShineExamples/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "The LyShine Examples Gem provides example code and assets for LyShine, the runtime UI system and editor for Open 3D Engine projects.", "canonical_tags": [ diff --git a/Gems/Maestro/gem.json b/Gems/Maestro/gem.json index d8f884e271..95aa43c179 100644 --- a/Gems/Maestro/gem.json +++ b/Gems/Maestro/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Maestro Cinematics Gem provides Track View, Open 3D Engine's animated sequence and cinematics editor.", "canonical_tags": [ diff --git a/Gems/MessagePopup/gem.json b/Gems/MessagePopup/gem.json index fb44dd93a5..5e1b4843b0 100644 --- a/Gems/MessagePopup/gem.json +++ b/Gems/MessagePopup/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Message Popup Gem provides an example implementation of popup messages using LyShine in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/Metastream/CMakeLists.txt b/Gems/Metastream/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Metastream/CMakeLists.txt +++ b/Gems/Metastream/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Metastream/Code/CMakeLists.txt b/Gems/Metastream/Code/CMakeLists.txt index a032fc34ff..f1652058ac 100644 --- a/Gems/Metastream/Code/CMakeLists.txt +++ b/Gems/Metastream/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) ly_add_target( NAME Metastream.Static STATIC diff --git a/Gems/Metastream/gem.json b/Gems/Metastream/gem.json index 309f16b221..9a37a0a8ee 100644 --- a/Gems/Metastream/gem.json +++ b/Gems/Metastream/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Metastream Gem provides functionality for an HTTP server that allows broadcasters to customize game streams with overlays of statistics and event data from a game session.", "canonical_tags": [ diff --git a/Gems/Microphone/CMakeLists.txt b/Gems/Microphone/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Microphone/CMakeLists.txt +++ b/Gems/Microphone/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Microphone/Code/CMakeLists.txt b/Gems/Microphone/Code/CMakeLists.txt index 5b40521f6a..873d05e98d 100644 --- a/Gems/Microphone/Code/CMakeLists.txt +++ b/Gems/Microphone/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME Microphone.Static STATIC diff --git a/Gems/Microphone/gem.json b/Gems/Microphone/gem.json index 6e57bec854..6a5b415a22 100644 --- a/Gems/Microphone/gem.json +++ b/Gems/Microphone/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Microphone Gem provides support for audio input through microphones.", "canonical_tags": [ diff --git a/Gems/Multiplayer/CMakeLists.txt b/Gems/Multiplayer/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Multiplayer/CMakeLists.txt +++ b/Gems/Multiplayer/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index afe40408ab..66085476e5 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -6,6 +6,8 @@ # # +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) + ly_add_target( NAME Multiplayer.Static STATIC NAMESPACE Gem diff --git a/Gems/Multiplayer/gem.json b/Gems/Multiplayer/gem.json index f895c78c5d..2b412084af 100644 --- a/Gems/Multiplayer/gem.json +++ b/Gems/Multiplayer/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Multiplayer Gem provides a public API for multiplayer functionality such as connecting and hosting.", "canonical_tags": [ @@ -16,6 +17,7 @@ ], "icon_path": "preview.png", "requirements": "", + "documentation_url": "", "dependencies": [ "CertificateManager", "Atom_Feature_Common", diff --git a/Gems/MultiplayerCompression/gem.json b/Gems/MultiplayerCompression/gem.json index 98156cc404..a9cf3fa460 100644 --- a/Gems/MultiplayerCompression/gem.json +++ b/Gems/MultiplayerCompression/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Multiplayer Compression Gem provides an open source Compressor for use with AzNetworking's transport layer.", "canonical_tags": [ diff --git a/Gems/NvCloth/CMakeLists.txt b/Gems/NvCloth/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/NvCloth/CMakeLists.txt +++ b/Gems/NvCloth/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/NvCloth/Code/CMakeLists.txt b/Gems/NvCloth/Code/CMakeLists.txt index 5b5bba9d8b..76f5bcfeb8 100644 --- a/Gems/NvCloth/Code/CMakeLists.txt +++ b/Gems/NvCloth/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) #for PAL_TRAIT_NVCLOTH Traits diff --git a/Gems/NvCloth/gem.json b/Gems/NvCloth/gem.json index 86a70b9373..9494d65e82 100644 --- a/Gems/NvCloth/gem.json +++ b/Gems/NvCloth/gem.json @@ -2,8 +2,9 @@ "gem_name": "NvCloth", "display_name": "NVIDIA Cloth (NvCloth)", "license": "Apache-2.0 Or MIT", - "origin": "Open 3D Engine - o3de.org", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The NVIDIA Cloth Gem provides functionality to create fast, realistic cloth simulation with the NVIDIA Cloth library.", "canonical_tags": [ diff --git a/Gems/PhysX/CMakeLists.txt b/Gems/PhysX/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/PhysX/CMakeLists.txt +++ b/Gems/PhysX/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt index f045d6b00d..1cad877542 100644 --- a/Gems/PhysX/Code/CMakeLists.txt +++ b/Gems/PhysX/Code/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(NumericalMethods) -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # for PAL_TRAIT_PHYSX_SUPPORTED set(LY_PHYSX_ENABLE_RUNNING_BENCHMARKS OFF CACHE BOOL "Adds a target to allow running of the physx benchmarks.") diff --git a/Gems/PhysXDebug/CMakeLists.txt b/Gems/PhysXDebug/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/PhysXDebug/CMakeLists.txt +++ b/Gems/PhysXDebug/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/PhysXDebug/Code/CMakeLists.txt b/Gems/PhysXDebug/Code/CMakeLists.txt index 3ddec9d105..0886f2bf34 100644 --- a/Gems/PhysXDebug/Code/CMakeLists.txt +++ b/Gems/PhysXDebug/Code/CMakeLists.txt @@ -6,7 +6,11 @@ # # -ly_get_list_relative_pal_filename(physx_pal_source_dir ${LY_ROOT_FOLDER}/Gems/PhysX/Code/Source/Platform/${PAL_PLATFORM_NAME}) +# This gem relies on the PhysX gem +o3de_find_gem("PhysX" physx_gem_path) +set(physx_gem_json ${physx_gem_path}/gem.json) +o3de_restricted_path(${physx_gem_json} physx_gem_restricted_path physx_gem_parent_relative_path) +o3de_pal_dir(physx_pal_source_dir ${physx_gem_path}/Code/Source/Platform/${PAL_PLATFORM_NAME} ${physx_gem_restricted_path} ${physx_gem_path} ${physx_gem_parent_relative_path}) include(${physx_pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # for PAL_TRAIT_PHYSX_SUPPORTED diff --git a/Gems/PhysXDebug/gem.json b/Gems/PhysXDebug/gem.json index 2d9f4dc24d..1087eefad4 100644 --- a/Gems/PhysXDebug/gem.json +++ b/Gems/PhysXDebug/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The PhysX Debug Gem provides debugging functionality and visualizations for NVIDIA PhysX in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/Prefab/PrefabBuilder/gem.json b/Gems/Prefab/PrefabBuilder/gem.json index 2233a7235e..1c0dcd9a72 100644 --- a/Gems/Prefab/PrefabBuilder/gem.json +++ b/Gems/Prefab/PrefabBuilder/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Prefab Builder Gem provides an Asset Processor module for prefabs, which are complex assets built by combining smaller entities.", "canonical_tags": [ diff --git a/Gems/Presence/CMakeLists.txt b/Gems/Presence/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Presence/CMakeLists.txt +++ b/Gems/Presence/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Presence/Code/CMakeLists.txt b/Gems/Presence/Code/CMakeLists.txt index c1c807d432..cc84771201 100644 --- a/Gems/Presence/Code/CMakeLists.txt +++ b/Gems/Presence/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME Presence.Headers HEADERONLY diff --git a/Gems/Presence/gem.json b/Gems/Presence/gem.json index 624af2e62d..48d9dd5ef0 100644 --- a/Gems/Presence/gem.json +++ b/Gems/Presence/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Presence Gem provides a target platform agnostic interface for Presence services.", "canonical_tags": [ diff --git a/Gems/PrimitiveAssets/gem.json b/Gems/PrimitiveAssets/gem.json index 0e4c4689dc..7669477220 100644 --- a/Gems/PrimitiveAssets/gem.json +++ b/Gems/PrimitiveAssets/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "The Primitive Assets Gem provides primitive shape mesh assets with physics enabled.", "canonical_tags": [ diff --git a/Gems/Profiler/gem.json b/Gems/Profiler/gem.json index b160bc4b3c..40478deae1 100644 --- a/Gems/Profiler/gem.json +++ b/Gems/Profiler/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "A collection of utilities for capturing performance data", "canonical_tags": [ diff --git a/Gems/PythonAssetBuilder/gem.json b/Gems/PythonAssetBuilder/gem.json index 8046104f03..54fbb949f9 100644 --- a/Gems/PythonAssetBuilder/gem.json +++ b/Gems/PythonAssetBuilder/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Python Asset Builder Gem provides functionality to implement custom asset builders in Python for Asset Processor.", "canonical_tags": [ diff --git a/Gems/QtForPython/Code/CMakeLists.txt b/Gems/QtForPython/Code/CMakeLists.txt index da763978a6..d63c71492d 100644 --- a/Gems/QtForPython/Code/CMakeLists.txt +++ b/Gems/QtForPython/Code/CMakeLists.txt @@ -9,7 +9,7 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) include(${CMAKE_CURRENT_SOURCE_DIR}/Source/Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Gems/QtForPython/gem.json b/Gems/QtForPython/gem.json index 17d3a26f21..63805a5bc7 100644 --- a/Gems/QtForPython/gem.json +++ b/Gems/QtForPython/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Qt for Python Gem provides the PySide2 Python libraries to manage Qt widgets.", "canonical_tags": [ diff --git a/Gems/SaveData/CMakeLists.txt b/Gems/SaveData/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/SaveData/CMakeLists.txt +++ b/Gems/SaveData/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/SaveData/Code/CMakeLists.txt b/Gems/SaveData/Code/CMakeLists.txt index 38d145f8e5..5d4eb361cc 100644 --- a/Gems/SaveData/Code/CMakeLists.txt +++ b/Gems/SaveData/Code/CMakeLists.txt @@ -6,7 +6,7 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) ly_add_target( NAME SaveData.Static STATIC diff --git a/Gems/SaveData/gem.json b/Gems/SaveData/gem.json index 1ee5a54cec..3a686242d7 100644 --- a/Gems/SaveData/gem.json +++ b/Gems/SaveData/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Save Data Gem provides a platform independent API to save and load persistent user data in Open 3D Engine projects.", "canonical_tags": [ diff --git a/Gems/SceneLoggingExample/gem.json b/Gems/SceneLoggingExample/gem.json index ad950f3992..dc6b5179b6 100644 --- a/Gems/SceneLoggingExample/gem.json +++ b/Gems/SceneLoggingExample/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "The Scene Logging Example Gem demonstrates the basics of extending the Open 3D Engine Scene API by adding additional logging to the pipeline.", "canonical_tags": [ diff --git a/Gems/SceneProcessing/gem.json b/Gems/SceneProcessing/gem.json index 576460d0a9..3689c2500a 100644 --- a/Gems/SceneProcessing/gem.json +++ b/Gems/SceneProcessing/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Scene Processing Gem provides Scene Settings, a tool you can use to specify the default settings for processing asset files for actors, meshes, motions, and PhysX.", "canonical_tags": [ diff --git a/Gems/ScriptCanvas/gem.json b/Gems/ScriptCanvas/gem.json index fc8a504917..ace6bca50c 100644 --- a/Gems/ScriptCanvas/gem.json +++ b/Gems/ScriptCanvas/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Script Canvas Gem provides Open 3D Engine's visual scripting environment, Script Canvas.", "canonical_tags": [ diff --git a/Gems/ScriptCanvasDeveloper/gem.json b/Gems/ScriptCanvasDeveloper/gem.json index fe1fdea0fc..c7e23dab9a 100644 --- a/Gems/ScriptCanvasDeveloper/gem.json +++ b/Gems/ScriptCanvasDeveloper/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Script Canvas Developer Gem provides a suite of utility features for the development and debugging of Script Canvas systems.", "canonical_tags": [ diff --git a/Gems/ScriptCanvasPhysics/gem.json b/Gems/ScriptCanvasPhysics/gem.json index 2e35e85c46..fdf83fe479 100644 --- a/Gems/ScriptCanvasPhysics/gem.json +++ b/Gems/ScriptCanvasPhysics/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Script Canvas Physics Gem provides Script Canvas nodes for physics scene queries such as raycasts.", "canonical_tags": [ diff --git a/Gems/ScriptCanvasTesting/gem.json b/Gems/ScriptCanvasTesting/gem.json index 5cb718e674..f62ec46fd4 100644 --- a/Gems/ScriptCanvasTesting/gem.json +++ b/Gems/ScriptCanvasTesting/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Script Canvas Testing Gem provides a framework for testing for and with Script Canvas.", "canonical_tags": [ diff --git a/Gems/ScriptEvents/gem.json b/Gems/ScriptEvents/gem.json index 5640e08489..c9391da996 100644 --- a/Gems/ScriptEvents/gem.json +++ b/Gems/ScriptEvents/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Script Events Gem provides a framework for creating event assets usable from any scripting solution in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/ScriptedEntityTweener/gem.json b/Gems/ScriptedEntityTweener/gem.json index 477345093c..bf7eec470f 100644 --- a/Gems/ScriptedEntityTweener/gem.json +++ b/Gems/ScriptedEntityTweener/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Scripted Entity Tweener Gem provides a script driven animation system for Open 3D Engine projects.", "canonical_tags": [ diff --git a/Gems/SliceFavorites/gem.json b/Gems/SliceFavorites/gem.json index c4536dc042..bbb873b20b 100644 --- a/Gems/SliceFavorites/gem.json +++ b/Gems/SliceFavorites/gem.json @@ -4,13 +4,18 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "Add the ability to favorite a slice to allow easy access and instantiation", + "canonical_tags": [ + "Gem" + ], "user_tags": [ "Editor", "Slices" ], "icon_path": "preview.png", "requirements": "", + "documentation_url": "", "dependencies": [] } diff --git a/Gems/StartingPointCamera/gem.json b/Gems/StartingPointCamera/gem.json index 1033770022..1a736d6e74 100644 --- a/Gems/StartingPointCamera/gem.json +++ b/Gems/StartingPointCamera/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Starting Point Camera Gem provides the behaviors used with the Camera Framework Gem to define a camera rig.", "canonical_tags": [ diff --git a/Gems/StartingPointInput/gem.json b/Gems/StartingPointInput/gem.json index ee1655b794..77a683658d 100644 --- a/Gems/StartingPointInput/gem.json +++ b/Gems/StartingPointInput/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Starting Point Input Gem provides functionality to map low-level input events to high-level actions.", "canonical_tags": [ diff --git a/Gems/StartingPointMovement/gem.json b/Gems/StartingPointMovement/gem.json index 188d8483bc..a9941098fa 100644 --- a/Gems/StartingPointMovement/gem.json +++ b/Gems/StartingPointMovement/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Starting Point Movement Gem provides a series of Lua scripts that listen and respond to input events and trigger transform operations such as translation and rotation.", "canonical_tags": [ diff --git a/Gems/SurfaceData/gem.json b/Gems/SurfaceData/gem.json index d16254040f..10100e3b90 100644 --- a/Gems/SurfaceData/gem.json +++ b/Gems/SurfaceData/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Surface Data Gem provides functionality to emit signals or tags from surfaces such as meshes and terrain.", "canonical_tags": [ diff --git a/Gems/Terrain/gem.json b/Gems/Terrain/gem.json index 0ca470c4d3..f038eb4d90 100644 --- a/Gems/Terrain/gem.json +++ b/Gems/Terrain/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "summary": "The Terrain Gem is an experimental terrain system. The terrain system maps height, color, and surface data to regions of the world, provides gradient-based and shape-based authoring tools and workflows, includes specialized rendering for efficient display, and integrates with physics for physical simulation.", "canonical_tags": [ "Gem" diff --git a/Gems/TestAssetBuilder/gem.json b/Gems/TestAssetBuilder/gem.json index 68ed706499..96c3bb4ffb 100644 --- a/Gems/TestAssetBuilder/gem.json +++ b/Gems/TestAssetBuilder/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Test Asset Builder Gem is used to feature test Asset Processor.", "canonical_tags": [ diff --git a/Gems/TextureAtlas/gem.json b/Gems/TextureAtlas/gem.json index 142f0fb082..970982fb48 100644 --- a/Gems/TextureAtlas/gem.json +++ b/Gems/TextureAtlas/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Texture Atlas Gem provides the formatting for texture atlases from 2D textures for LyShine.", "canonical_tags": [ diff --git a/Gems/TickBusOrderViewer/gem.json b/Gems/TickBusOrderViewer/gem.json index a6a6fd23ac..78b4d96c5c 100644 --- a/Gems/TickBusOrderViewer/gem.json +++ b/Gems/TickBusOrderViewer/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The Tick Bus Order Viewer Gem provides a console variable that displays the order of runtime tick events.", "canonical_tags": [ diff --git a/Gems/Twitch/CMakeLists.txt b/Gems/Twitch/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/Twitch/CMakeLists.txt +++ b/Gems/Twitch/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/Twitch/Code/CMakeLists.txt b/Gems/Twitch/Code/CMakeLists.txt index 80c74e5bd4..75b18627cf 100644 --- a/Gems/Twitch/Code/CMakeLists.txt +++ b/Gems/Twitch/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/Common) ly_add_target( NAME Twitch.Static STATIC diff --git a/Gems/Twitch/gem.json b/Gems/Twitch/gem.json index 42ec1b971e..70386e057f 100644 --- a/Gems/Twitch/gem.json +++ b/Gems/Twitch/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Twitch Gem provides access to the Twitch API v5 SDK including social functions, channels, and other APIs.", "canonical_tags": [ @@ -12,7 +13,8 @@ "user_tags": [ "Network", "SDK", - "Multiplayer" + "Multiplayer", + "Twitch" ], "icon_path": "preview.png", "requirements": "", diff --git a/Gems/UiBasics/gem.json b/Gems/UiBasics/gem.json index bb2416c235..4734aef779 100644 --- a/Gems/UiBasics/gem.json +++ b/Gems/UiBasics/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Asset", "summary": "The UI Basics Gem provides a collection of basic UI prefabs such as image, text, and button, that can be used with LyShine, the Open 3D Engine runtime User Interface system and editor.", "canonical_tags": [ diff --git a/Gems/Vegetation/gem.json b/Gems/Vegetation/gem.json index 75416933f0..8dfd3b3a59 100644 --- a/Gems/Vegetation/gem.json +++ b/Gems/Vegetation/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Vegetation Gem provides tools to place natural-looking vegetation in Open 3D Engine.", "canonical_tags": [ diff --git a/Gems/VideoPlaybackFramework/gem.json b/Gems/VideoPlaybackFramework/gem.json index 381738ab4b..9115148c50 100644 --- a/Gems/VideoPlaybackFramework/gem.json +++ b/Gems/VideoPlaybackFramework/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Video Playback Framework Gem provides the interface to play back video.", "canonical_tags": [ diff --git a/Gems/VirtualGamepad/gem.json b/Gems/VirtualGamepad/gem.json index 637776ac85..a2a669bb11 100644 --- a/Gems/VirtualGamepad/gem.json +++ b/Gems/VirtualGamepad/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "The Virtual Gamepad Gem provides controls that emulate a gamepad on touch screen devices.", "canonical_tags": [ diff --git a/Gems/WhiteBox/CMakeLists.txt b/Gems/WhiteBox/CMakeLists.txt index 2bb380fae3..50f9e78c74 100644 --- a/Gems/WhiteBox/CMakeLists.txt +++ b/Gems/WhiteBox/CMakeLists.txt @@ -6,4 +6,8 @@ # # +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + add_subdirectory(Code) diff --git a/Gems/WhiteBox/Code/CMakeLists.txt b/Gems/WhiteBox/Code/CMakeLists.txt index bfc4eb724a..91536503ac 100644 --- a/Gems/WhiteBox/Code/CMakeLists.txt +++ b/Gems/WhiteBox/Code/CMakeLists.txt @@ -6,8 +6,8 @@ # # -ly_get_list_relative_pal_filename(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) +o3de_pal_dir(pal_source_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) +set(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) include(${pal_source_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/Gems/WhiteBox/gem.json b/Gems/WhiteBox/gem.json index 2d173e9a6b..18a3022b74 100644 --- a/Gems/WhiteBox/gem.json +++ b/Gems/WhiteBox/gem.json @@ -4,6 +4,7 @@ "license": "Apache-2.0 Or MIT", "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Tool", "summary": "The White Box Gem provides White Box rapid design components for Open 3D Engine.", "canonical_tags": [ diff --git a/Templates/AssetGem/Template/gem.json b/Templates/AssetGem/Template/gem.json index 2a02362256..b04ecf9dd8 100644 --- a/Templates/AssetGem/Template/gem.json +++ b/Templates/AssetGem/Template/gem.json @@ -1,18 +1,21 @@ { "gem_name": "${Name}", "display_name": "${Name}", - "license": "What license ${Name} uses goes here: i.e. Apache-2.0 Or MIT", - "license_url": "", - "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "license": "What license ${Name} uses goes here: i.e. Apache-2.0 or MIT", + "license_url": "Link to the license web site goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT", + "origin": "The name of the originator goes here. i.e. XYZ Inc.", + "origin_url": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", "type": "Asset", - "summary": "A short description of ${Name}.", + "summary": "A short description of ${Name} goes here.", "canonical_tags": [ "Gem" ], "user_tags": [ - "Assets", "${Name}" ], "icon_path": "preview.png", - "requirements": "" + "requirements": "Notice of any requirements ${Name} has goes here. i.e. This requires X other gem", + "documentation_url": "Link to any documentation of ${Name} goes here: i.e. https://o3de.org/docs/user-guide/gems/reference/design/white-box/", + "dependencies": [ + ] } diff --git a/Templates/AssetGem/template.json b/Templates/AssetGem/template.json index e858dc526d..2f390f2077 100644 --- a/Templates/AssetGem/template.json +++ b/Templates/AssetGem/template.json @@ -1,10 +1,17 @@ { "template_name": "AssetGem", - "origin": "The primary repo for AssetGem goes here: i.e. http://www.mydomain.com", - "license": "What license AssetGem uses goes here: i.e. https://opensource.org/licenses/MIT", - "display_name": "AssetGem", - "summary": "A short description of AssetGem template.", - "canonical_tags": [], + "template_restricted_platform_relative_path": "Templates/AssetGem", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "display_name": "Asset Gem Template", + "summary": "Use this gem template to create the minimal gem needed for adding asset(s).", + "canonical_tags": [ + "Template", + "Gem", + "Asset" + ], "user_tags": [ "AssetGem" ], @@ -12,27 +19,20 @@ "copyFiles": [ { "file": "CMakeLists.txt", - "origin": "CMakeLists.txt", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "gem.json", - "origin": "gem.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "preview.png", - "origin": "preview.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false } ], "createDirectories": [ { - "dir": "Assets", - "origin": "Assets" + "dir": "Assets" } ] } diff --git a/Templates/CppToolGem/Template/gem.json b/Templates/CppToolGem/Template/gem.json index 079b7152ff..05be122226 100644 --- a/Templates/CppToolGem/Template/gem.json +++ b/Templates/CppToolGem/Template/gem.json @@ -1,11 +1,12 @@ { "gem_name": "${Name}", "display_name": "${Name}", - "license": "What license ${Name} uses goes here: i.e. Apache-2.0 Or MIT", - "license_url": "", - "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "license": "What license ${Name} uses goes here: i.e. Apache-2.0 or MIT", + "license_url": "Link to the license web site goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT", + "origin": "The name of the originator goes here. i.e. XYZ Inc.", + "origin_url": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", "type": "Code", - "summary": "A short description of ${Name}.", + "summary": "A short description of ${Name} goes here.", "canonical_tags": [ "Gem" ], @@ -13,6 +14,8 @@ "${Name}" ], "icon_path": "preview.png", - "requirements": "", - "restricted_name": "gems" + "requirements": "Notice of any requirements ${Name} has goes here. i.e. This requires X other gem", + "documentation_url": "Link to any documentation of ${Name} goes here: i.e. https://o3de.org/docs/user-guide/gems/reference/design/white-box/", + "dependencies": [ + ] } diff --git a/Templates/CppToolGem/template.json b/Templates/CppToolGem/template.json index b516dbaec3..16874326ef 100644 --- a/Templates/CppToolGem/template.json +++ b/Templates/CppToolGem/template.json @@ -1,10 +1,16 @@ { "template_name": "CppToolGem", - "origin": "The primary repo for CppToolGem goes here: i.e. http://www.mydomain.com", - "license": "What license CppToolGem uses goes here: i.e. https://opensource.org/licenses/MIT", + "template_restricted_platform_relative_path": "Templates/CppToolGem", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "display_name": "CppToolGem", "summary": "A gem template for a custom tool in C++ that gets registered with the Editor.", - "canonical_tags": [], + "canonical_tags": [ + "Template", + "Gem" + ], "user_tags": [ "CppToolGem" ], @@ -12,371 +18,255 @@ "copyFiles": [ { "file": "CMakeLists.txt", - "origin": "CMakeLists.txt", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Code/${NameLower}_editor_files.cmake", - "origin": "Code/${NameLower}_editor_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_shared_files.cmake", - "origin": "Code/${NameLower}_editor_shared_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_tests_files.cmake", - "origin": "Code/${NameLower}_editor_tests_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_files.cmake", - "origin": "Code/${NameLower}_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_shared_files.cmake", - "origin": "Code/${NameLower}_shared_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_tests_files.cmake", - "origin": "Code/${NameLower}_tests_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/CMakeLists.txt", - "origin": "Code/CMakeLists.txt", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Include/${Name}/${Name}Bus.h", - "origin": "Code/Include/${Name}/${Name}Bus.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Android/${NameLower}_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_android_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Android/PAL_android.cmake", - "origin": "Code/Platform/Android/PAL_android.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/PAL_linux.cmake", - "origin": "Code/Platform/Linux/PAL_linux.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/PAL_mac.cmake", - "origin": "Code/Platform/Mac/PAL_mac.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/PAL_windows.cmake", - "origin": "Code/Platform/Windows/PAL_windows.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/iOS/PAL_ios.cmake", - "origin": "Code/Platform/iOS/PAL_ios.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}.qrc", - "origin": "Code/Source/${Name}.qrc", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorModule.cpp", - "origin": "Code/Source/${Name}EditorModule.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorSystemComponent.cpp", - "origin": "Code/Source/${Name}EditorSystemComponent.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorSystemComponent.h", - "origin": "Code/Source/${Name}EditorSystemComponent.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}Module.cpp", - "origin": "Code/Source/${Name}Module.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}ModuleInterface.h", - "origin": "Code/Source/${Name}ModuleInterface.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}SystemComponent.cpp", - "origin": "Code/Source/${Name}SystemComponent.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}SystemComponent.h", - "origin": "Code/Source/${Name}SystemComponent.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}Widget.cpp", - "origin": "Code/Source/${Name}Widget.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}Widget.h", - "origin": "Code/Source/${Name}Widget.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/toolbar_icon.svg", - "origin": "Code/Source/toolbar_icon.svg", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Code/Tests/${Name}EditorTest.cpp", - "origin": "Code/Tests/${Name}EditorTest.cpp", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Code/Tests/${Name}Test.cpp", - "origin": "Code/Tests/${Name}Test.cpp", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Android/android_gem.cmake", - "origin": "Platform/Android/android_gem.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Android/android_gem.json", - "origin": "Platform/Android/android_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Linux/linux_gem.cmake", - "origin": "Platform/Linux/linux_gem.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Linux/linux_gem.json", - "origin": "Platform/Linux/linux_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Mac/mac_gem.cmake", - "origin": "Platform/Mac/mac_gem.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Mac/mac_gem.json", - "origin": "Platform/Mac/mac_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Windows/windows_gem.cmake", - "origin": "Platform/Windows/windows_gem.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Windows/windows_gem.json", - "origin": "Platform/Windows/windows_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/iOS/ios_gem.cmake", - "origin": "Platform/iOS/ios_gem.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/iOS/ios_gem.json", - "origin": "Platform/iOS/ios_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "gem.json", - "origin": "gem.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "preview.png", - "origin": "preview.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false } ], "createDirectories": [ { - "dir": "Assets", - "origin": "Assets" + "dir": "Assets" }, { - "dir": "Code", - "origin": "Code" + "dir": "Code" }, { - "dir": "Code/Include", - "origin": "Code/Include" + "dir": "Code/Include" }, { - "dir": "Code/Include/${Name}", - "origin": "Code/Include/${Name}" + "dir": "Code/Include/${Name}" }, { - "dir": "Code/Platform", - "origin": "Code/Platform" + "dir": "Code/Platform" }, { - "dir": "Code/Platform/Android", - "origin": "Code/Platform/Android" + "dir": "Code/Platform/Android" }, { - "dir": "Code/Platform/Linux", - "origin": "Code/Platform/Linux" + "dir": "Code/Platform/Linux" }, { - "dir": "Code/Platform/Mac", - "origin": "Code/Platform/Mac" + "dir": "Code/Platform/Mac" }, { - "dir": "Code/Platform/Windows", - "origin": "Code/Platform/Windows" + "dir": "Code/Platform/Windows" }, { - "dir": "Code/Platform/iOS", - "origin": "Code/Platform/iOS" + "dir": "Code/Platform/iOS" }, { - "dir": "Code/Source", - "origin": "Code/Source" + "dir": "Code/Source" }, { - "dir": "Code/Tests", - "origin": "Code/Tests" + "dir": "Code/Tests" }, { - "dir": "Platform", - "origin": "Platform" + "dir": "Platform" }, { - "dir": "Platform/Android", - "origin": "Platform/Android" + "dir": "Platform/Android" }, { - "dir": "Platform/Linux", - "origin": "Platform/Linux" + "dir": "Platform/Linux" }, { - "dir": "Platform/Mac", - "origin": "Platform/Mac" + "dir": "Platform/Mac" }, { - "dir": "Platform/Windows", - "origin": "Platform/Windows" + "dir": "Platform/Windows" }, { - "dir": "Platform/iOS", - "origin": "Platform/iOS" + "dir": "Platform/iOS" } ] } diff --git a/Templates/DefaultGem/Template/CMakeLists.txt b/Templates/DefaultGem/Template/CMakeLists.txt index b19ea2edce..f4c55dd1a5 100644 --- a/Templates/DefaultGem/Template/CMakeLists.txt +++ b/Templates/DefaultGem/Template/CMakeLists.txt @@ -6,12 +6,11 @@ # # {END_LICENSE} -set(o3de_gem_path ${CMAKE_CURRENT_LIST_DIR}) -set(o3de_gem_json ${o3de_gem_path}/gem.json) -o3de_read_json_key(o3de_gem_name ${o3de_gem_json} "gem_name") -o3de_restricted_path(${o3de_gem_json} o3de_gem_restricted_path) +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} "${o3de_gem_restricted_path}" ${o3de_gem_path} ${o3de_gem_name}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) # Now that we have the platform abstraction layer (PAL) folder for this folder, thats where we will find the # project cmake for this platform. diff --git a/Templates/DefaultGem/Template/Code/CMakeLists.txt b/Templates/DefaultGem/Template/Code/CMakeLists.txt index f462e7f2d4..c5ff305b2a 100644 --- a/Templates/DefaultGem/Template/Code/CMakeLists.txt +++ b/Templates/DefaultGem/Template/Code/CMakeLists.txt @@ -8,11 +8,11 @@ # Currently we are in the Code folder: ${CMAKE_CURRENT_LIST_DIR} # Get the platform specific folder ${pal_dir} for the current folder: ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} -# Note: ly_get_list_relative_pal_filename will take care of the details for us, as this may be a restricted platform +# Note: o3de_pal_dir will take care of the details for us, as this may be a restricted platform # in which case it will see if that platform is present here or in the restricted folder. # i.e. It could here in our gem : Gems/${Name}/Code/Platform/ or # //Gems/${Name}/Code -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${o3de_gem_restricted_path} ${o3de_gem_path} ${o3de_gem_name}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${o3de_gem_restricted_path} ${o3de_gem_path} ${o3de_gem_name}) # Now that we have the platform abstraction layer (PAL) folder for this folder, thats where we will find the # traits for this platform. Traits for a platform are defines for things like whether or not something in this gem diff --git a/Templates/DefaultGem/Template/gem.json b/Templates/DefaultGem/Template/gem.json index d4ff637bee..05be122226 100644 --- a/Templates/DefaultGem/Template/gem.json +++ b/Templates/DefaultGem/Template/gem.json @@ -1,11 +1,12 @@ { "gem_name": "${Name}", "display_name": "${Name}", - "license": "What license ${Name} uses goes here: i.e. Apache-2.0 Or MIT", - "license_url": "", - "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "license": "What license ${Name} uses goes here: i.e. Apache-2.0 or MIT", + "license_url": "Link to the license web site goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT", + "origin": "The name of the originator goes here. i.e. XYZ Inc.", + "origin_url": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", "type": "Code", - "summary": "A short description of ${Name}.", + "summary": "A short description of ${Name} goes here.", "canonical_tags": [ "Gem" ], @@ -13,5 +14,8 @@ "${Name}" ], "icon_path": "preview.png", - "requirements": "" + "requirements": "Notice of any requirements ${Name} has goes here. i.e. This requires X other gem", + "documentation_url": "Link to any documentation of ${Name} goes here: i.e. https://o3de.org/docs/user-guide/gems/reference/design/white-box/", + "dependencies": [ + ] } diff --git a/Templates/DefaultGem/template.json b/Templates/DefaultGem/template.json index e24632d6a0..e5dc570cbe 100644 --- a/Templates/DefaultGem/template.json +++ b/Templates/DefaultGem/template.json @@ -1,12 +1,16 @@ { "template_name": "DefaultGem", + "template_restricted_platform_relative_path": "Templates/DefaultGem", "restricted_name": "o3de", - "restricted_platform_relative_path": "Templates", - "origin": "The primary repo for DefaultGem goes here: i.e. http://www.mydomain.com", - "license": "What license DefaultGem uses goes here: i.e. https://opensource.org/licenses/MIT", - "display_name": "DefaultGem", - "summary": "A short description of DefaultGem.", - "canonical_tags": [], + "restricted_platform_relative_path": "Templates/DefaultGem", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "display_name": "Default Gem Template", + "summary": "This is the gem template that will be used if no gem template is specified during gem creation.", + "canonical_tags": [ + "Template", + "Gem" + ], "user_tags": [ "DefaultGem" ], @@ -14,347 +18,239 @@ "copyFiles": [ { "file": "CMakeLists.txt", - "origin": "CMakeLists.txt", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_files.cmake", - "origin": "Code/${NameLower}_editor_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_shared_files.cmake", - "origin": "Code/${NameLower}_editor_shared_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_tests_files.cmake", - "origin": "Code/${NameLower}_editor_tests_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_files.cmake", - "origin": "Code/${NameLower}_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_shared_files.cmake", - "origin": "Code/${NameLower}_shared_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_tests_files.cmake", - "origin": "Code/${NameLower}_tests_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/CMakeLists.txt", - "origin": "Code/CMakeLists.txt", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Include/${Name}/${Name}Bus.h", - "origin": "Code/Include/${Name}/${Name}Bus.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Android/${NameLower}_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_android_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Android/PAL_android.cmake", - "origin": "Code/Platform/Android/PAL_android.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/PAL_linux.cmake", - "origin": "Code/Platform/Linux/PAL_linux.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/PAL_mac.cmake", - "origin": "Code/Platform/Mac/PAL_mac.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/PAL_windows.cmake", - "origin": "Code/Platform/Windows/PAL_windows.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/iOS/PAL_ios.cmake", - "origin": "Code/Platform/iOS/PAL_ios.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorModule.cpp", - "origin": "Code/Source/${Name}EditorModule.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorSystemComponent.cpp", - "origin": "Code/Source/${Name}EditorSystemComponent.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorSystemComponent.h", - "origin": "Code/Source/${Name}EditorSystemComponent.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}Module.cpp", - "origin": "Code/Source/${Name}Module.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}ModuleInterface.h", - "origin": "Code/Source/${Name}ModuleInterface.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}SystemComponent.cpp", - "origin": "Code/Source/${Name}SystemComponent.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}SystemComponent.h", - "origin": "Code/Source/${Name}SystemComponent.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Tests/${Name}EditorTest.cpp", - "origin": "Code/Tests/${Name}EditorTest.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Tests/${Name}Test.cpp", - "origin": "Code/Tests/${Name}Test.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Android/android_gem.cmake", - "origin": "Platform/Android/android_gem.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Android/android_gem.json", - "origin": "Platform/Android/android_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Linux/linux_gem.cmake", - "origin": "Platform/Linux/linux_gem.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Linux/linux_gem.json", - "origin": "Platform/Linux/linux_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Mac/mac_gem.cmake", - "origin": "Platform/Mac/mac_gem.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Mac/mac_gem.json", - "origin": "Platform/Mac/mac_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Windows/windows_gem.cmake", - "origin": "Platform/Windows/windows_gem.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Windows/windows_gem.json", - "origin": "Platform/Windows/windows_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/iOS/ios_gem.cmake", - "origin": "Platform/iOS/ios_gem.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/iOS/ios_gem.json", - "origin": "Platform/iOS/ios_gem.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "gem.json", - "origin": "gem.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "preview.png", - "origin": "preview.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false } ], "createDirectories": [ { - "dir": "Assets", - "origin": "Assets" + "dir": "Assets" }, { - "dir": "Code", - "origin": "Code" + "dir": "Code" }, { - "dir": "Code/Include", - "origin": "Code/Include" + "dir": "Code/Include" }, { - "dir": "Code/Include/${Name}", - "origin": "Code/Include/${Name}" + "dir": "Code/Include/${Name}" }, { - "dir": "Code/Platform", - "origin": "Code/Platform" + "dir": "Code/Platform" }, { - "dir": "Code/Platform/Android", - "origin": "Code/Platform/Android" + "dir": "Code/Platform/Android" }, { - "dir": "Code/Platform/Linux", - "origin": "Code/Platform/Linux" + "dir": "Code/Platform/Linux" }, { - "dir": "Code/Platform/Mac", - "origin": "Code/Platform/Mac" + "dir": "Code/Platform/Mac" }, { - "dir": "Code/Platform/Windows", - "origin": "Code/Platform/Windows" + "dir": "Code/Platform/Windows" }, { - "dir": "Code/Platform/iOS", - "origin": "Code/Platform/iOS" + "dir": "Code/Platform/iOS" }, { - "dir": "Code/Source", - "origin": "Code/Source" + "dir": "Code/Source" }, { - "dir": "Code/Tests", - "origin": "Code/Tests" + "dir": "Code/Tests" }, { - "dir": "Platform", - "origin": "Platform" + "dir": "Platform" }, { - "dir": "Platform/Android", - "origin": "Platform/Android" + "dir": "Platform/Android" }, { - "dir": "Platform/Linux", - "origin": "Platform/Linux" + "dir": "Platform/Linux" }, { - "dir": "Platform/Mac", - "origin": "Platform/Mac" + "dir": "Platform/Mac" }, { - "dir": "Platform/Windows", - "origin": "Platform/Windows" + "dir": "Platform/Windows" }, { - "dir": "Platform/iOS", - "origin": "Platform/iOS" + "dir": "Platform/iOS" } ] } diff --git a/Templates/DefaultProject/Template/CMakeLists.txt b/Templates/DefaultProject/Template/CMakeLists.txt index ae4bb662a3..420a92948d 100644 --- a/Templates/DefaultProject/Template/CMakeLists.txt +++ b/Templates/DefaultProject/Template/CMakeLists.txt @@ -29,5 +29,4 @@ else() set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name}) - add_subdirectory(Code) endif() diff --git a/Templates/DefaultProject/Template/Code/${NameLower}_files.cmake b/Templates/DefaultProject/Template/Gem/${NameLower}_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/${NameLower}_files.cmake rename to Templates/DefaultProject/Template/Gem/${NameLower}_files.cmake diff --git a/Templates/DefaultProject/Template/Code/${NameLower}_shared_files.cmake b/Templates/DefaultProject/Template/Gem/${NameLower}_shared_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/${NameLower}_shared_files.cmake rename to Templates/DefaultProject/Template/Gem/${NameLower}_shared_files.cmake diff --git a/Templates/MinimalProject/Template/Code/CMakeLists.txt b/Templates/DefaultProject/Template/Gem/CMakeLists.txt similarity index 87% rename from Templates/MinimalProject/Template/Code/CMakeLists.txt rename to Templates/DefaultProject/Template/Gem/CMakeLists.txt index 5e646c0704..fc3eab6535 100644 --- a/Templates/MinimalProject/Template/Code/CMakeLists.txt +++ b/Templates/DefaultProject/Template/Gem/CMakeLists.txt @@ -6,13 +6,17 @@ # # {END_LICENSE} +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + # Currently we are in the ${Name}/Code folder: ${CMAKE_CURRENT_LIST_DIR} # Get the platform specific folder ${pal_dir} for the current folder: ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} -# Note: ly_get_list_relative_pal_filename will take care of the details for us, as this may be a restricted platform +# Note: o3de_pal_dir will take care of the details for us, as this may be a restricted platform # in which case it will see if that platform is present here or in the restricted folder. -# i.e. It could here : ${Name}/Code/Platform/ or +# i.e. It could here : ${Name}/Code/Platform/ or # //${Name}/Code -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${o3de_project_restricted_path} ${o3de_project_path} ${o3de_project_name}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) # Now that we have the platform abstraction layer (PAL) folder for this folder, thats where we will find the # traits for this platform. Traits for a platform are defines for things like whether or not something in this project @@ -71,7 +75,6 @@ ly_create_alias(NAME ${Name}.Servers NAMESPACE Gem TARGETS Gem::${Name}) # Enable the specified list of gems from GEM_FILE or GEMS list for this specific project: ly_enable_gems(PROJECT_NAME ${Name} GEM_FILE enabled_gems.cmake) - if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) # this property causes it to actually make a ServerLauncher. # if you don't want a Server application, you can remove this and the diff --git a/Templates/DefaultProject/Template/Code/Include/${Name}/${Name}Bus.h b/Templates/DefaultProject/Template/Gem/Include/${Name}/${Name}Bus.h similarity index 99% rename from Templates/DefaultProject/Template/Code/Include/${Name}/${Name}Bus.h rename to Templates/DefaultProject/Template/Gem/Include/${Name}/${Name}Bus.h index d09bb2b009..d72b5785c3 100644 --- a/Templates/DefaultProject/Template/Code/Include/${Name}/${Name}Bus.h +++ b/Templates/DefaultProject/Template/Gem/Include/${Name}/${Name}Bus.h @@ -22,7 +22,7 @@ namespace ${SanitizedCppName} virtual ~${SanitizedCppName}Requests() = default; // Put your public methods here }; - + class ${SanitizedCppName}BusTraits : public AZ::EBusTraits { diff --git a/Templates/DefaultProject/Template/Code/Platform/Android/${NameLower}_android_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Android/${NameLower}_android_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Android/${NameLower}_android_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Android/${NameLower}_android_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Android/${NameLower}_shared_android_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Android/${NameLower}_shared_android_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Android/${NameLower}_shared_android_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Android/${NameLower}_shared_android_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Android/PAL_android.cmake b/Templates/DefaultProject/Template/Gem/Platform/Android/PAL_android.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Android/PAL_android.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Android/PAL_android.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Linux/${NameLower}_linux_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Linux/${NameLower}_linux_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Linux/${NameLower}_linux_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Linux/${NameLower}_linux_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Linux/${NameLower}_shared_linux_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Linux/${NameLower}_shared_linux_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Linux/${NameLower}_shared_linux_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Linux/${NameLower}_shared_linux_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Linux/PAL_linux.cmake b/Templates/DefaultProject/Template/Gem/Platform/Linux/PAL_linux.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Linux/PAL_linux.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Linux/PAL_linux.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Mac/${NameLower}_mac_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Mac/${NameLower}_mac_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Mac/${NameLower}_mac_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Mac/${NameLower}_mac_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Mac/${NameLower}_shared_mac_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Mac/${NameLower}_shared_mac_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Mac/${NameLower}_shared_mac_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Mac/${NameLower}_shared_mac_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Mac/PAL_mac.cmake b/Templates/DefaultProject/Template/Gem/Platform/Mac/PAL_mac.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Mac/PAL_mac.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Mac/PAL_mac.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Windows/${NameLower}_shared_windows_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Windows/${NameLower}_shared_windows_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Windows/${NameLower}_shared_windows_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Windows/${NameLower}_shared_windows_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Windows/${NameLower}_windows_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/Windows/${NameLower}_windows_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Windows/${NameLower}_windows_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Windows/${NameLower}_windows_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/Windows/PAL_windows.cmake b/Templates/DefaultProject/Template/Gem/Platform/Windows/PAL_windows.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/Windows/PAL_windows.cmake rename to Templates/DefaultProject/Template/Gem/Platform/Windows/PAL_windows.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/iOS/${NameLower}_ios_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/iOS/${NameLower}_ios_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/iOS/${NameLower}_ios_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/iOS/${NameLower}_ios_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/iOS/${NameLower}_shared_ios_files.cmake b/Templates/DefaultProject/Template/Gem/Platform/iOS/${NameLower}_shared_ios_files.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/iOS/${NameLower}_shared_ios_files.cmake rename to Templates/DefaultProject/Template/Gem/Platform/iOS/${NameLower}_shared_ios_files.cmake diff --git a/Templates/DefaultProject/Template/Code/Platform/iOS/PAL_ios.cmake b/Templates/DefaultProject/Template/Gem/Platform/iOS/PAL_ios.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/Platform/iOS/PAL_ios.cmake rename to Templates/DefaultProject/Template/Gem/Platform/iOS/PAL_ios.cmake diff --git a/Templates/DefaultProject/Template/Code/Source/${Name}Module.cpp b/Templates/DefaultProject/Template/Gem/Source/${Name}Module.cpp similarity index 100% rename from Templates/DefaultProject/Template/Code/Source/${Name}Module.cpp rename to Templates/DefaultProject/Template/Gem/Source/${Name}Module.cpp diff --git a/Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.cpp b/Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.cpp similarity index 99% rename from Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.cpp rename to Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.cpp index cfb6ae3c42..487391c716 100644 --- a/Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.cpp +++ b/Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.cpp @@ -52,7 +52,7 @@ namespace ${SanitizedCppName} void ${SanitizedCppName}SystemComponent::GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent) { } - + ${SanitizedCppName}SystemComponent::${SanitizedCppName}SystemComponent() { if (${SanitizedCppName}Interface::Get() == nullptr) diff --git a/Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.h b/Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.h similarity index 100% rename from Templates/DefaultProject/Template/Code/Source/${Name}SystemComponent.h rename to Templates/DefaultProject/Template/Gem/Source/${Name}SystemComponent.h diff --git a/Templates/DefaultProject/Template/Code/enabled_gems.cmake b/Templates/DefaultProject/Template/Gem/enabled_gems.cmake similarity index 100% rename from Templates/DefaultProject/Template/Code/enabled_gems.cmake rename to Templates/DefaultProject/Template/Gem/enabled_gems.cmake diff --git a/Templates/DefaultProject/Template/Gem/gem.json b/Templates/DefaultProject/Template/Gem/gem.json new file mode 100644 index 0000000000..b60f512006 --- /dev/null +++ b/Templates/DefaultProject/Template/Gem/gem.json @@ -0,0 +1,21 @@ +{ + "gem_name": "${Name}", + "display_name": "${Name}", + "license": "What license ${Name} uses goes here: i.e. Apache-2.0 or MIT", + "license_url": "Link to the license web site goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT", + "origin": "The name of the originator goes here. i.e. XYZ Inc.", + "origin_url": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "type": "", + "summary": "A short description of ${Name}.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "${Name}" + ], + "icon_path": "preview.png", + "requirements": "", + "documentation_url": "", + "dependencies": [ + ] +} diff --git a/Templates/DefaultProject/Template/project.json b/Templates/DefaultProject/Template/project.json index f8d4643ce9..6d1875fcaa 100644 --- a/Templates/DefaultProject/Template/project.json +++ b/Templates/DefaultProject/Template/project.json @@ -2,7 +2,7 @@ "project_name": "${Name}", "project_id": "${ProjectId}", "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", - "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT", + "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT etc.", "display_name": "${Name}", "summary": "A short description of ${Name}.", "canonical_tags": [ @@ -13,5 +13,8 @@ ], "icon_path": "preview.png", "engine": "o3de", - "external_subdirectories": [] + "external_subdirectories": [ + "Gem" + ], + "restricted": "${Name}" } diff --git a/Templates/DefaultProject/template.json b/Templates/DefaultProject/template.json index fcffafcb34..203e1ec4ef 100644 --- a/Templates/DefaultProject/template.json +++ b/Templates/DefaultProject/template.json @@ -1,12 +1,18 @@ { "template_name": "DefaultProject", + "template_restricted_platform_relative_path": "Templates/DefaultProject", "restricted_name": "o3de", - "restricted_platform_relative_path": "Templates", - "origin": "The primary repo for DefaultProject goes here: i.e. http://www.mydomain.com", - "license": "What license DefaultProject uses goes here: i.e. https://opensource.org/licenses/MIT", - "display_name": "Standard", - "summary": "This template has everything you need to build a full online 3D game or application.", - "canonical_tags": [], + "restricted_platform_relative_path": "Templates/DefaultProject", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "display_name": "Default Project Template", + "summary": "This is the project template that will be used if no project template is specified during project creation.", + "canonical_tags": [ + "Template", + "Project" + ], "user_tags": [ "DefaultProject" ], @@ -14,657 +20,459 @@ "copyFiles": [ { "file": ".gitignore", - "origin": ".gitignore", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "CMakeLists.txt", - "origin": "CMakeLists.txt", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/${NameLower}_files.cmake", - "origin": "Code/${NameLower}_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/${NameLower}_shared_files.cmake", - "origin": "Code/${NameLower}_shared_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/CMakeLists.txt", - "origin": "Code/CMakeLists.txt", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Include/${Name}/${Name}Bus.h", - "origin": "Code/Include/${Name}/${Name}Bus.h", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Android/${NameLower}_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_android_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Android/PAL_android.cmake", - "origin": "Code/Platform/Android/PAL_android.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Linux/PAL_linux.cmake", - "origin": "Code/Platform/Linux/PAL_linux.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Mac/PAL_mac.cmake", - "origin": "Code/Platform/Mac/PAL_mac.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Windows/PAL_windows.cmake", - "origin": "Code/Platform/Windows/PAL_windows.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/iOS/PAL_ios.cmake", - "origin": "Code/Platform/iOS/PAL_ios.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Source/${Name}Module.cpp", - "origin": "Code/Source/${Name}Module.cpp", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Source/${Name}SystemComponent.cpp", - "origin": "Code/Source/${Name}SystemComponent.cpp", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Source/${Name}SystemComponent.h", - "origin": "Code/Source/${Name}SystemComponent.h", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/enabled_gems.cmake", - "origin": "Code/enabled_gems.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/gem.json", - "origin": "Code/gem.json", - "isTemplated": true, - "isOptional": true - }, - { - "file": "Config/shader_global_build_options.json", - "origin": "Config/shader_global_build_options.json", - "isTemplated": false, - "isOptional": false - }, - { - "file": "Config/default_aws_resource_mappings.json", - "origin": "Config/default_aws_resource_mappings.json", - "isTemplated": false, - "isOptional": false + "isTemplated": true }, { "file": "cmake/EngineFinder.cmake", - "origin": "cmake/EngineFinder.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": true }, { "file": "cmake/CompilerSettings.cmake", - "origin": "cmake/CompilerSettings.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "cmake/Platform/Linux/CompilerSettings_linux.cmake", - "origin": "cmake/Platform/Linux/CompilerSettings_linux.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false + }, + { + "file": "Config/default_aws_resource_mappings.json", + "isTemplated": false + }, + { + "file": "Config/shader_global_build_options.json", + "isTemplated": false + }, + { + "file": "Gem/${NameLower}_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/${NameLower}_shared_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/CMakeLists.txt", + "isTemplated": true + }, + { + "file": "Gem/Include/${Name}/${Name}Bus.h", + "isTemplated": true + }, + { + "file": "Gem/Platform/Android/${NameLower}_android_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Android/${NameLower}_shared_android_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Android/PAL_android.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Linux/${NameLower}_linux_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Linux/${NameLower}_shared_linux_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Linux/PAL_linux.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Mac/${NameLower}_mac_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Mac/${NameLower}_shared_mac_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Mac/PAL_mac.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Windows/${NameLower}_shared_windows_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Windows/${NameLower}_windows_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/Windows/PAL_windows.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/iOS/${NameLower}_ios_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/iOS/${NameLower}_shared_ios_files.cmake", + "isTemplated": false + }, + { + "file": "Gem/Platform/iOS/PAL_ios.cmake", + "isTemplated": true + }, + { + "file": "Gem/Source/${Name}Module.cpp", + "isTemplated": true + }, + { + "file": "Gem/Source/${Name}SystemComponent.cpp", + "isTemplated": true + }, + { + "file": "Gem/Source/${Name}SystemComponent.h", + "isTemplated": true + }, + { + "file": "Gem/enabled_gems.cmake", + "isTemplated": true + }, + { + "file": "Gem/gem.json", + "isTemplated": true }, { "file": "Platform/Android/android_project.cmake", - "origin": "Platform/Android/android_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Android/android_project.json", - "origin": "Platform/Android/android_project.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Linux/linux_project.cmake", - "origin": "Platform/Linux/linux_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Linux/linux_project.json", - "origin": "Platform/Linux/linux_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Mac/mac_project.cmake", - "origin": "Platform/Mac/mac_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Mac/mac_project.json", - "origin": "Platform/Mac/mac_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Windows/windows_project.cmake", - "origin": "Platform/Windows/windows_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Windows/windows_project.json", - "origin": "Platform/Windows/windows_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/iOS/ios_project.cmake", - "origin": "Platform/iOS/ios_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": false }, { "file": "Platform/iOS/ios_project.json", - "origin": "Platform/iOS/ios_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Registry/assets_scan_folders.setreg", - "origin": "Registry/assets_scan_folders.setreg", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Registry/awscoreconfiguration.setreg", - "origin": "Registry/awscoreconfiguration.setreg", - "isTemplated": false, - "isOptional": false - }, - { - "file": "Resources/LegacyLogoLauncher.bmp", - "origin": "Resources/LegacyLogoLauncher.bmp", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/GameSDK.ico", - "origin": "Resources/GameSDK.ico", - "isTemplated": false, - "isOptional": false + "isTemplated": false + }, + { + "file": "Resources/LegacyLogoLauncher.bmp", + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/Contents.json", - "origin": "Resources/Platform/Mac/Images.xcassets/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "isTemplated": false, - "isOptional": false - }, - { - "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128_2x.png", + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png", - "isTemplated": false, - "isOptional": false - }, - { - "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false + }, + { + "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256_2x.png", + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Info.plist", - "origin": "Resources/Platform/Mac/Info.plist", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Resources/Platform/iOS/Images.xcassets/Contents.json", - "origin": "Resources/Platform/iOS/Images.xcassets/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Info.plist", - "origin": "Resources/Platform/iOS/Info.plist", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "ShaderLib/README.md", - "origin": "ShaderLib/README.md", - "isTemplated": false, - "isOptional": true + "isTemplated": false }, { "file": "ShaderLib/scenesrg.srgi", - "origin": "ShaderLib/scenesrg.srgi", - "isTemplated": true, - "isOptional": false + "isTemplated": false }, { "file": "ShaderLib/viewsrg.srgi", - "origin": "ShaderLib/viewsrg.srgi", - "isTemplated": true, - "isOptional": false + "isTemplated": false }, { "file": "autoexec.cfg", - "origin": "autoexec.cfg", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "game.cfg", - "origin": "game.cfg", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "preview.png", - "origin": "preview.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "project.json", - "origin": "project.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true } ], "createDirectories": [ { - "dir": "Assets", - "origin": "Assets" + "dir": "Assets" }, { - "dir": "Code", - "origin": "Code" + "dir": "cmake" }, { - "dir": "Code/Include", - "origin": "Code/Include" + "dir": "cmake/Platform" }, { - "dir": "Code/Include/${Name}", - "origin": "Code/Include/${Name}" + "dir": "cmake/Platform/Linux" }, { - "dir": "Code/Platform", - "origin": "Code/Platform" + "dir": "Config" }, { - "dir": "Code/Platform/Android", - "origin": "Code/Platform/Android" + "dir": "Gem" }, { - "dir": "Code/Platform/Linux", - "origin": "Code/Platform/Linux" + "dir": "Gem/Include" }, { - "dir": "Code/Platform/Mac", - "origin": "Code/Platform/Mac" + "dir": "Gem/Include/${Name}" }, { - "dir": "Code/Platform/Windows", - "origin": "Code/Platform/Windows" + "dir": "Gem/Platform" }, { - "dir": "Code/Platform/iOS", - "origin": "Code/Platform/iOS" + "dir": "Gem/Platform/Android" }, { - "dir": "Code/Source", - "origin": "Code/Source" + "dir": "Gem/Platform/Linux" }, { - "dir": "Config", - "origin": "Config" + "dir": "Gem/Platform/Mac" }, { - "dir": "Platform", - "origin": "Platform" + "dir": "Gem/Platform/Windows" }, { - "dir": "Platform/Android", - "origin": "Platform/Android" + "dir": "Gem/Platform/iOS" }, { - "dir": "Platform/Linux", - "origin": "Platform/Linux" + "dir": "Gem/Source" }, { - "dir": "Platform/Mac", - "origin": "Platform/Mac" + "dir": "Platform" }, { - "dir": "Platform/Windows", - "origin": "Platform/Windows" + "dir": "Platform/Android" }, { - "dir": "Platform/iOS", - "origin": "Platform/iOS" + "dir": "Platform/Linux" }, { - "dir": "Registry", - "origin": "Registry" + "dir": "Platform/Mac" }, { - "dir": "Resources", - "origin": "Resources" + "dir": "Platform/Windows" }, { - "dir": "Resources/Platform", - "origin": "Resources/Platform" + "dir": "Platform/iOS" }, { - "dir": "Resources/Platform/Mac", - "origin": "Resources/Platform/Mac" + "dir": "Registry" }, { - "dir": "Resources/Platform/Mac/Images.xcassets", - "origin": "Resources/Platform/Mac/Images.xcassets" + "dir": "Resources" }, { - "dir": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset" + "dir": "Resources/Platform" }, { - "dir": "Resources/Platform/iOS", - "origin": "Resources/Platform/iOS" + "dir": "Resources/Platform/Mac" }, { - "dir": "Resources/Platform/iOS/Images.xcassets", - "origin": "Resources/Platform/iOS/Images.xcassets" + "dir": "Resources/Platform/Mac/Images.xcassets" }, { - "dir": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage" + "dir": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset" }, { - "dir": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset" + "dir": "Resources/Platform/iOS" }, { - "dir": "ShaderLib", - "origin": "ShaderLib" + "dir": "Resources/Platform/iOS/Images.xcassets" }, { - "dir": "Shaders", - "origin": "Shaders" + "dir": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage" }, { - "dir": "Shaders/ShaderResourceGroups", - "origin": "Shaders/ShaderResourceGroups" + "dir": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset" + }, + { + "dir": "ShaderLib" + }, + { + "dir": "Shaders" + }, + { + "dir": "Shaders/ShaderResourceGroups" } ] } diff --git a/Templates/GemRepo/Template/gem.json b/Templates/GemRepo/Template/gem.json index 292681b2b5..7ba555a127 100644 --- a/Templates/GemRepo/Template/gem.json +++ b/Templates/GemRepo/Template/gem.json @@ -1,19 +1,23 @@ { - "gem_name": "${Name}Gem", - "display_name": "${Name}Gem", - "license": "What license ${Name}Gem uses goes here: i.e. Apache-2.0 Or MIT", - "license_url": "", - "origin": "The primary repo for ${Name}Gem goes here: i.e. http://www.mydomain.com", - "summary": "A short description of ${Name}Gem which is zipped up in an archive named gem.zip in the root of the Gem Repo. Though not required, it is recommended that the sha256 of the gem.zip file should be placed in the sha256 field of this gem.json so the download can be verified.", + "gem_name": "${Name}", + "display_name": "${Name}", + "license": "What license ${Name} uses goes here: i.e. Apache-2.0 or MIT", + "license_url": "Link to the license web site goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT", + "origin": "The name of the originator goes here. i.e. XYZ Inc.", + "origin_url": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "type": "Code", + "summary": "A short description of ${Name} which is zipped up in an archive named gem.zip in the root of the Gem Repo. Though not required, it is recommended that the sha256 of the gem.zip file be placed in the sha256 field of this gem.json so the download can be verified.", "origin_uri": "${RepoURI}/gem.zip", "sha256": "", - "type": "Code", "canonical_tags": [ "Gem" ], "user_tags": [ - "${Name}Gem" + "${Name}" ], "icon_path": "preview.png", - "requirements": "" + "requirements": "", + "documentation_url": "", + "dependencies": [ + ] } diff --git a/Templates/GemRepo/template.json b/Templates/GemRepo/template.json index 88123a9dae..ca042329be 100644 --- a/Templates/GemRepo/template.json +++ b/Templates/GemRepo/template.json @@ -1,10 +1,14 @@ { "template_name": "GemRepo", - "origin": "The primary repo for GemRepo goes here: i.e. http://www.mydomain.com", - "license": "What license GemRepo uses goes here: i.e. https://opensource.org/licenses/MIT", + "origin_url": "https://github.com/o3de/o3de", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "display_name": "GemRepo", "summary": "A Gem Repository that contains a single Gem.", - "canonical_tags": [], + "canonical_tags": [ + "Gem", + "Repo" + ], "user_tags": [ "GemRepo" ], @@ -12,15 +16,11 @@ "copyFiles": [ { "file": "gem.json", - "origin": "gem.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "repo.json", - "origin": "repo.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true } ], "createDirectories": [] diff --git a/Templates/MinimalProject/Template/CMakeLists.txt b/Templates/MinimalProject/Template/CMakeLists.txt index ae4bb662a3..420a92948d 100644 --- a/Templates/MinimalProject/Template/CMakeLists.txt +++ b/Templates/MinimalProject/Template/CMakeLists.txt @@ -29,5 +29,4 @@ else() set_property(GLOBAL APPEND PROPERTY LY_PROJECTS_TARGET_NAME ${project_target_name}) - add_subdirectory(Code) endif() diff --git a/Templates/MinimalProject/Template/Code/${NameLower}_files.cmake b/Templates/MinimalProject/Template/Gem/${NameLower}_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/${NameLower}_files.cmake rename to Templates/MinimalProject/Template/Gem/${NameLower}_files.cmake diff --git a/Templates/MinimalProject/Template/Code/${NameLower}_shared_files.cmake b/Templates/MinimalProject/Template/Gem/${NameLower}_shared_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/${NameLower}_shared_files.cmake rename to Templates/MinimalProject/Template/Gem/${NameLower}_shared_files.cmake diff --git a/Templates/DefaultProject/Template/Code/CMakeLists.txt b/Templates/MinimalProject/Template/Gem/CMakeLists.txt similarity index 87% rename from Templates/DefaultProject/Template/Code/CMakeLists.txt rename to Templates/MinimalProject/Template/Gem/CMakeLists.txt index 7bbb9a0852..6b1dcf9172 100644 --- a/Templates/DefaultProject/Template/Code/CMakeLists.txt +++ b/Templates/MinimalProject/Template/Gem/CMakeLists.txt @@ -6,13 +6,17 @@ # # {END_LICENSE} +set(gem_path ${CMAKE_CURRENT_LIST_DIR}) +set(gem_json ${gem_path}/gem.json) +o3de_restricted_path(${gem_json} gem_restricted_path gem_parent_relative_path) + # Currently we are in the ${Name}/Code folder: ${CMAKE_CURRENT_LIST_DIR} # Get the platform specific folder ${pal_dir} for the current folder: ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} -# Note: ly_get_list_relative_pal_filename will take care of the details for us, as this may be a restricted platform +# Note: o3de_pal_dir will take care of the details for us, as this may be a restricted platform # in which case it will see if that platform is present here or in the restricted folder. -# i.e. It could here : ${Name}/Code/Platform/ or +# i.e. It could here : ${Name}/Code/Platform/ or # //${Name}/Code -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${o3de_project_restricted_path} ${o3de_project_path} ${o3de_project_name}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${gem_restricted_path} ${gem_path} ${gem_parent_relative_path}) # Now that we have the platform abstraction layer (PAL) folder for this folder, thats where we will find the # traits for this platform. Traits for a platform are defines for things like whether or not something in this project @@ -71,6 +75,7 @@ ly_create_alias(NAME ${Name}.Servers NAMESPACE Gem TARGETS Gem::${Name}) # Enable the specified list of gems from GEM_FILE or GEMS list for this specific project: ly_enable_gems(PROJECT_NAME ${Name} GEM_FILE enabled_gems.cmake) + if(PAL_TRAIT_BUILD_SERVER_SUPPORTED) # this property causes it to actually make a ServerLauncher. # if you don't want a Server application, you can remove this and the diff --git a/Templates/MinimalProject/Template/Code/Include/${Name}/${Name}Bus.h b/Templates/MinimalProject/Template/Gem/Include/${Name}/${Name}Bus.h similarity index 100% rename from Templates/MinimalProject/Template/Code/Include/${Name}/${Name}Bus.h rename to Templates/MinimalProject/Template/Gem/Include/${Name}/${Name}Bus.h diff --git a/Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_android_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Android/${NameLower}_android_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_android_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Android/${NameLower}_android_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_shared_android_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Android/${NameLower}_shared_android_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Android/${NameLower}_shared_android_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Android/${NameLower}_shared_android_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Android/PAL_android.cmake b/Templates/MinimalProject/Template/Gem/Platform/Android/PAL_android.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Android/PAL_android.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Android/PAL_android.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_linux_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Linux/${NameLower}_linux_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_linux_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Linux/${NameLower}_linux_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_shared_linux_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Linux/${NameLower}_shared_linux_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Linux/${NameLower}_shared_linux_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Linux/${NameLower}_shared_linux_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Linux/PAL_linux.cmake b/Templates/MinimalProject/Template/Gem/Platform/Linux/PAL_linux.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Linux/PAL_linux.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Linux/PAL_linux.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_mac_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Mac/${NameLower}_mac_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_mac_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Mac/${NameLower}_mac_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_shared_mac_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Mac/${NameLower}_shared_mac_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Mac/${NameLower}_shared_mac_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Mac/${NameLower}_shared_mac_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Mac/PAL_mac.cmake b/Templates/MinimalProject/Template/Gem/Platform/Mac/PAL_mac.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Mac/PAL_mac.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Mac/PAL_mac.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_shared_windows_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Windows/${NameLower}_shared_windows_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_shared_windows_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Windows/${NameLower}_shared_windows_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_windows_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/Windows/${NameLower}_windows_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Windows/${NameLower}_windows_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Windows/${NameLower}_windows_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/Windows/PAL_windows.cmake b/Templates/MinimalProject/Template/Gem/Platform/Windows/PAL_windows.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/Windows/PAL_windows.cmake rename to Templates/MinimalProject/Template/Gem/Platform/Windows/PAL_windows.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_ios_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/iOS/${NameLower}_ios_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_ios_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/iOS/${NameLower}_ios_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_shared_ios_files.cmake b/Templates/MinimalProject/Template/Gem/Platform/iOS/${NameLower}_shared_ios_files.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/iOS/${NameLower}_shared_ios_files.cmake rename to Templates/MinimalProject/Template/Gem/Platform/iOS/${NameLower}_shared_ios_files.cmake diff --git a/Templates/MinimalProject/Template/Code/Platform/iOS/PAL_ios.cmake b/Templates/MinimalProject/Template/Gem/Platform/iOS/PAL_ios.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/Platform/iOS/PAL_ios.cmake rename to Templates/MinimalProject/Template/Gem/Platform/iOS/PAL_ios.cmake diff --git a/Templates/MinimalProject/Template/Code/Source/${Name}Module.cpp b/Templates/MinimalProject/Template/Gem/Source/${Name}Module.cpp similarity index 100% rename from Templates/MinimalProject/Template/Code/Source/${Name}Module.cpp rename to Templates/MinimalProject/Template/Gem/Source/${Name}Module.cpp diff --git a/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.cpp b/Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.cpp similarity index 100% rename from Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.cpp rename to Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.cpp diff --git a/Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.h b/Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.h similarity index 100% rename from Templates/MinimalProject/Template/Code/Source/${Name}SystemComponent.h rename to Templates/MinimalProject/Template/Gem/Source/${Name}SystemComponent.h diff --git a/Templates/MinimalProject/Template/Code/enabled_gems.cmake b/Templates/MinimalProject/Template/Gem/enabled_gems.cmake similarity index 100% rename from Templates/MinimalProject/Template/Code/enabled_gems.cmake rename to Templates/MinimalProject/Template/Gem/enabled_gems.cmake diff --git a/Templates/MinimalProject/Template/Gem/gem.json b/Templates/MinimalProject/Template/Gem/gem.json new file mode 100644 index 0000000000..b60f512006 --- /dev/null +++ b/Templates/MinimalProject/Template/Gem/gem.json @@ -0,0 +1,21 @@ +{ + "gem_name": "${Name}", + "display_name": "${Name}", + "license": "What license ${Name} uses goes here: i.e. Apache-2.0 or MIT", + "license_url": "Link to the license web site goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT", + "origin": "The name of the originator goes here. i.e. XYZ Inc.", + "origin_url": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "type": "", + "summary": "A short description of ${Name}.", + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "${Name}" + ], + "icon_path": "preview.png", + "requirements": "", + "documentation_url": "", + "dependencies": [ + ] +} diff --git a/Templates/MinimalProject/Template/cmake/CompilerSettings.cmake b/Templates/MinimalProject/Template/cmake/CompilerSettings.cmake index 60bda1d45b..4efaecd60f 100644 --- a/Templates/MinimalProject/Template/cmake/CompilerSettings.cmake +++ b/Templates/MinimalProject/Template/cmake/CompilerSettings.cmake @@ -1,10 +1,10 @@ -# +# {BEGIN_LICENSE} # Copyright (c) Contributors to the Open 3D Engine Project. # For complete copyright and license terms please see the LICENSE at the root of this distribution. # # SPDX-License-Identifier: Apache-2.0 OR MIT # -# +# {END_LICENSE} # File to tweak compiler settings before compiler detection happens (before project() is called) # We dont have PAL enabled at this point, so we can only use pure-CMake variables diff --git a/Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings_linux.cmake b/Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings_linux.cmake index 9bb629c53b..386117873f 100644 --- a/Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings_linux.cmake +++ b/Templates/MinimalProject/Template/cmake/Platform/Linux/CompilerSettings_linux.cmake @@ -1,10 +1,10 @@ -# +# {BEGIN_LICENSE} # Copyright (c) Contributors to the Open 3D Engine Project. # For complete copyright and license terms please see the LICENSE at the root of this distribution. # # SPDX-License-Identifier: Apache-2.0 OR MIT # -# +# {END_LICENSE} if(NOT CMAKE_C_COMPILER AND NOT CMAKE_CXX_COMPILER AND NOT "$ENV{CC}" AND NOT "$ENV{CXX}") set(path_search diff --git a/Templates/MinimalProject/Template/project.json b/Templates/MinimalProject/Template/project.json index f8d4643ce9..a303186a64 100644 --- a/Templates/MinimalProject/Template/project.json +++ b/Templates/MinimalProject/Template/project.json @@ -2,7 +2,7 @@ "project_name": "${Name}", "project_id": "${ProjectId}", "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", - "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/MIT", + "license": "What license ${Name} uses goes here: i.e. https://opensource.org/licenses/Apache-2.0 Or https://opensource.org/licenses/MIT etc.", "display_name": "${Name}", "summary": "A short description of ${Name}.", "canonical_tags": [ @@ -13,5 +13,7 @@ ], "icon_path": "preview.png", "engine": "o3de", - "external_subdirectories": [] + "external_subdirectories": [ + "Gem" + ] } diff --git a/Templates/MinimalProject/template.json b/Templates/MinimalProject/template.json index 7d6a4f9b94..4cc3031ff5 100644 --- a/Templates/MinimalProject/template.json +++ b/Templates/MinimalProject/template.json @@ -1,10 +1,18 @@ { "template_name": "MinimalProject", - "origin": "The primary repo for MinimalProject goes here: i.e. http://www.mydomain.com", - "license": "What license MinimalProject uses goes here: i.e. https://opensource.org/licenses/MIT", - "display_name": "Minimal", - "summary": "This will be a good starting point for developers who are looking for building the game with the bare minimum of gems in O3DE, and adding more when needed. ", - "canonical_tags": [], + "template_restricted_platform_relative_path": "Templates/MinimalProject", + "restricted_name": "o3de", + "restricted_platform_relative_path": "Templates/MinimalProject", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "display_name": "Minimal Project Template", + "summary": "Use this project template to create project that is the absolute minimum needed to get started in O3DE.", + "canonical_tags": [ + "Template", + "Project" + ], "user_tags": [ "MinimalProject" ], @@ -12,645 +20,454 @@ "copyFiles": [ { "file": ".gitignore", - "origin": ".gitignore", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "CMakeLists.txt", - "origin": "CMakeLists.txt", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/${NameLower}_files.cmake", - "origin": "Code/${NameLower}_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/${NameLower}_shared_files.cmake", - "origin": "Code/${NameLower}_shared_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/CMakeLists.txt", - "origin": "Code/CMakeLists.txt", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Include/${Name}/${Name}Bus.h", - "origin": "Code/Include/${Name}/${Name}Bus.h", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Android/${NameLower}_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_android_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "origin": "Code/Platform/Android/${NameLower}_shared_android_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Android/PAL_android.cmake", - "origin": "Code/Platform/Android/PAL_android.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Linux/PAL_linux.cmake", - "origin": "Code/Platform/Linux/PAL_linux.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Mac/PAL_mac.cmake", - "origin": "Code/Platform/Mac/PAL_mac.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/Windows/PAL_windows.cmake", - "origin": "Code/Platform/Windows/PAL_windows.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_ios_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "origin": "Code/Platform/iOS/${NameLower}_shared_ios_files.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Platform/iOS/PAL_ios.cmake", - "origin": "Code/Platform/iOS/PAL_ios.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Source/${Name}Module.cpp", - "origin": "Code/Source/${Name}Module.cpp", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Source/${Name}SystemComponent.cpp", - "origin": "Code/Source/${Name}SystemComponent.cpp", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/Source/${Name}SystemComponent.h", - "origin": "Code/Source/${Name}SystemComponent.h", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/enabled_gems.cmake", - "origin": "Code/enabled_gems.cmake", - "isTemplated": true, - "isOptional": false - }, - { - "file": "Code/gem.json", - "origin": "Code/gem.json", - "isTemplated": true, - "isOptional": true - }, - { - "file": "Config/shader_global_build_options.json", - "origin": "Config/shader_global_build_options.json", - "isTemplated": false, - "isOptional": false + "isTemplated": true }, { "file": "cmake/EngineFinder.cmake", - "origin": "cmake/EngineFinder.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "cmake/CompilerSettings.cmake", - "origin": "cmake/CompilerSettings.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "cmake/Platform/Linux/CompilerSettings_linux.cmake", - "origin": "cmake/Platform/Linux/CompilerSettings_linux.cmake", - "isTemplated": false, - "isOptional": false + "isTemplated": false + }, + { + "file": "Config/shader_global_build_options.json", + "isTemplated": false + }, + { + "file": "Gem/${NameLower}_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/${NameLower}_shared_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/CMakeLists.txt", + "isTemplated": true + }, + { + "file": "Gem/Include/${Name}/${Name}Bus.h", + "isTemplated": true + }, + { + "file": "Gem/Platform/Android/${NameLower}_android_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Android/${NameLower}_shared_android_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Android/PAL_android.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Linux/${NameLower}_linux_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Linux/${NameLower}_shared_linux_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Linux/PAL_linux.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Mac/${NameLower}_mac_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Mac/${NameLower}_shared_mac_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Mac/PAL_mac.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Windows/${NameLower}_shared_windows_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Windows/${NameLower}_windows_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/Windows/PAL_windows.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/iOS/${NameLower}_ios_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/iOS/${NameLower}_shared_ios_files.cmake", + "isTemplated": true + }, + { + "file": "Gem/Platform/iOS/PAL_ios.cmake", + "isTemplated": true + }, + { + "file": "Gem/Source/${Name}Module.cpp", + "isTemplated": true + }, + { + "file": "Gem/Source/${Name}SystemComponent.cpp", + "isTemplated": true + }, + { + "file": "Gem/Source/${Name}SystemComponent.h", + "isTemplated": true + }, + { + "file": "Gem/enabled_gems.cmake", + "isTemplated": true + }, + { + "file": "Gem/gem.json", + "isTemplated": true }, { "file": "Platform/Android/android_project.cmake", - "origin": "Platform/Android/android_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Android/android_project.json", - "origin": "Platform/Android/android_project.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Linux/linux_project.cmake", - "origin": "Platform/Linux/linux_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Linux/linux_project.json", - "origin": "Platform/Linux/linux_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Mac/mac_project.cmake", - "origin": "Platform/Mac/mac_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Mac/mac_project.json", - "origin": "Platform/Mac/mac_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/Windows/windows_project.cmake", - "origin": "Platform/Windows/windows_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/Windows/windows_project.json", - "origin": "Platform/Windows/windows_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Platform/iOS/ios_project.cmake", - "origin": "Platform/iOS/ios_project.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Platform/iOS/ios_project.json", - "origin": "Platform/iOS/ios_project.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Registry/assets_scan_folders.setreg", - "origin": "Registry/assets_scan_folders.setreg", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Resources/LegacyLogoLauncher.bmp", - "origin": "Resources/LegacyLogoLauncher.bmp", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/GameSDK.ico", - "origin": "Resources/GameSDK.ico", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/Contents.json", - "origin": "Resources/Platform/Mac/Images.xcassets/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_128.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_16_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_256.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_32_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset/icon_512_2x.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/Mac/Info.plist", - "origin": "Resources/Platform/Mac/Info.plist", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Resources/Platform/iOS/Images.xcassets/Contents.json", - "origin": "Resources/Platform/iOS/Images.xcassets/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1024x768.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage1536x2048.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage2048x1536.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPadLaunchImage768x1024.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x1136.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage/iPhoneLaunchImage640x960.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/Contents.json", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon152x152.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadAppIcon76x76.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadProAppIcon167x167.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon29x29.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSettingsIcon58x58.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon40x40.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPadSpotlightIcon80x80.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon120x120.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneAppIcon180x180.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon58x58.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSettingsIcon87x87.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon120x120.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset/iPhoneSpotlightIcon80x80.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Resources/Platform/iOS/Info.plist", - "origin": "Resources/Platform/iOS/Info.plist", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "ShaderLib/README.md", - "origin": "ShaderLib/README.md", - "isTemplated": false, - "isOptional": true + "isTemplated": false }, { "file": "ShaderLib/scenesrg.srgi", - "origin": "ShaderLib/scenesrg.srgi", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "ShaderLib/viewsrg.srgi", - "origin": "ShaderLib/viewsrg.srgi", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "autoexec.cfg", - "origin": "autoexec.cfg", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "game.cfg", - "origin": "game.cfg", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "preview.png", - "origin": "preview.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "project.json", - "origin": "project.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true } ], "createDirectories": [ { - "dir": "Assets", - "origin": "Assets" + "dir": "Assets" }, { - "dir": "Code", - "origin": "Code" + "dir": "cmake" }, { - "dir": "Code/Include", - "origin": "Code/Include" + "dir": "cmake/Platform" }, { - "dir": "Code/Include/${Name}", - "origin": "Code/Include/${Name}" + "dir": "cmake/Platform/Linux" }, { - "dir": "Code/Platform", - "origin": "Code/Platform" + "dir": "Config" }, { - "dir": "Code/Platform/Android", - "origin": "Code/Platform/Android" + "dir": "Gem" }, { - "dir": "Code/Platform/Linux", - "origin": "Code/Platform/Linux" + "dir": "Gem/Include" }, { - "dir": "Code/Platform/Mac", - "origin": "Code/Platform/Mac" + "dir": "Gem/Include/${Name}" }, { - "dir": "Code/Platform/Windows", - "origin": "Code/Platform/Windows" + "dir": "Gem/Platform" }, { - "dir": "Code/Platform/iOS", - "origin": "Code/Platform/iOS" + "dir": "Gem/Platform/Android" }, { - "dir": "Code/Source", - "origin": "Code/Source" + "dir": "Gem/Platform/Linux" }, { - "dir": "Config", - "origin": "Config" + "dir": "Gem/Platform/Mac" }, { - "dir": "Platform", - "origin": "Platform" + "dir": "Gem/Platform/Windows" }, { - "dir": "Platform/Android", - "origin": "Platform/Android" + "dir": "Gem/Platform/iOS" }, { - "dir": "Platform/Linux", - "origin": "Platform/Linux" + "dir": "Gem/Source" }, { - "dir": "Platform/Mac", - "origin": "Platform/Mac" + "dir": "Config" }, { - "dir": "Platform/Windows", - "origin": "Platform/Windows" + "dir": "Platform" }, { - "dir": "Platform/iOS", - "origin": "Platform/iOS" + "dir": "Platform/Android" }, { - "dir": "Registry", - "origin": "Registry" + "dir": "Platform/Linux" }, { - "dir": "Resources", - "origin": "Resources" + "dir": "Platform/Mac" }, { - "dir": "Resources/Platform", - "origin": "Resources/Platform" + "dir": "Platform/Windows" }, { - "dir": "Resources/Platform/Mac", - "origin": "Resources/Platform/Mac" + "dir": "Platform/iOS" }, { - "dir": "Resources/Platform/Mac/Images.xcassets", - "origin": "Resources/Platform/Mac/Images.xcassets" + "dir": "Registry" }, { - "dir": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset", - "origin": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset" + "dir": "Resources" }, { - "dir": "Resources/Platform/iOS", - "origin": "Resources/Platform/iOS" + "dir": "Resources/Platform" }, { - "dir": "Resources/Platform/iOS/Images.xcassets", - "origin": "Resources/Platform/iOS/Images.xcassets" + "dir": "Resources/Platform/Mac" }, { - "dir": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage", - "origin": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage" + "dir": "Resources/Platform/Mac/Images.xcassets" }, { - "dir": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset", - "origin": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset" + "dir": "Resources/Platform/Mac/Images.xcassets/TestDPAppIcon.appiconset" }, { - "dir": "ShaderLib", - "origin": "ShaderLib" + "dir": "Resources/Platform/iOS" }, { - "dir": "Shaders", - "origin": "Shaders" + "dir": "Resources/Platform/iOS/Images.xcassets" }, { - "dir": "Shaders/ShaderResourceGroups", - "origin": "Shaders/ShaderResourceGroups" + "dir": "Resources/Platform/iOS/Images.xcassets/LaunchImage.launchimage" + }, + { + "dir": "Resources/Platform/iOS/Images.xcassets/TestDPAppIcon.appiconset" + }, + { + "dir": "ShaderLib" + }, + { + "dir": "Shaders" + }, + { + "dir": "Shaders/ShaderResourceGroups" } ] } diff --git a/Templates/PythonToolGem/Template/gem.json b/Templates/PythonToolGem/Template/gem.json index 84f5b65a3e..3164c7b5b8 100644 --- a/Templates/PythonToolGem/Template/gem.json +++ b/Templates/PythonToolGem/Template/gem.json @@ -2,8 +2,9 @@ "gem_name": "${Name}", "display_name": "${Name}", "license": "What license ${Name} uses goes here: i.e. Apache-2.0 Or MIT", - "license_url": "", - "origin": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "origin": "The name of the originator goes here. i.e. XYZ Inc.", + "origin_url": "The primary repo for ${Name} goes here: i.e. http://www.mydomain.com", "type": "Code", "summary": "A short description of ${Name}.", "canonical_tags": [ @@ -14,6 +15,7 @@ ], "icon_path": "preview.png", "requirements": "", + "documentation_url": "", "dependencies": [ "QtForPython" ] diff --git a/Templates/PythonToolGem/template.json b/Templates/PythonToolGem/template.json index 6dc68de3fc..3af74eb49f 100644 --- a/Templates/PythonToolGem/template.json +++ b/Templates/PythonToolGem/template.json @@ -1,12 +1,18 @@ { "template_name": "PythonToolGem", + "template_restricted_platform_relative_path": "Templates/PythonToolGem", "restricted_name": "o3de", - "restricted_platform_relative_path": "Templates", - "origin": "The primary repo for PythonToolGem goes here: i.e. http://www.mydomain.com", - "license": "What license PythonToolGem uses goes here: i.e. https://opensource.org/licenses/MIT", + "restricted_platform_relative_path": "Templates/PythonToolGem", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "display_name": "PythonToolGem", "summary": "A gem template for a custom tool in Python that gets registered with the Editor.", - "canonical_tags": [], + "canonical_tags": [ + "Python", + "Gem" + ], "user_tags": [ "PythonToolGem" ], @@ -14,221 +20,153 @@ "copyFiles": [ { "file": ".gitignore", - "origin": ".gitignore", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "CMakeLists.txt", - "origin": "CMakeLists.txt", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_files.cmake", - "origin": "Code/${NameLower}_editor_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_shared_files.cmake", - "origin": "Code/${NameLower}_editor_shared_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/${NameLower}_editor_tests_files.cmake", - "origin": "Code/${NameLower}_editor_tests_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/CMakeLists.txt", - "origin": "Code/CMakeLists.txt", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Include/${Name}/${Name}Bus.h", - "origin": "Code/Include/${Name}/${Name}Bus.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_linux_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "origin": "Code/Platform/Linux/${NameLower}_shared_linux_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Linux/PAL_linux.cmake", - "origin": "Code/Platform/Linux/PAL_linux.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_mac_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "origin": "Code/Platform/Mac/${NameLower}_shared_mac_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Mac/PAL_mac.cmake", - "origin": "Code/Platform/Mac/PAL_mac.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_shared_windows_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "origin": "Code/Platform/Windows/${NameLower}_windows_files.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Platform/Windows/PAL_windows.cmake", - "origin": "Code/Platform/Windows/PAL_windows.cmake", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}.qrc", - "origin": "Code/Source/${Name}.qrc", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorModule.cpp", - "origin": "Code/Source/${Name}EditorModule.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorSystemComponent.cpp", - "origin": "Code/Source/${Name}EditorSystemComponent.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}EditorSystemComponent.h", - "origin": "Code/Source/${Name}EditorSystemComponent.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/${Name}ModuleInterface.h", - "origin": "Code/Source/${Name}ModuleInterface.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Code/Source/toolbar_icon.svg", - "origin": "Code/Source/toolbar_icon.svg", - "isTemplated": false, - "isOptional": false + "isTemplated": false }, { "file": "Code/Tests/${Name}EditorTest.cpp", - "origin": "Code/Tests/${Name}EditorTest.cpp", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Editor/Scripts/__init__.py", - "origin": "Editor/Scripts/__init__.py", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Editor/Scripts/bootstrap.py", - "origin": "Editor/Scripts/bootstrap.py", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "Editor/Scripts/${NameLower}_dialog.py", - "origin": "Editor/Scripts/${NameLower}_dialog.py", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "gem.json", - "origin": "gem.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "preview.png", - "origin": "preview.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false } ], "createDirectories": [ { - "dir": "Assets", - "origin": "Assets" + "dir": "Assets" }, { - "dir": "Code", - "origin": "Code" + "dir": "Code" }, { - "dir": "Editor", - "origin": "Editor" + "dir": "Editor" }, { - "dir": "Editor/Scripts", - "origin": "Editor/Scripts" + "dir": "Editor/Scripts" }, { - "dir": "Code/Include", - "origin": "Code/Include" + "dir": "Code/Include" }, { - "dir": "Code/Include/${Name}", - "origin": "Code/Include/${Name}" + "dir": "Code/Include/${Name}" }, { - "dir": "Code/Platform", - "origin": "Code/Platform" + "dir": "Code/Platform" }, { - "dir": "Code/Platform/Linux", - "origin": "Code/Platform/Linux" + "dir": "Code/Platform/Linux" }, { - "dir": "Code/Platform/Mac", - "origin": "Code/Platform/Mac" + "dir": "Code/Platform/Mac" }, { - "dir": "Code/Platform/Windows", - "origin": "Code/Platform/Windows" + "dir": "Code/Platform/Windows" }, { - "dir": "Code/Source", - "origin": "Code/Source" + "dir": "Code/Source" }, { - "dir": "Code/Tests", - "origin": "Code/Tests" + "dir": "Code/Tests" } ] } diff --git a/cmake/3rdParty.cmake b/cmake/3rdParty.cmake index 7d98c3ea3e..1bea5f4f67 100644 --- a/cmake/3rdParty.cmake +++ b/cmake/3rdParty.cmake @@ -186,7 +186,7 @@ function(ly_add_external_target) endif() # Check if there is a pal file - ly_get_absolute_pal_filename(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/${ly_add_external_target_PACKAGE}_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) + o3de_pal_dir(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/${ly_add_external_target_PACKAGE}_${PAL_PLATFORM_NAME_LOWERCASE}.cmake ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) if(NOT EXISTS ${pal_file}) set(pal_file ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/${ly_add_external_target_PACKAGE}_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) endif() @@ -357,12 +357,12 @@ endfunction() # Add the 3rdParty folder to find the modules list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/3rdParty) -ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/3rdParty/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/3rdParty/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) list(APPEND CMAKE_MODULE_PATH ${pal_dir}) if(NOT INSTALLED_ENGINE) # Add the 3rdParty cmake files to the IDE ly_include_cmake_file_list(cmake/3rdParty/cmake_files.cmake) - ly_get_absolute_pal_filename(pal_3rdparty_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdParty/Platform/${PAL_PLATFORM_NAME}) + o3de_pal_dir(pal_3rdparty_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdParty/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) ly_include_cmake_file_list(${pal_3rdparty_dir}/cmake_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake) endif() diff --git a/cmake/3rdParty/BuiltInPackages.cmake b/cmake/3rdParty/BuiltInPackages.cmake index 743e2e983e..e81cfffe01 100644 --- a/cmake/3rdParty/BuiltInPackages.cmake +++ b/cmake/3rdParty/BuiltInPackages.cmake @@ -12,9 +12,9 @@ # cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake #include the platform-specific 3rd party packages. -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) -set(LY_PAL_PACKAGE_FILE_NAME ${CMAKE_CURRENT_LIST_DIR}/${pal_dir}/BuiltInPackages_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +set(LY_PAL_PACKAGE_FILE_NAME ${pal_dir}/BuiltInPackages_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) include(${LY_PAL_PACKAGE_FILE_NAME}) # add the above file to the ALLFILES list, so that they show up in IDEs diff --git a/cmake/3rdPartyPackages.cmake b/cmake/3rdPartyPackages.cmake index a3f15bdb22..f9a72672c0 100644 --- a/cmake/3rdPartyPackages.cmake +++ b/cmake/3rdPartyPackages.cmake @@ -614,7 +614,7 @@ endfunction() # and ensure the path to the package root is added to the find_package search paths. # For example # ly_associate_package(TARGETS zlib PACKAGE_NAME zlib-1.2.8-multiplatform PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -# - this waill cause it to automatically download and activate this package if it finds a target that +# - this will cause it to automatically download and activate this package if it finds a target that # depends on '3rdParty::zlib' in its runtime or its build time dependency list. # - note that '3rdParty' is implied, do not specify it in the TARGETS list. function(ly_associate_package) @@ -684,6 +684,7 @@ endmacro() # is associated with a package, as above. If it is, it makes sure that the package # is brought into scope (and if necessary, downloaded.) macro(ly_download_associated_package find_library_name) + unset(package_name) ly_get_package_association(${find_library_name} package_name) if (package_name) # it is an associated package. diff --git a/cmake/Configurations.cmake b/cmake/Configurations.cmake index 51dee2f07b..709c81e3d2 100644 --- a/cmake/Configurations.cmake +++ b/cmake/Configurations.cmake @@ -189,5 +189,5 @@ foreach(conf IN LISTS CMAKE_CONFIGURATION_TYPES) endforeach() # flags are defined per platform, follow platform files under Platform//Configurations_.cmake -ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/Configurations_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/cmake/FileUtil.cmake b/cmake/FileUtil.cmake index 4607e14452..5721cf452c 100644 --- a/cmake/FileUtil.cmake +++ b/cmake/FileUtil.cmake @@ -26,8 +26,16 @@ function(ly_include_cmake_file_list file) include(${file}) get_filename_component(file_path "${file}" PATH) if(file_path) - list(TRANSFORM FILES PREPEND ${file_path}/) + foreach(f ${FILES}) + cmake_path(IS_RELATIVE f is_relative) + if(is_relative) + string(PREPEND f ${file_path}/) + endif() + list(APPEND TRANSFORMED_FILES ${f}) + endforeach() + set(FILES ${TRANSFORMED_FILES}) endif() + foreach(f ${FILES}) get_filename_component(absolute_path ${f} ABSOLUTE) if(NOT EXISTS ${absolute_path}) @@ -41,12 +49,19 @@ function(ly_include_cmake_file_list file) list(APPEND UNITY_AUTO_EXCLUSIONS ${f}) endif() endif() - endforeach() + list(APPEND FILES ${file}) # Add the _files.cmake to the list so it shows in the IDE if(file_path) - list(TRANSFORM SKIP_UNITY_BUILD_INCLUSION_FILES PREPEND ${file_path}/) + foreach(f ${SKIP_UNITY_BUILD_INCLUSION_FILES}) + cmake_path(IS_RELATIVE f is_relative) + if(is_relative) + string(PREPEND f ${file_path}/) + endif() + list(APPEND SKIP_UNITY_BUILD_INCLUSION_TRANSFORMED_FILES ${f}) + endforeach() + set(SKIP_UNITY_BUILD_INCLUSION_FILES ${SKIP_UNITY_BUILD_INCLUSION_TRANSFORMED_FILES}) endif() # Check if there are any files to exclude from unity groupings diff --git a/cmake/Install.cmake b/cmake/Install.cmake index b558590b9e..55f56b05e8 100644 --- a/cmake/Install.cmake +++ b/cmake/Install.cmake @@ -30,7 +30,7 @@ function(ly_install) install(CODE "endif()\n" ALL_COMPONENTS) else() install(${ARGN}) - endif() + endif() endfunction() @@ -195,6 +195,6 @@ function(ly_install_run_script SCRIPT) endfunction() if(LY_INSTALL_ENABLED) - ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME}) + o3de_pal_dir(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/Install_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) endif() diff --git a/cmake/LYTestWrappers.cmake b/cmake/LYTestWrappers.cmake index 03146b6045..9f4cd41a47 100644 --- a/cmake/LYTestWrappers.cmake +++ b/cmake/LYTestWrappers.cmake @@ -141,7 +141,7 @@ function(ly_add_test) set(wrapper_file ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}/LYTestWrappers_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) if(NOT EXISTS ${wrapper_file}) - ly_get_absolute_pal_filename(wrapper_file ${wrapper_file}) + o3de_pal_dir(wrapper_file ${wrapper_file} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) endif() include(${wrapper_file}) diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index d4bf1d7423..a2f4359fd5 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -11,7 +11,7 @@ set(LY_UNITY_BUILD ON CACHE BOOL "UNITY builds") include(CMakeFindDependencyMacro) include(cmake/LyAutoGen.cmake) -ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/LYWrappers_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # Not all platforms support unity builds diff --git a/cmake/PAL.cmake b/cmake/PAL.cmake index 67ed17b6d4..d0d1ad5396 100644 --- a/cmake/PAL.cmake +++ b/cmake/PAL.cmake @@ -15,67 +15,205 @@ # PAL_PLATFORM_NAME_LOWERCASE: name of the platform in lower case (part of filenames) # -file(GLOB detection_files "cmake/Platform/*/PALDetection_*.cmake") -foreach(detection_file ${detection_files}) - include(${detection_file}) -endforeach() - - -#! o3de_restricted_id: Reads the "restricted" key from the o3de manifest +#! o3de_get_home_path: returns the home path # -# \arg:o3de_json_file name of the o3de json file to read the "restricted_name" key from -# \arg:restricted returns the restricted association element from an o3de json, otherwise engine 'o3de' is assumed -# \arg:o3de_json_file name of the o3de json file -function(o3de_restricted_id o3de_json_file restricted) - ly_file_read(${o3de_json_file} json_data) - string(JSON restricted_entry ERROR_VARIABLE json_error GET ${json_data} "restricted_name") +# \arg:o3de_manifest_path returns the path of the manifest +function(o3de_get_home_path o3de_home_path) + # The o3de_manifest.json is in the home directory / .o3de folder + file(TO_CMAKE_PATH "$ENV{USERPROFILE}" home_path) # Windows + if(NOT EXISTS ${home_path}) + file(TO_CMAKE_PATH "$ENV{HOME}" home_path) # Unix + if (NOT EXISTS ${home_path}) + message(FATAL_ERROR "o3de Home path not found") + endif() + endif() + set(${o3de_home_path} ${home_path} PARENT_SCOPE) +endfunction() + +#! o3de_get_manifest_path: returns the path to the manifest +# +# \arg:o3de_manifest_path returns the path of the manifest +function(o3de_get_manifest_path o3de_manifest_path) + # The o3de_manifest.json is in the home directory / .o3de folder + o3de_get_home_path(o3de_home_path) + set(${o3de_manifest_path} ${o3de_home_path}/.o3de/o3de_manifest.json PARENT_SCOPE) +endfunction() + +#! o3de_read_manifest: returns the contents of the manifest +# +# \arg:restricted_subdirs returns the restricted elements from the manifest +function(o3de_read_manifest o3de_manifest_json_data) + #get the manifest path + o3de_get_manifest_path(o3de_manifest_path) + if(EXISTS ${o3de_manifest_path}) + ly_file_read(${o3de_manifest_path} json_data) + set(${o3de_manifest_json_data} ${json_data} PARENT_SCOPE) + endif() +endfunction() + +#! o3de_recurse_gems: returns the gem paths +# +# \arg:object json path +# \arg:gems returns the gems from the external subdirectory elements from the manifest +function(o3de_recurse_gems object_json_path gems) + get_filename_component(object_json_parent_path ${object_json_path} DIRECTORY) + ly_file_read(${object_json_path} json_data) + string(JSON external_subdirectories_count ERROR_VARIABLE json_error LENGTH ${json_data} "external_subdirectories") + if(NOT json_error) + if(external_subdirectories_count GREATER 0) + math(EXPR external_subdirectories_range "${external_subdirectories_count}-1") + foreach(external_subdirectories_index RANGE ${external_subdirectories_range}) + string(JSON external_subdirectories_entry ERROR_VARIABLE json_error GET ${json_data} "external_subdirectories" "${external_subdirectories_index}") + cmake_path(IS_RELATIVE external_subdirectories_entry is_relative) + if(${is_relative}) + cmake_path(ABSOLUTE_PATH external_subdirectories_entry BASE_DIRECTORY ${object_json_parent_path} NORMALIZE OUTPUT_VARIABLE external_subdirectories_entry) + endif() + if(EXISTS ${external_subdirectories_entry}/gem.json) + list(APPEND gem_entries ${external_subdirectories_entry}) + o3de_recurse_gems(${external_subdirectories_entry}/gem.json gem_entries) + endif() + endforeach() + endif() + endif() + set(${gems} ${gem_entries} PARENT_SCOPE) +endfunction() + +#! o3de_find_gem: returns the gem path +# +# \arg:gem_name the gem name to find +# \arg:the path of the gem +function(o3de_find_gem gem_name gem_path) + o3de_get_manifest_path(manifest_path) + if(EXISTS ${manifest_path}) + o3de_recurse_gems(${manifest_path} gems) + endif() + o3de_recurse_gems(${LY_ROOT_FOLDER}/engine.json gems) + foreach(gem ${gems}) + ly_file_read(${gem}/gem.json json_data) + string(JSON gem_json_name ERROR_VARIABLE json_error GET ${json_data} "gem_name") + if(gem_json_name STREQUAL gem_name) + set(${gem_path} ${gem} PARENT_SCOPE) + return() + endif() + endforeach() +endfunction() + +#! o3de_manifest_restricted: returns the manifests restricted paths +# +# \arg:restricted returns the restricted elements from the manifest +function(o3de_manifest_restricted restricted) + #read the manifest + o3de_read_manifest(o3de_manifest_json_data) + string(JSON restricted_count ERROR_VARIABLE json_error LENGTH ${o3de_manifest_json_data} "restricted") if(json_error) # Restricted fields can never be a requirement so no warning is issued return() endif() - if(restricted_entry) - set(${restricted} ${restricted_entry} PARENT_SCOPE) + if(restricted_count GREATER 0) + math(EXPR restricted_range "${restricted_count}-1") + foreach(restricted_index RANGE ${restricted_range}) + string(JSON restricted_entry ERROR_VARIABLE json_error GET ${o3de_manifest_json_data} "restricted" "${restricted_index}") + list(APPEND restricted_entries ${restricted_entry}) + endforeach() endif() + set(${restricted} ${restricted_entries} PARENT_SCOPE) +endfunction() + +#! o3de_json_restricted: returns the restricted element from a json +# +# \arg:restricted returns the restricted element of the json +function(o3de_json_restricted json_path restricted) + if(EXISTS ${json_path}) + ly_file_read(${json_path} json_data) + string(JSON restricted_entry ERROR_VARIABLE json_error GET ${json_data} "restricted") + if(json_error) + # Restricted fields can never be a requirement so no warning is issued + return() + endif() + set(${restricted} ${restricted_entry} PARENT_SCOPE) + endif() +endfunction() + +#! o3de_restricted_id: determines the restricted object for this json +# +# Find this objects restricted name. If the object has a "restricted" element +# If it does not have one it inherits its parents "restricted" element if it has one +# If the parent does not have one it inherits its parents parent "restricted" element is it has one and so on... +# We stop looking if the object or parent is in the manifest, as the manifest only has top level objects +# which means they have no children. +# +# \arg:o3de_json_file name of the o3de json file to read the "restricted" key from +# \arg:restricted returns the restricted association element from an o3de json, otherwise its doesnt change anything +# \arg:o3de_json_file name of the o3de json file +function(o3de_restricted_id o3de_json_file restricted parent_relative_path) + # read the passed in o3de json and see if "restricted" is set + o3de_json_restricted(${o3de_json_file} restricted_name) + if(restricted_name) + set(${parent_relative_path} "" PARENT_SCOPE) + set(${restricted} ${restricted_name} PARENT_SCOPE) + return() + endif() + + # This object did not have a "restricted" set, now we must look at the parent + # Stop if this is a top level object + o3de_manifest_restricted(manifest_restricted_paths) + get_filename_component(o3de_json_file_parent ${o3de_json_file} DIRECTORY) + get_filename_component(relative_path ${o3de_json_file_parent} NAME) + get_filename_component(o3de_json_file_parent ${o3de_json_file_parent} DIRECTORY) + if(${o3de_json_file_parent} IN_LIST manifest_restricted_paths) + set(${parent_relative_path} "" PARENT_SCOPE) + set(${restricted} "" PARENT_SCOPE) + return() + endif() + + string(LENGTH ${o3de_json_file_parent} parent_len) + while(parent_len) + if(EXISTS ${o3de_json_file_parent}/engine.json) + o3de_json_restricted(${o3de_json_file_parent}/engine.json restricted_name) + if(restricted_name) + set(${parent_relative_path} ${relative_path} PARENT_SCOPE) + set(${restricted} ${restricted_name} PARENT_SCOPE) + return() + endif() + endif() + if(EXISTS ${o3de_json_file_parent}/project.json) + o3de_json_restricted(${o3de_json_file_parent}/project.json restricted_name) + if(restricted_name) + set(${parent_relative_path} ${relative_path} PARENT_SCOPE) + set(${restricted} ${restricted_name} PARENT_SCOPE) + return() + endif() + endif() + if(EXISTS ${o3de_json_file_parent}/gem.json) + o3de_json_restricted(${o3de_json_file_parent}/gem.json restricted_name) + if(restricted_name) + set(${parent_relative_path} ${relative_path} PARENT_SCOPE) + set(${restricted} ${restricted_name} PARENT_SCOPE) + return() + endif() + endif() + + if(${o3de_json_file_parent} IN_LIST manifest_restricted_paths) + set(${parent_relative_path} "" PARENT_SCOPE) + set(${restricted} "" PARENT_SCOPE) + return() + endif() + + get_filename_component(parent ${o3de_json_file_parent} NAME) + string(PREPEND relative_path ${parent}/) + get_filename_component(o3de_json_file_parent ${o3de_json_file_parent} DIRECTORY) + string(LENGTH ${o3de_json_file_parent} parent_len) + endwhile() endfunction() #! o3de_find_restricted_folder: # -# \arg:restricted_path returns the path of the o3de restricted folder with name restricted_name +# \arg:restricted_path returns the path of the o3de restricted folder using the restricted_name # \arg:restricted_name name of the restricted function(o3de_find_restricted_folder restricted_name restricted_path) - # Read the restricted path from engine.json if one EXISTS - ly_file_read(${LY_ROOT_FOLDER}/engine.json engine_json_data) - string(JSON restricted_subdirs_count ERROR_VARIABLE engine_json_error LENGTH ${engine_json_data} "restricted") - if(restricted_subdirs_count GREATER 0) - string(JSON restricted_subdir ERROR_VARIABLE engine_json_error GET ${engine_json_data} "restricted" "0") - set(${restricted_path} ${restricted_subdir} PARENT_SCOPE) - return() - endif() - - - file(TO_CMAKE_PATH "$ENV{USERPROFILE}" home_directory) # Windows - if(NOT EXISTS ${home_directory}) - file(TO_CMAKE_PATH "$ENV{HOME}" home_directory) # Unix - if (NOT EXISTS ${home_directory}) - return() - endif() - endif() - - # Examine the o3de manifest file for the list of restricted directories - set(o3de_manifest_path ${home_directory}/.o3de/o3de_manifest.json) - if(EXISTS ${o3de_manifest_path}) - ly_file_read(${o3de_manifest_path} o3de_manifest_json_data) - string(JSON restricted_subdirs_count ERROR_VARIABLE engine_json_error LENGTH ${o3de_manifest_json_data} "restricted") - if(restricted_subdirs_count GREATER 0) - math(EXPR restricted_subdirs_range "${restricted_subdirs_count}-1") - foreach(restricted_subdir_index RANGE ${restricted_subdirs_range}) - string(JSON restricted_subdir ERROR_VARIABLE engine_json_error GET ${o3de_manifest_json_data} "restricted" "${restricted_subdir_index}") - list(APPEND restricted_subdirs ${restricted_subdir}) - endforeach() - endif() - endif() + o3de_manifest_restricted(restricted_entries) # Iterate over the restricted directories from the manifest file - foreach(restricted_entry ${restricted_subdirs}) + foreach(restricted_entry ${restricted_entries}) set(restricted_json_file ${restricted_entry}/restricted.json) ly_file_read(${restricted_json_file} restricted_json) string(JSON this_restricted_name ERROR_VARIABLE json_error GET ${restricted_json} "restricted_name") @@ -95,30 +233,30 @@ endfunction() # # \arg:o3de_json_file json file to read restricted id from # \arg:restricted_name name of the restricted object -function(o3de_restricted_path o3de_json_file restricted_path) - o3de_restricted_id(${o3de_json_file} restricted_name) +function(o3de_restricted_path o3de_json_file restricted_path parent_relative_path) + o3de_restricted_id(${o3de_json_file} restricted_name parent_relative) + set(${parent_relative_path} ${parent_relative} PARENT_SCOPE) if(restricted_name) o3de_find_restricted_folder(${restricted_name} restricted_folder) if(restricted_folder) set(${restricted_path} ${restricted_folder} PARENT_SCOPE) + else() + get_filename_component(o3de_json_file_parent ${o3de_json_file} DIRECTORY) + set(${restricted_path} ${o3de_json_file_parent}/restricted PARENT_SCOPE) endif() endif() endfunction() -#! read_engine_restricted_path: Locates the restricted path within the engine from a json file -# -# \arg:output_restricted_path returns the path of the o3de restricted folder with name restricted_name -function(read_engine_restricted_path output_restricted_path) - # Set manifest path to path in the user home directory - set(manifest_path ${LY_ROOT_FOLDER}/engine.json) - if(EXISTS ${manifest_path}) - o3de_restricted_path(${manifest_path} read_restricted_path) - set(${output_restricted_path} ${read_restricted_path} PARENT_SCOPE) - endif() -endfunction() +# detect open platforms +file(GLOB detection_files "cmake/Platform/*/PALDetection_*.cmake") +foreach(detection_file ${detection_files}) + include(${detection_file}) +endforeach() -read_engine_restricted_path(O3DE_ENGINE_RESTRICTED_PATH) +# set the O3DE_ENGINE_RESTRICTED_PATH +o3de_restricted_path(${LY_ROOT_FOLDER}/engine.json O3DE_ENGINE_RESTRICTED_PATH engine_has_no_parent) +# detect platforms in the restricted path file(GLOB detection_files ${O3DE_ENGINE_RESTRICTED_PATH}/*/cmake/PALDetection_*.cmake) foreach(detection_file ${detection_files}) include(${detection_file}) @@ -146,21 +284,16 @@ foreach(pal_restricted_file ${pal_restricted_files}) string(TOLOWER ${platform} platform_lower) list(APPEND PAL_RESTRICTED_PLATFORMS ${platform_lower}) endforeach() +list(REMOVE_DUPLICATES PAL_RESTRICTED_PLATFORMS) + ly_set(PAL_RESTRICTED_PLATFORMS ${PAL_RESTRICTED_PLATFORMS}) function(ly_get_absolute_pal_filename out_name in_name) - set(full_name ${in_name}) + message(DEPRECATION "ly_get_list_relative_pal_filename is being deprecated, change your code to use o3de_pal_dir instead.") + # parent relative path is optional if(${ARGC} GREATER 4) - # The object name is used to resolve ambiguities when a PAL directory is requested from - # two different external subdirectory root paths - # Such as if a PAL directory for two root object paths with same relative structure was requested to be Palified - # i.e /Platform//IO and /Platform//IO - # Normally the restricted PAL path for both gems would be "//IO". - # The object name can be used to make this path unique - # "///IO" for gem 1 and - # "///IO" for gem 2 - set(object_name ${ARGV4}) + set(parent_relative_path ${ARGV4}) endif() # The Default object path for path is the LY_ROOT_FOLDER @@ -170,14 +303,30 @@ function(ly_get_absolute_pal_filename out_name in_name) cmake_path(SET object_path NORMALIZE ${ARGV3}) endif() - # The Default restricted object path is the result of the read_engine_restricted_path function + # The default restricted object path is O3DE_ENGINE_RESTRICTED_PATH cmake_path(SET object_restricted_path NORMALIZE "${O3DE_ENGINE_RESTRICTED_PATH}") if(${ARGC} GREATER 2) # The user has supplied an object restricted path cmake_path(SET object_restricted_path NORMALIZE ${ARGV2}) endif() - # The input path must exist in order to form a PAL path + if(${ARGC} GREATER 4) + o3de_pal_dir(abs_name ${in_name} ${object_restricted_path} ${object_path} ${parent_relative_path}) + else() + o3de_pal_dir(abs_name ${in_name} ${object_restricted_path} ${object_path}) + endif() + set(${out_name} ${abs_name} PARENT_SCOPE) +endfunction() + +function(o3de_pal_dir out_name in_name object_restricted_path object_path) #parent_relative_path) + set(full_name ${in_name}) + + # parent relative path is optional + if(${ARGC} GREATER 4) + set(parent_relative_path ${ARGV4}) + endif() + + # The input path must not exist in order to form a restricted PAL path if (NOT EXISTS ${full_name}) # if the file is not in the object path then we cannot determine a PAL file for it cmake_path(IS_PREFIX object_path ${full_name} is_input_path_in_root) @@ -222,7 +371,7 @@ function(ly_get_absolute_pal_filename out_name in_name) if(NOT EXISTS ${candidate_PAL_path}) string(TOLOWER ${candidate_platform_name} candidate_platform_name_lower) if("${candidate_platform_name_lower}" IN_LIST PAL_RESTRICTED_PLATFORMS) - cmake_path(APPEND object_restricted_path ${candidate_platform_name} ${object_name} + cmake_path(APPEND object_restricted_path ${candidate_platform_name} ${parent_relative_path} ${pre_platform_paths} OUTPUT_VARIABLE candidate_PAL_path) endif() endif() @@ -236,17 +385,43 @@ function(ly_get_absolute_pal_filename out_name in_name) endfunction() function(ly_get_list_relative_pal_filename out_name in_name) - ly_get_absolute_pal_filename(abs_name ${in_name} ${ARGN}) + message(DEPRECATION "ly_get_list_relative_pal_filename is being deprecated, change your code to use o3de_pal_dir instead.") + + # parent relative path is optional + if(${ARGC} GREATER 4) + set(parent_relative_path ${ARGV4}) + endif() + + # The Default object path for path is the LY_ROOT_FOLDER + cmake_path(SET object_path NORMALIZE "${LY_ROOT_FOLDER}") + if(${ARGC} GREATER 3) + # The user has supplied an object restricted path, the object path for consideration + cmake_path(SET object_path NORMALIZE ${ARGV3}) + endif() + + # The default restricted object path is O3DE_ENGINE_RESTRICTED_PATH + cmake_path(SET object_restricted_path NORMALIZE "${O3DE_ENGINE_RESTRICTED_PATH}") + if(${ARGC} GREATER 2) + # The user has supplied an object restricted path + cmake_path(SET object_restricted_path NORMALIZE ${ARGV2}) + endif() + + if(${ARGC} GREATER 4) + o3de_pal_dir(abs_name ${in_name} ${object_restricted_path} ${object_path} ${parent_relative_path}) + else() + o3de_pal_dir(abs_name ${in_name} ${object_restricted_path} ${object_path}) + endif() + cmake_path(RELATIVE_PATH abs_name BASE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} OUTPUT_VARIABLE relative_name) set(${out_name} ${relative_name} PARENT_SCOPE) endfunction() -ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_cmake_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) -ly_include_cmake_file_list(${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake) +ly_include_cmake_file_list(${pal_cmake_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake) -include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) -include(${pal_dir}/Toolchain_${PAL_PLATFORM_NAME_LOWERCASE}.cmake OPTIONAL) +include(${pal_cmake_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) +include(${pal_cmake_dir}/Toolchain_${PAL_PLATFORM_NAME_LOWERCASE}.cmake OPTIONAL) set(LY_DISABLE_TEST_MODULES FALSE CACHE BOOL "Option to forcibly disable the inclusion of test targets in the build") diff --git a/cmake/PALTools.cmake b/cmake/PALTools.cmake index 2204abf5ae..88e827f9c2 100644 --- a/cmake/PALTools.cmake +++ b/cmake/PALTools.cmake @@ -35,14 +35,14 @@ ly_set(LY_PAL_TOOLS_DEFINES ${LY_PAL_TOOLS_DEFINES}) # Include files to the CMakeFiles project foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${enabled_platform}) + o3de_pal_dir(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${enabled_platform}) ly_include_cmake_file_list(${pal_dir}/pal_tools_${enabled_platform_lowercase}_files.cmake) endforeach() function(ly_get_pal_tool_dirs out_list pal_path) set(pal_paths "") foreach(platform ${LY_PAL_TOOLS_ENABLED}) - ly_get_absolute_pal_filename(path ${pal_path}/${platform}) + o3d_pal_dir(path ${pal_path}/${platform} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) list(APPEND pal_paths ${path}) endforeach() set(${out_list} ${pal_paths} PARENT_SCOPE) diff --git a/cmake/Packaging.cmake b/cmake/Packaging.cmake index ecef5261b1..81409369dc 100644 --- a/cmake/Packaging.cmake +++ b/cmake/Packaging.cmake @@ -73,7 +73,7 @@ set(CPACK_PROJECT_CONFIG_FILE ${CPACK_SOURCE_DIR}/PackagingConfig.cmake) set(CPACK_AUTO_GEN_TAG ${LY_INSTALLER_AUTO_GEN_TAG}) # attempt to apply platform specific settings -ly_get_absolute_pal_filename(pal_dir ${CPACK_SOURCE_DIR}/Platform/${PAL_HOST_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CPACK_SOURCE_DIR}/Platform/${PAL_HOST_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/Packaging_${PAL_HOST_PLATFORM_NAME_LOWERCASE}.cmake) # if we get here and the generator hasn't been set, then a non fatal error occurred disabling packaging support diff --git a/cmake/Projects.cmake b/cmake/Projects.cmake index 13161c9e0f..c6aa6c382a 100644 --- a/cmake/Projects.cmake +++ b/cmake/Projects.cmake @@ -118,17 +118,27 @@ function(ly_generate_project_build_path_setreg project_real_path) file(GENERATE OUTPUT ${project_user_build_path_setreg_file} CONTENT ${project_build_path_setreg_content}) endfunction() +function(add_gem_json_external_subdirectories gem_path) + set(gem_json_path ${gem_path}/gem.json) + if(EXISTS ${gem_json_path}) + read_json_external_subdirs(gem_external_subdirs ${gem_path}/gem.json) + foreach(gem_external_subdir ${gem_external_subdirs}) + file(REAL_PATH ${gem_external_subdir} real_external_subdir BASE_DIRECTORY ${gem_path}) + set_property(GLOBAL APPEND PROPERTY LY_EXTERNAL_SUBDIRS ${real_external_subdir}) + add_gem_json_external_subdirectories(${real_external_subdir}) + endforeach() + endif() +endfunction() function(add_project_json_external_subdirectories project_path) set(project_json_path ${project_path}/project.json) if(EXISTS ${project_json_path}) - read_json_external_subdirs(external_subdirs ${project_path}/project.json) - foreach(external_subdir ${external_subdirs}) - file(REAL_PATH ${external_subdir} real_external_subdir BASE_DIRECTORY ${project_path}) - list(APPEND project_external_subdirs ${real_external_subdir}) + read_json_external_subdirs(project_external_subdirs ${project_path}/project.json) + foreach(project_external_subdir ${project_external_subdirs}) + file(REAL_PATH ${project_external_subdir} real_external_subdir BASE_DIRECTORY ${project_path}) + set_property(GLOBAL APPEND PROPERTY LY_EXTERNAL_SUBDIRS ${real_external_subdir}) + add_gem_json_external_subdirectories(${real_external_subdir}) endforeach() - - set_property(GLOBAL APPEND PROPERTY LY_EXTERNAL_SUBDIRS ${project_external_subdirs}) endif() endfunction() diff --git a/cmake/RuntimeDependencies.cmake b/cmake/RuntimeDependencies.cmake index 9cc7315b08..d36789791f 100644 --- a/cmake/RuntimeDependencies.cmake +++ b/cmake/RuntimeDependencies.cmake @@ -6,6 +6,6 @@ # # -ly_get_absolute_pal_filename(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/RuntimeDependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) diff --git a/engine.json b/engine.json index 737ac24fea..51b6738001 100644 --- a/engine.json +++ b/engine.json @@ -1,6 +1,6 @@ { "engine_name": "o3de", - "restricted_name": "o3de", + "restricted": "o3de", "FileVersion": 1, "O3DEVersion": "0.0.0.0", "O3DECopyrightYear": 2021, diff --git a/scripts/o3de/CMakeLists.txt b/scripts/o3de/CMakeLists.txt index 79836305c0..fced0f7727 100644 --- a/scripts/o3de/CMakeLists.txt +++ b/scripts/o3de/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(tests) -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +o3de_pal_dir(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME} ${O3DE_ENGINE_RESTRICTED_PATH} ${LY_ROOT_FOLDER}) include(${pal_dir}/o3de_install_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) ly_install_files(FILES ../o3de.py diff --git a/scripts/o3de/o3de/disable_gem.py b/scripts/o3de/o3de/disable_gem.py index 0b0e465d12..eecc765d32 100644 --- a/scripts/o3de/o3de/disable_gem.py +++ b/scripts/o3de/o3de/disable_gem.py @@ -98,9 +98,6 @@ def disable_gem_in_project(gem_name: str = None, def _run_disable_gem_in_project(args: argparse) -> int: - if args.override_home_folder: - manifest.override_home_folder = args.override_home_folder - return disable_gem_in_project(args.gem_name, args.gem_path, args.project_name, @@ -133,9 +130,6 @@ def add_parser_args(parser): help='The cmake enabled gem file in which gem names are to be removed from.' 'If not specified it will assume ') - parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False, - help='By default the home folder is the user folder, override it to this folder.') - parser.set_defaults(func=_run_disable_gem_in_project) diff --git a/scripts/o3de/o3de/download.py b/scripts/o3de/o3de/download.py index 8e28561e50..a7d5b56440 100644 --- a/scripts/o3de/o3de/download.py +++ b/scripts/o3de/o3de/download.py @@ -277,9 +277,6 @@ def is_o3de_restricted_update_available(restricted_name: str, local_last_updated return is_o3de_object_update_available(restricted_name, 'restricted_name', local_last_updated) def _run_download(args: argparse) -> int: - if args.override_home_folder: - manifest.override_home_folder = args.override_home_folder - if args.engine_name: return download_engine(args.engine_name, args.dest_path, @@ -331,8 +328,6 @@ def add_parser_args(parser): parser.add_argument('-f', '--force', action='store_true', required=False, default=False, help = 'Force overwrite the current object') - parser.add_argument('-ohf', '--override-home-folder', type=str, required=False, - help='By default the home folder is the user folder, override it to this folder.') parser.set_defaults(func=_run_download) diff --git a/scripts/o3de/o3de/enable_gem.py b/scripts/o3de/o3de/enable_gem.py index fc4dc6e9cf..ea79f6c73f 100644 --- a/scripts/o3de/o3de/enable_gem.py +++ b/scripts/o3de/o3de/enable_gem.py @@ -115,9 +115,6 @@ def enable_gem_in_project(gem_name: str = None, def _run_enable_gem_in_project(args: argparse) -> int: - if args.override_home_folder: - manifest.override_home_folder = args.override_home_folder - return enable_gem_in_project(args.gem_name, args.gem_path, args.project_name, @@ -150,9 +147,6 @@ def add_parser_args(parser): help='The cmake enabled_gem file in which the gem names are specified.' 'If not specified it will assume enabled_gems.cmake') - parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False, - help='By default the home folder is the user folder, override it to this folder.') - parser.set_defaults(func=_run_enable_gem_in_project) diff --git a/scripts/o3de/o3de/engine_template.py b/scripts/o3de/o3de/engine_template.py index 6b2e098cf0..d9993fb5d0 100755 --- a/scripts/o3de/o3de/engine_template.py +++ b/scripts/o3de/o3de/engine_template.py @@ -80,10 +80,20 @@ restricted_platforms = { 'Provo', 'Salem', 'Jasper', - 'Paris' + 'Paris', + 'Xenia', + 'Lancaster' } -template_file_name = 'template.json' +O3DE_LICENSE_TEXT = \ + """'# {BEGIN_LICENSE} +# Copyright (c) Contributors to the Open 3D Engine Project. +# For complete copyright and license terms please see the LICENSE at the root of this distribution. +# +# SPDX-License-Identifier: Apache-2.0 OR MIT +# {END_LICENSE} +""" + this_script_parent = pathlib.Path(os.path.dirname(os.path.realpath(__file__))) @@ -165,7 +175,8 @@ def _execute_template_json(json_data: dict, destination_path: pathlib.Path, template_path: pathlib.Path, replacements: list, - keep_license_text: bool = False) -> None: + keep_license_text: bool = False, + keep_restricted_in_instance: bool = False) -> None: # create dirs first # for each createDirectory entry, transform the folder name for create_directory in json_data['createDirectories']: @@ -174,6 +185,18 @@ def _execute_template_json(json_data: dict, # transform the folder name new_dir = _transform(new_dir.as_posix(), replacements, keep_license_text) + new_dir = pathlib.Path(new_dir) + + if not keep_restricted_in_instance and 'Platform' in new_dir.parts: + try: + # the name of the Platform should follow the '/Platform/' + pattern = r'/Platform/(?P[^/:*?\"<>|\r\n]+/?)' + found_platform = re.search(pattern, new_dir.as_posix()).group('Platform') + found_platform = found_platform.replace('/', '') + if found_platform in restricted_platforms: + continue + except Exception as e: + pass # create the folder os.makedirs(new_dir, exist_ok=True) @@ -184,16 +207,23 @@ def _execute_template_json(json_data: dict, # construct the input file name in_file = template_path / 'Template' / copy_file['file'] - # the file can be marked as optional, if it is and it does not exist skip - if copy_file['isOptional'] and copy_file['isOptional'] == 'true': - if not os.path.isfile(in_file): - continue - # construct the output file name out_file = destination_path / copy_file['file'] # transform the output file name out_file = _transform(out_file.as_posix(), replacements, keep_license_text) + out_file = pathlib.Path(out_file) + + if not keep_restricted_in_instance and 'Platform' in out_file.parts: + try: + # the name of the Platform should follow the '/Platform/' + pattern = r'/Platform/(?P[^/:*?\"<>|\r\n]+/?)' + found_platform = re.search(pattern, out_file.as_posix()).group('Platform') + found_platform = found_platform.replace('/', '') + if found_platform in restricted_platforms: + continue + except Exception as e: + pass # if for some reason the output folder for this file was not created above do it now os.makedirs(os.path.dirname(out_file), exist_ok=True) @@ -205,18 +235,20 @@ def _execute_template_json(json_data: dict, shutil.copy(in_file, out_file) -def _execute_restricted_template_json(json_data: dict, +def _execute_restricted_template_json(template_json_data: dict, + json_data: dict, restricted_platform: str, destination_name, - template_name, destination_path: pathlib.Path, destination_restricted_path: pathlib.Path, + template_path: pathlib.Path, template_restricted_path: pathlib.Path, destination_restricted_platform_relative_path: pathlib.Path, template_restricted_platform_relative_path: pathlib.Path, replacements: list, keep_restricted_in_instance: bool = False, keep_license_text: bool = False) -> None: + # if we are not keeping restricted in instance make restricted.json if not present if not keep_restricted_in_instance: restricted_json = destination_restricted_path / 'restricted.json' @@ -227,50 +259,96 @@ def _execute_restricted_template_json(json_data: dict, restricted_json_data.update({"restricted_name": destination_name}) s.write(json.dumps(restricted_json_data, indent=4) + '\n') + ################################################################################### + # for each createDirectories in the template copy any entries in the json_data that are for this platform + for create_directory in template_json_data['createDirectories']: + new_dir = pathlib.Path(create_directory['dir']) + if not keep_restricted_in_instance and 'Platform' in new_dir.parts: + try: + # the name of the Platform should follow the '/Platform/' + pattern = r'/Platform/(?P[^/:*?\"<>|\r\n]+/?)' + found_platform = re.search(pattern, new_dir.as_posix()).group('Platform') + except Exception as e: + pass + else: + found_platform = found_platform.replace('/', '') + if found_platform == restricted_platform: + create_dirs = [] + if 'createDirectories' in json_data.keys(): + create_dirs = json_data['createDirectories'] + create_dirs.append(create_directory) + json_data.update({'createDirectories': create_dirs}) + + # for each copyFiles in the template copy any entries in the json_data that are for this platform + for copy_file in template_json_data['copyFiles']: + new_file = pathlib.Path(copy_file['file']) + if not keep_restricted_in_instance and 'Platform' in new_file.parts: + try: + # the name of the Platform should follow the '/Platform/' + pattern = r'/Platform/(?P[^/:*?\"<>|\r\n]+/?)' + found_platform = re.search(pattern, new_file.as_posix()).group('Platform') + except Exception as e: + pass + else: + found_platform = found_platform.replace('/', '') + if found_platform == restricted_platform: + copy_files = [] + if 'copyFiles' in json_data.keys(): + copy_files = json_data['copyFiles'] + copy_files.append(copy_file) + json_data.update({'copyFiles': copy_files}) + + ################################################################################### + + # every entry is saved in its combined location, so if not keep_restricted_in_instance + # then we need to palify into the restricted folder + # create dirs first # for each createDirectory entry, transform the folder name - for create_directory in json_data['createDirectories']: - # construct the new folder name - new_dir = destination_restricted_path / restricted_platform / destination_restricted_platform_relative_path\ - / destination_name / create_directory['dir'] - if keep_restricted_in_instance: - new_dir = destination_path / create_directory['origin'] + if 'createDirectories' in json_data: + for create_directory in json_data['createDirectories']: + # construct the new folder name + if keep_restricted_in_instance: + new_dir = destination_path / create_directory['dir'] + else: + pal_dir = create_directory['dir'].replace(f'Platform/{restricted_platform}','') + new_dir = destination_restricted_path / restricted_platform / destination_restricted_platform_relative_path / pal_dir - # transform the folder name - new_dir = _transform(new_dir.as_posix(), replacements, keep_license_text) + # transform the folder name + new_dir = _transform(new_dir.as_posix(), replacements, keep_license_text) - # create the folder - os.makedirs(new_dir, exist_ok=True) + # create the folder + os.makedirs(new_dir, exist_ok=True) # for each copyFiles entry, _transformCopy the templated source file into a concrete instance file or # regular copy if not templated - for copy_file in json_data['copyFiles']: - # construct the input file name - in_file = template_restricted_path / restricted_platform / template_restricted_platform_relative_path\ - / template_name / 'Template' / copy_file['file'] + if 'copyFiles' in json_data: + for copy_file in json_data['copyFiles']: + # construct the input file name + if template_restricted_path: + pal_file = copy_file['file'].replace(f'Platform/{restricted_platform}/', '') + in_file = template_restricted_path / restricted_platform / template_restricted_platform_relative_path / 'Template' / pal_file + else: + in_file = template_path / 'Template' / copy_file['file'] - # the file can be marked as optional, if it is and it does not exist skip - if copy_file['isOptional'] and copy_file['isOptional'] == 'true': - if not os.path.isfile(in_file): - continue + # construct the output file name + if keep_restricted_in_instance: + out_file = destination_path / copy_file['file'] + else: + pal_file = copy_file['file'].replace(f'Platform/{restricted_platform}/', '') + out_file = destination_restricted_path / restricted_platform / destination_restricted_platform_relative_path / pal_file - # construct the output file name - out_file = destination_restricted_path / restricted_platform / destination_restricted_platform_relative_path\ - / destination_name / copy_file['file'] - if keep_restricted_in_instance: - out_file = destination_path / copy_file['origin'] + # transform the output file name + out_file = _transform(out_file.as_posix(), replacements, keep_license_text) - # transform the output file name - out_file = _transform(out_file.as_posix(), replacements, keep_license_text) + # if for some reason the output folder for this file was not created above do it now + os.makedirs(os.path.dirname(out_file), exist_ok=True) - # if for some reason the output folder for this file was not created above do it now - os.makedirs(os.path.dirname(out_file), exist_ok=True) - - # if templated _transformCopy the file, if not just copy it - if copy_file['isTemplated']: - _transform_copy(in_file, out_file, replacements, keep_license_text) - else: - shutil.copy(in_file, out_file) + # if templated _transformCopy the file, if not just copy it + if copy_file['isTemplated']: + _transform_copy(in_file, out_file, replacements, keep_license_text) + else: + shutil.copy(in_file, out_file) def _instantiate_template(template_json_data: dict, @@ -309,46 +387,51 @@ def _instantiate_template(template_json_data: dict, :return: 0 for success or non 0 failure code """ # execute the template json + # this will filter out any restricted platforms in the template _execute_template_json(template_json_data, destination_path, template_path, replacements, - keep_license_text) + keep_license_text, + keep_restricted_in_instance) - # execute restricted platform jsons if any - if template_restricted_path: - for restricted_platform in os.listdir(template_restricted_path): - if os.path.isfile(restricted_platform): - continue + # we execute the jason data again if there are any restricted platforms in the main template and + # execute any restricted platform jsons if separate + + for restricted_platform in restricted_platforms: + restricted_json_data = {} + if template_restricted_path: template_restricted_platform = template_restricted_path / restricted_platform - template_restricted_platform_path_rel = template_restricted_platform / template_restricted_platform_relative_path / template_name - platform_json = template_restricted_platform_path_rel / template_file_name + template_restricted_platform_path_rel = template_restricted_platform / template_restricted_platform_relative_path + platform_json = template_restricted_platform_path_rel / 'template.json' if os.path.isfile(platform_json): if not validation.valid_o3de_template_json(platform_json): logger.error(f'Template json {platform_json} is invalid.') return 1 - # load the template json and execute it + # load the template json with open(platform_json, 'r') as s: try: - json_data = json.load(s) + restricted_json_data = json.load(s) except json.JSONDecodeError as e: logger.error(f'Failed to load {platform_json}: ' + str(e)) return 1 - else: - _execute_restricted_template_json(json_data, - restricted_platform, - destination_name, - template_name, - destination_path, - destination_restricted_path, - template_restricted_path, - destination_restricted_platform_relative_path, - template_restricted_platform_relative_path, - replacements, - keep_restricted_in_instance, - keep_license_text) + + # execute for this restricted platform + _execute_restricted_template_json(template_json_data, + restricted_json_data, + restricted_platform, + destination_name, + destination_path, + destination_restricted_path, + template_path, + template_restricted_path, + destination_restricted_platform_relative_path, + template_restricted_platform_relative_path, + replacements, + keep_restricted_in_instance, + keep_license_text) return 0 @@ -365,7 +448,8 @@ def create_template(source_path: pathlib.Path, keep_restricted_in_template: bool = False, keep_license_text: bool = False, replace: list = None, - force: bool = False) -> int: + force: bool = False, + no_register: bool = False) -> int: """ Create a template from a source directory using replacement @@ -391,6 +475,7 @@ def create_template(source_path: pathlib.Path, this controls if you want to keep the license text from the template in the new instance. It is false by default because most people will not want license text in their instances. :param force Overrides existing files even if they exist + :param no_register: whether or not after completion that the new object is registered :return: 0 for success or non 0 failure code """ @@ -401,15 +486,19 @@ def create_template(source_path: pathlib.Path, if not source_path.is_dir(): logger.error(f'Src path {source_path} is not a folder.') return 1 - source_path = source_path.resolve() - # source_name is now the last component of the source_path + + # if not specified, source_name defaults to the last component of the source_path if not source_name: source_name = os.path.basename(source_path) sanitized_source_name = utils.sanitize_identifier_for_cpp(source_name) # if no template path, use default_templates_folder path if not template_path: + logger.info(f'Template path empty. Using source name {source_name}') + template_path = source_name + # if the template_path is not an absolute path, then it default to relative from the default template folder + if not template_path.is_absolute(): default_templates_folder = manifest.get_registered(default_folder='templates') template_path = default_templates_folder / source_name logger.info(f'Template path empty. Using default templates folder {template_path}') @@ -423,7 +512,8 @@ def create_template(source_path: pathlib.Path, except ValueError: pass else: - logger.error(f'Template output path {template_path} cannot be a subdirectory of the source_path {source_path}\n') + logger.error( + f'Template output path {template_path} cannot be a subdirectory of the source_path {source_path}\n') return 1 # template name is now the last component of the template_path @@ -434,69 +524,61 @@ def create_template(source_path: pathlib.Path, logger.error(f'Template path cannot be a restricted name. {template_name}') return 1 + # if the source restricted name was given and no source restricted path, look up the restricted name to fill + # in the path if source_restricted_name and not source_restricted_path: source_restricted_path = manifest.get_registered(restricted_name=source_restricted_name) - # source_restricted_path + # if we have a source restricted path, make sure its a real restricted object if source_restricted_path: - if not os.path.isabs(source_restricted_path): - engine_json = manifest.get_this_engine_path() / 'engine.json' - if not validation.valid_o3de_engine_json(engine_json): - logger.error(f"Engine json {engine_json} is not valid.") - return 1 - with open(engine_json) as s: - try: - engine_json_data = json.load(s) - except json.JSONDecodeError as e: - logger.error(f"Failed to read engine json {engine_json}: {str(e)}") - return 1 - try: - engine_restricted = engine_json_data['restricted_name'] - except KeyError as e: - logger.error(f"Engine json {engine_json} restricted not found.") - return 1 - engine_restricted_folder = manifest.get_registered(restricted_name=engine_restricted) - new_source_restricted_path = engine_restricted_folder / source_restricted_path - logger.info(f'Source restricted path {source_restricted_path} not a full path. We must assume this engines' - f' restricted folder {new_source_restricted_path}') - if not os.path.isdir(source_restricted_path): + if not source_restricted_path.is_dir(): logger.error(f'Source restricted path {source_restricted_path} is not a folder.') return 1 + restricted_json = source_restricted_path / 'restricted.json' + if not validation.valid_o3de_restricted_json(restricted_json): + logger.error(f"Restricted json {restricted_json} is not valid.") + return 1 + with open(restricted_json, 'r') as s: + try: + restricted_json_data = json.load(s) + except json.JSONDecodeError as e: + logger.error(f'Failed to load {restricted_json}: ' + str(e)) + return 1 + try: + source_restricted_name = restricted_json_data['restricted_name'] + except KeyError as e: + logger.error(f'Failed to read restricted_name from {restricted_json}') + return 1 + # if the template restricted name was given and no template restricted path, look up the restricted name to fill + # in the path if template_restricted_name and not template_restricted_path: template_restricted_path = manifest.get_registered(restricted_name=template_restricted_name) + # if we dont have a template restricted name then set it to the templates name if not template_restricted_name: template_restricted_name = template_name - # template_restricted_path + # if we have a template restricted path, it must either not exist yet or must be a restricted object already if template_restricted_path: - if not os.path.isabs(template_restricted_path): - default_templates_restricted_folder = manifest.get_registered(restricted_name='templates') - new_template_restricted_path = default_templates_restricted_folder / template_restricted_path - logger.info(f'Template restricted path {template_restricted_path} not a full path. We must assume the' - f' default templates restricted folder {new_template_restricted_path}') - template_restricted_path = new_template_restricted_path - - if os.path.isdir(template_restricted_path): + if template_restricted_path.is_dir(): # see if this is already a restricted path, if it is get the "restricted_name" from the restricted json # so we can set "restricted_name" to it for this template restricted_json = template_restricted_path / 'restricted.json' - if os.path.isfile(restricted_json): - if not validation.valid_o3de_restricted_json(restricted_json): - logger.error(f'{restricted_json} is not valid.') + if not validation.valid_o3de_restricted_json(restricted_json): + logger.error(f'{restricted_json} is not valid.') + return 1 + with open(restricted_json, 'r') as s: + try: + restricted_json_data = json.load(s) + except json.JSONDecodeError as e: + logger.error(f'Failed to load {restricted_json}: ' + str(e)) + return 1 + try: + template_restricted_name = restricted_json_data['restricted_name'] + except KeyError as e: + logger.error(f'Failed to read restricted_name from {restricted_json}') return 1 - with open(restricted_json, 'r') as s: - try: - restricted_json_data = json.load(s) - except json.JSONDecodeError as e: - logger.error(f'Failed to load {restricted_json}: ' + str(e)) - return 1 - try: - template_restricted_name = restricted_json_data['restricted_name'] - except KeyError as e: - logger.error(f'Failed to read restricted_name from {restricted_json}') - return 1 else: os.makedirs(template_restricted_path, exist_ok=True) @@ -610,36 +692,7 @@ def create_template(source_path: pathlib.Path, else: return False, t_data - def _transform_into_template_restricted_filename(s_data: object, - platform: str) -> (bool, object): - """ - Internal function to transform a restricted platform file name into restricted template file name - :param s_data: the input data, this could be file data or file name data - :return: bool: whether or not the returned data MAY need to be transformed to instantiate it - t_data: potentially transformed data 0 for success or non 0 failure code - """ - # copy the src data to the transformed data, then operate only on transformed data - t_data = s_data - - # run all the replacements - for replacement in replacements: - t_data = t_data.replace(replacement[0], replacement[1]) - - # the name of the Platform should follow the '/Platform/{platform}' - t_data = t_data.replace(f"Platform/{platform}", '') - - # we want to send back the transformed data and whether or not this file - # may require transformation when instantiated. So if the input data is not the - # same as the output, then we transformed it which means there may be a transformation - # needed to instance it. - if s_data != t_data: - return True, t_data - else: - return False, t_data - - def _transform_restricted_into_copyfiles_and_createdirs(source_path: pathlib.Path, - restricted_platform: str, - root_abs: pathlib.Path, + def _transform_restricted_into_copyfiles_and_createdirs(root_abs: pathlib.Path, path_abs: pathlib.Path = None) -> None: """ Internal function recursively called to transform any paths files into copyfiles and create dirs relative to @@ -657,70 +710,49 @@ def create_template(source_path: pathlib.Path, # create the absolute entry by joining the path_abs and the entry entry_abs = path_abs / entry + # report what file we are processing so we have a good idea if it breaks on what file it broke on + logger.info(f'Processing file: {entry_abs}') + # create the relative entry by removing the root_abs try: entry_rel = entry_abs.relative_to(root_abs) except ValueError as err: - logger.warning(f'Unable to create relative path: {str(err)}') + logger.fatal(f'Unable to create relative path: {str(err)}') - # report what file we are processing so we have a good idea if it breaks on what file it broke on - logger.info(f'Processing file: {entry_abs}') - - # this is a restricted file, so we need to transform it, unpalify it - # restricted///some/folders/ -> - # /some/folders/Platform// - # - # C:/repo/Lumberyard/restricted/Jasper/TestDP/CMakeLists.txt -> - # C:/repo/Lumberyard/TestDP/Platform/Jasper/CMakeLists.txt - # - _, origin_entry_rel = _transform_into_template(entry_rel.as_posix()) - components = list(origin_entry_rel.parts) - num_components = len(components) - - # see how far along the source path the restricted folder matches - # then hopefully there is a Platform folder, warn if there isn't - before = [] - after = [] - relative = '' - - if os.path.isdir(entry_abs): - for x in range(0, num_components): - relative += f'{components[x]}/' - if os.path.isdir(f'{source_path}/{relative}'): - before.append(components[x]) - else: - after.append(components[x]) - else: - for x in range(0, num_components - 1): - relative += f'{components[x]}/' - if os.path.isdir(f'{source_path}/{relative}'): - before.append(components[x]) - else: - after.append(components[x]) - - after.append(components[num_components - 1]) - - before.append("Platform") - warn_if_not_platform = source_path / pathlib.Path(*before) - before.append(restricted_platform) - before.extend(after) - - origin_entry_rel = pathlib.Path(*before) - - if not os.path.isdir(warn_if_not_platform): - logger.warning( - f'{entry_abs} -> {origin_entry_rel}: Other Platforms not found in {warn_if_not_platform}') - - destination_entry_rel = origin_entry_rel - destination_entry_abs = template_path / 'Template' / origin_entry_rel + # templatize the entry relative into the destination entry relative + _, destination_entry_rel = _transform_into_template(entry_rel.as_posix()) + destination_entry_rel = pathlib.Path(destination_entry_rel) # clean up any relative leading slashes - if origin_entry_rel.as_posix().startswith('/'): - origin_entry_rel = pathlib.Path(origin_entry_rel.as_posix().lstrip('/')) if destination_entry_rel.as_posix().startswith('/'): destination_entry_rel = pathlib.Path(destination_entry_rel.as_posix().lstrip('/')) + if isinstance(destination_entry_rel, pathlib.Path): + destination_entry_rel = destination_entry_rel.as_posix() - # make sure the dst folder may or may not exist yet, make sure it does exist before we transform + if template_restricted_path: + destination_entry_abs = template_restricted_path / restricted_platform / template_restricted_platform_relative_path / 'Template' / destination_entry_rel + destination_entry_rel = pathlib.Path(destination_entry_rel) + first = True + for component in destination_entry_rel.parts: + if first: + first = False + result = pathlib.Path(component) / 'Platform' / restricted_platform + else: + result = result / component + destination_entry_rel = result.as_posix() + else: + destination_entry_rel = pathlib.Path(destination_entry_rel) + first = True + for component in destination_entry_rel.parts: + if first: + first = False + result = pathlib.Path(component) / 'Platform' / restricted_platform + else: + result = result / component + destination_entry_rel = result.as_posix() + destination_entry_abs = template_path / 'Template' / destination_entry_rel + + # the destination folder may or may not exist yet, make sure it does exist before we transform # data into it os.makedirs(os.path.dirname(destination_entry_abs), exist_ok=True) @@ -730,8 +762,8 @@ def create_template(source_path: pathlib.Path, if os.path.isfile(entry_abs): # if this file is a known binary file, there is no transformation needed and just copy it - # if not a known binary file open it and try to transform the data. if it is an unknown binary - # type it will throw and we catch copy + # if not a known binary file open it and try to transform the data. + # if it is an unknown binary type it will throw and we catch copy # if we had no known binary type it would still work, but much slower name, ext = os.path.splitext(entry) if ext in binary_file_ext: @@ -743,7 +775,7 @@ def create_template(source_path: pathlib.Path, source_data = s.read() templated, source_data = _transform_into_template(source_data, _is_cpp_file(entry_abs)) - # if the file type is a file that we expect to fins license header and we don't find any + # if the file type is a file that we expect to find a license header and we don't find any # warn that the we didn't find the license info, this makes it easy to make sure we didn't # miss any files we want to have license info in. if keep_license_text and ext in expect_license_info_ext: @@ -761,19 +793,26 @@ def create_template(source_path: pathlib.Path, shutil.copy(entry_abs, destination_entry_abs) pass - copy_files.append({ - "file": destination_entry_rel, - "origin": origin_entry_rel, - "isTemplated": templated, - "isOptional": False - }) + if keep_restricted_in_template: + copy_files.append({ + "file": destination_entry_rel, + "isTemplated": templated + }) + else: + restricted_platform_entries[restricted_platform]['copyFiles'].append({ + "file": destination_entry_rel, + "isTemplated": templated + }) else: - create_dirs.append({ - "dir": destination_entry_rel, - "origin": origin_entry_rel - }) - _transform_restricted_into_copyfiles_and_createdirs(source_path, restricted_platform, root_abs, - entry_abs) + if keep_restricted_in_template: + create_dirs.append({ + "dir": destination_entry_rel + }) + else: + restricted_platform_entries[restricted_platform]['createDirs'].append({ + "dir": destination_entry_rel + }) + _transform_restricted_into_copyfiles_and_createdirs(root_abs, entry_abs) def _transform_dir_into_copyfiles_and_createdirs(root_abs: pathlib.Path, path_abs: pathlib.Path = None) -> None: @@ -793,18 +832,21 @@ def create_template(source_path: pathlib.Path, # create the absolute entry by joining the path_abs and the entry entry_abs = path_abs / entry - # create the relative entry by removing the root_abs - entry_rel = entry_abs - try: - entry_rel = entry_abs.relative_to(root_abs) - except ValueError as err: - logger.warning(f'Unable to create relative path: {str(err)}') - # report what file we are processing so we have a good idea if it breaks on what file it broke on logger.info(f'Processing file: {entry_abs}') - # see if the entry is a platform file, if it is then we save its copyfile data in a platform specific list - # then at the end we can save the restricted ones separately + # create the relative entry by removing the root_abs + try: + entry_rel = entry_abs.relative_to(root_abs).as_posix() + except ValueError as err: + logger.fatal(f'Unable to create relative path: {str(err)}') + + # templatize the entry relative into the origin entry relative + _, destination_entry_rel = _transform_into_template(entry_rel) + destination_entry_rel = pathlib.Path(destination_entry_rel) + + # see if the entry is a restricted platform file, if it is then we save its copyfile data in a + # platform specific list then at the end we can save the restricted ones separately found_platform = '' platform = False if not keep_restricted_in_template and 'Platform' in entry_abs.parts: @@ -812,7 +854,7 @@ def create_template(source_path: pathlib.Path, try: # the name of the Platform should follow the '/Platform/' pattern = r'/Platform/(?P[^/:*?\"<>|\r\n]+/?)' - found_platform = re.search(pattern, entry_abs).group('Platform') + found_platform = re.search(pattern, entry_abs.as_posix()).group('Platform') found_platform = found_platform.replace('/', '') except Exception as e: pass @@ -831,30 +873,35 @@ def create_template(source_path: pathlib.Path, # Now if we found a platform and still have a found_platform which is a restricted platform # then transform the entry relative name into a dst relative entry name and dst abs entry. # if not then create a normal relative and abs dst entry name - _, origin_entry_rel = _transform_into_template(entry_rel.as_posix()) if platform and found_platform in restricted_platforms: # if we don't have a template restricted path and we found restricted files... warn and skip # the file/dir if not template_restricted_path: - logger.warning("Restricted platform files found!!! {entry_rel}, {found_platform}") + logger.warning("Restricted platform file found!!! {destination_entry_rel}, {found_platform}") continue - _, destination_entry_rel = _transform_into_template_restricted_filename(entry_rel, found_platform) - destination_entry_abs = template_restricted_path / found_platform\ - / template_restricted_platform_relative_path / template_name / 'Template'\ - / destination_entry_rel + + # run all the replacements + for replacement in replacements: + destination_entry_rel = destination_entry_rel.replace(replacement[0], replacement[1]) + + # the name of the Platform should follow the '/Platform/{found_platform}' + destination_entry_rel = destination_entry_rel.replace(f"Platform/{found_platform}", '') + destination_entry_rel = destination_entry_rel.lstrip('/') + + # construct the absolute entry from the relative + if template_restricted_platform_relative_path: + destination_entry_abs = template_restricted_path / found_platform / template_restricted_platform_relative_path / template_name / 'Template' / destination_entry_rel + else: + destination_entry_abs = template_restricted_path / found_platform / 'Template' / destination_entry_rel else: - destination_entry_rel = origin_entry_rel + # construct the absolute entry from the relative destination_entry_abs = template_path / 'Template' / destination_entry_rel # clean up any relative leading slashes - if isinstance(origin_entry_rel, pathlib.Path): - origin_entry_rel = origin_entry_rel.as_posix() - if origin_entry_rel.startswith('/'): - origin_entry_rel = pathlib.Path(origin_entry_rel.lstrip('/')) if isinstance(destination_entry_rel, pathlib.Path): destination_entry_rel = destination_entry_rel.as_posix() if destination_entry_rel.startswith('/'): - destination_entry_rel = pathlib.Path(destination_entry_rel.lstrip('/')) + destination_entry_rel = destination_entry_rel.lstrip('/') # make sure the dst folder may or may not exist yet, make sure it does exist before we transform # data into it @@ -902,29 +949,23 @@ def create_template(source_path: pathlib.Path, if platform and found_platform in restricted_platforms: restricted_platform_entries[found_platform]['copyFiles'].append({ "file": destination_entry_rel, - "origin": origin_entry_rel, - "isTemplated": templated, - "isOptional": False + "isTemplated": templated }) else: copy_files.append({ "file": destination_entry_rel, - "origin": origin_entry_rel, - "isTemplated": templated, - "isOptional": False + "isTemplated": templated }) else: # if the folder was for a restricted platform add the entry to the restricted platform, otherwise add it # to the non restricted if platform and found_platform in restricted_platforms: restricted_platform_entries[found_platform]['createDirs'].append({ - "dir": destination_entry_rel, - "origin": origin_entry_rel + "dir": destination_entry_rel }) else: create_dirs.append({ - "dir": destination_entry_rel, - "origin": origin_entry_rel + "dir": destination_entry_rel }) # recurse using the same root and this folder @@ -937,11 +978,11 @@ def create_template(source_path: pathlib.Path, # when we run the transformation any restricted platforms entries we find will go in here restricted_platform_entries = {} - # Every project will have a unrestricted folder which is src_path_abs which MAY have restricted files in it, and - # each project MAY have a restricted folder which will only have restricted files in them. The process is the + # Every template will have a unrestricted folder which is src_path_abs which MAY have restricted files in it, and + # each template MAY have a restricted folder which will only have restricted files in them. The process is the # same for all of them and the result will be a separation of all restricted files from unrestricted files. We do - # this by running the transformation first over the src path abs and then on each restricted folder for this project - # we find. This will effectively combine all sources then separates all the restricted. + # this by running the transformation first over the src path abs and then on each restricted folder for this + # template we find. This will effectively combine all sources then separates all the restricted. # run the transformation on the src, which may or may not have restricted files _transform_dir_into_copyfiles_and_createdirs(source_path) @@ -950,11 +991,12 @@ def create_template(source_path: pathlib.Path, # run the transformation on each src restricted folder if source_restricted_path: for restricted_platform in os.listdir(source_restricted_path): - restricted_platform_src_path_abs = source_restricted_path / restricted_platform\ - / source_restricted_platform_relative_path / source_name + restricted_platform_src_path_abs = source_restricted_path / restricted_platform \ + / source_restricted_platform_relative_path if os.path.isdir(restricted_platform_src_path_abs): - _transform_restricted_into_copyfiles_and_createdirs(source_path, restricted_platform, - restricted_platform_src_path_abs) + if restricted_platform not in restricted_platform_entries: + restricted_platform_entries.update({restricted_platform: {'copyFiles': [], 'createDirs': []}}) + _transform_restricted_into_copyfiles_and_createdirs(restricted_platform_src_path_abs) # sort copy_files.sort(key=lambda x: x['file']) @@ -972,39 +1014,47 @@ def create_template(source_path: pathlib.Path, json_data.update({'canonical_tags': []}) json_data.update({'user_tags': [f"{template_name}"]}) json_data.update({'icon_path': "preview.png"}) - if template_restricted_path: + if not keep_restricted_in_template and template_restricted_path: json_data.update({'restricted_name': template_restricted_name}) if template_restricted_platform_relative_path != '': - json_data.update({'template_restricted_platform_relative_path': template_restricted_platform_relative_path}) + json_data.update({'template_restricted_platform_relative_path': template_restricted_platform_relative_path.as_posix()}) json_data.update({'copyFiles': copy_files}) json_data.update({'createDirectories': create_dirs}) - json_name = template_path / template_file_name + json_name = template_path / source_restricted_platform_relative_path / 'template.json' with json_name.open('w') as s: s.write(json.dumps(json_data, indent=4) + '\n') # copy the default preview.png preview_png_src = this_script_parent / 'resources' / 'preview.png' - preview_png_dst = template_path / 'Template' / 'preview.png' + preview_png_dst = template_path / 'preview.png' if not os.path.isfile(preview_png_dst): shutil.copy(preview_png_src, preview_png_dst) # if no restricted template path was given and restricted platform files were found - if not template_restricted_path and len(restricted_platform_entries): + if not keep_restricted_in_template and not template_restricted_path and len(restricted_platform_entries): logger.info(f'Restricted platform files found!!! and no template restricted path was found...') - if template_restricted_path: + if not keep_restricted_in_template and template_restricted_path: + json_name = template_restricted_path / 'restricted.json' + if not json_name.is_file(): + json_data = {} + json_data.update({'restricted_name': template_restricted_name}) + os.makedirs(os.path.dirname(json_name), exist_ok=True) + + with json_name.open('w') as s: + s.write(json.dumps(json_data, indent=4) + '\n') + # now write out each restricted platform template json separately for restricted_platform in restricted_platform_entries: - restricted_template_path = template_restricted_path / restricted_platform\ - / template_restricted_platform_relative_path / template_name - + restricted_template_path = template_restricted_path / restricted_platform / template_restricted_platform_relative_path # sort restricted_platform_entries[restricted_platform]['copyFiles'].sort(key=lambda x: x['file']) restricted_platform_entries[restricted_platform]['createDirs'].sort(key=lambda x: x['dir']) json_data = {} + json_data.update({'restricted_name': template_name}) json_data.update({'template_name': template_name}) json_data.update( {'origin': f'The primary repo for {template_name} goes here: i.e. http://www.mydomain.com'}) @@ -1012,23 +1062,25 @@ def create_template(source_path: pathlib.Path, {'license': f'What license {template_name} uses goes here: i.e. https://opensource.org/licenses/MIT'}) json_data.update({'display_name': template_name}) json_data.update({'summary': f"A short description of {template_name}."}) - json_data.update({'canonical_tags': []}) + json_data.update({'canonical_tags': [f'{restricted_platform}']}) json_data.update({'user_tags': [f'{template_name}']}) - json_data.update({'icon_path': "preview.png"}) json_data.update({'copyFiles': restricted_platform_entries[restricted_platform]['copyFiles']}) json_data.update({'createDirectories': restricted_platform_entries[restricted_platform]['createDirs']}) - json_name = restricted_template_path / template_file_name + json_name = restricted_template_path / 'template.json' os.makedirs(os.path.dirname(json_name), exist_ok=True) with json_name.open('w') as s: s.write(json.dumps(json_data, indent=4) + '\n') - preview_png_dst = restricted_template_path / 'Template' /' preview.png' - if not os.path.isfile(preview_png_dst): - shutil.copy(preview_png_src, preview_png_dst) + # Register the restricted + if not no_register: + if register.register(restricted_path=template_restricted_path): + logger.error(f'Failed to register the restricted {template_restricted_path}.') + return 1 - return 0 + # Register the template + return register.register(template_path=template_path) if not no_register else 0 def create_from_template(destination_path: pathlib.Path, @@ -1044,7 +1096,8 @@ def create_from_template(destination_path: pathlib.Path, keep_restricted_in_instance: bool = False, keep_license_text: bool = False, replace: list = None, - force: bool = False) -> int: + force: bool = False, + no_register: bool = False) -> int: """ Generic template instantiation for non o3de object templates. This function makes NO assumptions! Assumptions are made only for specializations like create_project or create_gem etc... So this function @@ -1251,17 +1304,18 @@ def create_from_template(destination_path: pathlib.Path, # destination restricted path elif destination_restricted_path: - if os.path.isabs(destination_restricted_path): + if not os.path.isabs(destination_restricted_path): restricted_default_path = manifest.get_registered(default_folder='restricted') - new_destination_restricted_path = restricted_default_path / destination_restricted_path + new_destination_restricted_path = restricted_default_path / "Templates" / destination_restricted_path logger.info(f'{destination_restricted_path} is not a full path, making it relative' f' to default restricted path = {new_destination_restricted_path}') destination_restricted_path = new_destination_restricted_path - elif template_restricted_path: - restricted_default_path = manifest.get_registered(restricted_name='restricted') - logger.info(f'--destination-restricted-path is not specified, using default restricted path / destination name' - f' = {restricted_default_path}') - destination_restricted_path = restricted_default_path + else: + restricted_default_path = manifest.get_registered(default_folder='restricted') + new_destination_restricted_path = restricted_default_path / "Templates" / destination_name + logger.info(f'--destination-restricted-path is not specified, using default restricted path' + f' / Templates / destination name = {new_destination_restricted_path}') + destination_restricted_path = new_destination_restricted_path # destination restricted relative if not destination_restricted_platform_relative_path: @@ -1306,7 +1360,7 @@ def create_from_template(destination_path: pathlib.Path, if destination_restricted_path: os.makedirs(destination_restricted_path, exist_ok=True) - # read the restricted_name from the destination restricted.json + # write the restricted_name to the destination restricted.json restricted_json = destination_restricted_path / 'restricted.json' if not os.path.isfile(restricted_json): with open(restricted_json, 'w') as s: @@ -1314,6 +1368,12 @@ def create_from_template(destination_path: pathlib.Path, restricted_json_data.update({'restricted_name': destination_name}) s.write(json.dumps(restricted_json_data, indent=4) + '\n') + # Register the restricted + if not no_register: + if register.register(restricted_path=destination_restricted_path): + logger.error(f'Failed to register the restricted {destination_restricted_path}.') + return 1 + logger.warning(f'Instantiation successful. NOTE: This is a generic instantiation of the template. If this' f' was a template of an o3de object like a project, gem, template, etc. then the create-project' f' or create-gem command can be used to register the object type via its project.json or gem.json, etc.' @@ -1364,6 +1424,7 @@ def create_project(project_path: pathlib.Path, Ex. ${Name},TestGem,${Player},TestGemPlayer This will cause all references to ${Name} be replaced by TestGem, and all ${Player} replaced by 'TestGemPlayer' :param force Overrides existing files even if they exist + :param no_register: whether or not after completion that the new object is registered :param system_component_class_id: optionally specify a uuid for the system component class, default is random uuid :param editor_system_component_class_id: optionally specify a uuid for the editor system component class, default is random uuid @@ -1422,12 +1483,10 @@ def create_project(project_path: pathlib.Path, # see if the template itself specifies a restricted name if not template_restricted_name and not template_restricted_path: try: - template_json_restricted_name = template_json_data['restricted_name'] + template_restricted_name = template_json_data['restricted_name'] except KeyError as e: # the template json doesn't have a 'restricted_name' element warn and use it logger.info(f'The template does not specify a "restricted_name".') - else: - template_restricted_name = template_json_restricted_name # if no restricted name or path we continue on as if there is no template restricted files. if template_restricted_name or template_restricted_path: @@ -1523,8 +1582,13 @@ def create_project(project_path: pathlib.Path, if not project_path: logger.error('Project path cannot be empty.') return 1 - project_path = project_path.resolve() + if not os.path.isabs(project_path): + default_projects_folder = manifest.get_registered(default_folder='projects') + new_project_path = default_projects_folder / project_path + logger.info(f'Project Path {project_path} is not a full path, we must assume its relative' + f' to default projects path = {new_project_path}') + project_path = new_project_path if not force and project_path.is_dir() and len(list(project_path.iterdir())): logger.error(f'Project path {project_path} already exists and is not empty.') return 1 @@ -1536,7 +1600,8 @@ def create_project(project_path: pathlib.Path, project_name = os.path.basename(project_path) if not utils.validate_identifier(project_name): - logger.error(f'Project name must be fewer than 64 characters, contain only alphanumeric, "_" or "-" characters, and start with a letter. {project_name}') + logger.error( + f'Project name must be fewer than 64 characters, contain only alphanumeric, "_" or "-" characters, and start with a letter. {project_name}') return 1 # project name cannot be the same as a restricted platform name @@ -1546,21 +1611,19 @@ def create_project(project_path: pathlib.Path, # project restricted name if project_restricted_name and not project_restricted_path: - project_restricted_path = manifest.get_registered(restricted_name=project_restricted_name) + gem_restricted_path = manifest.get_registered(restricted_name=project_restricted_name) + if not gem_restricted_path: + logger.error(f'Project Restricted Name {project_restricted_name} cannot be found.') + return 1 # project restricted path - elif project_restricted_path: + if project_restricted_path: if not os.path.isabs(project_restricted_path): - default_projects_restricted_folder = manifest.get_registered(restricted_name='projects') - new_project_restricted_path = default_projects_restricted_folder/ project_restricted_path - logger.info(f'Project restricted path {project_restricted_path} is not a full path, we must assume its' - f' relative to default projects restricted path = {new_project_restricted_path}') - project_restricted_path = new_project_restricted_path - elif template_restricted_path: - project_restricted_default_path = manifest.get_registered(restricted_name='projects') - logger.info(f'--project-restricted-path is not specified, using default project restricted path / project name' - f' = {project_restricted_default_path}') - project_restricted_path = project_restricted_default_path + logger.error(f'Project Restricted Path {project_restricted_path} is not an absolute path.') + return 1 + # neither put it in the default restricted projects + else: + project_restricted_path = manifest.get_o3de_restricted_folder() / 'Projects' / project_name # project restricted relative path if not project_restricted_platform_relative_path: @@ -1639,7 +1702,7 @@ def create_project(project_path: pathlib.Path, os.makedirs(project_restricted_path, exist_ok=True) # read the restricted_name from the projects restricted.json - restricted_json = project_restricted_path / 'restricted.json' + restricted_json = project_restricted_path / 'restricted.json' if os.path.isfile(restricted_json): if not validation.valid_o3de_restricted_json(restricted_json): logger.error(f'Restricted json {restricted_json} is not valid.') @@ -1663,7 +1726,8 @@ def create_project(project_path: pathlib.Path, logger.error(f'Failed to read "restricted_name" from restricted json {restricted_json}.') return 1 - # set the "restricted_name": "restricted_name" element of the project.json + # set the "restricted": element of the project.json + project_json = project_path / 'project.json' if not validation.valid_o3de_project_json(project_json): logger.error(f'Project json {project_json} is not valid.') return 1 @@ -1675,7 +1739,7 @@ def create_project(project_path: pathlib.Path, logger.error(f'Failed to load project json {project_json}.') return 1 - project_json_data.update({"restricted_name": restricted_name}) + project_json_data.update({"restricted": restricted_name}) os.unlink(project_json) with open(project_json, 'w') as s: try: @@ -1684,20 +1748,11 @@ def create_project(project_path: pathlib.Path, logger.error(f'Failed to write project json {project_json}.') return 1 - for restricted_platform in restricted_platforms: - restricted_project = project_restricted_path / restricted_platform / project_name - os.makedirs(restricted_project, exist_ok=True) - cmakelists_file_name = restricted_project/ 'CMakeLists.txt' - if not os.path.isfile(cmakelists_file_name): - with open(cmakelists_file_name, 'w') as d: - if keep_license_text: - d.write('# {BEGIN_LICENSE}\n') - d.write('# Copyright (c) Contributors to the Open 3D Engine Project.\n') - d.write('# For complete copyright and license terms please see the LICENSE at the root of this distribution.\n') - d.write('#\n') - d.write('# SPDX-License-Identifier: Apache-2.0 OR MIT\n') - d.write('# {END_LICENSE}\n') - + # Register the restricted + if not no_register: + if register.register(restricted_path=project_restricted_path): + logger.error(f'Failed to register the restricted {project_restricted_path}.') + return 1 # Register the project with the either o3de_manifest.json or engine.json # and set the project.json "engine" field to match the @@ -1906,10 +1961,15 @@ def create_gem(gem_path: pathlib.Path, if not gem_path: logger.error('Gem path cannot be empty.') return 1 - gem_path = gem_path.resolve() + if not os.path.isabs(gem_path): + default_gems_folder = manifest.get_registered(default_folder='gems') + new_gem_path = default_gems_folder / gem_path + logger.info(f'Gem Path {gem_path} is not a full path, we must assume its relative' + f' to default gems path = {new_gem_path}') + gem_path = new_gem_path if not force and gem_path.is_dir() and len(list(gem_path.iterdir())): - logger.error(f'Gem path {gem_path} already exists and is not empty.') + logger.error(f'Gem path {gem_path} already exists.') return 1 else: os.makedirs(gem_path, exist_ok=force) @@ -1930,22 +1990,18 @@ def create_gem(gem_path: pathlib.Path, # gem restricted name if gem_restricted_name and not gem_restricted_path: gem_restricted_path = manifest.get_registered(restricted_name=gem_restricted_name) + if not gem_restricted_path: + logger.error(f'Gem Restricted Name {gem_restricted_name} cannot be found.') + return 1 # gem restricted path - elif gem_restricted_path: + if gem_restricted_path: if not os.path.isabs(gem_restricted_path): - gem_restricted_default_path = manifest.get_registered(restricted_name='gems') - if gem_restricted_default_path: - new_gem_restricted_path = gem_restricted_default_path / gem_restricted_path - logger.info(f'Gem restricted path {gem_restricted_path} is not a full path, we must assume its' - f' relative to default gems restricted path = {new_gem_restricted_path}') - gem_restricted_path = new_gem_restricted_path + logger.error(f'Gem Restricted Path {gem_restricted_path} is not an absolute path.') + return 1 + # neither put it in the default restricted gems else: - gem_restricted_default_path = manifest.get_registered(restricted_name='gems') - if gem_restricted_default_path: - logger.info(f'--gem-restricted-path is not specified, using default / ' - f' = {gem_restricted_default_path}') - gem_restricted_path = gem_restricted_default_path / gem_name + gem_restricted_path = manifest.get_o3de_restricted_folder() / "Gems" / gem_name # gem restricted relative if not gem_restricted_platform_relative_path: @@ -2035,47 +2091,49 @@ def create_gem(gem_path: pathlib.Path, logger.error(f'Failed to load restricted json {restricted_json}.') return 1 + try: + restricted_name = restricted_json_data["restricted_name"] + except KeyError as e: + logger.error(f'Failed to read "restricted_name" from restricted json {restricted_json}.') + return 1 + + # set the "restricted_name": element of the gem.json + gem_json = gem_path / 'gem.json' + if not validation.valid_o3de_gem_json(gem_json): + logger.error(f'Gem json {gem_json} is not valid.') + return 1 + + with open(gem_json, 'r') as s: try: - restricted_name = restricted_json_data["restricted_name"] - except KeyError as e: - logger.error(f'Failed to read "restricted_name" from restricted json {restricted_json}.') + gem_json_data = json.load(s) + except json.JSONDecodeError as e: + logger.error(f'Failed to load gem json {gem_json}.') return 1 - # set the "restricted_name": "restricted_name" element of the gem.json - gem_json = gem_path / 'gem.json' - if not validation.valid_o3de_gem_json(gem_json): - logger.error(f'Gem json {gem_json} is not valid.') + gem_json_data.update({"restricted": restricted_name}) + os.unlink(gem_json) + with open(gem_json, 'w') as s: + try: + s.write(json.dumps(gem_json_data, indent=4) + '\n') + except OSError as e: + logger.error(f'Failed to write project json {gem_json}.') + return 1 + ''' + for restricted_platform in restricted_platforms: + restricted_gem = gem_restricted_path / restricted_platform / gem_name + os.makedirs(restricted_gem, exist_ok=True) + cmakelists_file_name = restricted_gem / 'CMakeLists.txt' + if not os.path.isfile(cmakelists_file_name): + with open(cmakelists_file_name, 'w') as d: + if keep_license_text: + d.write(O3DE_LICENSE_TEXT) + ''' + # Register the restricted + if not no_register: + if register.register(restricted_path=gem_restricted_path): + logger.error(f'Failed to register the restricted {gem_restricted_path}.') return 1 - with open(gem_json, 'r') as s: - try: - gem_json_data = json.load(s) - except json.JSONDecodeError as e: - logger.error(f'Failed to load gem json {gem_json}.') - return 1 - - gem_json_data.update({"restricted_name": restricted_name}) - os.unlink(gem_json) - with open(gem_json, 'w') as s: - try: - s.write(json.dumps(gem_json_data, indent=4) + '\n') - except OSError as e: - logger.error(f'Failed to write project json {gem_json}.') - return 1 - - for restricted_platform in restricted_platforms: - restricted_gem = gem_restricted_path / restricted_platform/ gem_name - os.makedirs(restricted_gem, exist_ok=True) - cmakelists_file_name = restricted_gem / 'CMakeLists.txt' - if not os.path.isfile(cmakelists_file_name): - with open(cmakelists_file_name, 'w') as d: - if keep_license_text: - d.write('# {BEGIN_LICENSE}\n') - d.write('# Copyright (c) Contributors to the Open 3D Engine Project.\n') - d.write('# For complete copyright and license terms please see the LICENSE at the root of this distribution.\n') - d.write('#\n') - d.write('# SPDX-License-Identifier: Apache-2.0 OR MIT\n') - d.write('# {END_LICENSE}\n') # Register the gem with the either o3de_manifest.json, engine.json or project.json based on the gem path return register.register(gem_path=gem_path) if not no_register else 0 @@ -2093,7 +2151,8 @@ def _run_create_template(args: argparse) -> int: args.keep_restricted_in_template, args.keep_license_text, args.replace, - args.force) + args.force, + args.no_register) def _run_create_from_template(args: argparse) -> int: @@ -2110,7 +2169,8 @@ def _run_create_from_template(args: argparse) -> int: args.keep_restricted_in_instance, args.keep_license_text, args.replace, - args.force) + args.force, + args.no_register) def _run_create_project(args: argparse) -> int: @@ -2166,7 +2226,6 @@ def add_args(subparsers) -> None: call add_args and execute: python o3de.py create-gem --gem-path TestGem :param subparsers: the caller instantiates subparsers and passes it in here """ - # turn a directory into a template create_template_subparser = subparsers.add_parser('create-template') @@ -2242,7 +2301,10 @@ def add_args(subparsers) -> None: ' Note: is automatically ${NameLower}' ' Note: is automatically ${NameUpper}') create_template_subparser.add_argument('-f', '--force', action='store_true', default=False, - help='Copies to new template directory even if it exist.') + help='Copies to new template directory even if it exist.') + create_template_subparser.add_argument('--no-register', action='store_true', default=False, + help='If the template is created successfully, it will not register the' + ' template with the global or engine manifest file.') create_template_subparser.set_defaults(func=_run_create_template) # create from template @@ -2268,11 +2330,11 @@ def add_args(subparsers) -> None: ' resolve the --template-path.') create_from_template_subparser.add_argument('-dn', '--destination-name', type=str, - help='The name to use when substituting the ${Name} placeholder in instantiated template,' - ' must be alphanumeric, ' - ' and can contain _ and - characters.' - ' If no name is provided, will use last component of destination path.' - ' Ex. New_Gem') + help='The name to use when substituting the ${Name} placeholder in instantiated template,' + ' must be alphanumeric, ' + ' and can contain _ and - characters.' + ' If no name is provided, will use last component of destination path.' + ' Ex. New_Gem') group = create_from_template_subparser.add_mutually_exclusive_group(required=False) group.add_argument('-drp', '--destination-restricted-path', type=pathlib.Path, required=False, @@ -2293,7 +2355,8 @@ def add_args(subparsers) -> None: help='The name of the registered restricted path to read from if any. If supplied this will' ' resolve the --template-restricted-path.') - create_from_template_subparser.add_argument('-drprp', '--destination-restricted-platform-relative-path', type=pathlib.Path, + create_from_template_subparser.add_argument('-drprp', '--destination-restricted-platform-relative-path', + type=pathlib.Path, required=False, default=None, help='Any path to append to the --destination-restricted-path/' @@ -2301,7 +2364,8 @@ def add_args(subparsers) -> None: ' --destination-restricted-path C:/instance' ' --destination-restricted-platform-relative-path some/folder' ' => C:/instance//some/folder/') - create_from_template_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', type=pathlib.Path, + create_from_template_subparser.add_argument('-trprp', '--template-restricted-platform-relative-path', + type=pathlib.Path, required=False, default=None, help='Any path to append to the --template-restricted-path/' @@ -2329,7 +2393,10 @@ def add_args(subparsers) -> None: ' Note: ${NameLower} is automatically ' ' Note: ${NameUpper} is automatically ') create_from_template_subparser.add_argument('-f', '--force', action='store_true', default=False, - help='Copies over instantiated template directory even if it exist.') + help='Copies over instantiated template directory even if it exist.') + create_from_template_subparser.add_argument('--no-register', action='store_true', default=False, + help='If the project template is instantiated successfully, it will not register the' + ' project with the global or engine manifest file.') create_from_template_subparser.set_defaults(func=_run_create_from_template) # creation of a project from a template (like create from template but makes project assumptions) @@ -2430,10 +2497,10 @@ def add_args(subparsers) -> None: help='The str id you want to associate with the project, default is a random uuid' ' Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') create_project_subparser.add_argument('-f', '--force', action='store_true', default=False, - help='Copies over instantiated template directory even if it exist.') + help='Copies over instantiated template directory even if it exist.') create_project_subparser.add_argument('--no-register', action='store_true', default=False, - help='If the project template is instantiated successfully, it will not register the' - ' project with the global or engine manifest file.') + help='If the project template is instantiated successfully, it will not register the' + ' project with the global or engine manifest file.') create_project_subparser.set_defaults(func=_run_create_project) # creation of a gem from a template (like create from template but makes gem assumptions) @@ -2445,11 +2512,11 @@ def add_args(subparsers) -> None: create_gem_subparser.add_argument('-gp', '--gem-path', type=pathlib.Path, required=True, help='The gem path, can be absolute or relative to the current working directory') create_gem_subparser.add_argument('-gn', '--gem-name', type=str, - help='The name to use when substituting the ${Name} placeholder for the gem,' - ' must be alphanumeric, ' - ' and can contain _ and - characters.' - ' If no name is provided, will use last component of gem path.' - ' Ex. New_Gem') + help='The name to use when substituting the ${Name} placeholder for the gem,' + ' must be alphanumeric, ' + ' and can contain _ and - characters.' + ' If no name is provided, will use last component of gem path.' + ' Ex. New_Gem') group = create_gem_subparser.add_mutually_exclusive_group(required=False) group.add_argument('-tp', '--template-path', type=pathlib.Path, required=False, @@ -2529,7 +2596,7 @@ def add_args(subparsers) -> None: help='The uuid you want to associate with the gem module,' ' default is a random uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}') create_gem_subparser.add_argument('-f', '--force', action='store_true', default=False, - help='Copies over instantiated template directory even if it exist.') + help='Copies over instantiated template directory even if it exist.') create_gem_subparser.add_argument('--no-register', action='store_true', default=False, help='If the gem template is instantiated successfully, it will not register the' ' gem with the global, project or engine manifest file.') diff --git a/scripts/o3de/o3de/get_registration.py b/scripts/o3de/o3de/get_registration.py index d64056e8b2..1271d56804 100644 --- a/scripts/o3de/o3de/get_registration.py +++ b/scripts/o3de/o3de/get_registration.py @@ -14,9 +14,6 @@ from o3de import manifest def _run_get_registered(args: argparse) -> int: - if args.override_home_folder: - manifest.override_home_folder = args.override_home_folder - registered_path = manifest.get_registered(args.engine_name, args.project_name, args.gem_name, @@ -55,9 +52,6 @@ def add_parser_args(parser): group.add_argument('-rsn', '--restricted-name', type=str, required=False, help='Restricted name.') - parser.add_argument('-ohf', '--override-home-folder', type=str, required=False, - help='By default the home folder is the user folder, override it to this folder.') - parser.set_defaults(func=_run_get_registered) diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index a334109e6a..88e6ae8229 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -22,18 +22,13 @@ logger = logging.getLogger('o3de.manifest') logging.basicConfig(format=utils.LOG_FORMAT) # Directory methods -override_home_folder = None - def get_this_engine_path() -> pathlib.Path: return pathlib.Path(os.path.realpath(__file__)).parents[3].resolve() def get_home_folder() -> pathlib.Path: - if override_home_folder: - return pathlib.Path(override_home_folder).resolve() - else: - return pathlib.Path(os.path.expanduser("~")).resolve() + return pathlib.Path(os.path.expanduser("~")).resolve() def get_o3de_folder() -> pathlib.Path: @@ -42,12 +37,6 @@ def get_o3de_folder() -> pathlib.Path: return o3de_folder -def get_o3de_user_folder() -> pathlib.Path: - o3de_user_folder = get_home_folder() / 'O3DE' - o3de_user_folder.mkdir(parents=True, exist_ok=True) - return o3de_user_folder - - def get_o3de_registry_folder() -> pathlib.Path: registry_folder = get_o3de_folder() / 'Registry' registry_folder.mkdir(parents=True, exist_ok=True) @@ -73,19 +62,19 @@ def get_o3de_engines_folder() -> pathlib.Path: def get_o3de_projects_folder() -> pathlib.Path: - projects_folder = get_o3de_user_folder() / 'Projects' + projects_folder = get_o3de_folder() / 'Projects' projects_folder.mkdir(parents=True, exist_ok=True) return projects_folder def get_o3de_gems_folder() -> pathlib.Path: - gems_folder = get_o3de_user_folder() / 'Gems' + gems_folder = get_o3de_folder() / 'Gems' gems_folder.mkdir(parents=True, exist_ok=True) return gems_folder def get_o3de_templates_folder() -> pathlib.Path: - templates_folder = get_o3de_user_folder() / 'Templates' + templates_folder = get_o3de_folder() / 'Templates' templates_folder.mkdir(parents=True, exist_ok=True) return templates_folder @@ -117,6 +106,10 @@ def get_default_o3de_manifest_json_data() -> dict: username = os.path.split(get_home_folder())[-1] o3de_folder = get_o3de_folder() + default_registry_folder = get_o3de_registry_folder() + default_cache_folder = get_o3de_cache_folder() + default_downloads_folder = get_o3de_download_folder() + default_logs_folder = get_o3de_logs_folder() default_engines_folder = get_o3de_engines_folder() default_projects_folder = get_o3de_projects_folder() default_gems_folder = get_o3de_gems_folder() @@ -124,12 +117,20 @@ def get_default_o3de_manifest_json_data() -> dict: default_restricted_folder = get_o3de_restricted_folder() default_third_party_folder = get_o3de_third_party_folder() - default_projects_restricted_folder = default_projects_folder / 'Restricted' - default_projects_restricted_folder.mkdir(parents=True, exist_ok=True) - default_gems_restricted_folder = default_gems_folder / 'Restricted' - default_gems_restricted_folder.mkdir(parents=True, exist_ok=True) - default_templates_restricted_folder = default_templates_folder / 'Restricted' - default_templates_restricted_folder.mkdir(parents=True, exist_ok=True) + default_restricted_projects_folder = default_restricted_folder / 'Projects' + default_restricted_projects_folder.mkdir(parents=True, exist_ok=True) + default_restricted_gems_folder = default_restricted_folder / 'Gems' + default_restricted_gems_folder.mkdir(parents=True, exist_ok=True) + default_restricted_engine_folder = default_restricted_folder / 'Engines' / 'o3de' + default_restricted_engine_folder.mkdir(parents=True, exist_ok=True) + default_restricted_templates_folder = default_restricted_folder / 'Templates' + default_restricted_templates_folder.mkdir(parents=True, exist_ok=True) + default_restricted_engine_folder_json = default_restricted_engine_folder / 'restricted.json' + if not default_restricted_engine_folder_json.is_file(): + with default_restricted_engine_folder_json.open('w') as s: + restricted_json_data = {} + restricted_json_data.update({'restricted_name': 'o3de'}) + s.write(json.dumps(restricted_json_data, indent=4) + '\n') json_data = {} json_data.update({'o3de_manifest_name': f'{username}'}) @@ -140,45 +141,14 @@ def get_default_o3de_manifest_json_data() -> dict: json_data.update({'default_templates_folder': default_templates_folder.as_posix()}) json_data.update({'default_restricted_folder': default_restricted_folder.as_posix()}) json_data.update({'default_third_party_folder': default_third_party_folder.as_posix()}) - - json_data.update({'engines': []}) json_data.update({'projects': []}) json_data.update({'external_subdirectories': []}) json_data.update({'templates': []}) - json_data.update({'restricted': []}) + json_data.update({'restricted': [default_restricted_engine_folder.as_posix()]}) json_data.update({'repos': []}) - - default_restricted_folder_json = default_restricted_folder / 'restricted.json' - if not default_restricted_folder_json.is_file(): - with default_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'o3de'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') - - default_projects_restricted_folder_json = default_projects_restricted_folder / 'restricted.json' - if not default_projects_restricted_folder_json.is_file(): - with default_projects_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'projects'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') - - default_gems_restricted_folder_json = default_gems_restricted_folder / 'restricted.json' - if not default_gems_restricted_folder_json.is_file(): - with default_gems_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'gems'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') - - default_templates_restricted_folder_json = default_templates_restricted_folder / 'restricted.json' - if not default_templates_restricted_folder_json.is_file(): - with default_templates_restricted_folder_json.open('w') as s: - restricted_json_data = {} - restricted_json_data.update({'restricted_name': 'templates'}) - s.write(json.dumps(restricted_json_data, indent=4) + '\n') - + json_data.update({'engines': []}) return json_data - def get_o3de_manifest() -> pathlib.Path: manifest_path = get_o3de_folder() / 'o3de_manifest.json' if not manifest_path.is_file(): @@ -229,12 +199,12 @@ def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> b return False -def get_gems_from_subdirectories(external_subdirs: list) -> list: - """ +def get_gems_from_external_subdirectories(external_subdirs: list) -> list: + ''' Helper Method for scanning a set of external subdirectories for gem.json files - """ + ''' def is_gem_subdirectory(subdir_files): - for name in subdir_files: + for name in files: if name == 'gem.json': return True return False @@ -250,7 +220,8 @@ def get_gems_from_subdirectories(external_subdirs: list) -> list: return gem_directories -def get_engines() -> list: +# Data query methods +def get_manifest_engines() -> list: json_data = load_o3de_manifest() engine_list = json_data['engines'] if 'engines' in json_data else [] # Convert each engine dict entry into a string entry @@ -259,31 +230,31 @@ def get_engines() -> list: engine_list)) -def get_projects() -> list: +def get_manifest_projects() -> list: json_data = load_o3de_manifest() return json_data['projects'] if 'projects' in json_data else [] -def get_gems() -> list: - return get_gems_from_subdirectories(get_external_subdirectories()) +def get_manifest_gems() -> list: + return get_gems_from_external_subdirectories(get_manifest_external_subdirectories()) -def get_external_subdirectories() -> list: +def get_manifest_external_subdirectories() -> list: json_data = load_o3de_manifest() return json_data['external_subdirectories'] if 'external_subdirectories' in json_data else [] -def get_templates() -> list: +def get_manifest_templates() -> list: json_data = load_o3de_manifest() return json_data['templates'] if 'templates' in json_data else [] -def get_restricted() -> list: +def get_manifest_restricted() -> list: json_data = load_o3de_manifest() return json_data['restricted'] if 'restricted' in json_data else [] -def get_repos() -> list: +def get_manifest_repos() -> list: json_data = load_o3de_manifest() return json_data['repos'] if 'repos' in json_data else [] @@ -299,7 +270,7 @@ def get_engine_projects() -> list: def get_engine_gems() -> list: - return get_gems_from_subdirectories(get_engine_external_subdirectories()) + return get_gems_from_external_subdirectories(get_engine_external_subdirectories()) def get_engine_external_subdirectories() -> list: @@ -320,23 +291,9 @@ def get_engine_templates() -> list: return [] -def get_engine_restricted() -> list: - engine_path = get_this_engine_path() - engine_object = get_engine_json_data(engine_path=engine_path) - if engine_object: - return list(map(lambda rel_path: (pathlib.Path(engine_path) / rel_path).as_posix(), - engine_object['restricted'])) if 'restricted' in engine_object else [] - return [] - - # project.json queries -def get_project_engine_name(project_path: pathlib.Path) -> str or None: - project_object = get_project_json_data(project_path=project_path) - return project_object.get('engine', None) if project_object else None - - def get_project_gems(project_path: pathlib.Path) -> list: - return get_gems_from_subdirectories(get_project_external_subdirectories(project_path)) + return get_gems_from_external_subdirectories(get_project_external_subdirectories(project_path)) def get_project_external_subdirectories(project_path: pathlib.Path) -> list: @@ -355,74 +312,95 @@ def get_project_templates(project_path: pathlib.Path) -> list: return [] -def get_project_restricted(project_path: pathlib.Path) -> list: - project_object = get_project_json_data(project_path=project_path) - if project_object: - return list(map(lambda rel_path: (pathlib.Path(project_path) / rel_path).as_posix(), - project_object['restricted'])) if 'restricted' in project_object else [] +# gem.json queries +def get_gem_gems(gem_path: pathlib.Path) -> list: + return get_gems_from_external_subdirectories(get_gem_external_subdirectories(gem_path)) + + +def get_gem_external_subdirectories(gem_path: pathlib.Path) -> list: + gem_object = get_gem_json_data(gem_path=gem_path) + if gem_object: + return list(map(lambda rel_path: (pathlib.Path(gem_path) / rel_path).as_posix(), + gem_object[ + 'external_subdirectories'])) if 'external_subdirectories' in gem_object else [] + return [] + + +def get_gem_templates(gem_path: pathlib.Path) -> list: + gem_object = get_gem_json_data(gem_path=gem_path) + if gem_object: + return list(map(lambda rel_path: (pathlib.Path(gem_path) / rel_path).as_posix(), + gem_object['templates'])) if 'templates' in gem_object else [] return [] # Combined manifest queries def get_all_projects() -> list: - projects_data = get_projects() + projects_data = get_manifest_projects() projects_data.extend(get_engine_projects()) # Remove duplicates from the list return list(dict.fromkeys(projects_data)) def get_all_gems(project_path: pathlib.Path = None) -> list: - gems_data = get_gems() - gems_data.extend(get_engine_gems()) - if project_path: - gems_data.extend(get_project_gems(project_path)) - return list(dict.fromkeys(gems_data)) + return get_gems_from_external_subdirectories(get_all_external_subdirectories(project_path)) def get_all_external_subdirectories(project_path: pathlib.Path = None) -> list: - external_subdirectories_data = get_external_subdirectories() + external_subdirectories_data = get_manifest_external_subdirectories() external_subdirectories_data.extend(get_engine_external_subdirectories()) if project_path: external_subdirectories_data.extend(get_project_external_subdirectories(project_path)) + + def descend_gems(gem_path: pathlib.Path): + new_external_subdirectories_data = get_gem_external_subdirectories(gem_path) + external_subdirectories_data.extend(new_external_subdirectories_data) + new_gems_data = get_gems_from_external_subdirectories(new_external_subdirectories_data) + for new_gem in new_gems_data: + descend_gems(new_gem) + + gems_data = get_gems_from_external_subdirectories(external_subdirectories_data) + for gem in gems_data: + descend_gems(gem) + + # Remove duplicates from the list return list(dict.fromkeys(external_subdirectories_data)) def get_all_templates(project_path: pathlib.Path = None) -> list: - templates_data = get_templates() + templates_data = get_manifest_templates() templates_data.extend(get_engine_templates()) if project_path: templates_data.extend(get_project_templates(project_path)) + + gems_data = get_all_gems(project_path) + for gem_path in gems_data: + templates_data.extend(get_gem_templates(gem_path)) + + # Remove duplicates from the list return list(dict.fromkeys(templates_data)) -def get_all_restricted(project_path: pathlib.Path = None) -> list: - restricted_data = get_restricted() - restricted_data.extend(get_engine_restricted()) - if project_path: - restricted_data.extend(get_project_restricted(project_path)) - return list(dict.fromkeys(restricted_data)) - - # Template functions -def get_templates_for_project_creation(): +def get_templates_for_project_creation(project_path: pathlib.Path = None) -> list: project_templates = [] - for template_path in get_all_templates(): + for template_path in get_all_templates(project_path): template_path = pathlib.Path(template_path) - template_json_path = pathlib.Path(template_path) / 'template.json' + template_json_path = template_path / 'template.json' if not validation.valid_o3de_template_json(template_json_path): continue - project_json_path = template_path / 'Template' / 'project.json' if validation.valid_o3de_project_json(project_json_path): project_templates.append(template_path) + return project_templates -def get_templates_for_gem_creation(): +def get_templates_for_gem_creation(project_path: pathlib.Path = None) -> list: gem_templates = [] - for template_path in get_all_templates(): + for template_path in get_all_templates(project_path): template_path = pathlib.Path(template_path) - template_json_path = pathlib.Path(template_path) / 'template.json' + template_json_path = template_path / 'template.json' if not validation.valid_o3de_template_json(template_json_path): continue @@ -432,58 +410,20 @@ def get_templates_for_gem_creation(): return gem_templates -def get_templates_for_generic_creation(): # temporary until we have a better way to do this... maybe template_type element - def filter_project_and_gem_templates_out(template_path, - templates_for_project_creation = get_templates_for_project_creation(), - templates_for_gem_creation = get_templates_for_gem_creation()): +def get_templates_for_generic_creation(project_path: pathlib.Path = None) -> list: + generic_templates = [] + for template_path in get_all_templates(project_path): template_path = pathlib.Path(template_path) - return template_path not in templates_for_project_creation and template_path not in templates_for_gem_creation + template_json_path = template_path / 'template.json' + if not validation.valid_o3de_template_json(template_json_path): + continue + gem_json_path = template_path / 'Template' / 'gem.json' + project_json_path = template_path / 'Template' / 'project.json' + if not validation.valid_o3de_gem_json(gem_json_path) and\ + not validation.valid_o3de_project_json(project_json_path): + generic_templates.append(template_path) - return list(filter(filter_project_and_gem_templates_out, get_all_templates())) - - -def get_json_file_path(object_typename: str, - object_path: str or pathlib.Path) -> pathlib.Path: - if not object_typename or not object_path: - logger.error('Must specify an object typename and object path.') - return None - - object_path = pathlib.Path(object_path).resolve() - return object_path / f'{object_typename}.json' - - -def get_json_data_file(object_json: pathlib.Path, - object_typename: str, - object_validator: callable) -> dict or None: - if not object_typename: - logger.error('Missing object typename.') - return None - - if not object_json or not object_json.is_file(): - logger.error(f'Invalid {object_typename} json {object_json} supplied or file missing.') - return None - - if not object_validator or not object_validator(object_json): - logger.error(f'{object_typename} json {object_json} is not valid or could not be validated.') - return None - - with object_json.open('r') as f: - try: - object_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warning(f'{object_json} failed to load: {e}') - else: - return object_json_data - - return None - - -def get_json_data(object_typename: str, - object_path: str or pathlib.Path, - object_validator: callable) -> dict or None: - object_json = get_json_file_path(object_typename, object_path) - - return get_json_data_file(object_json, object_typename, object_validator) + return generic_templates def get_engine_json_data(engine_name: str = None, @@ -495,7 +435,28 @@ def get_engine_json_data(engine_name: str = None, if engine_name and not engine_path: engine_path = get_registered(engine_name=engine_name) - return get_json_data('engine', engine_path, validation.valid_o3de_engine_json) + if not engine_path: + logger.error(f'Engine Path {engine_path} has not been registered.') + return None + + engine_path = pathlib.Path(engine_path).resolve() + engine_json = engine_path / 'engine.json' + if not engine_json.is_file(): + logger.error(f'Engine json {engine_json} is not present.') + return None + if not validation.valid_o3de_engine_json(engine_json): + logger.error(f'Engine json {engine_json} is not valid.') + return None + + with engine_json.open('r') as f: + try: + engine_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{engine_json} failed to load: {str(e)}') + else: + return engine_json_data + + return None def get_project_json_data(project_name: str = None, @@ -507,7 +468,28 @@ def get_project_json_data(project_name: str = None, if project_name and not project_path: project_path = get_registered(project_name=project_name) - return get_json_data('project', project_path, validation.valid_o3de_project_json) + if not project_path: + logger.error(f'Project Path {project_path} has not been registered.') + return None + + project_path = pathlib.Path(project_path).resolve() + project_json = project_path / 'project.json' + if not project_json.is_file(): + logger.error(f'Project json {project_json} is not present.') + return None + if not validation.valid_o3de_project_json(project_json): + logger.error(f'Project json {project_json} is not valid.') + return None + + with project_json.open('r') as f: + try: + project_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{project_json} failed to load: {str(e)}') + else: + return project_json_data + + return None def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None, @@ -519,10 +501,28 @@ def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None if gem_name and not gem_path: gem_path = get_registered(gem_name=gem_name, project_path=project_path) - if pathlib.Path(gem_path).is_file(): - return get_json_data_file(gem_path, 'gem', validation.valid_o3de_gem_json) - else: - return get_json_data('gem', gem_path, validation.valid_o3de_gem_json) + if not gem_path: + logger.error(f'Gem Path {gem_path} has not been registered.') + return None + + gem_path = pathlib.Path(gem_path).resolve() + gem_json = gem_path / 'gem.json' + if not gem_json.is_file(): + logger.error(f'Gem json {gem_json} is not present.') + return None + if not validation.valid_o3de_gem_json(gem_json): + logger.error(f'Gem json {gem_json} is not valid.') + return None + + with gem_json.open('r') as f: + try: + gem_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{gem_json} failed to load: {str(e)}') + else: + return gem_json_data + + return None def get_template_json_data(template_name: str = None, template_path: str or pathlib.Path = None, @@ -534,7 +534,28 @@ def get_template_json_data(template_name: str = None, template_path: str or path if template_name and not template_path: template_path = get_registered(template_name=template_name, project_path=project_path) - return get_json_data('template', template_path, validation.valid_o3de_template_json) + if not template_path: + logger.error(f'Template Path {template_path} has not been registered.') + return None + + template_path = pathlib.Path(template_path).resolve() + template_json = template_path / 'template.json' + if not template_json.is_file(): + logger.error(f'Template json {template_json} is not present.') + return None + if not validation.valid_o3de_template_json(template_json): + logger.error(f'Template json {template_json} is not valid.') + return None + + with template_json.open('r') as f: + try: + template_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{template_json} failed to load: {str(e)}') + else: + return template_json_data + + return None def get_restricted_json_data(restricted_name: str = None, restricted_path: str or pathlib.Path = None, @@ -546,26 +567,28 @@ def get_restricted_json_data(restricted_name: str = None, restricted_path: str o if restricted_name and not restricted_path: restricted_path = get_registered(restricted_name=restricted_name, project_path=project_path) - return get_json_data('restricted', restricted_path, validation.valid_o3de_restricted_json) - - -def get_repo_json_data(repo_uri: str) -> dict or None: - if not repo_uri: - logger.error('Must specify a Repo Uri.') + if not restricted_path: + logger.error(f'Restricted Path {restricted_path} has not been registered.') return None - repo_json = get_repo_path(repo_uri=repo_uri) + restricted_path = pathlib.Path(restricted_path).resolve() + restricted_json = restricted_path / 'restricted.json' + if not restricted_json.is_file(): + logger.error(f'Restricted json {restricted_json} is not present.') + return None + if not validation.valid_o3de_restricted_json(restricted_json): + logger.error(f'Restricted json {restricted_json} is not valid.') + return None - return get_json_data_file(repo_json, "Repo", validation.valid_o3de_repo_json) + with restricted_json.open('r') as f: + try: + restricted_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{restricted_json} failed to load: {str(e)}') + else: + return restricted_json_data - -def get_repo_path(repo_uri: str, cache_folder: str or pathlib.Path = None) -> pathlib.Path: - if not cache_folder: - cache_folder = get_o3de_cache_folder() - - repo_manifest = f'{repo_uri}/repo.json' - repo_sha256 = hashlib.sha256(repo_manifest.encode()) - return cache_folder / str(repo_sha256.hexdigest() + '.json') + return None def get_registered(engine_name: str = None, @@ -604,7 +627,7 @@ def get_registered(engine_name: str = None, # check global first then this engine if isinstance(engine_name, str): - engines = get_engines() + engines = get_manifest_engines() for engine in engines: if isinstance(engine, dict): engine_path = pathlib.Path(engine['path']).resolve() @@ -633,72 +656,60 @@ def get_registered(engine_name: str = None, for project_path in projects: project_path = pathlib.Path(project_path).resolve() project_json = project_path / 'project.json' - if not pathlib.Path(project_json).is_file(): - logger.warning(f'{project_json} does not exist') - else: - with project_json.open('r') as f: - try: - project_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warning(f'{project_json} failed to load: {str(e)}') - else: - this_projects_name = project_json_data['project_name'] - if this_projects_name == project_name: - return project_path + with project_json.open('r') as f: + try: + project_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{project_json} failed to load: {str(e)}') + else: + this_projects_name = project_json_data['project_name'] + if this_projects_name == project_name: + return project_path elif isinstance(gem_name, str): gems = get_all_gems(project_path) for gem_path in gems: gem_path = pathlib.Path(gem_path).resolve() gem_json = gem_path / 'gem.json' - if not pathlib.Path(gem_json).is_file(): - logger.warning(f'{gem_json} does not exist') - else: - with gem_json.open('r') as f: - try: - gem_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warning(f'{gem_json} failed to load: {str(e)}') - else: - this_gems_name = gem_json_data['gem_name'] - if this_gems_name == gem_name: - return gem_path + with gem_json.open('r') as f: + try: + gem_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{gem_json} failed to load: {str(e)}') + else: + this_gems_name = gem_json_data['gem_name'] + if this_gems_name == gem_name: + return gem_path elif isinstance(template_name, str): templates = get_all_templates(project_path) for template_path in templates: template_path = pathlib.Path(template_path).resolve() template_json = template_path / 'template.json' - if not pathlib.Path(template_json).is_file(): - logger.warning(f'{template_json} does not exist') - else: - with template_json.open('r') as f: - try: - template_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warning(f'{template_path} failed to load: {str(e)}') - else: - this_templates_name = template_json_data['template_name'] - if this_templates_name == template_name: - return template_path + with template_json.open('r') as f: + try: + template_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{template_path} failed to load: {str(e)}') + else: + this_templates_name = template_json_data['template_name'] + if this_templates_name == template_name: + return template_path elif isinstance(restricted_name, str): - restricted = get_all_restricted(project_path) + restricted = get_manifest_restricted() for restricted_path in restricted: restricted_path = pathlib.Path(restricted_path).resolve() restricted_json = restricted_path / 'restricted.json' - if not pathlib.Path(restricted_json).is_file(): - logger.warning(f'{restricted_json} does not exist') - else: - with restricted_json.open('r') as f: - try: - restricted_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warning(f'{restricted_json} failed to load: {str(e)}') - else: - this_restricted_name = restricted_json_data['restricted_name'] - if this_restricted_name == restricted_name: - return restricted_path + with restricted_json.open('r') as f: + try: + restricted_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warning(f'{restricted_json} failed to load: {str(e)}') + else: + this_restricted_name = restricted_json_data['restricted_name'] + if this_restricted_name == restricted_name: + return restricted_path elif isinstance(default_folder, str): if default_folder == 'engines': @@ -720,7 +731,9 @@ def get_registered(engine_name: str = None, elif isinstance(repo_name, str): cache_folder = get_o3de_cache_folder() for repo_uri in json_data['repos']: - cache_file = get_repo_path(repo_uri=repo_uri, cache_folder=cache_folder) + repo_uri = pathlib.Path(repo_uri).resolve() + repo_sha256 = hashlib.sha256(repo_uri.encode()) + cache_file = cache_folder / str(repo_sha256.hexdigest() + '.json') if cache_file.is_file(): repo = pathlib.Path(cache_file).resolve() with repo.open('r') as f: diff --git a/scripts/o3de/o3de/print_registration.py b/scripts/o3de/o3de/print_registration.py index 77e098d0ba..2bd3202ca0 100644 --- a/scripts/o3de/o3de/print_registration.py +++ b/scripts/o3de/o3de/print_registration.py @@ -39,69 +39,68 @@ def get_project_path(project_path: pathlib.Path, project_name: str) -> pathlib.P return project_path -def print_this_engine(verbose: int) -> int: +def print_this_engine(verbose: int = 0) -> int: this_engine_path = manifest.get_this_engine_path() print(f'This Engine:\n{json.dumps(str(this_engine_path), indent=4)}') if verbose > 0: return print_manifest_json_data([this_engine_path], 'This Engine', - manifest.get_engine_json_data, 'engine_path') + manifest.get_engine_json_data, 'engine_path') return 0 -def print_engines(verbose: int) -> None: - engines_data = manifest.get_engines() +def print_engines(verbose: int = 0) -> int: + engines_data = manifest.get_manifest_engines() print(f'Engine Paths:\n{json.dumps(engines_data, indent=4)}') if verbose > 0: return print_manifest_json_data(engines_data, 'Engine Jsons', - manifest.get_engine_json_data, 'engine_path') + manifest.get_engine_json_data, 'engine_path') return 0 -def print_projects(verbose: int) -> int: - projects_data = manifest.get_projects() +def print_projects(verbose: int = 0) -> int: + projects_data = manifest.get_all_projects() print(f'Project Paths:\n{json.dumps(projects_data, indent=4)}') if verbose > 0: return print_manifest_json_data(projects_data, 'Project Jsons', - manifest.get_project_json_data, 'project_path') + manifest.get_project_json_data, 'project_path') return 0 -def print_gems(verbose: int) -> int: - gems_data = manifest.get_gems() +def print_gems(verbose: int = 0) -> int: + gems_data = manifest.get_all_gems() print(f'Gem Paths:\n{json.dumps(gems_data, indent=4)}') if verbose > 0: return print_manifest_json_data(gems_data, 'Gem Jsons', - manifest.get_gem_json_data, 'gem_path') + manifest.get_gem_json_data, 'gem_path') return 0 -def print_external_subdirectories(verbose: int) -> int: - external_subdirs_data = manifest.get_external_subdirectories() +def print_external_subdirectories(verbose: int = 0) -> int: + external_subdirs_data = manifest.get_all_external_subdirectories() print(f'External Subdirectories:\n{json.dumps(external_subdirs_data, indent=4)}') return 0 - def print_templates(verbose: int) -> int: - templates_data = manifest.get_templates() + templates_data = manifest.get_all_templates() print(f'Template Paths:\n{json.dumps(templates_data, indent=4)}') if verbose > 0: return print_manifest_json_data(templates_data, 'Template Jsons', - manifest.get_template_json_data, 'template_path') + manifest.get_template_json_data, 'template_path') return 0 def print_restricted(verbose: int) -> int: - restricted_data = manifest.get_restricted() + restricted_data = manifest.get_manifest_restricted() print(f'Restricted Paths:\n{json.dumps(restricted_data, indent=4)}') if verbose > 0: return print_manifest_json_data(restricted_data, 'Restricted Jsons', - manifest.get_restricted_json_data, 'restricted_path') + manifest.get_restricted_json_data, 'restricted_path') return 0 @@ -112,7 +111,7 @@ def print_engine_projects(verbose: int) -> int: if verbose > 0: return print_manifest_json_data(engine_projects_data, 'Project Jsons', - manifest.get_project_json_data, 'project_path') + manifest.get_project_json_data, 'project_path') return 0 @@ -122,7 +121,7 @@ def print_engine_gems(verbose: int) -> int: if verbose > 0: return print_manifest_json_data(engine_gems_data, 'Gem Jsons', - manifest.get_gem_json_data, 'gem_path') + manifest.get_gem_json_data, 'gem_path') return 0 @@ -132,17 +131,7 @@ def print_engine_templates(verbose: int) -> int: if verbose > 0: return print_manifest_json_data(engine_templates_data, 'Template Jsons', - manifest.get_template_json_data, 'template_path') - return 0 - - -def print_engine_restricted(verbose: int) -> int: - engine_restricted_data = manifest.get_engine_restricted() - print(f'Restricted Paths:\n{json.dumps(engine_restricted_data, indent=4)}') - - if verbose > 0: - return print_manifest_json_data(engine_restricted_data, 'Restricted Jsons', - manifest.get_restricted_json_data, 'restricted_path') + manifest.get_template_json_data, 'template_path') return 0 @@ -153,21 +142,6 @@ def print_engine_external_subdirectories(verbose: int) -> int: # Project output methods -def print_project_engine_name(verbose: int, project_path: pathlib.Path, project_name: str) -> int: - project_path = get_project_path(project_path, project_name) - if not project_path: - return 1 - - engine_name = manifest.get_project_engine_name(project_path) - if engine_name: - print(f'Project\'s engine name:\n{engine_name}') - return 0 - - if verbose > 0: - logger.info(f'project.json at path "{project_path}" contains no registered "engine" field') - return 1 - - def print_project_gems(verbose: int, project_path: pathlib.Path, project_name: str) -> int: project_path = get_project_path(project_path, project_name) if not project_path: @@ -178,7 +152,7 @@ def print_project_gems(verbose: int, project_path: pathlib.Path, project_name: s if verbose > 0: return print_manifest_json_data(project_gems_data, 'Gems Jsons', - manifest.get_gem_json_data, 'gem_path') + manifest.get_gem_json_data, 'gem_path') return 0 @@ -201,20 +175,7 @@ def print_project_templates(verbose: int, project_path: pathlib.Path, project_na print(f'Template Paths:\n{json.dumps(project_templates_data, indent=4)}') if verbose > 0: return print_manifest_json_data(project_templates_data, 'Template Jsons', - manifest.get_template_json_data, 'template_path') - return 0 - - -def print_project_restricted(verbose: int, project_path: pathlib.Path, project_name: str) -> int: - project_path = get_project_path(project_path, project_name) - if not project_path: - return 1 - - project_restricted_data = manifest.get_project_restricted(project_path) - print(f'Restricted Paths:\n{json.dumps(project_restricted_data, indent=4)}') - if verbose > 0: - return print_manifest_json_data(project_restricted_data, 'Restricted Jsons', - manifest.get_restricted_json_data, 'restricted_path') + manifest.get_template_json_data, 'template_path') return 0 @@ -224,12 +185,12 @@ def print_all_projects(verbose: int) -> int: if verbose > 0: return print_manifest_json_data(all_projects_data, 'Project Jsons', - manifest.get_project_json_data, 'project_path') + manifest.get_project_json_data, 'project_path') return 0 def print_all_gems(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: - all_gems = manifest.get_gems() + all_gems = manifest.get_manifest_gems() all_gems.extend(manifest.get_engine_gems()) # If a project path or project name is supplied query the gems from that project, otherwise query the gems from @@ -245,12 +206,12 @@ def print_all_gems(verbose: int, project_path: pathlib.Path = None, project_name if verbose > 0: return print_manifest_json_data(all_gems, 'Gem Jsons', - manifest.get_gem_json_data, 'gem_path') + manifest.get_gem_json_data, 'gem_path') return 0 def print_all_external_subdirectories(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: - all_external_subdirectories = manifest.get_external_subdirectories() + all_external_subdirectories = manifest.get_manifest_external_subdirectories() all_external_subdirectories.extend(manifest.get_engine_external_subdirectories()) # If a project path or project name is supplied query the external subdirectories from that project, @@ -267,7 +228,7 @@ def print_all_external_subdirectories(verbose: int, project_path: pathlib.Path = def print_all_templates(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: - all_templates = manifest.get_templates() + all_templates = manifest.get_manifest_templates() all_templates.extend(manifest.get_engine_templates()) # If a project path or project name is supplied query the templates from that project, @@ -283,31 +244,9 @@ def print_all_templates(verbose: int, project_path: pathlib.Path = None, project if verbose > 0: return print_manifest_json_data(all_templates, 'Template Jsons', - manifest.get_template_json_data, 'template_path') + manifest.get_template_json_data, 'template_path') return 0 - -def print_all_restricted(verbose: int, project_path: pathlib.Path = None, project_name: str = None) -> int: - all_restricted = manifest.get_restricted() - all_restricted.extend(manifest.get_engine_restricted()) - - # If a project path or project name is supplied query the restricted from that project, - # otherwise query the restricted from all projects - project_path = get_project_path(project_path, project_name) if project_path or project_name else None - projects = [project_path] if project_path else manifest.get_all_projects() - for project in projects: - all_restricted.extend(manifest.get_project_restricted(project)) - - # Filter out duplicates - all_restricted = list(dict.fromkeys(all_restricted)) - print(f'Restricted Paths:\n{json.dumps(all_restricted, indent=4)}') - - if verbose > 0: - return print_manifest_json_data(all_restricted, 'Restricted Jsons', - manifest.get_restricted_json_data, 'restricted_path') - return 0 - - def print_manifest_json_data(uri_json_data: list, print_prefix: str, get_json_func: callable, get_json_data_kw: str) -> int: print('\n') @@ -351,7 +290,7 @@ def print_repos_data(repos_data: dict) -> int: def print_repos(verbose: int) -> int: - repos_data = manifest.get_repos() + repos_data = manifest.get_manifest_repos() print(json.dumps(repos_data, indent=4)) if verbose > 0: @@ -370,16 +309,13 @@ def register_show(verbose: int, project_path: pathlib.Path = None, project_name: result = print_all_projects(verbose) or result result = print_all_gems(verbose, project_path, project_name) or result result = print_all_templates(verbose, project_path, project_name) or result - result = print_all_restricted(verbose, project_path, project_name) or result + result = print_restricted(verbose) or result result = print_repos(verbose) or result return result def _run_register_show(args: argparse) -> int: - if args.override_home_folder: - manifest.override_home_folder = args.override_home_folder - if args.this_engine: return print_this_engine(args.verbose) elif args.engines: @@ -393,7 +329,7 @@ def _run_register_show(args: argparse) -> int: elif args.templates: return print_templates(args.verbose) elif args.repos: - return register_show_repos(args.verbose) + return print_repos(args.verbose) elif args.restricted: return print_restricted(args.verbose) @@ -405,8 +341,6 @@ def _run_register_show(args: argparse) -> int: return print_engine_external_subdirectories(args.verbose) elif args.engine_templates: return print_engine_templates(args.verbose) - elif args.engine_restricted: - return print_engine_restricted(args.verbose) elif args.project_gems: return print_project_gems(args.verbose, args.project_path, args.project_name) @@ -414,8 +348,6 @@ def _run_register_show(args: argparse) -> int: return print_project_external_subdirectories(args.verbose, args.project_path, args.project_name) elif args.project_templates: return print_project_templates(args.verbose, args.project_path, args.project_name) - elif args.project_restricted: - return print_project_restricted(args.verbose, args.project_path, args.project_name) elif args.project_engine_name: return print_project_engine_name(args.verbose, args.project_path, args.project_name) @@ -427,8 +359,6 @@ def _run_register_show(args: argparse) -> int: return print_all_external_subdirectories(args.verbose, args.project_path, args.project_name) elif args.all_templates: return print_all_templates(args.verbose, args.project_path, args.project_name) - elif args.all_restricted: - return print_all_restricted(args.verbose, args.project_path, args.project_name) else: return register_show(args.verbose, args.project_path, args.project_name) @@ -538,9 +468,6 @@ def add_parser_args(parser): project_group.add_argument('-pn', '--project-name', type=str, help='The name of a project.') - parser.add_argument('-ohf', '--override-home-folder', type=str, required=False, - help='By default the home folder is the user folder, override it to this folder.') - parser.set_defaults(func=_run_register_show) diff --git a/scripts/o3de/o3de/register.py b/scripts/o3de/o3de/register.py index a175104997..926c413521 100644 --- a/scripts/o3de/o3de/register.py +++ b/scripts/o3de/o3de/register.py @@ -490,7 +490,7 @@ def register_repo(json_data: dict, repo_sha256 = hashlib.sha256(url.encode()) cache_file = manifest.get_o3de_cache_folder() / str(repo_sha256.hexdigest() + '.json') - result = utils.download_file(parsed_uri, cache_file, True) + result = utils.download_file(url, cache_file, True) if result == 0: json_data.setdefault('repos', []).insert(0, repo_uri) @@ -793,9 +793,6 @@ def register(engine_path: pathlib.Path = None, def _run_register(args: argparse) -> int: - if args.override_home_folder: - manifest.override_home_folder = args.override_home_folder - if args.update: remove_invalid_o3de_objects() return repo.refresh_repos() @@ -891,8 +888,6 @@ def add_parser_args(parser): default=False, help='Refresh the repo cache.') - parser.add_argument('-ohf', '--override-home-folder', type=pathlib.Path, required=False, - help='By default the home folder is the user folder, override it to this folder.') parser.add_argument('-r', '--remove', action='store_true', required=False, default=False, help='Remove entry.') diff --git a/scripts/o3de/tests/unit_test_enable_gem.py b/scripts/o3de/tests/unit_test_enable_gem.py index c765f74731..8067fc329d 100644 --- a/scripts/o3de/tests/unit_test_enable_gem.py +++ b/scripts/o3de/tests/unit_test_enable_gem.py @@ -42,8 +42,10 @@ TEST_GEM_JSON_PAYLOAD = ''' { "gem_name": "TestGem", "display_name": "TestGem", - "license": "What license TestGem uses goes here: i.e. https://opensource.org/licenses/MIT", - "origin": "The primary repo for TestGem goes here: i.e. http://www.mydomain.com", + "license": "Apache-2.0 Or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", + "origin": "Open 3D Engine - o3de.org", + "origin_url": "https://github.com/o3de/o3de", "type": "Code", "summary": "A short description of TestGem.", "canonical_tags": [ @@ -53,7 +55,10 @@ TEST_GEM_JSON_PAYLOAD = ''' "TestGem" ], "icon_path": "preview.png", - "requirements": "" + "requirements": "Any requirement goes here.", + "documentation_url": "The link to the documentation goes here.", + "dependencies": [ + ] } ''' diff --git a/scripts/o3de/tests/unit_test_engine_template.py b/scripts/o3de/tests/unit_test_engine_template.py index ed1c8258d3..da23ee11f1 100755 --- a/scripts/o3de/tests/unit_test_engine_template.py +++ b/scripts/o3de/tests/unit_test_engine_template.py @@ -93,37 +93,28 @@ TEST_TEMPLATE_JSON_CONTENTS = """\ "copyFiles": [ { "file": "Code/Include/${Name}/${Name}Bus.h", - "origin": "Code/Include/${Name}/${Name}Bus.h", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { - "file": "Code/Include/Platform/Salem/${Name}Bus.h", - "origin": "Code/Include/Platform/Salem/${Name}Bus.h", - "isTemplated": true, - "isOptional": false + "file": "Code/Include/Platform/Windows/${Name}Bus.h", + "isTemplated": true } ], "createDirectories": [ { - "dir": "Code", - "origin": "Code" + "dir": "Code" }, { - "dir": "Code/Include", - "origin": "Code/Include" + "dir": "Code/Include" }, { - "dir": "Code/Include/${Name}", - "origin": "Code/Include/${Name}" + "dir": "Code/Include/${Name}" }, { - "dir": "Code/Include/Platform", - "origin": "Code/Include/Platform" + "dir": "Code/Include/Platform" }, { - "dir": "Code/Include/Platform/Salem", - "origin": "Code/Include/Platform/Salem" + "dir": "Code/Include/Platform/Windows" } ] } @@ -174,10 +165,10 @@ def test_create_template(tmpdir, with gem_bus_file.open('w') as s: s.write(concrete_contents) - engine_gem_code_include_platform_salem = template_source_path / 'Code/Include/Platform/Salem' - engine_gem_code_include_platform_salem.mkdir(parents=True, exist_ok=True) + engine_gem_code_include_platform_windows = template_source_path / 'Code/Include/Platform/Windows' + engine_gem_code_include_platform_windows.mkdir(parents=True, exist_ok=True) - restricted_gem_bus_file = engine_gem_code_include_platform_salem / 'TestTemplateBus.h' + restricted_gem_bus_file = engine_gem_code_include_platform_windows / 'TestTemplateBus.h' with restricted_gem_bus_file.open('w') as s: s.write(concrete_contents) @@ -209,9 +200,9 @@ def test_create_template(tmpdir, else: assert s_data == templated_contents_without_license - platform_template_folder = engine_root / 'Salem/Templates' + platform_template_folder = engine_root / 'Windows/Templates' - new_platform_default_name_bus_file = template_content_folder / 'Code/Include/Platform/Salem/${Name}Bus.h' + new_platform_default_name_bus_file = template_content_folder / 'Code/Include/Platform/Windows/${Name}Bus.h' assert new_platform_default_name_bus_file.is_file() with new_platform_default_name_bus_file.open('r') as s: s_data = s.read() @@ -255,7 +246,7 @@ class TestCreateTemplate: s.write(templated_contents) template_content_folder = template_default_folder / 'Template' - platform_default_name_bus_dir = template_content_folder / 'Code/Include/Platform/Salem' + platform_default_name_bus_dir = template_content_folder / 'Code/Include/Platform/Windows' platform_default_name_bus_dir.mkdir(parents=True, exist_ok=True) platform_default_name_bus_file = platform_default_name_bus_dir / '${Name}Bus.h' @@ -263,10 +254,13 @@ class TestCreateTemplate: s.write(templated_contents) template_dest_path = engine_root / instantiated_name - # Skip registeration in test + # Skip registration in test with patch('uuid.uuid4', return_value=uuid.uuid5(uuid.NAMESPACE_DNS, instantiated_name)) as uuid4_mock: - result = create_from_template_func(template_dest_path, template_path=template_default_folder, force=True, - keep_license_text=keep_license_text, **create_from_template_kwargs) + result = create_from_template_func(template_dest_path, + template_path=template_default_folder, + keep_license_text=keep_license_text, + force=True, + **create_from_template_kwargs) if expect_failure: assert result != 0 else: @@ -281,7 +275,7 @@ class TestCreateTemplate: s_data = s.read() assert s_data == concrete_contents - platform_test_bus_folder = test_folder / 'Code/Include/Platform/Salem' + platform_test_bus_folder = test_folder / 'Code/Include/Platform/Windows' assert platform_test_bus_folder.is_dir() platform_default_name_bus_file = platform_test_bus_folder / f'{instantiated_name}Bus.h' @@ -338,9 +332,7 @@ class TestCreateTemplate: template_json_dict.setdefault('copyFiles', []).append( { "file": "project.json", - "origin": "project.json", - "isTemplated": True, - "isOptional": False + "isTemplated": True }) # Convert the python dictionary back into a json string template_json_contents = json.dumps(template_json_dict, indent=4) @@ -376,9 +368,7 @@ class TestCreateTemplate: template_json_dict.setdefault('copyFiles', []).append( { "file": "gem.json", - "origin": "gem.json", - "isTemplated": True, - "isOptional": False + "isTemplated": True }) #Convert dict back to string template_json_contents = json.dumps(template_json_dict, indent=4) diff --git a/scripts/o3de/tests/unit_test_gem_properties.py b/scripts/o3de/tests/unit_test_gem_properties.py index dee5811b65..6358917852 100644 --- a/scripts/o3de/tests/unit_test_gem_properties.py +++ b/scripts/o3de/tests/unit_test_gem_properties.py @@ -18,10 +18,9 @@ TEST_GEM_JSON_PAYLOAD = ''' { "gem_name": "TestGem", "display_name": "TestGem", - "license": "MIT", - "license_url": "https://opensource.org/licenses/MIT", + "license": "Apache-2.0 or MIT", + "license_url": "https://github.com/o3de/o3de/blob/development/LICENSE.txt", "origin": "The primary repo for TestGem goes here: i.e. http://www.mydomain.com", - "type": "Code", "summary": "A short description of TestGem.", "canonical_tags": [ "Gem" @@ -31,7 +30,9 @@ TEST_GEM_JSON_PAYLOAD = ''' ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/" + "documentation_url": "https://o3de.org/docs/", + "dependencies": [ + ] } ''' diff --git a/scripts/o3de/tests/unit_test_manifest.py b/scripts/o3de/tests/unit_test_manifest.py index ad4809dc1d..c7d7a7573b 100644 --- a/scripts/o3de/tests/unit_test_manifest.py +++ b/scripts/o3de/tests/unit_test_manifest.py @@ -22,7 +22,7 @@ from o3de import manifest ]) class TestGetTemplatesForCreation: @staticmethod - def get_templates() -> list: + def get_manifest_templates() -> list: return [] @staticmethod @@ -40,20 +40,24 @@ class TestGetTemplatesForCreation: ) def test_get_templates_for_generic_creation(self, valid_project_json_paths, valid_gem_json_paths, expected_template_paths): - def validate_project_json(template_path) -> bool: - return pathlib.Path(template_path) in valid_project_json_paths + def validate_project_json(project_json_path) -> bool: + return pathlib.Path(project_json_path) in valid_project_json_paths - def validate_gem_json(template_path) -> bool: - return pathlib.Path(template_path) in valid_gem_json_paths + def validate_gem_json(gem_json_path) -> bool: + return pathlib.Path(gem_json_path) in valid_gem_json_paths - with patch('o3de.manifest.get_templates', side_effect=self.get_templates) as get_templates_patch, \ + with patch('o3de.manifest.get_manifest_templates', side_effect=self.get_manifest_templates)\ + as get_manifest_templates_patch, \ patch('o3de.manifest.get_project_templates', side_effect=self.get_project_templates)\ as get_project_templates_patch, \ patch('o3de.manifest.get_engine_templates', side_effect=self.get_engine_templates)\ as get_engine_templates_patch, \ - patch('o3de.validation.valid_o3de_template_json', return_value=True) as validate_template_json,\ - patch('o3de.validation.valid_o3de_project_json', side_effect=validate_project_json) as validate_project_json,\ - patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) as validate_gem_json: + patch('o3de.validation.valid_o3de_template_json', return_value=True) \ + as validate_template_json,\ + patch('o3de.validation.valid_o3de_project_json', side_effect=validate_project_json) \ + as validate_project_json,\ + patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) \ + as validate_gem_json: templates = manifest.get_templates_for_generic_creation() assert templates == expected_template_paths @@ -64,21 +68,24 @@ class TestGetTemplatesForCreation: ) def test_get_templates_for_gem_creation(self, valid_project_json_paths, valid_gem_json_paths, expected_template_paths): - def validate_project_json(template_path) -> bool: - return pathlib.Path(template_path) in valid_project_json_paths + def validate_project_json(project_json_path) -> bool: + return pathlib.Path(project_json_path) in valid_project_json_paths - def validate_gem_json(template_path) -> bool: - return pathlib.Path(template_path) in valid_gem_json_paths + def validate_gem_json(gem_json_path) -> bool: + return pathlib.Path(gem_json_path) in valid_gem_json_paths - with patch('o3de.manifest.get_templates', side_effect=self.get_templates) as get_templates_patch, \ + with patch('o3de.manifest.get_manifest_templates', side_effect=self.get_manifest_templates)\ + as get_manifest_templates_patch, \ patch('o3de.manifest.get_project_templates', side_effect=self.get_project_templates) \ as get_project_templates_patch, \ patch('o3de.manifest.get_engine_templates', side_effect=self.get_engine_templates) \ as get_engine_templates_patch, \ - patch('o3de.validation.valid_o3de_template_json', return_value=True) as validate_template_json, \ - patch('o3de.validation.valid_o3de_project_json', - side_effect=validate_project_json) as validate_project_json, \ - patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) as validate_gem_json: + patch('o3de.validation.valid_o3de_template_json', return_value=True) \ + as validate_template_json, \ + patch('o3de.validation.valid_o3de_project_json', side_effect=validate_project_json) \ + as validate_project_json, \ + patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) \ + as validate_gem_json: templates = manifest.get_templates_for_project_creation() assert templates == expected_template_paths @@ -89,20 +96,23 @@ class TestGetTemplatesForCreation: ) def test_get_templates_for_project_creation(self, valid_project_json_paths, valid_gem_json_paths, expected_template_paths): - def validate_project_json(template_path) -> bool: - return pathlib.Path(template_path) in valid_project_json_paths + def validate_project_json(project_json_path) -> bool: + return pathlib.Path(project_json_path) in valid_project_json_paths - def validate_gem_json(template_path) -> bool: - return pathlib.Path(template_path) in valid_gem_json_paths + def validate_gem_json(gem_json_path) -> bool: + return pathlib.Path(gem_json_path) in valid_gem_json_paths - with patch('o3de.manifest.get_templates', side_effect=self.get_templates) as get_templates_patch, \ + with patch('o3de.manifest.get_manifest_templates', side_effect=self.get_manifest_templates) \ + as get_manifest_templates_patch, \ patch('o3de.manifest.get_project_templates', side_effect=self.get_project_templates) \ as get_project_templates_patch, \ patch('o3de.manifest.get_engine_templates', side_effect=self.get_engine_templates) \ as get_engine_templates_patch, \ - patch('o3de.validation.valid_o3de_template_json', return_value=True) as validate_template_json, \ - patch('o3de.validation.valid_o3de_project_json', - side_effect=validate_project_json) as validate_project_json, \ - patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) as validate_gem_json: + patch('o3de.validation.valid_o3de_template_json', return_value=True) \ + as validate_template_json, \ + patch('o3de.validation.valid_o3de_project_json', side_effect=validate_project_json) \ + as validate_project_json, \ + patch('o3de.validation.valid_o3de_gem_json', side_effect=validate_gem_json) \ + as validate_gem_json: templates = manifest.get_templates_for_gem_creation() assert templates == expected_template_paths \ No newline at end of file diff --git a/scripts/o3de/tests/unit_test_print_registration.py b/scripts/o3de/tests/unit_test_print_registration.py index 7e3e75edcd..d01434c99f 100644 --- a/scripts/o3de/tests/unit_test_print_registration.py +++ b/scripts/o3de/tests/unit_test_print_registration.py @@ -90,27 +90,20 @@ TEST_TEMPLATE_JSON_PAYLOAD = ''' "copyFiles": [ { "file": "CMakeLists.txt", - "origin": "CMakeLists.txt", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "gem.json", - "origin": "gem.json", - "isTemplated": true, - "isOptional": false + "isTemplated": true }, { "file": "preview.png", - "origin": "preview.png", - "isTemplated": false, - "isOptional": false + "isTemplated": false } ], "createDirectories": [ { - "dir": "Assets", - "origin": "Assets" + "dir": "Assets" } ] } @@ -277,13 +270,9 @@ class TestPrintRegistration: # Patch the manifest.py function to locate gem.json files in external subdirectories # to just return a fake path to a single test gem - def get_gems_from_subdirectories(external_subdirs: list) -> list: - return ["D:/TestGem"] - with patch('o3de.manifest.load_o3de_manifest', side_effect=self.load_manifest_json) as load_manifest_patch, \ patch('o3de.manifest.get_gem_json_data', side_effect=self.get_gem_json_data) as get_json_patch, \ patch('o3de.manifest.get_project_json_data', side_effect=self.get_project_json_data) as get_project_json_patch, \ - patch('o3de.manifest.get_gems_from_subdirectories', side_effect=get_gems_from_subdirectories) as get_gems_from_subdirs_patch, \ patch('o3de.print_registration.get_project_path', return_value=project_path) as get_project_path_patch: result = print_registration._run_register_show(test_args) assert result == 0 From 284ae60139eef1c69cd8981048dc77c4bd26631a Mon Sep 17 00:00:00 2001 From: moudgils <47460854+moudgils@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:34:57 -0800 Subject: [PATCH 090/108] Add missing 'precise' keyword for Vertex shaders (#6902) Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com> --- .../Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl | 4 ++-- .../Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl | 2 +- Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl | 2 +- .../Types/StandardMultilayerPBR_DepthPass_WithPS.azsl | 4 ++-- .../Materials/Types/StandardMultilayerPBR_ForwardPass.azsl | 2 +- .../TestData/Materials/Types/AutoBrick_ForwardPass.azsl | 2 +- .../TestData/Materials/Types/MinimalPBR_ForwardPass.azsl | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl index f2564cf10c..08642decc0 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_DepthPass_WithPS.azsl @@ -28,7 +28,7 @@ struct VSInput struct VSDepthOutput { - float4 m_position : SV_Position; + precise linear centroid float4 m_position : SV_Position; float2 m_uv[UvSetCount] : UV1; // only used for parallax depth calculation @@ -62,7 +62,7 @@ VSDepthOutput MainVS(VSInput IN) struct PSDepthOutput { - float m_depth : SV_Depth; + precise float m_depth : SV_Depth; }; PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 0f9771e480..4b37f67930 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -67,7 +67,7 @@ struct VSInput struct VSOutput { // Base fields (required by the template azsli file)... - float4 m_position : SV_Position; + precise linear centroid float4 m_position : SV_Position; float3 m_normal: NORMAL; float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 523353f8fa..00dee50c93 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -86,7 +86,7 @@ struct VSInput struct VSOutput { // Base fields (required by the template azsli file)... - float4 m_position : SV_Position; + precise linear centroid float4 m_position : SV_Position; float3 m_normal: NORMAL; float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl index 39597e2bdd..7875457489 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_DepthPass_WithPS.azsl @@ -41,7 +41,7 @@ struct VSInput struct VSDepthOutput { - float4 m_position : SV_Position; + precise linear centroid float4 m_position : SV_Position; float2 m_uv[UvSetCount] : UV1; // only used for parallax depth calculation @@ -88,7 +88,7 @@ VSDepthOutput MainVS(VSInput IN) struct PSDepthOutput { - float m_depth : SV_Depth; + precise float m_depth : SV_Depth; }; PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 8f58c6dd33..5b05e48d3b 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -80,7 +80,7 @@ struct VSInput struct VSOutput { // Base fields (required by the template azsli file)... - float4 m_position : SV_Position; + precise linear centroid float4 m_position : SV_Position; float3 m_normal: NORMAL; float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; diff --git a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl index 2dbba46d8b..05ce5f4774 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl @@ -28,7 +28,7 @@ struct VSInput struct VSOutput { - float4 m_position : SV_Position; + precise linear centroid float4 m_position : SV_Position; float3 m_normal: NORMAL; float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl index 2f6f038e4b..fe9e4099d0 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl @@ -33,7 +33,7 @@ struct VSInput struct VSOutput { - float4 m_position : SV_Position; + precise linear centroid float4 m_position : SV_Position; float3 m_normal: NORMAL; float3 m_tangent : TANGENT; float3 m_bitangent : BITANGENT; From bbfe740cc9c9eb1772aa35f76a1ba0a98606f9c7 Mon Sep 17 00:00:00 2001 From: allisaurus <34254888+allisaurus@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:52:32 -0800 Subject: [PATCH 091/108] Disable flaky HttpRequestor test (#6866) Signed-off-by: allisaurus <34254888+allisaurus@users.noreply.github.com> --- Gems/HttpRequestor/Code/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/HttpRequestor/Code/CMakeLists.txt b/Gems/HttpRequestor/Code/CMakeLists.txt index 4ebca5518c..56d3527e24 100644 --- a/Gems/HttpRequestor/Code/CMakeLists.txt +++ b/Gems/HttpRequestor/Code/CMakeLists.txt @@ -71,5 +71,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ) ly_add_googletest( NAME Gem::HttpRequestor.Tests + TEST_SUITE sandbox ) endif() From 7680d1f9d0ea0b2ac2a5f073ba5329f8b7080033 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Fri, 14 Jan 2022 11:28:21 -0800 Subject: [PATCH 092/108] [development] fixed issue with dangling budget pointers if the budget tracker is torn down and rebuilt (#6801) Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com --- .../AzCore/Component/ComponentApplication.cpp | 10 +++++---- Code/Framework/AzCore/AzCore/Debug/Budget.h | 16 +++++++++----- .../AzCore/AzCore/Debug/BudgetTracker.cpp | 22 +++++++++++++------ .../AzCore/AzCore/Debug/BudgetTracker.h | 4 ++-- 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp index 693b2f1648..72b6e807d2 100644 --- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp +++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp @@ -565,10 +565,6 @@ namespace AZ m_entityActivatedEvent.DisconnectAllHandlers(); m_entityDeactivatedEvent.DisconnectAllHandlers(); -#if !defined(_RELEASE) - m_budgetTracker.Reset(); -#endif - DestroyAllocator(); } @@ -758,6 +754,12 @@ namespace AZ static_cast(m_settingsRegistry.get())->ClearNotifiers(); static_cast(m_settingsRegistry.get())->ClearMergeEvents(); +#if !defined(_RELEASE) + // the budget tracker must be cleaned up prior to module unloading to ensure + // budgets initialized cross boundary are freed properly + m_budgetTracker.Reset(); +#endif + // Uninit and unload any dynamic modules. m_moduleManager->UnloadModules(); ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "GemsUnloaded", R"({})"); diff --git a/Code/Framework/AzCore/AzCore/Debug/Budget.h b/Code/Framework/AzCore/AzCore/Debug/Budget.h index 4646ef8b2c..c909302886 100644 --- a/Code/Framework/AzCore/AzCore/Debug/Budget.h +++ b/Code/Framework/AzCore/AzCore/Debug/Budget.h @@ -62,12 +62,16 @@ namespace AZ::Debug // // Anywhere the budget is used, the budget must be declared (either in a header or in the source file itself) // AZ_DECLARE_BUDGET(AzCore); -#define AZ_DEFINE_BUDGET(name) \ - ::AZ::Debug::Budget* AZ_BUDGET_GETTER(name)() \ - { \ - constexpr static uint32_t crc = AZ_CRC_CE(#name); \ - static ::AZ::Debug::Budget* budget = ::AZ::Debug::BudgetTracker::GetBudgetFromEnvironment(#name, crc); \ - return budget; \ +#define AZ_DEFINE_BUDGET(name) \ + ::AZ::Debug::Budget* AZ_BUDGET_GETTER(name)() \ + { \ + static ::AZ::Debug::Budget* budget = nullptr; \ + if (budget == nullptr) \ + { \ + constexpr static uint32_t crc = AZ_CRC_CE(#name); \ + ::AZ::Debug::BudgetTracker::GetBudgetFromEnvironment(budget, #name, crc); \ + } \ + return budget; \ } #endif diff --git a/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.cpp b/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.cpp index 2dac9a566e..faadbfc31a 100644 --- a/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.cpp +++ b/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.cpp @@ -13,23 +13,24 @@ #include #include #include +#include #include namespace AZ::Debug { struct BudgetTracker::BudgetTrackerImpl { - AZStd::unordered_map m_budgets; + AZStd::unordered_map m_budgets; + AZStd::unordered_set m_externalBudgetRefs; }; - Budget* BudgetTracker::GetBudgetFromEnvironment(const char* budgetName, uint32_t crc) + void BudgetTracker::GetBudgetFromEnvironment(Budget*& extBudgetRef, const char* budgetName, uint32_t crc) { BudgetTracker* tracker = Interface::Get(); if (tracker) { - return &tracker->GetBudget(budgetName, crc); + tracker->GetBudget(extBudgetRef, budgetName, crc); } - return nullptr; } BudgetTracker::~BudgetTracker() @@ -54,17 +55,24 @@ namespace AZ::Debug if (m_impl) { Interface::Unregister(this); + + for (auto budgetRef : m_impl->m_externalBudgetRefs) + { + *budgetRef = nullptr; + } + delete m_impl; m_impl = nullptr; } } - Budget& BudgetTracker::GetBudget(const char* budgetName, uint32_t crc) + void BudgetTracker::GetBudget(Budget*& extBudgetRef, const char* budgetName, uint32_t crc) { AZStd::scoped_lock lock{ m_mutex }; - auto it = m_impl->m_budgets.try_emplace(budgetName, budgetName, crc).first; + m_impl->m_externalBudgetRefs.insert(&extBudgetRef); - return it->second; + auto iter = m_impl->m_budgets.try_emplace(budgetName, budgetName, crc).first; + extBudgetRef = &iter->second; } } // namespace AZ::Debug diff --git a/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h b/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h index 34d8510349..69e8185746 100644 --- a/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h +++ b/Code/Framework/AzCore/AzCore/Debug/BudgetTracker.h @@ -20,7 +20,7 @@ namespace AZ::Debug { public: AZ_TYPE_INFO(BudgetTracker, "{E14A746D-BFFE-4C02-90FB-4699B79864A5}"); - static Budget* GetBudgetFromEnvironment(const char* budgetName, uint32_t crc); + static void GetBudgetFromEnvironment(Budget*& extBudgetRef, const char* budgetName, uint32_t crc); ~BudgetTracker(); @@ -28,7 +28,7 @@ namespace AZ::Debug bool Init(); void Reset(); - Budget& GetBudget(const char* budgetName, uint32_t crc); + void GetBudget(Budget*& extBudgetRef, const char* budgetName, uint32_t crc); private: struct BudgetTrackerImpl; From c403fa3db6d3dc8653c8f5908b6cbb908636c2c7 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Fri, 14 Jan 2022 13:30:45 -0600 Subject: [PATCH 093/108] More GetValues() overrides (#6896) * Benchmarks and tests for Image and Constant GetValues Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Verify GetValues for Perlin and Random Gradients Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Standardized the assert format for GetValues(). Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * More GetValues unit tests and test cleanup Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed typos Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * GetValues() unit tests for surface gradients. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Benchmarks for ShapeAreaFalloff Gradient Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added benchmarks for all remaining gradients and cleaned up the helper methods. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Renamed class for better report formatting. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Added missing Mocks dependencies for the Editor tests. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * First batch of specific GetValues() overrides. Each one is measurably faster than the generic version. Also, in ShapeAreaFalloffGradient, I optimized and simplified the logic a bit, so GetValue() is marginally faster too. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Change GetValues() to use span and add more overrides. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Convert GetValues() to use AZStd::span and added more overrides. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Add missing include. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * PR feedback - switch to fill Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> * Fixed the logic and added unit tests and comments. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../AzCore/AzCore/std/containers/span.h | 2 +- .../AzCore/AzCore/std/containers/span.inl | 2 +- Gems/GradientSignal/Code/CMakeLists.txt | 5 - .../Components/ConstantGradientComponent.h | 2 +- .../Components/DitherGradientComponent.h | 8 + .../Components/ImageGradientComponent.h | 2 +- .../Components/InvertGradientComponent.h | 1 + .../Components/LevelsGradientComponent.h | 1 + .../Components/PerlinGradientComponent.h | 2 +- .../Components/RandomGradientComponent.h | 2 +- .../ShapeAreaFalloffGradientComponent.h | 2 +- .../Ebuses/GradientRequestBus.h | 11 +- .../Include/GradientSignal/GradientSampler.h | 20 +-- .../Code/Include/GradientSignal/Util.h | 60 ++++++-- .../Components/ConstantGradientComponent.cpp | 8 +- .../Components/DitherGradientComponent.cpp | 140 +++++++++++------- .../Components/ImageGradientComponent.cpp | 10 +- .../Components/InvertGradientComponent.cpp | 15 ++ .../Components/LevelsGradientComponent.cpp | 17 ++- .../Components/PerlinGradientComponent.cpp | 10 +- .../Components/RandomGradientComponent.cpp | 10 +- .../ShapeAreaFalloffGradientComponent.cpp | 13 +- .../Tests/GradientSignalGetValuesTests.cpp | 6 +- .../Tests/GradientSignalServicesTests.cpp | 126 ++++++++++++++++ 24 files changed, 331 insertions(+), 144 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/std/containers/span.h b/Code/Framework/AzCore/AzCore/std/containers/span.h index 8f68e921d8..5bb51bf481 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/span.h +++ b/Code/Framework/AzCore/AzCore/std/containers/span.h @@ -59,7 +59,7 @@ namespace AZStd constexpr span(pointer s, size_type length); - constexpr span(pointer first, const_pointer last); + constexpr span(pointer first, pointer last); // We explicitly delete this constructor because it's too easy to accidentally // create a span to just the first element instead of an entire array. diff --git a/Code/Framework/AzCore/AzCore/std/containers/span.inl b/Code/Framework/AzCore/AzCore/std/containers/span.inl index c33e4a7227..01bab9a5a4 100644 --- a/Code/Framework/AzCore/AzCore/std/containers/span.inl +++ b/Code/Framework/AzCore/AzCore/std/containers/span.inl @@ -24,7 +24,7 @@ namespace AZStd } template - inline constexpr span::span(pointer first, const_pointer last) + inline constexpr span::span(pointer first, pointer last) : m_begin(first) , m_end(last) { } diff --git a/Gems/GradientSignal/Code/CMakeLists.txt b/Gems/GradientSignal/Code/CMakeLists.txt index d4cf666630..d2d8f8c696 100644 --- a/Gems/GradientSignal/Code/CMakeLists.txt +++ b/Gems/GradientSignal/Code/CMakeLists.txt @@ -19,7 +19,6 @@ ly_add_target( BUILD_DEPENDENCIES PUBLIC AZ::AzCore - AZ::AtomCore AZ::AzFramework Gem::SurfaceData Gem::ImageProcessingAtom.Headers @@ -41,7 +40,6 @@ ly_add_target( Gem::LmbrCentral PUBLIC AZ::AzCore - AZ::AtomCore Gem::GradientSignal.Static Gem::ImageProcessingAtom.Headers # Atom/ImageProcessing/PixelFormats.h is part of a header in Includes RUNTIME_DEPENDENCIES @@ -73,7 +71,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) PUBLIC 3rdParty::Qt::Widgets AZ::AzCore - AZ::AtomCore AZ::AzFramework AZ::AzToolsFramework AZ::AssetBuilderSDK @@ -97,8 +94,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) PRIVATE Gem::GradientSignal.Editor.Static Gem::LmbrCentral.Editor - PUBLIC - AZ::AtomCore RUNTIME_DEPENDENCIES Gem::LmbrCentral.Editor ) diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h index af896f0933..1ed06a976a 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ConstantGradientComponent.h @@ -62,7 +62,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; - void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; protected: ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/DitherGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/DitherGradientComponent.h index ed12ec2ff7..add6de06cf 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/DitherGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/DitherGradientComponent.h @@ -77,6 +77,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; ////////////////////////////////////////////////////////////////////////// @@ -102,6 +103,13 @@ namespace GradientSignal GradientSampler& GetGradientSampler() override; private: + static int ScaledPositionToPatternIndex(const AZ::Vector3& scaledPosition, int patternSize); + static float GetDitherValue4x4(const AZ::Vector3& scaledPosition); + static float GetDitherValue8x8(const AZ::Vector3& scaledPosition); + + float GetCalculatedPointsPerUnit() const; + float GetDitherValue(const AZ::Vector3& scaledPosition, float value) const; + DitherGradientConfig m_configuration; LmbrCentral::DependencyMonitor m_dependencyMonitor; }; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h index 9fc98124cb..79d42ec478 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h @@ -69,7 +69,7 @@ namespace GradientSignal // GradientRequestBus overrides... float GetValue(const GradientSampleParams& sampleParams) const override; - void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; // AZ::Data::AssetBus overrides... void OnAssetReady(AZ::Data::Asset asset) override; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/InvertGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/InvertGradientComponent.h index 79dbea975b..a370286b0b 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/InvertGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/InvertGradientComponent.h @@ -64,6 +64,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; protected: diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/LevelsGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/LevelsGradientComponent.h index 5e70adfe32..093f84ef3a 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/LevelsGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/LevelsGradientComponent.h @@ -69,6 +69,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override; protected: diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h index 1b39f7f17b..19f3fe7294 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/PerlinGradientComponent.h @@ -70,7 +70,7 @@ namespace GradientSignal // GradientRequestBus overrides... float GetValue(const GradientSampleParams& sampleParams) const override; - void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; private: PerlinGradientConfig m_configuration; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h index 274442a2c0..328fed5118 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/RandomGradientComponent.h @@ -61,7 +61,7 @@ namespace GradientSignal // GradientRequestBus overrides... float GetValue(const GradientSampleParams& sampleParams) const override; - void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; private: RandomGradientConfig m_configuration; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h index df86c38069..27b2da58a3 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ShapeAreaFalloffGradientComponent.h @@ -69,7 +69,7 @@ namespace GradientSignal ////////////////////////////////////////////////////////////////////////// // GradientRequestBus float GetValue(const GradientSampleParams& sampleParams) const override; - void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const override; + void GetValues(AZStd::span positions, AZStd::span outValues) const override; protected: ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h b/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h index 3a215c5b5d..45b5a173a3 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Ebuses/GradientRequestBus.h @@ -10,8 +10,7 @@ #include #include #include - -#include +#include namespace GradientSignal { @@ -57,7 +56,7 @@ namespace GradientSignal * \param positions The input list of positions to query. * \param outValues The output list of values. This list is expected to be the same size as the positions list. */ - virtual void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + virtual void GetValues(AZStd::span positions, AZStd::span outValues) const { // Reference implementation of GetValues for any gradients that don't have their own optimized implementations. // This is 10%-60% faster than calling GetValue via EBus many times due to the per-call EBus overhead. @@ -72,11 +71,7 @@ namespace GradientSignal for (size_t index = 0; index < positions.size(); index++) { sampleParams.m_position = positions[index]; - - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); - outValue = GetValue(sampleParams); + outValues[index] = GetValue(sampleParams); } } diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h b/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h index a2e1849590..c9aa7f680c 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/GradientSampler.h @@ -33,7 +33,7 @@ namespace GradientSignal static void Reflect(AZ::ReflectContext* context); inline float GetValue(const GradientSampleParams& sampleParams) const; - inline void GetValues(AZStd::array_view positions, AZStd::array_view outValues) const; + inline void GetValues(AZStd::span positions, AZStd::span outValues) const; bool IsEntityInHierarchy(const AZ::EntityId& entityId) const; @@ -147,18 +147,12 @@ namespace GradientSignal return output * m_opacity; } - inline void GradientSampler::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + inline void GradientSampler::GetValues(AZStd::span positions, AZStd::span outValues) const { - auto ClearOutputValues = [](AZStd::array_view outValues) + auto ClearOutputValues = [](AZStd::span outValues) { // If we don't have a valid gradient (or it is fully transparent), clear out all the output values. - for (size_t index = 0; index < outValues.size(); index++) - { - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); - outValue = 0.0f; - } + memset(outValues.data(), 0, outValues.size() * sizeof(float)); }; if (m_opacity <= 0.0f || !m_gradientId.IsValid()) @@ -214,12 +208,8 @@ namespace GradientSignal } // Perform any post-fetch transformations on the gradient values (invert, levels, opacity). - for (size_t index = 0; index < outValues.size(); index++) + for (auto& outValue : outValues) { - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); - if (m_invertInput) { outValue = 1.0f - outValue; diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Util.h b/Gems/GradientSignal/Code/Include/GradientSignal/Util.h index fa1791c053..f91c5d54f1 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Util.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Util.h @@ -7,11 +7,12 @@ */ #pragma once +#include #include #include -#include #include #include +#include #include #include @@ -53,28 +54,61 @@ namespace GradientSignal inline float GetLevels(float input, float inputMid, float inputMin, float inputMax, float outputMin, float outputMax) { - input = AZ::GetClamp(input, 0.0f, 1.0f); - inputMid = AZ::GetClamp(inputMid, 0.01f, 10.0f); // Clamp the midpoint to a non-zero value so that it's always safe to divide by it. + inputMid = AZ::GetClamp(inputMid, 0.01f, 10.0f); // Clamp the midpoint to a non-zero value so that it's always safe to divide by it. inputMin = AZ::GetClamp(inputMin, 0.0f, 1.0f); inputMax = AZ::GetClamp(inputMax, 0.0f, 1.0f); outputMin = AZ::GetClamp(outputMin, 0.0f, 1.0f); outputMax = AZ::GetClamp(outputMax, 0.0f, 1.0f); - float inputCorrected = 0.0f; if (inputMin == inputMax) { - inputCorrected = (input <= inputMin) ? 0.0f : 1.0f; - } - else - { - const float inputRemapped = AZ::GetMin(AZ::GetMax(input - inputMin, 0.0f) / (inputMax - inputMin), 1.0f); - // Note: Some paint programs map the midpoint using 1/mid where low values are dark and high values are light, - // others do the reverse and use mid directly, so low values are light and high values are dark. We've chosen to - // align with 1/mid since it appears to be the more prevalent of the two approaches. - inputCorrected = powf(inputRemapped, 1.0f / inputMid); + return (AZ::GetClamp(input, 0.0f, 1.0f) <= inputMin) ? outputMin : outputMax; } + const float inputMidReciprocal = 1.0f / inputMid; + const float inputExtentsReciprocal = 1.0f / (inputMax - inputMin); + + const float inputRemapped = + AZ::GetMin(AZ::GetMax(AZ::GetClamp(input, 0.0f, 1.0f) - inputMin, 0.0f) * inputExtentsReciprocal, 1.0f); + + // Note: Some paint programs map the midpoint using 1/mid where low values are dark and high values are light, + // others do the reverse and use mid directly, so low values are light and high values are dark. We've chosen to + // align with 1/mid since it appears to be the more prevalent of the two approaches. + const float inputCorrected = powf(inputRemapped, inputMidReciprocal); + return AZ::Lerp(outputMin, outputMax, inputCorrected); } + inline void GetLevels(AZStd::span inOutValues, float inputMid, float inputMin, float inputMax, float outputMin, float outputMax) + { + inputMid = AZ::GetClamp(inputMid, 0.01f, 10.0f); // Clamp the midpoint to a non-zero value so that it's always safe to divide by it. + inputMin = AZ::GetClamp(inputMin, 0.0f, 1.0f); + inputMax = AZ::GetClamp(inputMax, 0.0f, 1.0f); + outputMin = AZ::GetClamp(outputMin, 0.0f, 1.0f); + outputMax = AZ::GetClamp(outputMax, 0.0f, 1.0f); + + if (inputMin == inputMax) + { + for (auto& inOutValue : inOutValues) + { + inOutValue = (AZ::GetClamp(inOutValue, 0.0f, 1.0f) <= inputMin) ? outputMin : outputMax; + } + } + + const float inputMidReciprocal = 1.0f / inputMid; + const float inputExtentsReciprocal = 1.0f / (inputMax - inputMin); + + for (auto& inOutValue : inOutValues) + { + const float inputRemapped = + AZ::GetMin(AZ::GetMax(AZ::GetClamp(inOutValue, 0.0f, 1.0f) - inputMin, 0.0f) * inputExtentsReciprocal, 1.0f); + + // Note: Some paint programs map the midpoint using 1/mid where low values are dark and high values are light, + // others do the reverse and use mid directly, so low values are light and high values are dark. We've chosen to + // align with 1/mid since it appears to be the more prevalent of the two approaches. + const float inputCorrected = powf(inputRemapped, inputMidReciprocal); + + inOutValue = AZ::Lerp(outputMin, outputMax, inputCorrected); + } + } } // namespace GradientSignal diff --git a/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp index 2b1487f75e..ac81f616c6 100644 --- a/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ConstantGradientComponent.cpp @@ -135,7 +135,7 @@ namespace GradientSignal } void ConstantGradientComponent::GetValues( - [[maybe_unused]] AZStd::array_view positions, AZStd::array_view outValues) const + [[maybe_unused]] AZStd::span positions, AZStd::span outValues) const { if (positions.size() != outValues.size()) { @@ -143,11 +143,7 @@ namespace GradientSignal return; } - for (auto& outValue : outValues) - { - float& writableOutValue = const_cast(outValue); - writableOutValue = m_configuration.m_value; - } + AZStd::fill(outValues.begin(), outValues.end(), m_configuration.m_value); } float ConstantGradientComponent::GetConstantValue() const diff --git a/Gems/GradientSignal/Code/Source/Components/DitherGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/DitherGradientComponent.cpp index c7845a41a6..1b320afeb9 100644 --- a/Gems/GradientSignal/Code/Source/Components/DitherGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/DitherGradientComponent.cpp @@ -174,90 +174,122 @@ namespace GradientSignal return false; } - int PositionToMatrixIndex(float position, int patternSize) + int DitherGradientComponent::ScaledPositionToPatternIndex(const AZ::Vector3& scaledPosition, int patternSize) { - int result = static_cast(std::floor(fmod(position, static_cast(patternSize)))); + // The input position is expected to be scaled up so that each integer value is a unique point in our dither pattern, and + // the fractional value is just the amount within the point. The output is the specific index into an NxN pattern to use + // for the dither comparison value. - if (result < 0) - { - result += patternSize; - } + // Get the floor before casting to int because we want fractional negative values to go "down" to the next negative value. + AZ::Vector3 flooredScaledPosition = scaledPosition.GetFloor(); - return result; + // For a pattern of 4, we want our indices to go 0, 1, 2, 3, 0, 1, 2, 3, etc. However, we want it continuous across + // negative and positive positions so we can't just use mod with abs(). Instead, we use a double-mod which gives us + // a result that's continuous across all coordinate space. + const int x = ((static_cast(flooredScaledPosition.GetX()) % patternSize) + patternSize) % patternSize; + const int y = ((static_cast(flooredScaledPosition.GetY()) % patternSize) + patternSize) % patternSize; + + return (patternSize * y + x); } - float GetDitherValue4x4(const AZ::Vector3& position) + float DitherGradientComponent::GetDitherValue4x4(const AZ::Vector3& scaledPosition) { - const int patternSize = 4; - const int patternSizeSq = patternSize * patternSize; - const int indexMatrix[patternSizeSq] = { - 0, 8, 2, 10, - 12, 4, 14, 6, - 3, 11, 1, 9, - 15, 7, 13, 5 }; + constexpr int patternSize = 4; + constexpr float indexMatrix[] = { + 0.0f / 16.0f, 8.0f / 16.0f, 2.0f / 16.0f, 10.0f / 16.0f, + 12.0f / 16.0f, 4.0f / 16.0f, 14.0f / 16.0f, 6.0f / 16.0f, + 3.0f / 16.0f, 11.0f / 16.0f, 1.0f / 16.0f, 9.0f / 16.0f, + 15.0f / 16.0f, 7.0f / 16.0f, 13.0f / 16.0f, 5.0f / 16.0f }; - const int x = PositionToMatrixIndex(position.GetX(), patternSize); - const int y = PositionToMatrixIndex(position.GetY(), patternSize); - - return indexMatrix[patternSize * y + x] / static_cast(patternSizeSq); + return indexMatrix[ScaledPositionToPatternIndex(scaledPosition, patternSize)]; } - float GetDitherValue8x8(const AZ::Vector3& position) + float DitherGradientComponent::GetDitherValue8x8(const AZ::Vector3& scaledPosition) { - const int patternSize = 8; - const int patternSizeSq = patternSize * patternSize; - const int indexMatrix[patternSizeSq] = { - 0, 32, 8, 40, 2, 34, 10, 42, - 48, 16, 56, 24, 50, 18, 58, 26, - 12, 44, 4, 36, 14, 46, 6, 38, - 60, 28, 52, 20, 62, 30, 54, 22, - 3, 35, 11, 43, 1, 33, 9, 41, - 51, 19, 59, 27, 49, 17, 57, 25, - 15, 47, 7, 39, 13, 45, 5, 37, - 63, 31, 55, 23, 61, 29, 53, 21 }; + constexpr int patternSize = 8; + constexpr float indexMatrix[] = { + 0.0f / 64.0f, 32.0f / 64.0f, 8.0f / 64.0f, 40.0f / 64.0f, 2.0f / 64.0f, 34.0f / 64.0f, 10.0f / 64.0f, 42.0f / 64.0f, + 48.0f / 64.0f, 16.0f / 64.0f, 56.0f / 64.0f, 24.0f / 64.0f, 50.0f / 64.0f, 18.0f / 64.0f, 58.0f / 64.0f, 26.0f / 64.0f, + 12.0f / 64.0f, 44.0f / 64.0f, 4.0f / 64.0f, 36.0f / 64.0f, 14.0f / 64.0f, 46.0f / 64.0f, 6.0f / 64.0f, 38.0f / 64.0f, + 60.0f / 64.0f, 28.0f / 64.0f, 52.0f / 64.0f, 20.0f / 64.0f, 62.0f / 64.0f, 30.0f / 64.0f, 54.0f / 64.0f, 22.0f / 64.0f, + 3.0f / 64.0f, 35.0f / 64.0f, 11.0f / 64.0f, 43.0f / 64.0f, 1.0f / 64.0f, 33.0f / 64.0f, 9.0f / 64.0f, 41.0f / 64.0f, + 51.0f / 64.0f, 19.0f / 64.0f, 59.0f / 64.0f, 27.0f / 64.0f, 49.0f / 64.0f, 17.0f / 64.0f, 57.0f / 64.0f, 25.0f / 64.0f, + 15.0f / 64.0f, 47.0f / 64.0f, 7.0f / 64.0f, 39.0f / 64.0f, 13.0f / 64.0f, 45.0f / 64.0f, 5.0f / 64.0f, 37.0f / 64.0f, + 63.0f / 64.0f, 31.0f / 64.0f, 55.0f / 64.0f, 23.0f / 64.0f, 61.0f / 64.0f, 29.0f / 64.0f, 53.0f / 64.0f, 21.0f / 64.0f + }; - const int x = PositionToMatrixIndex(position.GetX(), patternSize); - const int y = PositionToMatrixIndex(position.GetY(), patternSize); - - return indexMatrix[patternSize * y + x] / static_cast(patternSizeSq); + return indexMatrix[ScaledPositionToPatternIndex(scaledPosition, patternSize)]; } - float DitherGradientComponent::GetValue(const GradientSampleParams& sampleParams) const + float DitherGradientComponent::GetCalculatedPointsPerUnit() const { - AZ_PROFILE_FUNCTION(Entity); - - const AZ::Vector3& coordinate = sampleParams.m_position; - float pointsPerUnit = m_configuration.m_pointsPerUnit; if (m_configuration.m_useSystemPointsPerUnit) { SectorDataRequestBus::Broadcast(&SectorDataRequestBus::Events::GetPointsPerMeter, pointsPerUnit); } - pointsPerUnit = AZ::GetMax(pointsPerUnit, 0.0001f); - - auto scaledCoordinate = coordinate * pointsPerUnit; - auto x = std::floor(scaledCoordinate.GetX()) / pointsPerUnit; - auto y = std::floor(scaledCoordinate.GetY()) / pointsPerUnit; - auto z = std::floor(scaledCoordinate.GetZ()) / pointsPerUnit; - AZ::Vector3 flooredCoordinate(x, y, z); - - GradientSampleParams adjustedSampleParams = sampleParams; - adjustedSampleParams.m_position = flooredCoordinate; - float value = m_configuration.m_gradientSampler.GetValue(adjustedSampleParams); + return AZ::GetMax(pointsPerUnit, 0.0001f); + } + float DitherGradientComponent::GetDitherValue(const AZ::Vector3& scaledPosition, float value) const + { float d = 0.0f; switch (m_configuration.m_patternType) { default: case DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4: - d = GetDitherValue4x4((scaledCoordinate) + m_configuration.m_patternOffset); + d = GetDitherValue4x4(scaledPosition + m_configuration.m_patternOffset); break; case DitherGradientConfig::BayerPatternType::PATTERN_SIZE_8x8: - d = GetDitherValue8x8((scaledCoordinate) + m_configuration.m_patternOffset); + d = GetDitherValue8x8(scaledPosition + m_configuration.m_patternOffset); break; } - return value > d ? 1.0f : 0.0f; + return (value > d) ? 1.0f : 0.0f; + } + + float DitherGradientComponent::GetValue(const GradientSampleParams& sampleParams) const + { + const AZ::Vector3& coordinate = sampleParams.m_position; + + const float pointsPerUnit = GetCalculatedPointsPerUnit(); + + AZ::Vector3 scaledCoordinate = coordinate * pointsPerUnit; + AZ::Vector3 flooredCoordinate = scaledCoordinate.GetFloor() / pointsPerUnit; + + GradientSampleParams adjustedSampleParams = sampleParams; + adjustedSampleParams.m_position = flooredCoordinate; + float value = m_configuration.m_gradientSampler.GetValue(adjustedSampleParams); + + return GetDitherValue(scaledCoordinate, value); + } + + void DitherGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + const float pointsPerUnit = GetCalculatedPointsPerUnit(); + + // Create the entire set of floored coordinates to use in the gradient value lookups. + AZStd::vector flooredCoordinates(positions.size()); + for (size_t index = 0; index < positions.size(); index++) + { + AZ::Vector3 scaledCoordinate = positions[index] * pointsPerUnit; + flooredCoordinates[index] = scaledCoordinate.GetFloor() / pointsPerUnit; + } + + m_configuration.m_gradientSampler.GetValues(flooredCoordinates, outValues); + + // For each gradient value, turn it into a 0 or 1 based on the location and the dither pattern. + for (size_t index = 0; index < positions.size(); index++) + { + AZ::Vector3 scaledCoordinate = positions[index] * pointsPerUnit; + outValues[index] = GetDitherValue(scaledCoordinate, outValues[index]); + } } bool DitherGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const diff --git a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp index 06a3674188..d948f6269e 100644 --- a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp @@ -219,7 +219,7 @@ namespace GradientSignal return 0.0f; } - void ImageGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + void ImageGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const { if (positions.size() != outValues.size()) { @@ -234,20 +234,16 @@ namespace GradientSignal for (size_t index = 0; index < positions.size(); index++) { - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); - m_gradientTransform.TransformPositionToUVWNormalized(positions[index], uvw, wasPointRejected); if (!wasPointRejected) { - outValue = GetValueFromImageAsset( + outValues[index] = GetValueFromImageAsset( m_configuration.m_imageAsset, uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); } else { - outValue = 0.0f; + outValues[index] = 0.0f; } } } diff --git a/Gems/GradientSignal/Code/Source/Components/InvertGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/InvertGradientComponent.cpp index 678f3b363c..aef5cc7a52 100644 --- a/Gems/GradientSignal/Code/Source/Components/InvertGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/InvertGradientComponent.cpp @@ -137,6 +137,21 @@ namespace GradientSignal return output; } + void InvertGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + m_configuration.m_gradientSampler.GetValues(positions, outValues); + for (auto& outValue : outValues) + { + outValue = 1.0f - AZ::GetClamp(outValue, 0.0f, 1.0f); + } + } + bool InvertGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const { return m_configuration.m_gradientSampler.IsEntityInHierarchy(entityId); diff --git a/Gems/GradientSignal/Code/Source/Components/LevelsGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/LevelsGradientComponent.cpp index b2958c590c..25f6a34614 100644 --- a/Gems/GradientSignal/Code/Source/Components/LevelsGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/LevelsGradientComponent.cpp @@ -172,8 +172,6 @@ namespace GradientSignal float LevelsGradientComponent::GetValue(const GradientSampleParams& sampleParams) const { - AZ_PROFILE_FUNCTION(Entity); - float output = 0.0f; output = GetLevels( @@ -187,6 +185,21 @@ namespace GradientSignal return output; } + void LevelsGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const + { + if (positions.size() != outValues.size()) + { + AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size()); + return; + } + + m_configuration.m_gradientSampler.GetValues(positions, outValues); + + GetLevels(outValues, + m_configuration.m_inputMid, m_configuration.m_inputMin, m_configuration.m_inputMax, + m_configuration.m_outputMin, m_configuration.m_outputMax); + } + bool LevelsGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const { return m_configuration.m_gradientSampler.IsEntityInHierarchy(entityId); diff --git a/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp index 667d8c30a7..e3dfaf2161 100644 --- a/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/PerlinGradientComponent.cpp @@ -203,7 +203,7 @@ namespace GradientSignal return 0.0f; } - void PerlinGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + void PerlinGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const { if (positions.size() != outValues.size()) { @@ -218,21 +218,17 @@ namespace GradientSignal for (size_t index = 0; index < positions.size(); index++) { - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); - m_gradientTransform.TransformPositionToUVW(positions[index], uvw, wasPointRejected); if (!wasPointRejected) { - outValue = m_perlinImprovedNoise->GenerateOctaveNoise( + outValues[index] = m_perlinImprovedNoise->GenerateOctaveNoise( uvw.GetX(), uvw.GetY(), uvw.GetZ(), m_configuration.m_octave, m_configuration.m_amplitude, m_configuration.m_frequency); } else { - outValue = 0.0f; + outValues[index] = 0.0f; } } } diff --git a/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp index ae51bdd4ac..0f4ece38a1 100644 --- a/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/RandomGradientComponent.cpp @@ -183,7 +183,7 @@ namespace GradientSignal return 0.0f; } - void RandomGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + void RandomGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const { if (positions.size() != outValues.size()) { @@ -200,19 +200,15 @@ namespace GradientSignal for (size_t index = 0; index < positions.size(); index++) { - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); - m_gradientTransform.TransformPositionToUVW(positions[index], uvw, wasPointRejected); if (!wasPointRejected) { - outValue = GetRandomValue(uvw, seed); + outValues[index] = GetRandomValue(uvw, seed); } else { - outValue = 0.0f; + outValues[index] = 0.0f; } } } diff --git a/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp index f2416f4fb6..77b7f1a428 100644 --- a/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ShapeAreaFalloffGradientComponent.cpp @@ -168,7 +168,7 @@ namespace GradientSignal return (distance <= 0.0f) ? 1.0f : AZ::GetMax(1.0f - (distance / m_configuration.m_falloffWidth), 0.0f); } - void ShapeAreaFalloffGradientComponent::GetValues(AZStd::array_view positions, AZStd::array_view outValues) const + void ShapeAreaFalloffGradientComponent::GetValues(AZStd::span positions, AZStd::span outValues) const { if (positions.size() != outValues.size()) { @@ -187,10 +187,6 @@ namespace GradientSignal for (size_t index = 0; index < positions.size(); index++) { - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); - float distance = shapeRequests->DistanceFromPoint(positions[index]); // Since this is outer falloff, distance should give us values from 1.0 at the minimum distance to 0.0 at the maximum @@ -198,18 +194,15 @@ namespace GradientSignal // inside the shape (0 distance) return 1.0, and all points outside the shape return 0. This works because division by 0 // gives infinity, which gets clamped by the GetMax() to 0. However, if distance == 0, it would give us NaN, so we have // the separate conditional check to handle that case and clamp to 1.0. - outValue = (distance <= 0.0f) ? 1.0f : AZ::GetMax(1.0f - (distance / falloffWidth), 0.0f); + outValues[index] = (distance <= 0.0f) ? 1.0f : AZ::GetMax(1.0f - (distance / falloffWidth), 0.0f); } }); // If there's no shape, there's no falloff. if (!shapeConnected) { - for (size_t index = 0; index < positions.size(); index++) + for (auto& outValue : outValues) { - // The const_cast is necessary for now since array_view currently only supports const entries. - // If/when array_view is fixed to support non-const, or AZStd::span gets created, the const_cast can get removed. - auto& outValue = const_cast(outValues[index]); outValue = 1.0f; } } diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp index 5504fa5b45..6c4ebcc4c0 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalGetValuesTests.cpp @@ -56,9 +56,9 @@ namespace UnitTest params.m_position = positions[positionIndex]; float value = gradientSampler.GetValue(params); - // We use ASSERT_EQ instead of EXPECT_EQ because if one value doesn't match, they probably all won't, so there's no reason - // to keep running and printing failures for every value. - ASSERT_EQ(value, results[positionIndex]); + // We use ASSERT_NEAR instead of EXPECT_NEAR because if one value doesn't match, they probably all won't, so there's no + // reason to keep running and printing failures for every value. + ASSERT_NEAR(value, results[positionIndex], 0.000001f); } } }; diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp b/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp index 449719af67..830c578b9b 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp +++ b/Gems/GradientSignal/Code/Tests/GradientSignalServicesTests.cpp @@ -10,6 +10,8 @@ #include +#include + #include #include #include @@ -81,6 +83,130 @@ namespace UnitTest TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); } + TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At50Pct_CrossingZero) + { + // With a 4x4 gradient filled with 8/16 (0.5), verify that the resulting dithered output + // is an expected checkerboard pattern with 8 of 16 pixels filled. The pattern offset is + // shifted -2 in the X direction so that the lookups go from [-2, 2) to verify that the + // pattern remains consistent across negative and positive coordinates. + + constexpr int dataSize = 4; + + AZStd::vector inputData(dataSize * dataSize, 8.0f / 16.0f); + AZStd::vector expectedOutput = { + 1.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + }; + + auto entityMock = CreateEntity(); + const AZ::EntityId id = entityMock->GetId(); + UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize); + + GradientSignal::DitherGradientConfig config; + config.m_useSystemPointsPerUnit = false; + config.m_pointsPerUnit = 1.0f; + config.m_patternOffset = AZ::Vector3(-2.0f, 0.0f, 0.0f); + config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4; + config.m_gradientSampler.m_gradientId = entityMock->GetId(); + + auto entity = CreateEntity(); + entity->CreateComponent(config); + ActivateEntity(entity.get()); + + TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); + } + + TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At50Pct_MorePointsPerUnit) + { + // With a 4x4 gradient filled with 8/16 (0.5), and 1/2 point per unit, if we query a 4x4 region, + // we should get a checkerboard in 2x2 blocks of the same value because it takes 2 units before the value changes. + + constexpr int dataSize = 4; + + AZStd::vector inputData(dataSize * dataSize, 8.0f / 16.0f); + AZStd::vector expectedOutput = { + 1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, + }; + + auto entityMock = CreateEntity(); + const AZ::EntityId id = entityMock->GetId(); + UnitTest::MockGradientArrayRequestsBus mockGradientRequestsBus(id, inputData, dataSize); + + GradientSignal::DitherGradientConfig config; + config.m_useSystemPointsPerUnit = false; + config.m_pointsPerUnit = 0.5f; + config.m_patternOffset = AZ::Vector3::CreateZero(); + config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4; + config.m_gradientSampler.m_gradientId = entityMock->GetId(); + + auto entity = CreateEntity(); + entity->CreateComponent(config); + ActivateEntity(entity.get()); + + TestFixedDataSampler(expectedOutput, dataSize, entity->GetId()); + } + + TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At50Pct_MorePointsAndCrossingZero) + { + // With a 4x4 gradient filled with 8/16 (0.5), and 2 points per unit, verify that querying + // from -1 to 1 produces a constant checkerboard pattern of results as it crosses the 0 boundary. + // Our expected results are a consistent checkerboard pattern, but with 2x2 blocks of the same value because we're + // querying at 2x the point density (i.e. querying 4 points per unit) to ensure that fractional position lookups work too. + + float expectedValues[] = { + 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + }; + + // Create a 50% constant gradient. + GradientSignal::ConstantGradientConfig constantConfig; + constantConfig.m_value = 8.0f / 16.0f; + auto constantGradientEntity = CreateEntity(); + constantGradientEntity->CreateComponent(constantConfig); + ActivateEntity(constantGradientEntity.get()); + + GradientSignal::DitherGradientConfig config; + config.m_useSystemPointsPerUnit = false; + config.m_pointsPerUnit = 2.0f; + config.m_patternOffset = AZ::Vector3::CreateZero(); + config.m_patternType = GradientSignal::DitherGradientConfig::BayerPatternType::PATTERN_SIZE_4x4; + config.m_gradientSampler.m_gradientId = constantGradientEntity->GetId(); + + auto entity = CreateEntity(); + entity->CreateComponent(config); + ActivateEntity(entity.get()); + + // Run through [-1, 1) at 1/4 intervals and make sure we get our expected checkerboard. This is testing both that + // we have a consistent pattern across the 0 boundary and that fractional position lookups work correctly + GradientSignal::GradientSampler gradientSampler; + gradientSampler.m_gradientId = entity->GetId(); + int expectedValueIndex = 0; + for (float y = -1.0f; y < 1.0f; y += 0.25f) + { + for (float x = -1.0f; x < 1.0f; x += 0.25f) + { + GradientSignal::GradientSampleParams params; + params.m_position = AZ::Vector3(x, y, 0.0f); + + float actualValue = gradientSampler.GetValue(params); + float expectedValue = expectedValues[expectedValueIndex++]; + + EXPECT_NEAR(actualValue, expectedValue, 0.01f); + } + } + } + TEST_F(GradientSignalServicesTestsFixture, DitherGradientComponent_4x4At31Pct) { // With a 4x4 gradient filled with 5/16 (0.3125), verify that the resulting dithered output From d95e157f480c92086ac38a79f6ae764ae0f1f3d8 Mon Sep 17 00:00:00 2001 From: moudgils <47460854+moudgils@users.noreply.github.com> Date: Fri, 14 Jan 2022 12:24:58 -0800 Subject: [PATCH 094/108] Different Pso cache per vendor/driver (#6893) * Support to add a different PSO cache per vendor/driver version. Also added support to have a differnt cache for Warp Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com> * Added a way to reset PSO cache for everyone Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com> * Fix tabbing for one line which is failing validation Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com> --- .../Atom/RHI.Reflect/PhysicalDeviceDescriptor.h | 3 ++- Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h | 12 ++++++++---- Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h | 3 +++ .../RHI/Code/Include/Atom/RHI/RHISystemInterface.h | 3 +++ Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 6 ++++++ .../Source/Platform/Windows/RHI/Device_Windows.cpp | 5 ++++- .../RHI/DX12/Code/Source/RHI/PipelineLibrary.cpp | 10 ++++------ .../RPI/Code/Source/RPI.Public/Shader/Shader.cpp | 12 ++++++++++-- 8 files changed, 40 insertions(+), 14 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PhysicalDeviceDescriptor.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PhysicalDeviceDescriptor.h index ac79ff0521..4d78d24ca8 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PhysicalDeviceDescriptor.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/PhysicalDeviceDescriptor.h @@ -28,7 +28,8 @@ namespace AZ (AMD, 0x1002), (Qualcomm, 0x5143), (Samsung, 0x1099), - (ARM, 0x13B5) + (ARM, 0x13B5), + (Warp, 0x1414) ); void ReflectVendorIdEnums(ReflectContext* context); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h index eb2b0b5b0c..47cf7709db 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h @@ -164,23 +164,27 @@ namespace AZ //! it will defer to the platform for parallel dispatch support. void Execute(JobPolicy jobPolicy); - /// Returns the timing statistics for the previous frame. + //! Returns the timing statistics for the previous frame. const TransientAttachmentStatistics* GetTransientAttachmentStatistics() const; - /// Returns current CPU frame to frame time in milliseconds. + //! Returns current CPU frame to frame time in milliseconds. double GetCpuFrameTime() const; - /// Returns memory statistics for the previous frame. + //! Returns memory statistics for the previous frame. const MemoryStatistics* GetMemoryStatistics() const; - /// Returns the implicit root scope id. + //! Returns the implicit root scope id. ScopeId GetRootScopeId() const; + //! Returns the descriptor which has information on the properties of a TransientAttachmentPool. const TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const; //! Adds a RayTracingShaderTable to be built this frame void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable); + //! Returns PhysicalDeviceDescriptor which can be used to extract vendor/driver information + const PhysicalDeviceDescriptor& GetPhysicalDeviceDescriptor(); + private: const ScopeId m_rootScopeId{"Root"}; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h index 6d416b77fc..c2a3162025 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h @@ -53,6 +53,7 @@ namespace AZ const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const override; ConstPtr GetPlatformLimitsDescriptor() const override; void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable) override; + const PhysicalDeviceDescriptor& GetPhysicalDeviceDescriptor() override; ////////////////////////////////////////////////////////////////////////// private: @@ -65,6 +66,8 @@ namespace AZ RHI::Ptr m_pipelineStateCache; RHI::FrameScheduler m_frameScheduler; RHI::FrameSchedulerCompileRequest m_compileRequest; + PhysicalDeviceDescriptor m_physicalDeviceDescriptor; + }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h index 19ba1cb762..66f6b2bcde 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h @@ -26,6 +26,7 @@ namespace AZ class PipelineState; class PipelineStateCache; class PlatformLimitsDescriptor; + class PhysicalDeviceDescriptor; class RayTracingShaderTable; struct FrameSchedulerCompileRequest; struct TransientAttachmentStatistics; @@ -65,6 +66,8 @@ namespace AZ virtual ConstPtr GetPlatformLimitsDescriptor() const = 0; virtual void QueueRayTracingShaderTableForBuild(RayTracingShaderTable* rayTracingShaderTable) = 0; + + virtual const PhysicalDeviceDescriptor& GetPhysicalDeviceDescriptor() = 0; }; //! This bus exists to give RHI samples the ability to slot in scopes manually diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index e7515bbf6e..3ec0cfeb93 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -165,6 +165,7 @@ namespace AZ RHI::Ptr device = RHI::Factory::Get().CreateDevice(); if (device->Init(*physicalDeviceFound) == RHI::ResultCode::Success) { + m_physicalDeviceDescriptor = physicalDeviceFound->GetDescriptor(); PlatformLimitsDescriptor::Create(); return device; } @@ -279,5 +280,10 @@ namespace AZ { m_frameScheduler.QueueRayTracingShaderTableForBuild(rayTracingShaderTable); } + + const PhysicalDeviceDescriptor& RHISystem::GetPhysicalDeviceDescriptor() + { + return m_physicalDeviceDescriptor; + } } //namespace RPI } //namespace AZ diff --git a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp index f6ed3be692..a2ed31ff84 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/Platform/Windows/RHI/Device_Windows.cpp @@ -157,7 +157,10 @@ namespace AZ disabledMessages.push_back(D3D12_MESSAGE_ID_COPY_DESCRIPTORS_INVALID_RANGES); } - // [GFX TODO][ATOM-4712] - Fix PipelineLibrary Loading. These warnings were silenced for a release and need to be fixed properly. + // We disable these warnings as the our current implementation of Pipeline Library will trigger these warnings unknowingly. For example + // it will always first try to load a pso from pipelinelibrary triggering D3D12_MESSAGE_ID_LOADPIPELINE_NAMENOTFOUND (for the first time) before storing the PSO in a library. + // Similarly when we merge multiple pipeline libraries (in multiple threads) we may trigger D3D12_MESSAGE_ID_STOREPIPELINE_DUPLICATENAME as it is possible to save + // a PSO already saved in the main library. #if defined (AZ_DX12_USE_PIPELINE_LIBRARY) disabledMessages.push_back(D3D12_MESSAGE_ID_LOADPIPELINE_NAMENOTFOUND); disabledMessages.push_back(D3D12_MESSAGE_ID_STOREPIPELINE_DUPLICATENAME); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLibrary.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLibrary.cpp index 63625fde72..ae3053f446 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLibrary.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/PipelineLibrary.cpp @@ -50,10 +50,9 @@ namespace AZ bool shouldCreateLibFromSerializedData = true; if (RHI::Factory::Get().IsRenderDocModuleLoaded() || - RHI::Factory::Get().IsPixModuleLoaded() || - RHI::Factory::Get().UsingWarpDevice()) + RHI::Factory::Get().IsPixModuleLoaded()) { - // CreatePipelineLibrary api does not function properly if Renderdoc, Pix or Warp is enabled + // CreatePipelineLibrary api does not function properly if Renderdoc or Pix is enabled shouldCreateLibFromSerializedData = false; } @@ -218,10 +217,9 @@ namespace AZ RHI::ResultCode PipelineLibrary::MergeIntoInternal([[maybe_unused]] AZStd::array_view pipelineLibraries) { if (RHI::Factory::Get().IsRenderDocModuleLoaded() || - RHI::Factory::Get().IsPixModuleLoaded() || - RHI::Factory::Get().UsingWarpDevice()) + RHI::Factory::Get().IsPixModuleLoaded()) { - // StorePipeline api does not function properly if RenderDoc, Pix or Warp is enabled + // StorePipeline api does not function properly if RenderDoc or Pix is enabled return RHI::ResultCode::Fail; } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp index b1ae460af6..92c2e30594 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp @@ -17,6 +17,7 @@ #include +#define PSOCacheVersion 0 // Bump this if you want to reset PSO cache for everyone namespace AZ { @@ -85,10 +86,17 @@ namespace AZ AZStd::string uuidString; assetId.m_guid.ToString(uuidString, false, false); + RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get(); + RHI::PhysicalDeviceDescriptor physicalDeviceDesc = rhiSystem->GetPhysicalDeviceDescriptor(); + char pipelineLibraryPathTemp[AZ_MAX_PATH_LEN]; azsnprintf( - pipelineLibraryPathTemp, AZ_MAX_PATH_LEN, "@user@/Atom/PipelineStateCache/%s/%s_%s_%d.bin", platformName.GetCStr(), - shaderName.GetCStr(), uuidString.data(), assetId.m_subId); + pipelineLibraryPathTemp, AZ_MAX_PATH_LEN, "@user@/Atom/PipelineStateCache_%s_%i_%i _Ver_%i/%s/%s_%s_%d.bin", + ToString(physicalDeviceDesc.m_vendorId).data(), physicalDeviceDesc.m_deviceId, physicalDeviceDesc.m_driverVersion, PSOCacheVersion, + platformName.GetCStr(), + shaderName.GetCStr(), + uuidString.data(), + assetId.m_subId); fileIOBase->ResolvePath(pipelineLibraryPathTemp, pipelineLibraryPath, pipelineLibraryPathLength); return true; From aa18deef5d70f2468a67df535de4e64fcd799ff3 Mon Sep 17 00:00:00 2001 From: Adi Bar-Lev <82479970+Adi-Amazon@users.noreply.github.com> Date: Fri, 14 Jan 2022 15:26:41 -0500 Subject: [PATCH 095/108] AtomTressFX - fixing crash bug for prefab (#6892) - The crash happens due to attempt to get an instance of the hair dynamic data before it was initialized. Signed-off-by: Adi Bar-Lev <82479970+Adi-Amazon@users.noreply.github.com> --- .../Code/Rendering/HairRenderObject.cpp | 16 +++++++++++++--- .../Code/Rendering/HairRenderObject.h | 10 ++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Gems/AtomTressFX/Code/Rendering/HairRenderObject.cpp b/Gems/AtomTressFX/Code/Rendering/HairRenderObject.cpp index fe167cae8b..472a610016 100644 --- a/Gems/AtomTressFX/Code/Rendering/HairRenderObject.cpp +++ b/Gems/AtomTressFX/Code/Rendering/HairRenderObject.cpp @@ -213,6 +213,8 @@ namespace AZ Data::Instance rasterShader, uint32_t vertexCount, uint32_t strandsCount ) { + m_initialized = false; + AZ_Assert(vertexCount <= std::numeric_limits().max(), "Hair vertex count exceeds uint32_t size."); // Create the dynamic shared buffers Srg. @@ -608,8 +610,16 @@ namespace AZ // First, Directly loading from the asset stored in the render settings. if (pRenderSettings) { - m_baseAlbedo = RPI::StreamingImage::FindOrCreate(pRenderSettings->m_baseAlbedoAsset); - m_strandAlbedo = RPI::StreamingImage::FindOrCreate(pRenderSettings->m_strandAlbedoAsset); + if (pRenderSettings->m_baseAlbedoAsset) + { + pRenderSettings->m_baseAlbedoAsset.BlockUntilLoadComplete(); + m_baseAlbedo = RPI::StreamingImage::FindOrCreate(pRenderSettings->m_baseAlbedoAsset); + } + if (pRenderSettings->m_strandAlbedoAsset) + { + pRenderSettings->m_strandAlbedoAsset.BlockUntilLoadComplete(); + m_strandAlbedo = RPI::StreamingImage::FindOrCreate(pRenderSettings->m_strandAlbedoAsset); + } } // Fallback using the texture name stored in the render settings. @@ -1142,7 +1152,7 @@ namespace AZ if (!renderMaterialSrg || !simSrg) { - AZ_Error("Hair Gem", false, "Failed to get thre hair material Srg for the raster pass."); + AZ_Error("Hair Gem", false, "Failed to get the hair material Srg for the raster pass."); return false; } // No need to compile the simSrg since it was compiled already by the Compute pass this frame diff --git a/Gems/AtomTressFX/Code/Rendering/HairRenderObject.h b/Gems/AtomTressFX/Code/Rendering/HairRenderObject.h index 817ebd89fa..564272e6f0 100644 --- a/Gems/AtomTressFX/Code/Rendering/HairRenderObject.h +++ b/Gems/AtomTressFX/Code/Rendering/HairRenderObject.h @@ -110,8 +110,14 @@ namespace AZ PrepareSrgDescriptors(m_dynamicBuffersDescriptors, vertexCount, strandsCount); } - Data::Instance GetSimSrgForCompute() { return m_simSrgForCompute; } - Data::Instance GetSimSrgForRaster() { return m_simSrgForRaster; } + Data::Instance GetSimSrgForCompute() + { + return m_initialized ? m_simSrgForCompute : nullptr; + } + + Data::Instance GetSimSrgForRaster() + { + return m_initialized ? m_simSrgForRaster : nullptr; } bool IsInitialized() { return m_initialized; } From 295c836ed81839cc13695df1e2c6b6bf13b06adb Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Fri, 14 Jan 2022 12:46:08 -0800 Subject: [PATCH 096/108] clean up comments, add set type action in disabled form Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Source/Components/Slots/Data/DataSlotComponent.cpp | 1 - Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp | 3 --- Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp | 8 ++++++-- Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp | 1 - .../Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp | 6 +++--- .../Variable/GraphVariableManagerComponent.cpp | 1 - 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp index 7eb9187123..c053c37fbc 100644 --- a/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp +++ b/Gems/GraphCanvas/Code/Source/Components/Slots/Data/DataSlotComponent.cpp @@ -328,7 +328,6 @@ namespace GraphCanvas bool DataSlotComponent::CanConvertToReference([[maybe_unused]] bool isNewSlot) const { - // #sc_user_slot_variable_ux make sure this can be converted to reference, or created as one bool canToggleReference = false; if (m_canConvertSlotTypes && DataSlotUtils::IsValueDataSlotType(m_dataSlotType) && !HasConnections()) diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp index 92045b505f..510962cf4b 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorGraph.cpp @@ -667,7 +667,6 @@ namespace ScriptCanvasEditor } // Now that the slot has a valid type/name, we can actually promote it to a variable - // #sc_user_slot_variable_ux add a value indicating that the slot is new if (PromoteToVariableAction(endpoint, true)) { ScriptCanvas::GraphVariable* variable = slot->GetVariable(); @@ -2191,7 +2190,6 @@ namespace ScriptCanvasEditor bool Graph::PromoteToVariableAction(const GraphCanvas::Endpoint& endpoint, bool isNewSlot) { - // #sc_user_slot_variable_ux make the fix here...rework is user added or something ScriptCanvas::Endpoint scriptCanvasEndpoint = ConvertToScriptCanvasEndpoint(endpoint); auto activeNode = FindNode(scriptCanvasEndpoint.GetNodeId()); @@ -2283,7 +2281,6 @@ namespace ScriptCanvasEditor AZ::Outcome addOutcome; - // #sc_user_slot_variable_ux re-use the activeDatum, send the pointer (actually, all of the source slot information, and make a special conversion) ScriptCanvas::GraphVariableManagerRequestBus::EventResult(addOutcome, GetScriptCanvasId(), &ScriptCanvas::GraphVariableManagerRequests::AddVariable, variableName, variableDatum, true); if (addOutcome.IsSuccess()) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp index 573a3f6e57..b5b4fc7787 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/MainWindow.cpp @@ -3874,8 +3874,12 @@ namespace ScriptCanvasEditor contextMenu.AddMenuAction(aznew ExposeSlotMenuAction(&contextMenu)); contextMenu.AddMenuAction(aznew CreateAzEventHandlerSlotMenuAction(&contextMenu)); - // disabling until references can be changed - // contextMenu.AddMenuAction(aznew SetDataSlotTypeMenuAction(&contextMenu)); + auto setSlotTypeAction = aznew SetDataSlotTypeMenuAction(&contextMenu); + // Changing slot type is disabled temporarily because now that that user data slots are correctly coordinated with their reference + // variables, their type cannot be changed. The next change will allow all variables to change their type post creation, and then + // that will allow this action to be enabled. + setSlotTypeAction->setEnabled(false); + contextMenu.AddMenuAction(setSlotTypeAction); return HandleContextMenu(contextMenu, slotId, screenPoint, scenePoint); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp index 6aef61b12f..4bdd0daae6 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Slot.cpp @@ -462,7 +462,6 @@ namespace ScriptCanvas bool Slot::CanConvertToReference(bool isNewSlot) const { - // #sc_user_slot_variable_ux make sure this can be converted to reference, or created as one return (!m_isUserAdded || isNewSlot) && CanConvertTypes() && !m_isVariableReference && !m_node->HasConnectedNodes((*this)); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index b2194e1bd0..345dc1ebda 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -237,7 +237,7 @@ namespace ScriptCanvas if (auto datum = variablePair.second.GetDatum()) { - // #sc_user_slot_variable_ux consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering + // #functions2 slot<->variable consider getting all variables from the UX variable manager, or from the ACM and looking them up in the variable manager for ordering m_sourceVariableByDatum.insert(AZStd::make_pair(datum, &variablePair.second)); } } @@ -247,7 +247,7 @@ namespace ScriptCanvas auto datum = sourceVariable->GetDatum(); AZ_Assert(datum != nullptr, "the datum must be valid"); - // #sc_user_slot_variable_ux check to verify if it is a member variable + // #functions2 slot<->variable check to verify if it is a member variable auto variable = sourceVariable->GetScope() == VariableFlags::Scope::Graph ? AddMemberVariable(*datum, sourceVariable->GetVariableName(), sourceVariable->GetVariableId()) : AddVariable(*datum, sourceVariable->GetVariableName(), sourceVariable->GetVariableId()); @@ -1670,7 +1670,7 @@ namespace ScriptCanvas if (returnValue.second->m_source->m_sourceSlotId == slot->GetId()) { - // #sc_user_slot_variable_ux determine if the root or the function call should be passed in here...the slot/node lead to the user call on the thread, but it may not even be created yet + // #functions2 slot<->variable determine if the root or the function call should be passed in here...the slot/node lead to the user call on the thread, but it may not even be created yet return AZStd::make_pair(root, returnValue.second->m_source); } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp index 81383bf747..0bd1b2c5a4 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Variable/GraphVariableManagerComponent.cpp @@ -220,7 +220,6 @@ namespace ScriptCanvas return AZ::Success(newId); } - // #sc_user_slot_variable_ux add this to the graph, using the old datum AZ::Outcome GraphVariableManagerComponent::AddVariable(AZStd::string_view name, const Datum& value, bool functionScope) { if (FindVariable(name)) From c9ee1f7871b5875de19b943df05d7a705f0ce7ef Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Fri, 14 Jan 2022 13:31:13 -0800 Subject: [PATCH 097/108] ATOM-17132 Image builder failed to build some images after preset was fixed (#6900) The issue was because the preset reload was only happened in CreateJobs but not ProcessJobs. But these two functions might be called from different AssetBuilder. The fix is to add preset reload for Processjobs too. There was another change to add debug device name for streaming image. Signed-off-by: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> --- .../BuilderSettings/TextureSettings.cpp | 8 +++++ .../Code/Source/ImageBuilderComponent.cpp | 34 +++++++++++++++++-- .../RPI.Public/Image/StreamingImage.cpp | 12 ++++--- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp index 29d9b21775..4772a94ffa 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp @@ -226,6 +226,14 @@ namespace ImageProcessingAtom MultiplatformTextureSettings settings; PlatformNameList platformsList = BuilderSettingManager::Instance()->GetPlatformList(); PresetName suggestedPreset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilepath); + + // If the suggested preset doesn't exist (or was failed to be loaded), return empty texture settings + if (BuilderSettingManager::Instance()->GetPreset(suggestedPreset) == nullptr) + { + AZ_Error("Image Processing", false, "Failed to find suggested preset [%s]", suggestedPreset.GetCStr()); + return settings; + } + for (PlatformName& platform : platformsList) { TextureSettings textureSettings; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp index 5e021a3fdd..55a6c1ea8f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp @@ -241,8 +241,7 @@ namespace ImageProcessingAtom // Reload preset if it was changed ImageProcessingAtom::BuilderSettingManager::Instance()->ReloadPreset(presetName); - AZStd::string_view filePath; - auto presetSettings = BuilderSettingManager::Instance()->GetPreset(presetName, /*default platform*/"", &filePath); + auto presetSettings = BuilderSettingManager::Instance()->GetPreset(presetName, /*default platform*/""); AssetBuilderSDK::SourceFileDependency sourceFileDependency; sourceFileDependency.m_sourceDependencyType = AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Absolute; @@ -274,6 +273,32 @@ namespace ImageProcessingAtom } } + void ReloadPresetIfNeeded(PresetName presetName) + { + // Reload preset if it was changed + ImageProcessingAtom::BuilderSettingManager::Instance()->ReloadPreset(presetName); + + auto presetSettings = BuilderSettingManager::Instance()->GetPreset(presetName, /*default platform*/""); + + if (presetSettings) + { + // handle special case here + // Cubemap setting may reference some other presets + if (presetSettings->m_cubemapSetting) + { + if (presetSettings->m_cubemapSetting->m_generateIBLDiffuse && !presetSettings->m_cubemapSetting->m_iblDiffusePreset.IsEmpty()) + { + ImageProcessingAtom::BuilderSettingManager::Instance()->ReloadPreset(presetSettings->m_cubemapSetting->m_iblDiffusePreset); + } + + if (presetSettings->m_cubemapSetting->m_generateIBLSpecular && !presetSettings->m_cubemapSetting->m_iblSpecularPreset.IsEmpty()) + { + ImageProcessingAtom::BuilderSettingManager::Instance()->ReloadPreset(presetSettings->m_cubemapSetting->m_iblSpecularPreset); + } + } + } + } + // this happens early on in the file scanning pass // this function should consistently always create the same jobs, and should do no checking whether the job is up to date or not - just be consistent. void ImageBuilderWorker::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response) @@ -336,6 +361,11 @@ namespace ImageProcessingAtom // Do conversion and get exported file's path if (needConversion) { + + // Handles preset changes + auto presetName = GetImagePreset(request.m_fullPath); + ReloadPresetIfNeeded(presetName); + AZ_TracePrintf(AssetBuilderSDK::InfoWindow, "Performing image conversion: %s\n", request.m_fullPath.c_str()); ImageConvertProcess* process = CreateImageConvertProcess(request.m_fullPath, request.m_tempDirPath, request.m_jobDescription.GetPlatformIdentifier(), response.m_outputProducts); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp index fb03d109a2..49cd52f212 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/StreamingImage.cpp @@ -143,11 +143,6 @@ namespace AZ RHI::ResultCode resultCode = RHI::ResultCode::Success; const ImageMipChainAsset& mipChainTailAsset = imageAsset.GetTailMipChain(); - -#ifdef AZ_RPI_STREAMING_IMAGE_DEBUG_LOG - m_image->SetName(Name(imageAsset.GetHint().c_str())); - AZ_TracePrintf("StreamingImage", "Init image [%s]\n", m_image->GetName().data()); -#endif { RHI::StreamingImageInitRequest initRequest; @@ -193,6 +188,13 @@ namespace AZ m_rhiPool = rhiPool; m_pool = pool; m_pool->AttachImage(this); + + // Set rhi image name + m_image->SetName(Name(m_imageAsset.GetHint())); + +#ifdef AZ_RPI_STREAMING_IMAGE_DEBUG_LOG + AZ_TracePrintf("StreamingImage", "Init image [%s]\n", m_image->GetName().data()); +#endif #if defined (AZ_RPI_STREAMING_IMAGE_HOT_RELOADING) BusConnect(imageAsset.GetId()); From 588527064019a15f81c8626a80db7ada0b472e49 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Fri, 14 Jan 2022 14:36:15 -0800 Subject: [PATCH 098/108] [iOS] Update to use AWSNativeSDK 1.9.50 (#6890) Signed-off-by: onecent1101 --- Gems/AWSCore/Code/Platform/iOS/AWSCore_Traits_iOS.h | 2 +- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/AWSCore/Code/Platform/iOS/AWSCore_Traits_iOS.h b/Gems/AWSCore/Code/Platform/iOS/AWSCore_Traits_iOS.h index d7b1f32461..2cacfb0d34 100644 --- a/Gems/AWSCore/Code/Platform/iOS/AWSCore_Traits_iOS.h +++ b/Gems/AWSCore/Code/Platform/iOS/AWSCore_Traits_iOS.h @@ -7,4 +7,4 @@ */ #pragma once -#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 0 +#define AWSCORE_BACKWARD_INCOMPATIBLE_CHANGE 1 diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index d8dd7e8134..4b99efc9d0 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -18,7 +18,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS gla # platform-specific: ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-ios TARGETS TIFF PACKAGE_HASH e9067e88649fb6e93a926d9ed38621a9fae360a2e6f6eb24ebca63c1bc7761ea) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-ios TARGETS freetype PACKAGE_HASH 3ac3c35e056ae4baec2e40caa023d76a7a3320895ef172b6655e9261b0dc2e29) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-ios TARGETS AWSNativeSDK PACKAGE_HASH d10e7496ca705577032821011beaf9f2507689f23817bfa0ed4d2a2758afcd02) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-ios TARGETS AWSNativeSDK PACKAGE_HASH c3c9478c259ecb569fb2ce6fcfa733647adc3b6bd2854e8eff9de64bcd18c745) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev5-ios TARGETS PhysX PACKAGE_HASH 4a5e38b385837248590018eb133444b4e440190414e6756191200a10c8fa5615) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-ios TARGETS mikkelsen PACKAGE_HASH 976aaa3ccd8582346132a10af253822ccc5d5bcc9ea5ba44d27848f65ee88a8a) From c15d3f35bf37fb4fd5f49f33350d34557f1a9c49 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Fri, 14 Jan 2022 14:57:35 -0800 Subject: [PATCH 099/108] fix release build errors Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp | 4 ++-- .../Source/AutomationActions/DynamicSlotFullCreation.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp b/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp index 525386a1a3..5face707c3 100644 --- a/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp +++ b/Gems/GraphModel/Code/Tests/MockGraphCanvas.cpp @@ -94,12 +94,12 @@ namespace MockGraphCanvasServices GraphCanvas::DataSlotRequestBus::Handler::BusDisconnect(); } - bool MockDataSlotComponent::ConvertToReference([[maybe_unused]] bool isNewSlot = false) + bool MockDataSlotComponent::ConvertToReference([[maybe_unused]] bool isNewSlot) { return false; } - bool MockDataSlotComponent::CanConvertToReference([[maybe_unused]] bool isNewSlot = false) const + bool MockDataSlotComponent::CanConvertToReference([[maybe_unused]] bool isNewSlot) const { return false; } diff --git a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp index 090622646a..c71219cc8c 100644 --- a/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp +++ b/Gems/ScriptCanvasDeveloper/Code/Editor/Source/AutomationActions/DynamicSlotFullCreation.cpp @@ -295,11 +295,11 @@ namespace ScriptCanvasDeveloperEditor GraphCanvas::Endpoint endpoint = ConvertToGraphCanvasEndpoint(slot->GetEndpoint()); bool canConvertToReference = false; - GraphCanvas::DataSlotRequestBus::EventResult(canConvertToReference, endpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::CanConvertToReference); + GraphCanvas::DataSlotRequestBus::EventResult(canConvertToReference, endpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::CanConvertToReference, false); if (canConvertToReference) { - GraphCanvas::DataSlotRequestBus::Event(endpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference); + GraphCanvas::DataSlotRequestBus::Event(endpoint.GetSlotId(), &GraphCanvas::DataSlotRequests::ConvertToReference, false); } } From 1ef868437a67ec87057df8b87cedb16907df84ee Mon Sep 17 00:00:00 2001 From: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> Date: Fri, 14 Jan 2022 17:28:14 -0700 Subject: [PATCH 100/108] Added supervariantIndex check in Shader::OnShaderVariantAssetReady Signed-off-by: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> --- .../Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h | 1 + Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp | 6 ++++++ .../Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h index 5146ae370a..b65d9837f7 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Shader/ShaderVariantAsset.h @@ -50,6 +50,7 @@ namespace AZ RPI::ShaderVariantStableId GetStableId() const { return m_stableId; } const ShaderVariantId& GetShaderVariantId() const { return m_shaderVariantId; } + uint32_t GetSupervariantIndex() const; //! Returns the shader stage function associated with the provided stage enum value. const RHI::ShaderStageFunction* GetShaderStageFunction(RHI::ShaderStage shaderStage) const; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp index 3830d8ee42..ed9d3430d9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp @@ -253,6 +253,12 @@ namespace AZ AZ_Assert(shaderVariantAsset, "Reloaded ShaderVariantAsset is null"); const ShaderVariantStableId stableId = shaderVariantAsset->GetStableId(); + // check the supervariantIndex of the ShaderVariantAsset to make sure it matches the supervariantIndex of this shader instance + if (shaderVariantAsset->GetSupervariantIndex() != m_supervariantIndex.GetIndex()) + { + return; + } + // We make a copy of the updated variant because OnShaderVariantReinitialized must not be called inside // m_variantCacheMutex or deadlocks may occur. // Or if there is an error, we leave this object in its default state to indicate there was an error. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp index ec1a65a6d5..f9f046ac8a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderVariantAsset.cpp @@ -65,6 +65,11 @@ namespace AZ return m_buildTimestamp; } + uint32_t ShaderVariantAsset::GetSupervariantIndex() const + { + return (m_assetId.m_subId >> SupervariantIndexBitPosition) & SupervariantIndexMaxValue; + } + const RHI::ShaderStageFunction* ShaderVariantAsset::GetShaderStageFunction(RHI::ShaderStage shaderStage) const { return m_functionsByStage[static_cast(shaderStage)].get(); From b87e6896e6784e35220365f9441313c3c4304a8b Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Fri, 14 Jan 2022 16:43:01 -0800 Subject: [PATCH 101/108] ScreenToWorld and WorldToScreen Camera functionality (#6903) Signed-off-by: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> --- .../AzFramework/Components/CameraBus.h | 26 ++++ .../Component/DebugCamera/CameraComponent.h | 4 + .../Code/Source/CameraComponent.cpp | 26 +++- Gems/Camera/Code/Source/CameraComponent.cpp | 4 + .../Code/Source/CameraComponentController.cpp | 63 ++++++++ .../Code/Source/CameraComponentController.h | 7 + .../EBus/Senders/CameraRequestBus.names | 134 +++++++++++++++++- ...hysXWorld_RayCastFromScreenWithGroup.names | 88 ++++++++++++ .../Code/Source/WorldNodes.h | 39 +++++ 9 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 Gems/ScriptCanvas/Assets/TranslationAssets/Nodes/PhysXWorld_RayCastFromScreenWithGroup.names diff --git a/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h b/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h index e20578e939..964bf664a0 100644 --- a/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h +++ b/Code/Framework/AzFramework/AzFramework/Components/CameraBus.h @@ -129,6 +129,32 @@ namespace Camera GetFrustumHeight() }; } + + //! Unprojects a position in screen space pixel coordinates to world space. + //! With a depth of zero, the position returned will be on the near clip plane of the camera + //! in world space. + //! @param screenPosition The absolute screen position + //! @param depth The depth offset into the world relative to the near clip plane of the camera + //! @return the position in world space + virtual AZ::Vector3 ScreenToWorld(const AZ::Vector2& screenPosition, float depth) = 0; + + //! Unprojects a position in screen space normalized device coordinates to world space. + //! With a depth of zero, the position returned will be on the near clip plane of the camera + //! in world space. + //! @param screenNdcPosition The normalized device coordinates in the range [0,1] + //! @param depth The depth offset into the world relative to the near clip plane of the camera + //! @return the position in world space + virtual AZ::Vector3 ScreenNdcToWorld(const AZ::Vector2& screenNdcPosition, float depth) = 0; + + //! Projects a position in world space to screen space for the given camera. + //! @param worldPosition The world position + //! @return The absolute screen position + virtual AZ::Vector2 WorldToScreen(const AZ::Vector3& worldPosition) = 0; + + //! Projects a position in world space to screen space normalized device coordinates. + //! @param worldPosition The world position + //! @return The normalized device coordinates in the range [0,1] + virtual AZ::Vector2 WorldToScreenNdc(const AZ::Vector3& worldPosition) = 0; }; using CameraRequestBus = AZ::EBus; diff --git a/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h b/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h index fb9c543bca..47254bcdc5 100644 --- a/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h +++ b/Gems/Atom/Component/DebugCamera/Code/Include/Atom/Component/DebugCamera/CameraComponent.h @@ -104,6 +104,10 @@ namespace AZ void SetOrthographicHalfWidth(float halfWidth) override; void MakeActiveView() override; bool IsActiveView() override; + AZ::Vector3 ScreenToWorld(const AZ::Vector2& screenPosition, float depth) override; + AZ::Vector3 ScreenNdcToWorld(const AZ::Vector2& screenPosition, float depth) override; + AZ::Vector2 WorldToScreen(const AZ::Vector3& worldPosition) override; + AZ::Vector2 WorldToScreenNdc(const AZ::Vector3& worldPosition) override; // RPI::WindowContextNotificationBus overrides... void OnViewportResized(uint32_t width, uint32_t height) override; diff --git a/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp b/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp index f3123e2b38..c4420dc417 100644 --- a/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp +++ b/Gems/Atom/Component/DebugCamera/Code/Source/CameraComponent.cpp @@ -245,7 +245,7 @@ namespace AZ AZ_Assert(false, "DebugCamera does not support orthographic projection"); } - void CameraComponent::MakeActiveView() + void CameraComponent::MakeActiveView() { // do nothing } @@ -255,6 +255,30 @@ namespace AZ return false; } + AZ::Vector3 CameraComponent::ScreenToWorld([[maybe_unused]] const AZ::Vector2& screenPosition, [[maybe_unused]] float depth) + { + // not implemented + return AZ::Vector3::CreateZero(); + } + + AZ::Vector3 CameraComponent::ScreenNdcToWorld([[maybe_unused]] const AZ::Vector2& screenPosition, [[maybe_unused]] float depth) + { + // not implemented + return AZ::Vector3::CreateZero(); + } + + AZ::Vector2 CameraComponent::WorldToScreen([[maybe_unused]] const AZ::Vector3& worldPosition) + { + // not implemented + return AZ::Vector2::CreateZero(); + } + + AZ::Vector2 CameraComponent::WorldToScreenNdc([[maybe_unused]] const AZ::Vector3& worldPosition) + { + // not implemented + return AZ::Vector2::CreateZero(); + } + void CameraComponent::OnViewportResized(uint32_t width, uint32_t height) { AZ_UNUSED(width); diff --git a/Gems/Camera/Code/Source/CameraComponent.cpp b/Gems/Camera/Code/Source/CameraComponent.cpp index 960f13a082..290691bbbe 100644 --- a/Gems/Camera/Code/Source/CameraComponent.cpp +++ b/Gems/Camera/Code/Source/CameraComponent.cpp @@ -106,6 +106,10 @@ namespace Camera ->Event("SetOrthographic", &CameraRequestBus::Events::SetOrthographic) ->Event("GetOrthographicHalfWidth", &CameraRequestBus::Events::GetOrthographicHalfWidth) ->Event("SetOrthographicHalfWidth", &CameraRequestBus::Events::SetOrthographicHalfWidth) + ->Event("ScreenToWorld", &CameraRequestBus::Events::ScreenToWorld) + ->Event("ScreenNdcToWorld", &CameraRequestBus::Events::ScreenNdcToWorld) + ->Event("WorldToScreen", &CameraRequestBus::Events::WorldToScreen) + ->Event("WorldToScreenNdc", &CameraRequestBus::Events::WorldToScreenNdc) ->VirtualProperty("FieldOfView","GetFovDegrees","SetFovDegrees") ->VirtualProperty("NearClipDistance", "GetNearClipDistance", "SetNearClipDistance") ->VirtualProperty("FarClipDistance", "GetFarClipDistance", "SetFarClipDistance") diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index 5b2e26b897..dfb2810fe2 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -10,12 +10,15 @@ #include "CameraViewRegistrationBus.h" #include +#include #include #include #include #include +#include + namespace Camera { void CameraComponentConfig::Reflect(AZ::ReflectContext* context) @@ -412,6 +415,66 @@ namespace Camera return m_isActiveView; } + namespace Util + { + AZ::Vector3 GetWorldPosition(const AZ::Vector3& origin, float depth, const AzFramework::CameraState& cameraState) + { + if (depth == 0.f) + { + return origin; + } + else + { + const AZ::Vector3 rayDirection = cameraState.m_orthographic ? cameraState.m_forward : (origin - cameraState.m_position); + return origin + (rayDirection.GetNormalized() * depth); + } + } + } + + AZ::Vector3 CameraComponentController::ScreenToWorld(const AZ::Vector2& screenPosition, float depth) + { + const AzFramework::ScreenPoint point{ static_cast(screenPosition.GetX()), static_cast(screenPosition.GetY()) }; + const AzFramework::CameraState& cameraState = GetCameraState(); + const AZ::Vector3 origin = AzFramework::ScreenToWorld(point, cameraState); + return Util::GetWorldPosition(origin, depth, cameraState); + } + + AZ::Vector3 CameraComponentController::ScreenNdcToWorld(const AZ::Vector2& screenNdcPosition, float depth) + { + const AzFramework::CameraState& cameraState = GetCameraState(); + const AZ::Vector3 origin = AzFramework::ScreenNdcToWorld(screenNdcPosition, AzFramework::InverseCameraView(cameraState), AzFramework::InverseCameraProjection(cameraState)); + return Util::GetWorldPosition(origin, depth, cameraState); + } + + AZ::Vector2 CameraComponentController::WorldToScreenNdc(const AZ::Vector3& worldPosition) + { + const AzFramework::CameraState& cameraState = GetCameraState(); + const AZ::Vector3 screenPosition = AzFramework::WorldToScreenNdc(worldPosition, AzFramework::CameraView(cameraState), AzFramework::CameraProjection(cameraState)); + return AZ::Vector3ToVector2(screenPosition); + } + + AZ::Vector2 CameraComponentController::WorldToScreen(const AZ::Vector3& worldPosition) + { + const AzFramework::ScreenPoint& point = AzFramework::WorldToScreen(worldPosition, GetCameraState()); + return AZ::Vector2(static_cast(point.m_x), static_cast(point.m_y)); + } + + AzFramework::CameraState CameraComponentController::GetCameraState() + { + auto viewportContext = GetViewportContext(); + if (!m_atomCamera || ! viewportContext) + { + return AzFramework::CameraState(); + } + + auto windowSize = viewportContext->GetViewportSize(); + auto viewportSize = AzFramework::Vector2FromScreenSize(AzFramework::ScreenSize(windowSize.m_width, windowSize.m_height)); + + AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(m_atomCamera->GetCameraTransform(), viewportSize); + AzFramework::SetCameraClippingVolumeFromPerspectiveFovMatrixRH(cameraState, m_atomCamera->GetViewToClipMatrix()); + return cameraState; + } + void CameraComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world) { if (m_updatingTransformFromEntity) diff --git a/Gems/Camera/Code/Source/CameraComponentController.h b/Gems/Camera/Code/Source/CameraComponentController.h index 09af7529dc..265ffaa0e9 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.h +++ b/Gems/Camera/Code/Source/CameraComponentController.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,11 @@ namespace Camera void MakeActiveView() override; bool IsActiveView() override; + AZ::Vector3 ScreenToWorld(const AZ::Vector2& screenPosition, float depth) override; + AZ::Vector3 ScreenNdcToWorld(const AZ::Vector2& screenNdcPosition, float depth) override; + AZ::Vector2 WorldToScreen(const AZ::Vector3& worldPosition) override; + AZ::Vector2 WorldToScreenNdc(const AZ::Vector3& worldPosition) override; + // AZ::TransformNotificationBus::Handler interface void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; @@ -127,6 +133,7 @@ namespace Camera void DeactivateAtomView(); void UpdateCamera(); void SetupAtomAuxGeom(AZ::RPI::ViewportContextPtr viewportContext); + AzFramework::CameraState GetCameraState(); CameraComponentConfig m_config; AZ::EntityId m_entityId; diff --git a/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/CameraRequestBus.names b/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/CameraRequestBus.names index 6c0112bfc2..ad2127c2a1 100644 --- a/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/CameraRequestBus.names +++ b/Gems/ScriptCanvas/Assets/TranslationAssets/EBus/Senders/CameraRequestBus.names @@ -31,6 +31,66 @@ } ] }, + { + "base": "WorldToScreen", + "entry": { + "name": "In", + "tooltip": "When signaled, this will invoke World To Screen" + }, + "exit": { + "name": "Out", + "tooltip": "Signaled after World To Screen is invoked" + }, + "details": { + "name": "World To Screen" + }, + "params": [ + { + "typeid": "{8379EB7D-01FA-4538-B64B-A6543B4BE73D}", + "details": { + "name": "World Position" + } + } + ], + "results": [ + { + "typeid": "{3D80F623-C85C-4741-90D0-E4E66164E6BF}", + "details": { + "name": "Screen Position" + } + } + ] + }, + { + "base": "WorldToScreenNdc", + "entry": { + "name": "In", + "tooltip": "When signaled, this will invoke World To Screen Ndc" + }, + "exit": { + "name": "Out", + "tooltip": "Signaled after World To Screen Ndc is invoked" + }, + "details": { + "name": "World To Screen NDC" + }, + "params": [ + { + "typeid": "{8379EB7D-01FA-4538-B64B-A6543B4BE73D}", + "details": { + "name": "World Position" + } + } + ], + "results": [ + { + "typeid": "{3D80F623-C85C-4741-90D0-E4E66164E6BF}", + "details": { + "name": "Screen NDC Position" + } + } + ] + }, { "base": "GetFov", "entry": { @@ -53,6 +113,78 @@ } ] }, + { + "base": "ScreenToWorld", + "entry": { + "name": "In", + "tooltip": "When signaled, this will invoke Screen To World" + }, + "exit": { + "name": "Out", + "tooltip": "Signaled after Screen To World is invoked" + }, + "details": { + "name": "Screen To World" + }, + "params": [ + { + "typeid": "{3D80F623-C85C-4741-90D0-E4E66164E6BF}", + "details": { + "name": "Screen Position" + } + }, + { + "typeid": "{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}", + "details": { + "name": "Depth" + } + } + ], + "results": [ + { + "typeid": "{8379EB7D-01FA-4538-B64B-A6543B4BE73D}", + "details": { + "name": "World Position" + } + } + ] + }, + { + "base": "ScreenNdcToWorld", + "entry": { + "name": "In", + "tooltip": "When signaled, this will invoke Screen Ndc To World" + }, + "exit": { + "name": "Out", + "tooltip": "Signaled after Screen Ndc To World is invoked" + }, + "details": { + "name": "Screen NDC To World" + }, + "params": [ + { + "typeid": "{3D80F623-C85C-4741-90D0-E4E66164E6BF}", + "details": { + "name": "Screen NDC Position" + } + }, + { + "typeid": "{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}", + "details": { + "name": "Depth" + } + } + ], + "results": [ + { + "typeid": "{8379EB7D-01FA-4538-B64B-A6543B4BE73D}", + "details": { + "name": "World Position" + } + } + ] + }, { "base": "SetFovRadians", "entry": { @@ -356,4 +488,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/Gems/ScriptCanvas/Assets/TranslationAssets/Nodes/PhysXWorld_RayCastFromScreenWithGroup.names b/Gems/ScriptCanvas/Assets/TranslationAssets/Nodes/PhysXWorld_RayCastFromScreenWithGroup.names new file mode 100644 index 0000000000..447866ae44 --- /dev/null +++ b/Gems/ScriptCanvas/Assets/TranslationAssets/Nodes/PhysXWorld_RayCastFromScreenWithGroup.names @@ -0,0 +1,88 @@ +{ + "entries": [ + { + "base": "{B164D87F-6620-5A1D-A2BC-CC09BA18C9B1}", + "context": "ScriptCanvas::Node", + "variant": "", + "details": { + "name": "Ray Cast From Screen With Group", + "category": "PhysX/World", + "tooltip": "Returns the first entity hit by a ray cast from the provided absolute 2D screen position." + }, + "slots": [ + { + "base": "Input_In_0", + "details": { + "name": "In" + } + }, + { + "base": "Output_Out_0", + "details": { + "name": "Out" + } + }, + { + "base": "DataInput_Screen Position_0", + "details": { + "name": "Screen Position" + } + }, + { + "base": "DataInput_Distance_1", + "details": { + "name": "Distance" + } + }, + { + "base": "DataInput_Collision group_2", + "details": { + "name": "Collision group" + } + }, + { + "base": "DataInput_Ignore_3", + "details": { + "name": "Ignore" + } + }, + { + "base": "DataOutput_Object hit_0", + "details": { + "name": "Object hit" + } + }, + { + "base": "DataOutput_Position_1", + "details": { + "name": "Position" + } + }, + { + "base": "DataOutput_Normal_2", + "details": { + "name": "Normal" + } + }, + { + "base": "DataOutput_Distance_3", + "details": { + "name": "Distance" + } + }, + { + "base": "DataOutput_EntityId_4", + "details": { + "name": "EntityId" + } + }, + { + "base": "DataOutput_Surface_5", + "details": { + "name": "Surface" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/Gems/ScriptCanvasPhysics/Code/Source/WorldNodes.h b/Gems/ScriptCanvasPhysics/Code/Source/WorldNodes.h index 96a15a9d29..1b03bd1851 100644 --- a/Gems/ScriptCanvasPhysics/Code/Source/WorldNodes.h +++ b/Gems/ScriptCanvasPhysics/Code/Source/WorldNodes.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -120,6 +121,43 @@ namespace ScriptCanvasPhysics "EntityId", "Surface"); + AZ_INLINE Result RayCastFromScreenWithGroup( + const AZ::Vector2& screenPosition, + float distance, + const AZStd::string& collisionGroup, + AZ::EntityId ignore) + { + AZ::EntityId camera; + Camera::CameraSystemRequestBus::BroadcastResult(camera, &Camera::CameraSystemRequestBus::Events::GetActiveCamera); + if (camera.IsValid()) + { + AZ::Vector3 origin = AZ::Vector3::CreateZero(); + Camera::CameraRequestBus::EventResult(origin, camera, &Camera::CameraRequestBus::Events::ScreenToWorld, screenPosition, 0.f); + AZ::Vector3 offset = AZ::Vector3::CreateZero(); + Camera::CameraRequestBus::EventResult(offset, camera, &Camera::CameraRequestBus::Events::ScreenToWorld, screenPosition, 1.f); + const AZ::Vector3 direction = (offset - origin).GetNormalized(); + return RayCastWorldSpaceWithGroup(origin, direction, distance, collisionGroup, ignore); + } + + // fallback in the rare case there is no active camera + return AZStd::make_tuple(false, AZ::Vector3::CreateZero(), AZ::Vector3::CreateZero(), 0.0f, AZ::EntityId(), AZ::Crc32()); + } + + SCRIPT_CANVAS_GENERIC_FUNCTION_NODE(RayCastFromScreenWithGroup, + k_categoryName, + "{8F98A766-A93F-4DA7-B281-482C3DB20649}", + "Returns the first entity hit by a ray cast from the provided absolute 2D screen position.", + "Screen Position", + "Distance", + "Collision group", + "Ignore", + "Object hit", + "Position", + "Normal", + "Distance", + "EntityId", + "Surface"); + AZ_INLINE Result RayCastLocalSpaceWithGroup(const AZ::EntityId& fromEntityId, const AZ::Vector3& direction, float distance, @@ -389,6 +427,7 @@ namespace ScriptCanvasPhysics Date: Fri, 14 Jan 2022 17:41:18 -0800 Subject: [PATCH 102/108] Fix type (#6919) Signed-off-by: amzn-sj --- cmake/Platform/Mac/runtime_dependencies_mac.cmake.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in index c27bf1fde4..fff816cb3e 100644 --- a/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in +++ b/cmake/Platform/Mac/runtime_dependencies_mac.cmake.in @@ -216,7 +216,7 @@ if(@target_file_dir@ MATCHES ".app/Contents/MacOS") # fixup bundle ends up removing the rpath of dxc (despite we exclude it) if(EXISTS "${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7") - execute_process(COMMAND $"{LY_INSTALL_NAME_TOOL}" -add_rpath @executable_path/../lib ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7) + execute_process(COMMAND "${LY_INSTALL_NAME_TOOL}" -add_rpath @executable_path/../lib ${bundle_path}/Contents/MacOS/Builders/DirectXShaderCompiler/bin/dxc-3.7) endif() # misplaced .DS_Store files can cause signing to fail From 0b9dc78d67d1ddea29b4fae29bd75c0335dee9ae Mon Sep 17 00:00:00 2001 From: John Jones-Steele <82226755+jjjoness@users.noreply.github.com> Date: Mon, 17 Jan 2022 17:58:19 +0000 Subject: [PATCH 103/108] Fixed problem with inputting numbers in sliders (#6859) * Fixed problem with inputting numbers in sliders Signed-off-by: John Jones-Steele <82226755+jjjoness@users.noreply.github.com> * Changes from PR Signed-off-by: John Jones-Steele <82226755+jjjoness@users.noreply.github.com> * Missed removing pragma optimize Signed-off-by: John Jones-Steele <82226755+jjjoness@users.noreply.github.com> --- .../AzQtComponents/Components/Widgets/Slider.cpp | 3 +-- .../AzQtComponents/Components/Widgets/SliderCombo.cpp | 10 +++++----- .../AzQtComponents/Components/Widgets/SliderCombo.h | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Slider.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Slider.cpp index 14ac2010bc..f50b9c36ec 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Slider.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/Slider.cpp @@ -870,8 +870,7 @@ void SliderDouble::setCurveMidpoint(double midpoint) QString SliderDouble::hoverValueText(int sliderValue) const { - // maybe format this, max number of digits? - QString valueText = locale().toString(calculateRealSliderValue(sliderValue), 'f', m_decimals); + QString valueText = toString(calculateRealSliderValue(sliderValue), m_decimals, locale(), false, true); return QStringLiteral("%1").arg(valueText); } diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.cpp index 6333d28365..9d289e5d44 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.cpp @@ -14,6 +14,7 @@ #include #include +#include namespace AzQtComponents { @@ -254,11 +255,12 @@ SliderDoubleCombo::~SliderDoubleCombo() { } +bool m_fromSlider{ false }; + void SliderDoubleCombo::setValueSlider(double value) { const bool doEmit = m_value != value; m_value = value; - updateSpinBox(); updateSlider(); @@ -267,6 +269,8 @@ void SliderDoubleCombo::setValueSlider(double value) // We don't want to update the slider from setValue as this // causes rounding errors in the tooltip hint. m_fromSlider = true; + QTimer::singleShot( 10, []() { m_fromSlider = false; }); + Q_EMIT valueChanged(); } } @@ -286,10 +290,6 @@ void SliderDoubleCombo::setValue(double value) Q_EMIT valueChanged(); } } - else - { - m_fromSlider = false; - } } SliderDouble* SliderDoubleCombo::slider() const diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h index 05d0f7b51b..be6c86b520 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/SliderCombo.h @@ -237,6 +237,5 @@ namespace AzQtComponents double m_softMinimum = 0.0; double m_softMaximum = 100.0; double m_value = 0.0; - bool m_fromSlider{ false }; }; } // namespace AzQtComponents From c1bbe3806db1cb4dea1eea710a1c9fbd8ef2bb67 Mon Sep 17 00:00:00 2001 From: Ignacio Martinez <82394219+AMZN-Igarri@users.noreply.github.com> Date: Tue, 18 Jan 2022 13:29:06 +0100 Subject: [PATCH 104/108] Asset Browser Search Entries Highlight (#6133) * Adding hilight to search entries Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Delegate Cleanup Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * delegate cleanup Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * General cleanup Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * reformatting file Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Updated Comments Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Abstracted richText functions Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Extracting highlighting behavior Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Added highlighter to the entity outliner Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Addressed Code Review Comments Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Switched to static functions Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * changed variable name Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Removed unused variable Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Apply changes to the Entity Outliner Model Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> * Removed duplicated line Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> --- .../AzAssetBrowser/AzAssetBrowserWindow.cpp | 4 ++ .../UI/Outliner/OutlinerListModel.cpp | 22 ++------ .../AssetBrowser/AssetBrowserFilterModel.cpp | 5 ++ .../AssetBrowser/AssetBrowserFilterModel.h | 4 +- .../AssetBrowser/AssetBrowserModel.cpp | 16 ++++++ .../AssetBrowser/AssetBrowserModel.h | 9 ++- .../AssetBrowser/Search/Filter.cpp | 5 ++ .../AssetBrowser/Search/Filter.h | 1 + .../Views/AssetBrowserTableView.cpp | 1 + .../AssetBrowser/Views/EntryDelegate.cpp | 27 +++++++-- .../AssetBrowser/Views/EntryDelegate.h | 3 +- .../Editor/RichTextHighlighter.cpp | 55 +++++++++++++++++++ .../Editor/RichTextHighlighter.h | 36 ++++++++++++ .../UI/Outliner/EntityOutlinerListModel.cpp | 30 +--------- .../aztoolsframework_files.cmake | 2 + 15 files changed, 167 insertions(+), 53 deletions(-) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h diff --git a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp index bcaaa02b67..a7faea36f6 100644 --- a/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp +++ b/Code/Editor/AzAssetBrowser/AzAssetBrowserWindow.cpp @@ -17,6 +17,7 @@ #include #include #include +#include // AzQtComponents #include @@ -83,6 +84,9 @@ AzAssetBrowserWindow::AzAssetBrowserWindow(QWidget* parent) m_ui->m_assetBrowserTableViewWidget->setVisible(false); m_ui->m_toggleDisplayViewBtn->setVisible(false); m_ui->m_searchWidget->SetFilterInputInterval(AZStd::chrono::milliseconds(250)); + + m_assetBrowserModel->SetFilterModel(m_filterModel.data()); + if (ed_useNewAssetBrowserTableView) { m_ui->m_toggleDisplayViewBtn->setVisible(true); diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp index 08d79adcf5..1c361b050d 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerListModel.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include "OutlinerDisplayOptionsMenu.h" #include "OutlinerSortFilterProxyModel.hxx" @@ -252,17 +253,7 @@ QVariant OutlinerListModel::dataForName(const QModelIndex& index, int role) cons if (s_paintingName && !m_filterString.empty()) { // highlight characters in filter - int highlightTextIndex = 0; - do - { - highlightTextIndex = label.lastIndexOf(QString(m_filterString.c_str()), highlightTextIndex - 1, Qt::CaseInsensitive); - if (highlightTextIndex >= 0) - { - const QString BACKGROUND_COLOR{ "#707070" }; - label.insert(static_cast(highlightTextIndex + m_filterString.length()), ""); - label.insert(highlightTextIndex, ""); - } - } while(highlightTextIndex > 0); + label = AzToolsFramework::RichTextHighlighter::HighlightText(label, m_filterString.c_str()); } return label; } @@ -2609,16 +2600,11 @@ void OutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optionV4.widget->style()->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter); // Now we setup a Text Document so it can draw the rich text - QTextDocument textDoc; - textDoc.setDefaultFont(optionV4.font); - textDoc.setDefaultStyleSheet("body {color: white}"); - textDoc.setHtml("" + entityNameRichText + ""); int verticalOffset = GetEntityNameVerticalOffset(entityId); painter->translate(textRect.topLeft() + QPoint(0, verticalOffset)); - textDoc.setTextWidth(textRect.width()); - textDoc.drawContents(painter, QRectF(0, 0, textRect.width(), textRect.height())); - painter->restore(); + AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect); + OutlinerListModel::s_paintingName = false; } else diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp index c6772ea2d7..21229e5570 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.cpp @@ -68,6 +68,11 @@ namespace AzToolsFramework } } + QSharedPointer AssetBrowserFilterModel::GetStringFilter() const + { + return m_stringFilter; + } + bool AssetBrowserFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { //get the source idx, if invalid early out diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h index 5d3ad0e1b0..cafe694ad6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h @@ -48,7 +48,7 @@ namespace AzToolsFramework // AssetBrowserComponentNotificationBus ////////////////////////////////////////////////////////////////////////// void OnAssetBrowserComponentReady() override; - + QSharedPointer GetStringFilter() const; Q_SIGNALS: void filterChanged(); ////////////////////////////////////////////////////////////////////////// @@ -70,7 +70,7 @@ namespace AzToolsFramework //Asset source name match filter FilterConstType m_filter; AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...' - QWeakPointer m_stringFilter; + QSharedPointer m_stringFilter; QWeakPointer m_assetTypeFilter; QCollator m_collator; // cache the collator as its somewhat expensive to constantly create and destroy one. AZ_POP_DISABLE_WARNING diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp index f0e1520aab..fd05543097 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 'QRegularExpression::d': class 'QExplicitlySharedDataPointer' needs to have dll-interface to be used by clients of class 'QRegularExpression' @@ -268,6 +269,21 @@ namespace AzToolsFramework m_rootEntry = rootEntry; } + AssetBrowserFilterModel* AssetBrowserModel::GetFilterModel() + { + return m_filterModel; + } + + const AssetBrowserFilterModel* AssetBrowserModel::GetFilterModel() const + { + return m_filterModel; + } + + void AssetBrowser::AssetBrowserModel::SetFilterModel(AssetBrowserFilterModel* filterModel) + { + m_filterModel = filterModel; + } + QModelIndex AssetBrowserModel::parent(const QModelIndex& child) const { if (!child.isValid()) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h index c46b73417c..2905844a23 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserModel.h @@ -35,6 +35,7 @@ namespace AzToolsFramework class AssetBrowserEntry; class RootAssetBrowserEntry; class AssetEntryChangeset; + class AssetBrowserFilterModel; class AssetBrowserModel : public QAbstractItemModel @@ -75,7 +76,7 @@ namespace AzToolsFramework void EndAddEntry(AssetBrowserEntry* parent) override; void BeginRemoveEntry(AssetBrowserEntry* entry) override; void EndRemoveEntry() override; - + ////////////////////////////////////////////////////////////////////////// // TickBus ////////////////////////////////////////////////////////////////////////// @@ -84,10 +85,16 @@ namespace AzToolsFramework AZStd::shared_ptr GetRootEntry() const; void SetRootEntry(AZStd::shared_ptr rootEntry); + AssetBrowserFilterModel* GetFilterModel(); + const AssetBrowserFilterModel* GetFilterModel() const; + void SetFilterModel(AssetBrowserFilterModel* filterModel); + static void SourceIndexesToAssetIds(const QModelIndexList& indexes, AZStd::vector& assetIds); static void SourceIndexesToAssetDatabaseEntries(const QModelIndexList& indexes, AZStd::vector& entries); private: + //Non owning pointer + AssetBrowserFilterModel* m_filterModel = nullptr; AZStd::shared_ptr m_rootEntry; bool m_loaded; bool m_addingEntry; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp index d617638632..4ec26d4c3d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.cpp @@ -229,6 +229,11 @@ namespace AzToolsFramework Q_EMIT updatedSignal(); } + QString StringFilter::GetFilterString() const + { + return m_filterString; + } + QString StringFilter::GetNameInternal() const { return m_filterString; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h index 94f47e0599..1d93d4d0cf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Search/Filter.h @@ -106,6 +106,7 @@ namespace AzToolsFramework ~StringFilter() override = default; void SetFilterString(const QString& filterString); + QString GetFilterString() const; protected: QString GetNameInternal() const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp index cfcac579ff..a913009da0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.cpp @@ -66,6 +66,7 @@ namespace AzToolsFramework m_tableModel = qobject_cast(model); AZ_Assert(m_tableModel, "Expecting AssetBrowserTableModel"); m_sourceFilterModel = qobject_cast(m_tableModel->sourceModel()); + m_delegate->Init(); AzQtComponents::TableView::setModel(model); connect(m_tableModel, &AssetBrowserTableModel::layoutChanged, this, &AssetBrowserTableView::layoutChangedSlot); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index 8b58791e68..8e69d5f788 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -9,12 +9,16 @@ #include #include #include +#include #include #include #include #include +#include #include +#include + AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // 4251: class 'QScopedPointer' needs to have dll-interface to be used by clients of class 'QBrush' // 4800: 'uint': forcing value to bool 'true' or 'false' (performance warning) #include @@ -160,13 +164,20 @@ namespace AzToolsFramework LoadBranchPixMaps(); } + void SearchEntryDelegate::Init() + { + AssetBrowserModel* assetBrowserModel; + AssetBrowserComponentRequestBus::BroadcastResult(assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel); + AZ_Assert(assetBrowserModel, "Failed to get filebrowser model"); + m_assetBrowserFilerModel = assetBrowserModel->GetFilterModel(); + } + void SearchEntryDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { auto data = index.data(AssetBrowserModel::Roles::EntryRole); if (data.canConvert()) { bool isEnabled = (option.state & QStyle::State_Enabled) != 0; - bool isSelected = (option.state & QStyle::State_Selected) != 0; QStyle* style = option.widget ? option.widget->style() : QApplication::style(); @@ -265,13 +276,21 @@ namespace AzToolsFramework remainingRect.adjust(thumbX, 0, 0, 0); // bump it to the right by the size of the thumbnail remainingRect.adjust(EntrySpacingLeftPixels, 0, 0, 0); // bump it to the right by the spacing. } + QString displayString = index.column() == aznumeric_cast(AssetBrowserEntry::Column::Name) ? qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Name))) : qvariant_cast(entry->data(aznumeric_cast(AssetBrowserEntry::Column::Path))); - style->drawItemText( - painter, remainingRect, option.displayAlignment, actualPalette, isEnabled, displayString, - isSelected ? QPalette::HighlightedText : QPalette::Text); + QStyleOptionViewItem optionV4{ option }; + initStyleOption(&optionV4, index); + optionV4.state &= ~(QStyle::State_HasFocus | QStyle::State_Selected); + + if (m_assetBrowserFilerModel && m_assetBrowserFilerModel->GetStringFilter() + && !m_assetBrowserFilerModel->GetStringFilter()->GetFilterString().isEmpty()) + { + displayString = RichTextHighlighter::HighlightText(displayString, m_assetBrowserFilerModel->GetStringFilter()->GetFilterString()); + } + RichTextHighlighter::PaintHighlightedRichText(displayString, painter, optionV4, remainingRect); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h index ac68c19248..7c7d919f2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.h @@ -70,7 +70,7 @@ namespace AzToolsFramework Q_OBJECT public: explicit SearchEntryDelegate(QWidget* parent = nullptr); - + void Init(); void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; private: @@ -78,6 +78,7 @@ namespace AzToolsFramework void DrawBranchPixMap(EntryBranchType branchType, QPainter* painter, const QPoint& point, const QSize& size) const; private: + AssetBrowserFilterModel* m_assetBrowserFilerModel; QMap m_branchIcons; }; } // namespace AssetBrowser diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp new file mode 100644 index 0000000000..8b28298c3d --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include "RichTextHighlighter.h" + +namespace AzToolsFramework +{ + + QString RichTextHighlighter::HighlightText(const QString& displayString, const QString& matchingSubstring) + { + QString highlightedString = displayString; + int highlightTextIndex = 0; + do + { + highlightTextIndex = highlightedString.lastIndexOf(matchingSubstring, highlightTextIndex - 1, Qt::CaseInsensitive); + if (highlightTextIndex >= 0) + { + const QString backgroundColor{ "#707070" }; + highlightedString.insert(static_cast(highlightTextIndex + matchingSubstring.length()), ""); + highlightedString.insert(highlightTextIndex, ""); + } + } while (highlightTextIndex > 0); + + return highlightedString; + } + + void RichTextHighlighter::PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect) + { + painter->save(); + painter->setRenderHint(QPainter::Antialiasing); + + // Now we setup a Text Document so it can draw the rich text + QTextDocument textDoc; + textDoc.setDefaultFont(option.font); + if (option.state & QStyle::State_Enabled) + { + textDoc.setDefaultStyleSheet("body {color: white}"); + } + else + { + textDoc.setDefaultStyleSheet("body {color: #7C7C7C}"); + } + textDoc.setHtml("" + highlightedString + ""); + painter->translate(availableRect.topLeft()); + textDoc.setTextWidth(availableRect.width()); + textDoc.drawContents(painter, QRectF(0, 0, availableRect.width(), availableRect.height())); + + painter->restore(); + } +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h new file mode 100644 index 0000000000..b5c1859497 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Editor/RichTextHighlighter.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include +#include + +AZ_PUSH_DISABLE_WARNING(4251 4800,"-Wunknown-warning-option") // 4251: class 'QScopedPointer' needs to have dll-interface to be used + // by clients of class 'QBrush' 4800: 'uint': forcing value to bool 'true' or 'false' (performance warning) +#include +AZ_POP_DISABLE_WARNING + +namespace AzToolsFramework +{ + //! @class RichTextHighlighter + //! @brief Highlights a given string given a matching substring. + class RichTextHighlighter + { + public: + AZ_CLASS_ALLOCATOR(RichTextHighlighter, AZ::SystemAllocator, 0); + RichTextHighlighter() = delete; + + static QString HighlightText(const QString& displayString, const QString& matchingSubstring); + static void PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect); + + }; +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp index 056f16c52f..e0060e2b42 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerListModel.cpp @@ -66,6 +66,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////////////// // EntityOutlinerListModel @@ -259,17 +260,7 @@ namespace AzToolsFramework if (s_paintingName && !m_filterString.empty()) { // highlight characters in filter - int highlightTextIndex = 0; - do - { - highlightTextIndex = label.lastIndexOf(QString(m_filterString.c_str()), highlightTextIndex - 1, Qt::CaseInsensitive); - if (highlightTextIndex >= 0) - { - const QString BACKGROUND_COLOR{ "#707070" }; - label.insert(highlightTextIndex + static_cast(m_filterString.length()), ""); - label.insert(highlightTextIndex, ""); - } - } while(highlightTextIndex > 0); + label = AzToolsFramework::RichTextHighlighter::HighlightText(label, m_filterString.c_str()); } return label; } @@ -2375,23 +2366,8 @@ namespace AzToolsFramework optionV4.text.clear(); optionV4.widget->style()->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter); - // Now we setup a Text Document so it can draw the rich text - QTextDocument textDoc; - textDoc.setDefaultFont(optionV4.font); - if (option.state & QStyle::State_Enabled) - { - textDoc.setDefaultStyleSheet("body {color: white}"); - } - else - { - textDoc.setDefaultStyleSheet("body {color: #7C7C7C}"); - } - textDoc.setHtml("" + entityNameRichText + ""); - painter->translate(textRect.topLeft()); - textDoc.setTextWidth(textRect.width()); - textDoc.drawContents(painter, QRectF(0, 0, textRect.width(), textRect.height())); + AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect); - painter->restore(); EntityOutlinerListModel::s_paintingName = false; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 05c07afecd..0d7bf05211 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -123,6 +123,8 @@ set(FILES ContainerEntity/ContainerEntitySystemComponent.h Editor/EditorContextMenuBus.h Editor/EditorSettingsAPIBus.h + Editor/RichTextHighlighter.h + Editor/RichTextHighlighter.cpp Entity/EditorEntityStartStatus.h Entity/EditorEntityAPIBus.h Entity/EditorEntityContextComponent.cpp From e166479bb7c77e0d0ebc391ff9bc9d2835ebb5eb Mon Sep 17 00:00:00 2001 From: Ignacio Martinez <82394219+AMZN-Igarri@users.noreply.github.com> Date: Tue, 18 Jan 2022 16:47:27 +0100 Subject: [PATCH 105/108] Fixed Camera angle on switch levels (#6954) Signed-off-by: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> --- Code/Editor/EditorViewportWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Editor/EditorViewportWidget.cpp b/Code/Editor/EditorViewportWidget.cpp index e9a57dba4f..a8180bcace 100644 --- a/Code/Editor/EditorViewportWidget.cpp +++ b/Code/Editor/EditorViewportWidget.cpp @@ -582,11 +582,11 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event) case eNotify_OnCloseScene: m_renderViewport->SetScene(nullptr); - SetDefaultCamera(); break; case eNotify_OnEndSceneOpen: UpdateScene(); + SetDefaultCamera(); break; case eNotify_OnBeginNewScene: From 338eecd9e687815a56bca750a3f830e22a944976 Mon Sep 17 00:00:00 2001 From: moraaar Date: Tue, 18 Jan 2022 16:00:28 +0000 Subject: [PATCH 106/108] Blast memory allocator must allocate with 16 byte aligment (#6968) From Blast allocator documentation "Allocates size bytes of memory, which must be 16-byte aligned." https://gameworksdocs.nvidia.com/Blast/1.1/api_docs/files/class_nv_1_1_blast_1_1_allocator_callback.html Fixes #5162 Signed-off-by: moraaar moraaar@amazon.com --- Gems/Blast/Code/Source/Components/BlastSystemComponent.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Gems/Blast/Code/Source/Components/BlastSystemComponent.h b/Gems/Blast/Code/Source/Components/BlastSystemComponent.h index 8f6c200870..a3d4b200bc 100644 --- a/Gems/Blast/Code/Source/Components/BlastSystemComponent.h +++ b/Gems/Blast/Code/Source/Components/BlastSystemComponent.h @@ -100,11 +100,14 @@ namespace Blast class AZBlastAllocatorCallback : public Nv::Blast::AllocatorCallback { public: + // Blast requires 16-byte alignment + static const size_t alignment = 16; + void* allocate( size_t size, const char* typeName, [[maybe_unused]] const char* filename, [[maybe_unused]] int line) override { - return azmalloc_4(size, 0, AZ::SystemAllocator, typeName); + return azmalloc_4(size, alignment, AZ::SystemAllocator, typeName); } void deallocate(void* ptr) override From 27d256679ac7fb2d820afb0be5f678e11ac6dee3 Mon Sep 17 00:00:00 2001 From: Nicholas Lawson <70027408+lawsonamzn@users.noreply.github.com> Date: Tue, 18 Jan 2022 08:16:25 -0800 Subject: [PATCH 107/108] Update the package of Pybind11 that o3de points at to be the latest version (#6898) Signed-off-by: lawsonamzn <70027408+lawsonamzn@users.noreply.github.com> --- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index f1e8fdc950..d174f935e2 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -11,7 +11,7 @@ ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) -ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) +ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev3-multiplatform TARGETS pybind11 PACKAGE_HASH dccb5546607b8b31cd207033aaf24ab044ce6e188a9f12411236a010f9e0c4ff) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 575a2dd70e..95f7c89930 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -11,7 +11,7 @@ ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) -ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) +ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev3-multiplatform TARGETS pybind11 PACKAGE_HASH dccb5546607b8b31cd207033aaf24ab044ce6e188a9f12411236a010f9e0c4ff) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 7fd07927cc..1f7cb8d28f 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -11,7 +11,7 @@ ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023) ly_associate_package(PACKAGE_NAME RapidXML-1.13-rev1-multiplatform TARGETS RapidXML PACKAGE_HASH 4b7b5651e47cfd019b6b295cc17bb147b65e53073eaab4a0c0d20a37ab74a246) -ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b) +ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev3-multiplatform TARGETS pybind11 PACKAGE_HASH dccb5546607b8b31cd207033aaf24ab044ce6e188a9f12411236a010f9e0c4ff) ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2) ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418) ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665) From 2a9990ead3da2a82ca9d113eaee6f272a9c11ad7 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Tue, 18 Jan 2022 10:27:06 -0600 Subject: [PATCH 108/108] Fix engine template issue (#6927) * fix get_enabled_gem_cmake_file to work with "Dem" or "Code" or "Gem/Code" folder in a project fix o3de_restricted_path to make the past paramter optional Signed-off-by: byrcolin * Fix resolution of variables in `cmake_path(COMPARE)` calls in PAL.cmake The documentation for `cmake_path(COMPARE)` states that parameters marked as [](https://cmake.org/cmake/help/latest/command/cmake_path.html#conventions) are string literals. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Co-authored-by: byrcolin Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- cmake/PAL.cmake | 35 ++++++++++++++++++++--------------- scripts/o3de/o3de/cmake.py | 28 ++++++++++++++++++---------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/cmake/PAL.cmake b/cmake/PAL.cmake index d0d1ad5396..ef431ff92a 100644 --- a/cmake/PAL.cmake +++ b/cmake/PAL.cmake @@ -157,17 +157,17 @@ function(o3de_restricted_id o3de_json_file restricted parent_relative_path) # This object did not have a "restricted" set, now we must look at the parent # Stop if this is a top level object o3de_manifest_restricted(manifest_restricted_paths) - get_filename_component(o3de_json_file_parent ${o3de_json_file} DIRECTORY) - get_filename_component(relative_path ${o3de_json_file_parent} NAME) - get_filename_component(o3de_json_file_parent ${o3de_json_file_parent} DIRECTORY) + cmake_path(GET o3de_json_file PARENT_PATH o3de_json_file_parent) + cmake_path(GET o3de_json_file_parent FILENAME relative_path) + cmake_path(GET o3de_json_file_parent PARENT_PATH o3de_json_file_parent) if(${o3de_json_file_parent} IN_LIST manifest_restricted_paths) set(${parent_relative_path} "" PARENT_SCOPE) set(${restricted} "" PARENT_SCOPE) return() endif() - string(LENGTH ${o3de_json_file_parent} parent_len) - while(parent_len) + set(is_prev_path_segment TRUE) + while(is_prev_path_segment) if(EXISTS ${o3de_json_file_parent}/engine.json) o3de_json_restricted(${o3de_json_file_parent}/engine.json restricted_name) if(restricted_name) @@ -199,10 +199,12 @@ function(o3de_restricted_id o3de_json_file restricted parent_relative_path) return() endif() - get_filename_component(parent ${o3de_json_file_parent} NAME) - string(PREPEND relative_path ${parent}/) - get_filename_component(o3de_json_file_parent ${o3de_json_file_parent} DIRECTORY) - string(LENGTH ${o3de_json_file_parent} parent_len) + # Remove one path segment from the end of the o3de json candidate path + cmake_path(GET o3de_json_file_parent PARENT_PATH parent_path) + cmake_path(GET o3de_json_file_parent FILENAME path_segment) + cmake_path(COMPARE "${o3de_json_file_parent}" NOT_EQUAL "${parent_path}" is_prev_path_segment) + cmake_path(SET o3de_json_file_parent "${parent_path}") + cmake_path(SET relative_path "${path_segment}/${relative_path}") endwhile() endfunction() @@ -232,10 +234,13 @@ endfunction() #! o3de_restricted_path: # # \arg:o3de_json_file json file to read restricted id from -# \arg:restricted_name name of the restricted object -function(o3de_restricted_path o3de_json_file restricted_path parent_relative_path) +# \arg:restricted_path output path of the restricted object +# \arg:parent_relative_path optional output of the path relative to the parent +function(o3de_restricted_path o3de_json_file restricted_path) #parent_relative_path o3de_restricted_id(${o3de_json_file} restricted_name parent_relative) - set(${parent_relative_path} ${parent_relative} PARENT_SCOPE) + if(${ARGC} GREATER 2) + set(${ARGV2} ${parent_relative} PARENT_SCOPE) + endif() if(restricted_name) o3de_find_restricted_folder(${restricted_name} restricted_folder) if(restricted_folder) @@ -254,7 +259,7 @@ foreach(detection_file ${detection_files}) endforeach() # set the O3DE_ENGINE_RESTRICTED_PATH -o3de_restricted_path(${LY_ROOT_FOLDER}/engine.json O3DE_ENGINE_RESTRICTED_PATH engine_has_no_parent) +o3de_restricted_path(${LY_ROOT_FOLDER}/engine.json O3DE_ENGINE_RESTRICTED_PATH) # detect platforms in the restricted path file(GLOB detection_files ${O3DE_ENGINE_RESTRICTED_PATH}/*/cmake/PALDetection_*.cmake) @@ -338,7 +343,7 @@ function(o3de_pal_dir out_name in_name object_restricted_path object_path) #pare cmake_path(GET current_object_path PARENT_PATH parent_path) cmake_path(GET current_object_path FILENAME path_segment) list(PREPEND path_segments_visited ${path_segment}) - cmake_path(COMPARE current_object_path NOT_EQUAL parent_path is_prev_path_segment) + cmake_path(COMPARE "${current_object_path}" NOT_EQUAL "${parent_path}" is_prev_path_segment) cmake_path(SET current_object_path "${parent_path}") set(is_prev_path_segment TRUE) @@ -346,7 +351,7 @@ function(o3de_pal_dir out_name in_name object_restricted_path object_path) #pare # Remove one path segment from the end of the current_object_path and prepend it to the list path_segments cmake_path(GET current_object_path PARENT_PATH parent_path) cmake_path(GET current_object_path FILENAME path_segment) - cmake_path(COMPARE current_object_path NOT_EQUAL parent_path is_prev_path_segment) + cmake_path(COMPARE "${current_object_path}" NOT_EQUAL "${parent_path}" is_prev_path_segment) cmake_path(SET current_object_path "${parent_path}") # The Path is in a PAL structure # Decompose the path into sections before "Platform" and after "Platform" diff --git a/scripts/o3de/o3de/cmake.py b/scripts/o3de/o3de/cmake.py index ec970d06f4..7a820a9677 100644 --- a/scripts/o3de/o3de/cmake.py +++ b/scripts/o3de/o3de/cmake.py @@ -235,14 +235,22 @@ def get_enabled_gem_cmake_file(project_name: str = None, enable_gem_filename = "enabled_gems.cmake" if platform == 'Common': - project_code_dir = project_path / 'Gem/Code' - if project_code_dir.is_dir(): - dependencies_file_path = project_code_dir / enable_gem_filename - return dependencies_file_path.resolve() - return (project_path / 'Code' / enable_gem_filename).resolve() + possible_project_enable_gem_filename_paths = [ + pathlib.Path(project_path / 'Gem' / enable_gem_filename), + pathlib.Path(project_path / 'Gem/Code' / enable_gem_filename), + pathlib.Path(project_path / 'Code' / enable_gem_filename) + ] + for possible_project_enable_gem_filename_path in possible_project_enable_gem_filename_paths: + if possible_project_enable_gem_filename_path.is_file(): + return possible_project_enable_gem_filename_path.resolve() + return possible_project_enable_gem_filename_paths[0].resolve() else: - project_code_dir = project_path / 'Gem/Code/Platform' / platform - if project_code_dir.is_dir(): - dependencies_file_path = project_code_dir / enable_gem_filename - return dependencies_file_path.resolve() - return (project_path / 'Code/Platform' / platform / enable_gem_filename).resolve() + possible_project_platform_enable_gem_filename_paths = [ + pathlib.Path(project_path / 'Gem/Platform' / platform / enable_gem_filename), + pathlib.Path(project_path / 'Gem/Code/Platform' / platform / enable_gem_filename), + pathlib.Path(project_path / 'Code/Platform' / platform / enable_gem_filename) + ] + for possible_project_platform_enable_gem_filename_path in possible_project_platform_enable_gem_filename_paths: + if possible_project_platform_enable_gem_filename_path.is_file(): + return possible_project_platform_enable_gem_filename_path.resolve() + return possible_project_platform_enable_gem_filename_paths[0].resolve()