Merge remote-tracking branch 'upstream/development' into Atom/santorac/MaterialAssetDeferredBaking3

monroegm-disable-blank-issue-2
santorac 4 years ago
commit fbe17b0022

@ -112,29 +112,31 @@ void EditorPreferencesDialog::showEvent(QShowEvent* event)
QDialog::showEvent(event);
}
void WidgetHandleKeyPressEvent(QWidget* widget, QKeyEvent* event)
bool WidgetConsumesKeyPressEvent(QKeyEvent* event)
{
// If the enter key is pressed during any text input, the dialog box will close
// making it inconvenient to do multiple edits. This routine captures the
// Key_Enter or Key_Return and clears the focus to give a visible cue that
// editing of that field has finished and then doesn't propogate it.
// editing of that field has finished and then doesn't propagate it.
if (event->key() != Qt::Key::Key_Enter && event->key() != Qt::Key::Key_Return)
{
QApplication::sendEvent(widget, event);
return false;
}
else
if (QWidget* editWidget = QApplication::focusWidget())
{
if (QWidget* editWidget = QApplication::focusWidget())
{
editWidget->clearFocus();
}
editWidget->clearFocus();
}
}
return true;
}
void EditorPreferencesDialog::keyPressEvent(QKeyEvent* event)
{
WidgetHandleKeyPressEvent(this, event);
if (!WidgetConsumesKeyPressEvent(event))
{
QDialog::keyPressEvent(event);
}
}
void EditorPreferencesDialog::OnTreeCurrentItemChanged()

@ -19,7 +19,7 @@ namespace Ui
class EditorPreferencesTreeWidgetItem;
void WidgetHandleKeyPressEvent(QWidget* widget, QKeyEvent* event);
bool WidgetConsumesKeyPressEvent(QKeyEvent* event);
class EditorPreferencesDialog
: public QDialog

@ -2599,11 +2599,12 @@ void OutlinerItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem&
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
int verticalOffset = GetEntityNameVerticalOffset(entityId);
painter->translate(textRect.topLeft() + QPoint(0, verticalOffset));
AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect);
AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(
entityNameRichText, painter, optionV4, textRect, QPoint(0, verticalOffset));
painter->restore();
OutlinerListModel::s_paintingName = false;
}

@ -77,8 +77,8 @@ namespace AZ::Dom::Utils
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))
auto rhsIt = rhs.FindMember(lhsChild.first);
if (rhsIt == rhs.MemberEnd() || !DeepCompareIsEqual(lhsChild.second, rhsIt->second))
{
return false;
}
@ -144,8 +144,8 @@ namespace AZ::Dom::Utils
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))
auto rhsIt = rhs.FindMember(lhsChild.first);
if (rhsIt == rhs.MemberEnd() || !DeepCompareIsEqual(lhsChild.second, rhsIt->second))
{
return false;
}

@ -283,64 +283,33 @@ namespace AZ::Dom
Type Dom::Value::GetType() const
{
return AZStd::visit(
[](auto&& value) -> Type
{
using CurrentType = AZStd::decay_t<decltype(value)>;
if constexpr (AZStd::is_same_v<CurrentType, AZStd::monostate>)
{
return Type::Null;
}
else if constexpr (AZStd::is_same_v<CurrentType, int64_t>)
{
return Type::Int64;
}
else if constexpr (AZStd::is_same_v<CurrentType, uint64_t>)
{
return Type::Uint64;
}
else if constexpr (AZStd::is_same_v<CurrentType, double>)
{
return Type::Double;
}
else if constexpr (AZStd::is_same_v<CurrentType, bool>)
{
return Type::Bool;
}
else if constexpr (AZStd::is_same_v<CurrentType, AZStd::string_view>)
{
return Type::String;
}
else if constexpr (AZStd::is_same_v<CurrentType, SharedStringType>)
{
return Type::String;
}
else if constexpr (AZStd::is_same_v<CurrentType, ShortStringType>)
{
return Type::String;
}
else if constexpr (AZStd::is_same_v<CurrentType, ObjectPtr>)
{
return Type::Object;
}
else if constexpr (AZStd::is_same_v<CurrentType, ArrayPtr>)
{
return Type::Array;
}
else if constexpr (AZStd::is_same_v<CurrentType, NodePtr>)
{
return Type::Node;
}
else if constexpr (AZStd::is_same_v<CurrentType, OpaqueStorageType>)
{
return Type::Opaque;
}
else
{
AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type");
}
},
m_value);
switch (m_value.index())
{
case GetTypeIndex<AZStd::monostate>():
return Type::Null;
case GetTypeIndex<int64_t>():
return Type::Int64;
case GetTypeIndex<uint64_t>():
return Type::Uint64;
case GetTypeIndex<double>():
return Type::Double;
case GetTypeIndex<bool>():
return Type::Bool;
case GetTypeIndex<AZStd::string_view>():
case GetTypeIndex<SharedStringType>():
case GetTypeIndex<ShortStringType>():
return Type::String;
case GetTypeIndex<ObjectPtr>():
return Type::Object;
case GetTypeIndex<ArrayPtr>():
return Type::Array;
case GetTypeIndex<NodePtr>():
return Type::Node;
case GetTypeIndex<AZStd::shared_ptr<AZStd::any>>():
return Type::Opaque;
}
AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type");
return Type::Null;
}
bool Value::IsNull() const
@ -594,12 +563,12 @@ namespace AZ::Dom
return GetObjectInternal().end();
}
Object::Iterator Value::MemberBegin()
Object::Iterator Value::MutableMemberBegin()
{
return GetObjectInternal().begin();
}
Object::Iterator Value::MemberEnd()
Object::Iterator Value::MutableMemberEnd()
{
return GetObjectInternal().end();
}
@ -725,12 +694,12 @@ namespace AZ::Dom
return object.end();
}
Object::Iterator Value::EraseMember(Object::ConstIterator pos)
Object::Iterator Value::EraseMember(Object::Iterator pos)
{
return GetObjectInternal().erase(pos);
}
Object::Iterator Value::EraseMember(Object::ConstIterator first, Object::ConstIterator last)
Object::Iterator Value::EraseMember(Object::Iterator first, Object::Iterator last)
{
return GetObjectInternal().erase(first, last);
}
@ -811,12 +780,12 @@ namespace AZ::Dom
return GetArrayInternal().end();
}
Array::Iterator Value::ArrayBegin()
Array::Iterator Value::MutableArrayBegin()
{
return GetArrayInternal().begin();
}
Array::Iterator Value::ArrayEnd()
Array::Iterator Value::MutableArrayEnd()
{
return GetArrayInternal().end();
}
@ -843,12 +812,12 @@ namespace AZ::Dom
return *this;
}
Array::Iterator Value::ArrayErase(Array::ConstIterator pos)
Array::Iterator Value::ArrayErase(Array::Iterator pos)
{
return GetArrayInternal().erase(pos);
}
Array::Iterator Value::ArrayErase(Array::ConstIterator first, Array::ConstIterator last)
Array::Iterator Value::ArrayErase(Array::Iterator first, Array::Iterator last)
{
return GetArrayInternal().erase(first, last);
}
@ -1113,6 +1082,10 @@ namespace AZ::Dom
{
result = visitor.RefCountedString(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent);
}
else if constexpr (AZStd::is_same_v<Alternative, ShortStringType>)
{
result = visitor.String(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent);
}
else if constexpr (AZStd::is_same_v<Alternative, ObjectPtr>)
{
result = visitor.StartObject();

@ -268,8 +268,8 @@ namespace AZ::Dom
Object::ConstIterator MemberBegin() const;
Object::ConstIterator MemberEnd() const;
Object::Iterator MemberBegin();
Object::Iterator MemberEnd();
Object::Iterator MutableMemberBegin();
Object::Iterator MutableMemberEnd();
Object::Iterator FindMutableMember(KeyType name);
Object::Iterator FindMutableMember(AZStd::string_view name);
@ -289,8 +289,8 @@ namespace AZ::Dom
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(Object::Iterator pos);
Object::Iterator EraseMember(Object::Iterator first, Object::Iterator last);
Object::Iterator EraseMember(KeyType name);
Object::Iterator EraseMember(AZStd::string_view name);
@ -313,15 +313,15 @@ namespace AZ::Dom
Array::ConstIterator ArrayBegin() const;
Array::ConstIterator ArrayEnd() const;
Array::Iterator ArrayBegin();
Array::Iterator ArrayEnd();
Array::Iterator MutableArrayBegin();
Array::Iterator MutableArrayEnd();
Value& ArrayReserve(size_t newCapacity);
Value& ArrayPushBack(Value value);
Value& ArrayPopBack();
Array::Iterator ArrayErase(Array::ConstIterator pos);
Array::Iterator ArrayErase(Array::ConstIterator first, Array::ConstIterator last);
Array::Iterator ArrayErase(Array::Iterator pos);
Array::Iterator ArrayErase(Array::Iterator first, Array::Iterator last);
Array::ContainerType& GetMutableArray();
const Array::ContainerType& GetArray() const;

@ -33,23 +33,24 @@ namespace AZStd
*
* 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 Element>
template <class T>
class span final
{
public:
using value_type = Element;
using element_type = T;
using value_type = AZStd::remove_cv_t<T>;
using pointer = value_type*;
using const_pointer = const value_type*;
using pointer = T*;
using const_pointer = const T*;
using reference = value_type&;
using const_reference = const value_type&;
using reference = T&;
using const_reference = const T&;
using size_type = AZStd::size_t;
using difference_type = AZStd::ptrdiff_t;
using iterator = value_type*;
using const_iterator = const value_type*;
using iterator = T*;
using const_iterator = const T*;
using reverse_iterator = AZStd::reverse_iterator<iterator>;
using const_reverse_iterator = AZStd::reverse_iterator<const_iterator>;
@ -65,21 +66,11 @@ namespace AZStd
// create a span to just the first element instead of an entire array.
constexpr span(const_pointer s) = delete;
template<AZStd::size_t N>
constexpr span(AZStd::array<value_type, N>& data);
template<typename Container>
constexpr span(Container& data);
constexpr span(AZStd::vector<value_type>& data);
template<AZStd::size_t N>
constexpr span(AZStd::fixed_vector<value_type, N>& data);
template<AZStd::size_t N>
constexpr span(const AZStd::array<value_type, N>& data);
constexpr span(const AZStd::vector<value_type>& data);
template<AZStd::size_t N>
constexpr span(const AZStd::fixed_vector<value_type, N>& data);
template<typename Container>
constexpr span(const Container& data);
constexpr span(const span&) = default;
@ -132,6 +123,7 @@ namespace AZStd
pointer m_begin;
pointer m_end;
};
} // namespace AZStd
#include <AzCore/std/containers/span.inl>

@ -29,42 +29,16 @@ namespace AZStd
, m_end(last)
{ }
template <class Element>
template<AZStd::size_t N>
inline constexpr span<Element>::span(AZStd::array<Element, N>& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }
template <class Element>
inline constexpr span<Element>::span(AZStd::vector<Element>& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }
template <class Element>
template<AZStd::size_t N>
inline constexpr span<Element>::span(AZStd::fixed_vector<Element, N>& data)
template<class Element>
template<typename Container>
inline constexpr span<Element>::span(Container& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }
template <class Element>
template<AZStd::size_t N>
inline constexpr span<Element>::span(const AZStd::array<Element, N>& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }
template <class Element>
inline constexpr span<Element>::span(const AZStd::vector<Element>& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }
template <class Element>
template<AZStd::size_t N>
inline constexpr span<Element>::span(const AZStd::fixed_vector<Element, N>& data)
template<class Element>
template<typename Container>
inline constexpr span<Element>::span(const Container& data)
: m_begin(data.data())
, m_end(m_begin + data.size())
{ }

@ -954,25 +954,6 @@ namespace AZStd
return true;
}
/// Validates an iter iterator. Returns a combination of \ref iterator_status_flag.
AZ_FORCE_INLINE int validate_iterator(const iterator& iter) const
{
#ifdef AZSTD_HAS_CHECKED_ITERATORS
AZ_Assert(iter.m_container == this, "Iterator doesn't belong to this container");
pointer iterPtr = iter.m_iter;
#else
pointer iterPtr = iter;
#endif
if (iterPtr < m_start || iterPtr > m_last)
{
return isf_none;
}
else if (iterPtr == m_last)
{
return isf_valid;
}
return isf_valid | isf_can_dereference;
}
AZ_FORCE_INLINE int validate_iterator(const const_iterator& iter) const
{
#ifdef AZSTD_HAS_CHECKED_ITERATORS
@ -992,7 +973,6 @@ namespace AZStd
return isf_valid | isf_can_dereference;
}
AZ_FORCE_INLINE int validate_iterator(const reverse_iterator& iter) const { return validate_iterator(iter.base()); }
AZ_FORCE_INLINE int validate_iterator(const const_reverse_iterator& iter) const { return validate_iterator(iter.base()); }
/**

@ -0,0 +1,189 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/DOM/DomValue.h>
#include <AzCore/Name/NameDictionary.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <Tests/DOM/DomFixtures.h>
namespace AZ::Dom::Tests
{
void DomTestHarness::SetUpHarness()
{
NameDictionary::Create();
AZ::AllocatorInstance<ValueAllocator>::Create();
}
void DomTestHarness::TearDownHarness()
{
AZ::AllocatorInstance<ValueAllocator>::Destroy();
NameDictionary::Destroy();
}
void DomBenchmarkFixture::SetUp(const ::benchmark::State& st)
{
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
SetUpHarness();
}
void DomBenchmarkFixture::SetUp(::benchmark::State& st)
{
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
SetUpHarness();
}
void DomBenchmarkFixture::TearDown(::benchmark::State& st)
{
TearDownHarness();
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
}
void DomBenchmarkFixture::TearDown(const ::benchmark::State& st)
{
TearDownHarness();
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
}
rapidjson::Document DomBenchmarkFixture::GenerateDomJsonBenchmarkDocument(int64_t entryCount, int64_t stringTemplateLength)
{
rapidjson::Document document;
document.SetObject();
AZStd::string entryTemplate;
while (entryTemplate.size() < aznumeric_cast<size_t>(stringTemplateLength))
{
entryTemplate += "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ";
}
entryTemplate.resize(stringTemplateLength);
AZStd::string buffer;
auto createString = [&](int n) -> rapidjson::Value
{
buffer = AZStd::string::format("#%i %s", n, entryTemplate.c_str());
return rapidjson::Value(buffer.data(), aznumeric_cast<rapidjson::SizeType>(buffer.size()), document.GetAllocator());
};
auto createEntry = [&](int n) -> rapidjson::Value
{
rapidjson::Value entry(rapidjson::kObjectType);
entry.AddMember("string", createString(n), document.GetAllocator());
entry.AddMember("int", rapidjson::Value(n), document.GetAllocator());
entry.AddMember("double", rapidjson::Value(aznumeric_cast<double>(n) * 0.5), document.GetAllocator());
entry.AddMember("bool", rapidjson::Value(n % 2 == 0), document.GetAllocator());
entry.AddMember("null", rapidjson::Value(rapidjson::kNullType), document.GetAllocator());
return entry;
};
auto createArray = [&]() -> rapidjson::Value
{
rapidjson::Value array;
array.SetArray();
for (int i = 0; i < entryCount; ++i)
{
array.PushBack(createEntry(i), document.GetAllocator());
}
return array;
};
auto createObject = [&]() -> rapidjson::Value
{
rapidjson::Value object;
object.SetObject();
for (int i = 0; i < entryCount; ++i)
{
buffer = AZStd::string::format("Key%i", i);
rapidjson::Value key;
key.SetString(buffer.data(), aznumeric_cast<rapidjson::SizeType>(buffer.length()), document.GetAllocator());
object.AddMember(key.Move(), createArray(), document.GetAllocator());
}
return object;
};
document.SetObject();
document.AddMember("entries", createObject(), document.GetAllocator());
return document;
}
AZStd::string DomBenchmarkFixture::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");
return serializedJson;
}
Value DomBenchmarkFixture::GenerateDomBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength)
{
Value root(Type::Object);
AZStd::string entryTemplate;
while (entryTemplate.size() < aznumeric_cast<size_t>(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::Object);
entry.AddMember("string", createString(n));
entry.AddMember("int", Value(n));
entry.AddMember("double", Value(aznumeric_cast<double>(n) * 0.5));
entry.AddMember("bool", Value(n % 2 == 0));
entry.AddMember("null", Value(Type::Null));
return entry;
};
auto createArray = [&]() -> Value
{
Value array(Type::Array);
for (int i = 0; i < entryCount; ++i)
{
array.ArrayPushBack(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;
}
void DomTestFixture::SetUp()
{
UnitTest::AllocatorsFixture::SetUp();
SetUpHarness();
}
void DomTestFixture::TearDown()
{
TearDownHarness();
UnitTest::AllocatorsFixture::TearDown();
}
} // namespace AZ::Dom::Tests

@ -0,0 +1,66 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/DOM/DomUtils.h>
#include <AzCore/JSON/document.h>
#include <AzCore/UnitTest/TestTypes.h>
#define DOM_REGISTER_SERIALIZATION_BENCHMARK(BaseClass, Method) \
BENCHMARK_REGISTER_F(BaseClass, Method)->Args({ 10, 5 })->Args({ 10, 500 })->Args({ 100, 5 })->Args({ 100, 500 })
#define DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(BaseClass, Method) \
DOM_REGISTER_SERIALIZATION_BENCHMARK(BaseClass, Method)->Unit(benchmark::kMillisecond);
#define DOM_REGISTER_SERIALIZATION_BENCHMARK_NS(BaseClass, Method) \
DOM_REGISTER_SERIALIZATION_BENCHMARK(BaseClass, Method)->Unit(benchmark::kNanosecond);
namespace AZ::Dom::Tests
{
class DomTestHarness
{
public:
virtual ~DomTestHarness() = default;
virtual void SetUpHarness();
virtual void TearDownHarness();
};
class DomBenchmarkFixture
: public DomTestHarness
, public UnitTest::AllocatorsBenchmarkFixture
{
public:
void SetUp(const ::benchmark::State& st) override;
void SetUp(::benchmark::State& st) override;
void TearDown(::benchmark::State& st) override;
void TearDown(const ::benchmark::State& st) override;
rapidjson::Document GenerateDomJsonBenchmarkDocument(int64_t entryCount, int64_t stringTemplateLength);
AZStd::string GenerateDomJsonBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength);
Value GenerateDomBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength);
template<class T>
static void TakeAndDiscardWithoutTimingDtor(T&& value, benchmark::State& state)
{
{
T instance = AZStd::move(value);
state.PauseTiming();
}
state.ResumeTiming();
}
};
class DomTestFixture
: public DomTestHarness
, public UnitTest::AllocatorsFixture
{
public:
void SetUp() override;
void TearDown() override;
};
} // namespace AZ::Dom::Tests

@ -16,131 +16,14 @@
#include <AzCore/Name/NameDictionary.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <Tests/DOM/DomFixtures.h>
namespace Benchmark
namespace AZ::Dom::Benchmark
{
class DomJsonBenchmark : public UnitTest::AllocatorsBenchmarkFixture
class DomJsonBenchmark : public Tests::DomBenchmarkFixture
{
public:
void SetUp(const ::benchmark::State& st) override
{
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
AZ::NameDictionary::Create();
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Create();
}
void SetUp(::benchmark::State& st) override
{
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
AZ::NameDictionary::Create();
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Create();
}
void TearDown(::benchmark::State& st) override
{
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Destroy();
AZ::NameDictionary::Destroy();
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
}
void TearDown(const ::benchmark::State& st) override
{
AZ::AllocatorInstance<AZ::Dom::ValueAllocator>::Destroy();
AZ::NameDictionary::Destroy();
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
}
rapidjson::Document GenerateDomJsonBenchmarkDocument(int64_t entryCount, int64_t stringTemplateLength)
{
rapidjson::Document document;
document.SetObject();
AZStd::string entryTemplate;
while (entryTemplate.size() < static_cast<size_t>(stringTemplateLength))
{
entryTemplate += "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor ";
}
entryTemplate.resize(stringTemplateLength);
AZStd::string buffer;
auto createString = [&](int n) -> rapidjson::Value
{
buffer = AZStd::string::format("#%i %s", n, entryTemplate.c_str());
return rapidjson::Value(buffer.data(), static_cast<rapidjson::SizeType>(buffer.size()), document.GetAllocator());
};
auto createEntry = [&](int n) -> rapidjson::Value
{
rapidjson::Value entry(rapidjson::kObjectType);
entry.AddMember("string", createString(n), document.GetAllocator());
entry.AddMember("int", rapidjson::Value(n), document.GetAllocator());
entry.AddMember("double", rapidjson::Value(static_cast<double>(n) * 0.5), document.GetAllocator());
entry.AddMember("bool", rapidjson::Value(n % 2 == 0), document.GetAllocator());
entry.AddMember("null", rapidjson::Value(rapidjson::kNullType), document.GetAllocator());
return entry;
};
auto createArray = [&]() -> rapidjson::Value
{
rapidjson::Value array;
array.SetArray();
for (int i = 0; i < entryCount; ++i)
{
array.PushBack(createEntry(i), document.GetAllocator());
}
return array;
};
auto createObject = [&]() -> rapidjson::Value
{
rapidjson::Value object;
object.SetObject();
for (int i = 0; i < entryCount; ++i)
{
buffer = AZStd::string::format("Key%i", i);
rapidjson::Value key;
key.SetString(buffer.data(), static_cast<rapidjson::SizeType>(buffer.length()), document.GetAllocator());
object.AddMember(key.Move(), createArray(), document.GetAllocator());
}
return object;
};
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");
return serializedJson;
}
template <class T>
void TakeAndDiscardWithoutTimingDtor(T&& value, benchmark::State& state)
{
{
T instance = AZStd::move(value);
state.PauseTiming();
}
state.ResumeTiming();
}
};
// Helper macro for registering JSON benchmarks
#define BENCHMARK_REGISTER_JSON(BaseClass, Method) \
BENCHMARK_REGISTER_F(BaseClass, Method) \
->Args({ 10, 5 }) \
->Args({ 10, 500 }) \
->Args({ 100, 5 }) \
->Args({ 100, 500 }) \
->Unit(benchmark::kMillisecond);
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToRapidjsonInPlace)(benchmark::State& state)
{
AZ::Dom::JsonBackend backend;
@ -163,7 +46,7 @@ namespace Benchmark
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToRapidjsonInPlace)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, AzDomDeserializeToRapidjsonInPlace)
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToAzDomValueInPlace)(benchmark::State& state)
{
@ -187,7 +70,7 @@ namespace Benchmark
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToAzDomValueInPlace)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, AzDomDeserializeToAzDomValueInPlace)
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToRapidjson)(benchmark::State& state)
{
@ -207,7 +90,7 @@ namespace Benchmark
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToRapidjson)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, AzDomDeserializeToRapidjson)
BENCHMARK_DEFINE_F(DomJsonBenchmark, AzDomDeserializeToAzDomValue)(benchmark::State& state)
{
@ -227,7 +110,7 @@ namespace Benchmark
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, AzDomDeserializeToAzDomValue)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, AzDomDeserializeToAzDomValue)
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonDeserializeToRapidjson)(benchmark::State& state)
{
@ -243,7 +126,7 @@ namespace Benchmark
state.SetBytesProcessed(serializedPayload.size() * state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonDeserializeToRapidjson)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, RapidjsonDeserializeToRapidjson)
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonMakeComplexObject)(benchmark::State& state)
{
@ -254,7 +137,7 @@ namespace Benchmark
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonMakeComplexObject)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, RapidjsonMakeComplexObject)
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonLookupMemberByString)(benchmark::State& state)
{
@ -264,7 +147,9 @@ namespace Benchmark
{
AZStd::string key(AZStd::string::format("key%" PRId64, i));
keys.push_back(key);
document.AddMember(rapidjson::Value(key.data(), static_cast<rapidjson::SizeType>(key.size()), document.GetAllocator()), rapidjson::Value(i), document.GetAllocator());
document.AddMember(
rapidjson::Value(key.data(), static_cast<rapidjson::SizeType>(key.size()), document.GetAllocator()), rapidjson::Value(i),
document.GetAllocator());
}
for (auto _ : state)
@ -293,7 +178,7 @@ namespace Benchmark
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonDeepCopy)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, RapidjsonDeepCopy)
BENCHMARK_DEFINE_F(DomJsonBenchmark, RapidjsonCopyAndMutate)(benchmark::State& state)
{
@ -309,9 +194,8 @@ namespace Benchmark
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_JSON(DomJsonBenchmark, RapidjsonCopyAndMutate)
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomJsonBenchmark, RapidjsonCopyAndMutate)
#undef BENCHMARK_REGISTER_JSON
} // namespace Benchmark
} // namespace AZ::Dom::Benchmark
#endif // defined(HAVE_BENCHMARK)

@ -13,24 +13,23 @@
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <Tests/DOM/DomFixtures.h>
namespace AZ::Dom::Tests
{
class DomJsonTests : public UnitTest::AllocatorsFixture
class DomJsonTests : public DomTestFixture
{
public:
void SetUp() override
{
UnitTest::AllocatorsFixture::SetUp();
NameDictionary::Create();
DomTestFixture::SetUp();
m_document = AZStd::make_unique<rapidjson::Document>();
}
void TearDown() override
{
m_document.reset();
NameDictionary::Destroy();
UnitTest::AllocatorsFixture::TearDown();
DomTestFixture::TearDown();
}
rapidjson::Value CreateString(const AZStd::string& text)

@ -6,110 +6,133 @@
*
*/
#include <AzCore/DOM/DomValue.h>
#include <AzCore/DOM/DomUtils.h>
#include <AzCore/DOM/DomValue.h>
#include <AzCore/Name/NameDictionary.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <cinttypes>
#include <Tests/DOM/DomFixtures.h>
namespace AZ::Dom::Benchmark
{
class DomValueBenchmark : public UnitTest::AllocatorsBenchmarkFixture
class DomValueBenchmark : public Tests::DomBenchmarkFixture
{
public:
void SetUp(const ::benchmark::State& st) override
{
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
AZ::NameDictionary::Create();
AZ::AllocatorInstance<ValueAllocator>::Create();
}
};
void SetUp(::benchmark::State& st) override
{
UnitTest::AllocatorsBenchmarkFixture::SetUp(st);
AZ::NameDictionary::Create();
AZ::AllocatorInstance<ValueAllocator>::Create();
}
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueGetType_UsingVariantIndex)(benchmark::State& state)
{
Value intValue(5);
Value boolValue(true);
Value objValue(Type::Object);
Value nodeValue(Type::Node);
Value arrValue(Type::Array);
Value uintValue(5u);
Value doubleValue(4.0);
Value stringValue("foo", true);
void TearDown(::benchmark::State& st) override
for (auto _ : state)
{
AZ::AllocatorInstance<ValueAllocator>::Destroy();
AZ::NameDictionary::Destroy();
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
(intValue.GetType());
(boolValue.GetType());
(objValue.GetType());
(nodeValue.GetType());
(arrValue.GetType());
(uintValue.GetType());
(doubleValue.GetType());
(stringValue.GetType());
}
void TearDown(const ::benchmark::State& st) override
{
AZ::AllocatorInstance<ValueAllocator>::Destroy();
AZ::NameDictionary::Destroy();
UnitTest::AllocatorsBenchmarkFixture::TearDown(st);
}
state.SetItemsProcessed(8 * state.iterations());
}
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueGetType_UsingVariantIndex);
Value GenerateDomBenchmarkPayload(int64_t entryCount, int64_t stringTemplateLength)
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueGetType_UsingVariantVisit)(benchmark::State& state)
{
Value intValue(5);
Value boolValue(true);
Value objValue(Type::Object);
Value nodeValue(Type::Node);
Value arrValue(Type::Array);
Value uintValue(5u);
Value doubleValue(4.0);
Value stringValue("foo", true);
auto getTypeViaVisit = [](const Value& value)
{
Value root(Type::Object);
AZStd::string entryTemplate;
while (entryTemplate.size() < static_cast<size_t>(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::Object);
entry.AddMember("string", createString(n));
entry.AddMember("int", Value(n));
entry.AddMember("double", Value(static_cast<double>(n) * 0.5));
entry.AddMember("bool", Value(n % 2 == 0));
entry.AddMember("null", Value(Type::Null));
return entry;
};
auto createArray = [&]() -> Value
{
Value array(Type::Array);
for (int i = 0; i < entryCount; ++i)
return AZStd::visit(
[](auto&& value) constexpr -> Type
{
array.ArrayPushBack(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;
}
using CurrentType = AZStd::decay_t<decltype(value)>;
if constexpr (AZStd::is_same_v<CurrentType, AZStd::monostate>)
{
return Type::Null;
}
else if constexpr (AZStd::is_same_v<CurrentType, int64_t>)
{
return Type::Int64;
}
else if constexpr (AZStd::is_same_v<CurrentType, uint64_t>)
{
return Type::Uint64;
}
else if constexpr (AZStd::is_same_v<CurrentType, double>)
{
return Type::Double;
}
else if constexpr (AZStd::is_same_v<CurrentType, bool>)
{
return Type::Bool;
}
else if constexpr (AZStd::is_same_v<CurrentType, AZStd::string_view>)
{
return Type::String;
}
else if constexpr (AZStd::is_same_v<CurrentType, Value::SharedStringType>)
{
return Type::String;
}
else if constexpr (AZStd::is_same_v<CurrentType, Value::ShortStringType>)
{
return Type::String;
}
else if constexpr (AZStd::is_same_v<CurrentType, ObjectPtr>)
{
return Type::Object;
}
else if constexpr (AZStd::is_same_v<CurrentType, ArrayPtr>)
{
return Type::Array;
}
else if constexpr (AZStd::is_same_v<CurrentType, NodePtr>)
{
return Type::Node;
}
else if constexpr (AZStd::is_same_v<CurrentType, Value::OpaqueStorageType>)
{
return Type::Opaque;
}
else
{
AZ_Assert(false, "AZ::Dom::Value::GetType: m_value has an unexpected type");
}
},
value.GetInternalValue());
};
template<class T>
void TakeAndDiscardWithoutTimingDtor(T&& value, benchmark::State& state)
for (auto _ : state)
{
{
T instance = AZStd::move(value);
state.PauseTiming();
}
state.ResumeTiming();
(getTypeViaVisit(intValue));
(getTypeViaVisit(boolValue));
(getTypeViaVisit(objValue));
(getTypeViaVisit(nodeValue));
(getTypeViaVisit(arrValue));
(getTypeViaVisit(uintValue));
(getTypeViaVisit(doubleValue));
(getTypeViaVisit(stringValue));
}
};
state.SetItemsProcessed(8 * state.iterations());
}
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueGetType_UsingVariantVisit);
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueMakeComplexObject)(benchmark::State& state)
{
@ -120,12 +143,7 @@ namespace AZ::Dom::Benchmark
state.SetItemsProcessed(state.range(0) * state.range(0) * state.iterations());
}
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueMakeComplexObject)
->Args({ 10, 5 })
->Args({ 10, 500 })
->Args({ 100, 5 })
->Args({ 100, 500 })
->Unit(benchmark::kMillisecond);
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomValueBenchmark, AzDomValueMakeComplexObject)
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueShallowCopy)(benchmark::State& state)
{
@ -139,12 +157,7 @@ namespace AZ::Dom::Benchmark
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueShallowCopy)
->Args({ 10, 5 })
->Args({ 10, 500 })
->Args({ 100, 5 })
->Args({ 100, 500 })
->Unit(benchmark::kNanosecond);
DOM_REGISTER_SERIALIZATION_BENCHMARK_NS(DomValueBenchmark, AzDomValueShallowCopy)
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueCopyAndMutate)(benchmark::State& state)
{
@ -159,12 +172,7 @@ namespace AZ::Dom::Benchmark
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueCopyAndMutate)
->Args({ 10, 5 })
->Args({ 10, 500 })
->Args({ 100, 5 })
->Args({ 100, 500 })
->Unit(benchmark::kNanosecond);
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomValueBenchmark, AzDomValueCopyAndMutate)
BENCHMARK_DEFINE_F(DomValueBenchmark, AzDomValueDeepCopy)(benchmark::State& state)
{
@ -178,12 +186,7 @@ namespace AZ::Dom::Benchmark
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_F(DomValueBenchmark, AzDomValueDeepCopy)
->Args({ 10, 5 })
->Args({ 10, 500 })
->Args({ 100, 5 })
->Args({ 100, 500 })
->Unit(benchmark::kMillisecond);
DOM_REGISTER_SERIALIZATION_BENCHMARK_MS(DomValueBenchmark, AzDomValueDeepCopy)
BENCHMARK_DEFINE_F(DomValueBenchmark, LookupMemberByName)(benchmark::State& state)
{

@ -15,26 +15,18 @@
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/numeric.h>
#include <Tests/DOM/DomFixtures.h>
namespace AZ::Dom::Tests
{
class DomValueTests : public UnitTest::AllocatorsFixture
class DomValueTests : public DomTestFixture
{
public:
void SetUp() override
{
UnitTest::AllocatorsFixture::SetUp();
NameDictionary::Create();
AZ::AllocatorInstance<ValueAllocator>::Create();
}
void TearDown() override
{
m_value = Value();
AZ::AllocatorInstance<ValueAllocator>::Destroy();
NameDictionary::Destroy();
UnitTest::AllocatorsFixture::TearDown();
DomTestFixture::TearDown();
}
void PerformValueChecks()

@ -215,6 +215,8 @@ set(FILES
AZStd/Variant.cpp
AZStd/VariantSerialization.cpp
AZStd/VectorAndArray.cpp
DOM/DomFixtures.cpp
DOM/DomFixtures.h
DOM/DomJsonTests.cpp
DOM/DomJsonBenchmarks.cpp
DOM/DomValueTests.cpp

@ -230,7 +230,10 @@ namespace AzToolsFramework
{
QModelIndex curIndex = selectedIndexes[0];
m_expandToEntriesByDefault = true;
m_treeStateSaver->ApplySnapshot();
if (m_treeStateSaver)
{
m_treeStateSaver->ApplySnapshot();
}
setCurrentIndex(curIndex);
scrollTo(curIndex);
@ -240,8 +243,12 @@ namespace AzToolsFramework
// Flag our default expansion state so that we expand down to source entries after filtering
m_expandToEntriesByDefault = hasFilter;
// Then ask our state saver to apply its current snapshot again, falling back on asking us if entries should be expanded or not
m_treeStateSaver->ApplySnapshot();
if (m_treeStateSaver)
{
m_treeStateSaver->ApplySnapshot();
}
// If we're filtering for a valid entry, select the first valid entry
if (hasFilter && selectFirstValidEntry)

@ -290,6 +290,7 @@ namespace AzToolsFramework
{
displayString = RichTextHighlighter::HighlightText(displayString, m_assetBrowserFilerModel->GetStringFilter()->GetFilterString());
}
RichTextHighlighter::PaintHighlightedRichText(displayString, painter, optionV4, remainingRect);
}
}

@ -29,12 +29,11 @@ namespace AzToolsFramework
return highlightedString;
}
void RichTextHighlighter::PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect)
void RichTextHighlighter::PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect, QPoint offset /* = QPoint()*/)
{
// Now we setup a Text Document so it can draw the rich text
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)
@ -46,10 +45,9 @@ namespace AzToolsFramework
textDoc.setDefaultStyleSheet("body {color: #7C7C7C}");
}
textDoc.setHtml("<body>" + highlightedString + "</body>");
painter->translate(availableRect.topLeft());
painter->translate(availableRect.topLeft() + offset);
textDoc.setTextWidth(availableRect.width());
textDoc.drawContents(painter, QRectF(0, 0, availableRect.width(), availableRect.height()));
painter->restore();
}
} // namespace AzToolsFramework

@ -30,7 +30,8 @@ namespace AzToolsFramework
RichTextHighlighter() = delete;
static QString HighlightText(const QString& displayString, const QString& matchingSubstring);
static void PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option, QRect availableRect);
static void PaintHighlightedRichText(const QString& highlightedString,QPainter* painter, QStyleOptionViewItem option,
QRect availableRect, QPoint offset = QPoint());
};
} // namespace AzToolsFramework

@ -2368,6 +2368,8 @@ namespace AzToolsFramework
AzToolsFramework::RichTextHighlighter::PaintHighlightedRichText(entityNameRichText, painter, optionV4, textRect);
painter->restore();
EntityOutlinerListModel::s_paintingName = false;
}

@ -25,6 +25,24 @@ ly_add_target(
AZ::AzCore
)
ly_add_target(
NAME AWSNativeSDKTestLibs STATIC
NAMESPACE AZ
FILES_CMAKE
aws_native_sdk_test_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
include
tests/libs
PRIVATE
source
BUILD_DEPENDENCIES
PRIVATE
3rdParty::AWSNativeSDK::Core
AZ::AzCore
AZ::AzTest
)
################################################################################
# Tests
################################################################################

@ -0,0 +1,12 @@
#
# 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
#
#
set(FILES
tests/libs/AWSNativeSDKTestManager.cpp
tests/libs/AWSNativeSDKTestManager.h
)

@ -89,5 +89,4 @@ namespace AWSNativeSDKInit
Platform::CustomizeShutdown();
#endif // #if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK)
}
}

@ -0,0 +1,45 @@
/*
* 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 <AWSNativeSDKTestManager.h>
#include <AzCore/Module/Environment.h>
#include <AzTest/Utils.h>
#include <AWSNativeSDKInit/AWSLogSystemInterface.h>
#include <aws/core/Aws.h>
#include <aws/core/utils/logging/AWSLogging.h>
namespace AWSNativeSDKTestLibs
{
AZ::EnvironmentVariable<AWSNativeSDKTestManager> AWSNativeSDKTestManager::s_sdkManager = nullptr;
AWSNativeSDKTestManager::AWSNativeSDKTestManager()
{
AZ::Test::SetEnv("AWS_DEFAULT_REGION", "us-east-1", 1);
m_awsSDKOptions.memoryManagementOptions.memoryManager = &m_memoryManager;
Aws::InitAPI(m_awsSDKOptions);
}
AWSNativeSDKTestManager::~AWSNativeSDKTestManager()
{
Aws::ShutdownAPI(m_awsSDKOptions);
AZ::Test::UnsetEnv("AWS_DEFAULT_REGION");
}
void AWSNativeSDKTestManager::Init()
{
s_sdkManager = AZ::Environment::CreateVariable<AWSNativeSDKTestManager>(AWSNativeSDKTestManager::SdkManagerTag);
}
void AWSNativeSDKTestManager::Shutdown()
{
s_sdkManager = nullptr;
}
}

@ -0,0 +1,39 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Module/Environment.h>
#include <AzCore/PlatformIncl.h>
#include <AWSNativeSDKInit/AWSMemoryInterface.h>
#include <aws/core/Aws.h>
namespace AWSNativeSDKTestLibs
{
// Entry point for AWSNativeSDK's initialization and shutdown for test environment
// Use an AZ::Environment variable to enforce only one init and shutdown
class AWSNativeSDKTestManager
{
public:
static constexpr const char SdkManagerTag[] = "TestAWSSDKManager";
AWSNativeSDKTestManager();
~AWSNativeSDKTestManager();
static void Init();
static void Shutdown();
private:
static AZ::EnvironmentVariable<AWSNativeSDKTestManager> s_sdkManager;
AWSNativeSDKInit::MemoryManager m_memoryManager;
Aws::SDKOptions m_awsSDKOptions;
};
}

@ -106,13 +106,12 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
3rdParty::AWSNativeSDK::AWSClientAuth
AZ::AzCore
AZ::AzFramework
AZ::AWSNativeSDKInit
AZ::AWSNativeSDKTestLibs
Gem::AWSClientAuth.Static
Gem::AWSCore
Gem::HttpRequestor
RUNTIME_DEPENDENCIES
Gem::AWSCore
AZ::AWSNativeSDKInit
Gem::HttpRequestor
)
ly_add_googletest(

@ -30,7 +30,7 @@
#include <AWSCoreBus.h>
#include <ResourceMapping/AWSResourceMappingBus.h>
#include <AWSClientAuthBus.h>
#include <AWSNativeSDKInit/AWSNativeSDKInit.h>
#include <AWSNativeSDKTestManager.h>
#include <HttpRequestor/HttpRequestorBus.h>
#include <aws/core/utils/Outcome.h>
@ -542,7 +542,7 @@ namespace AWSClientAuthUnitTest
m_jobContext.reset(aznew AZ::JobContext(*m_jobManager, *m_jobCancelGroup));
AZ::JobContext::SetGlobalContext(m_jobContext.get());
AWSNativeSDKInit::InitializationManager::InitAwsApi();
AWSNativeSDKTestLibs::AWSNativeSDKTestManager::Init();
m_cognitoIdentityProviderClientMock = std::make_shared<CognitoIdentityProviderClientMock>();
m_cognitoIdentityClientMock = std::make_shared<CognitoIdentityClientMock>();
}
@ -557,8 +557,7 @@ namespace AWSClientAuthUnitTest
m_cognitoIdentityProviderClientMock.reset();
m_cognitoIdentityClientMock.reset();
AWSNativeSDKInit::InitializationManager::Shutdown();
AWSNativeSDKTestLibs::AWSNativeSDKTestManager::Shutdown();
AZ::AllocatorInstance<AZ::ThreadPoolAllocator>::Destroy();

@ -163,7 +163,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
PRIVATE
AZ::AzTest
AZ::AzFramework
AZ::AWSNativeSDKInit
AZ::AWSNativeSDKTestLibs
Gem::AWSCore.Static
)
@ -202,7 +202,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
3rdParty::Qt::Gui
3rdParty::Qt::Widgets
AZ::AzTest
AZ::AWSNativeSDKInit
AZ::AWSNativeSDKTestLibs
Gem::AWSCore.Static
Gem::AWSCore.Editor.Static
)

@ -19,7 +19,7 @@
#include <AzTest/AzTest.h>
#include <AWSCoreSystemComponent.h>
#include <AWSNativeSDKInit/AWSNativeSDKInit.h>
#include <AWSNativeSDKTestManager.h>
#include <Configuration/AWSCoreConfiguration.h>
#include <Credential/AWSCredentialManager.h>
#include <Framework/AWSApiJob.h>
@ -105,7 +105,7 @@ public:
TEST_F(AWSCoreSystemComponentTest, ComponentActivateTest)
{
// Shutdown SDK which is init in fixture setup step
AWSNativeSDKInit::InitializationManager::Shutdown();
AWSNativeSDKTestLibs::AWSNativeSDKTestManager::Shutdown();
EXPECT_FALSE(m_coreSystemsComponent->IsAWSApiInitialized());

@ -17,7 +17,7 @@
#include <Framework/JsonObjectHandler.h>
#include <Framework/JsonWriter.h>
#include <AWSNativeSDKInit/AWSNativeSDKInit.h>
#include <AWSNativeSDKTestManager.h>
namespace AWSCoreTestingUtils
{
@ -138,7 +138,7 @@ public:
m_app = AZStd::make_unique<AZ::ComponentApplication>();
}
AWSNativeSDKInit::InitializationManager::InitAwsApi();
AWSNativeSDKTestLibs::AWSNativeSDKTestManager::Init();
}
void TearDown() override
@ -148,7 +148,7 @@ public:
void TearDownFixture(bool mockSettingsRegistry = true)
{
AWSNativeSDKInit::InitializationManager::Shutdown();
AWSNativeSDKTestLibs::AWSNativeSDKTestManager::Shutdown();
if (mockSettingsRegistry)
{

@ -90,7 +90,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
Gem::AWSCore
Gem::AWSGameLift.Client.Static
3rdParty::AWSNativeSDK::GameLiftClient
AZ::AWSNativeSDKInit
AZ::AWSNativeSDKTestLibs
)
# Add AWSGameLift.Client.Tests to googletest
ly_add_googletest(

@ -8,12 +8,13 @@
#pragma once
#include <AWSNativeSDKInit/AWSNativeSDKInit.h>
#include <AWSNativeSDKTestManager.h>
#include <AzCore/Jobs/JobManager.h>
#include <AzCore/Jobs/JobManagerBus.h>
#include <AzCore/Jobs/JobContext.h>
#include <AzCore/Memory/PoolAllocator.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzTest/Utils.h>
class AWSGameLiftClientFixture
: public UnitTest::ScopedAllocatorSetupFixture
@ -38,12 +39,12 @@ public:
m_jobContext.reset(aznew AZ::JobContext(*m_jobManager, *m_jobCancelGroup));
AZ::JobContext::SetGlobalContext(m_jobContext.get());
AWSNativeSDKInit::InitializationManager::InitAwsApi();
AWSNativeSDKTestLibs::AWSNativeSDKTestManager::Init();
}
void TearDown() override
{
AWSNativeSDKInit::InitializationManager::Shutdown();
AWSNativeSDKTestLibs::AWSNativeSDKTestManager::Shutdown();
AZ::JobContext::SetGlobalContext(nullptr);
m_jobContext.reset();

@ -21,16 +21,16 @@ namespace AWSMetrics
static constexpr char AwsMetricsAttributeKeyEventData[] = "event_data";
//! Service API request and response object keys
static constexpr char AwsMetricsSuccessResponseRecordKeyErrorCode[] = "error_code";
static constexpr char AwsMetricsSuccessResponseRecordKeyResult[] = "result";
static constexpr char AwsMetricsSuccessResponseKeyFailedRecordCount[] = "failed_record_count";
static constexpr char AwsMetricsSuccessResponseKeyEvents[] = "events";
static constexpr char AwsMetricsSuccessResponseKeyTotal[] = "total";
static constexpr char AwsMetricsErrorKeyMessage[] = "message";
static constexpr char AwsMetricsErrorKeyType[] = "type";
static constexpr char AwsMetricsRequestParameterKeyEvents[] = "events";
static constexpr char AwsMetricsPostMetricsEventsResponseEntryKeyErrorCode[] = "error_code";
static constexpr char AwsMetricsPostMetricsEventsResponseEntryKeyResult[] = "result";
static constexpr char AwsMetricsPostMetricsEventsResponseKeyFailedRecordCount[] = "failed_record_count";
static constexpr char AwsMetricsPostMetricsEventsResponseKeyEvents[] = "events";
static constexpr char AwsMetricsPostMetricsEventsResponseKeyTotal[] = "total";
static constexpr char AwsMetricsPostMetricsEventsErrorKeyMessage[] = "message";
static constexpr char AwsMetricsPostMetricsEventsErrorKeyType[] = "type";
static constexpr char AwsMetricsPostMetricsEventsRequestParameterKeyEvents[] = "events";
static constexpr char AwsMetricsSuccessResponseRecordResult[] = "Ok";
static constexpr char AwsMetricsPostMetricsEventsResponseEntrySuccessResult[] = "Ok";
//! Service API limits
//! https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html

@ -15,56 +15,77 @@ namespace AWSMetrics
{
namespace ServiceAPI
{
bool MetricsEventSuccessResponseRecord::OnJsonKey(const char* key, AWSCore::JsonReader& reader)
bool PostMetricsEventsResponseEntry::OnJsonKey(const char* key, AWSCore::JsonReader& reader)
{
if (strcmp(key, AwsMetricsSuccessResponseRecordKeyErrorCode) == 0) return reader.Accept(errorCode);
if (strcmp(key, AwsMetricsPostMetricsEventsResponseEntryKeyErrorCode) == 0)
{
return reader.Accept(m_errorCode);
}
if (strcmp(key, AwsMetricsSuccessResponseRecordKeyResult) == 0) return reader.Accept(result);
if (strcmp(key, AwsMetricsPostMetricsEventsResponseEntryKeyResult) == 0)
{
return reader.Accept(m_result);
}
return reader.Ignore();
}
bool MetricsEventSuccessResponse::OnJsonKey(const char* key, AWSCore::JsonReader& reader)
bool PostMetricsEventsResponse::OnJsonKey(const char* key, AWSCore::JsonReader& reader)
{
if (strcmp(key, AwsMetricsSuccessResponseKeyFailedRecordCount) == 0) return reader.Accept(failedRecordCount);
if (strcmp(key, AwsMetricsPostMetricsEventsResponseKeyFailedRecordCount) == 0)
{
return reader.Accept(m_failedRecordCount);
}
if (strcmp(key, AwsMetricsSuccessResponseKeyEvents) == 0) return reader.Accept(events);
if (strcmp(key, AwsMetricsPostMetricsEventsResponseKeyEvents) == 0)
{
return reader.Accept(m_responseEntries);
}
if (strcmp(key, AwsMetricsSuccessResponseKeyTotal) == 0) return reader.Accept(total);
if (strcmp(key, AwsMetricsPostMetricsEventsResponseKeyTotal) == 0)
{
return reader.Accept(m_total);
}
return reader.Ignore();
}
bool Error::OnJsonKey(const char* key, AWSCore::JsonReader& reader)
bool PostMetricsEventsError::OnJsonKey(const char* key, AWSCore::JsonReader& reader)
{
if (strcmp(key, AwsMetricsErrorKeyMessage) == 0) return reader.Accept(message);
if (strcmp(key, AwsMetricsPostMetricsEventsErrorKeyMessage) == 0)
{
return reader.Accept(message);
}
if (strcmp(key, AwsMetricsErrorKeyType) == 0) return reader.Accept(type);
if (strcmp(key, AwsMetricsPostMetricsEventsErrorKeyType) == 0)
{
return reader.Accept(type);
}
return reader.Ignore();
}
// Generated Function Parameters
bool PostProducerEventsRequest::Parameters::BuildRequest(AWSCore::RequestBuilder& request)
// Generated request parameters
bool PostMetricsEventsRequest::Parameters::BuildRequest(AWSCore::RequestBuilder& request)
{
bool ok = true;
bool buildResult = true;
buildResult = buildResult && request.WriteJsonBodyParameter(*this);
ok = ok && request.WriteJsonBodyParameter(*this);
return ok;
return buildResult;
}
bool PostProducerEventsRequest::Parameters::WriteJson(AWSCore::JsonWriter& writer) const
bool PostMetricsEventsRequest::Parameters::WriteJson(AWSCore::JsonWriter& writer) const
{
bool ok = true;
bool writeResult = true;
ok = ok && writer.StartObject();
writeResult = writeResult && writer.StartObject();
ok = ok && writer.Key(AwsMetricsRequestParameterKeyEvents);
ok = ok && data.SerializeToJson(writer);
writeResult = writeResult && writer.Key(AwsMetricsPostMetricsEventsRequestParameterKeyEvents);
writeResult = writeResult && m_metricsQueue.SerializeToJson(writer);
ok = ok && writer.EndObject();
writeResult = writeResult && writer.EndObject();
return ok;
return writeResult;
}
}
}

@ -16,41 +16,44 @@ namespace AWSMetrics
{
namespace ServiceAPI
{
//! Struct for storing event record from the response.
struct MetricsEventSuccessResponseRecord
//! Response for an individual metrics event from a PostMetricsEvents request.
//! If the event is successfully sent to the backend, it receives an "Ok" result.
//! If the event fails to be sent to the backend, the result includes an error code and an "Error" result.
struct PostMetricsEventsResponseEntry
{
//! Identify the expected property type and provide a location where the property value can be stored.
//! Identify the expected property type in the response entry for each individual metrics event and provide a location where the property value can be stored.
//! @param key Name of the property.
//! @param reader JSON reader to read the property.
bool OnJsonKey(const char* key, AWSCore::JsonReader& reader);
AZStd::string errorCode; //!< Error code if the event is not sent successfully.
AZStd::string result; //!< Processing result for the input record.
AZStd::string m_errorCode; //!< Error code if the individual metrics event failed to be sent.
AZStd::string m_result; //!< Result for the processed individual metrics event. Expected value: "Error" or "Ok".
};
using MetricsEventSuccessResponsePropertyEvents = AZStd::vector<MetricsEventSuccessResponseRecord>;
using PostMetricsEventsResponseEntries = AZStd::vector<PostMetricsEventsResponseEntry>;
//! Struct for storing the success response.
struct MetricsEventSuccessResponse
//! Response for all the processed metrics events from a PostMetricsEvents request.
struct PostMetricsEventsResponse
{
//! Identify the expected property type and provide a location where the property value can be stored.
//! Identify the expected property type in the response and provide a location where the property value can be stored.
//! @param key Name of the property.
//! @param reader JSON reader to read the property.
bool OnJsonKey(const char* key, AWSCore::JsonReader& reader);
int failedRecordCount{ 0 }; //!< Number of events that failed to be saved to metrics events stream.
MetricsEventSuccessResponsePropertyEvents events; //! List of input event records.
int total{ 0 }; //!< Total number of events that were processed in the request
int m_failedRecordCount{ 0 }; //!< Number of events that failed to be sent to the backend.
PostMetricsEventsResponseEntries m_responseEntries; //! Response list for all the processed metrics events.
int m_total{ 0 }; //!< Total number of events that were processed in the request.
};
//! Struct for storing the failure response.
struct Error
//! Failure response for sending the PostMetricsEvents request.
struct PostMetricsEventsError
{
//! Identify the expected property type and provide a location where the property value can be stored.
//! Identify the expected property type in the failure response and provide a location where the property value can be stored.
//! @param key Name of the property.
//! @param reader JSON reader to read the property.
bool OnJsonKey(const char* key, AWSCore::JsonReader& reader);
//! Do not rename the following members since they are expected by the AWSCore dependency.
AZStd::string message; //!< Error message.
AZStd::string type; //!< Error type.
};
@ -60,7 +63,7 @@ namespace AWSMetrics
//! POST request defined by api_spec.json to send metrics to the backend.
//! The path for this service API is "/producer/events".
class PostProducerEventsRequest
class PostMetricsEventsRequest
: public AWSCore::ServiceRequest
{
public:
@ -79,14 +82,15 @@ namespace AWSMetrics
//! @return Whether the serialization is successful.
bool WriteJson(AWSCore::JsonWriter& writer) const;
MetricsQueue data; //!< Data to send via the service API request.
MetricsQueue m_metricsQueue; //!< Metrics events to send via the service API request.
};
MetricsEventSuccessResponse result; //! Success response.
Error error; //! Failure response.
//! Do not rename the following members since they are expected by the AWSCore dependency.
PostMetricsEventsResponse result; //! Success response.
PostMetricsEventsError error; //! Failure response.
Parameters parameters; //! Request parameter.
};
using PostProducerEventsRequestJob = AWSCore::ServiceRequestJob<PostProducerEventsRequest>;
using PostMetricsEventsRequestJob = AWSCore::ServiceRequestJob<PostMetricsEventsRequest>;
} // ServiceAPI
} // AWSMetrics

@ -172,17 +172,17 @@ namespace AWSMetrics
if (outcome.IsSuccess())
{
// Generate response records for success call to keep consistency with the Service API response
ServiceAPI::MetricsEventSuccessResponsePropertyEvents responseRecords;
ServiceAPI::PostMetricsEventsResponseEntries responseEntries;
int numMetricsEventsInRequest = metricsQueue->GetNumMetrics();
for (int index = 0; index < numMetricsEventsInRequest; ++index)
{
ServiceAPI::MetricsEventSuccessResponseRecord responseRecord;
responseRecord.result = AwsMetricsSuccessResponseRecordResult;
ServiceAPI::PostMetricsEventsResponseEntry responseEntry;
responseEntry.m_result = AwsMetricsPostMetricsEventsResponseEntrySuccessResult;
responseRecords.emplace_back(responseRecord);
responseEntries.emplace_back(responseEntry);
}
OnResponseReceived(*metricsQueue, responseRecords);
OnResponseReceived(*metricsQueue, responseEntries);
AZ::TickBus::QueueFunction([requestId]()
{
@ -209,19 +209,19 @@ namespace AWSMetrics
{
int requestId = ++m_sendMetricsId;
ServiceAPI::PostProducerEventsRequestJob* requestJob = ServiceAPI::PostProducerEventsRequestJob::Create(
[this, requestId](ServiceAPI::PostProducerEventsRequestJob* successJob)
ServiceAPI::PostMetricsEventsRequestJob* requestJob = ServiceAPI::PostMetricsEventsRequestJob::Create(
[this, requestId](ServiceAPI::PostMetricsEventsRequestJob* successJob)
{
OnResponseReceived(successJob->parameters.data, successJob->result.events);
OnResponseReceived(successJob->parameters.m_metricsQueue, successJob->result.m_responseEntries);
AZ::TickBus::QueueFunction([requestId]()
{
AWSMetricsNotificationBus::Broadcast(&AWSMetricsNotifications::OnSendMetricsSuccess, requestId);
});
},
[this, requestId](ServiceAPI::PostProducerEventsRequestJob* failedJob)
[this, requestId](ServiceAPI::PostMetricsEventsRequestJob* failedJob)
{
OnResponseReceived(failedJob->parameters.data);
OnResponseReceived(failedJob->parameters.m_metricsQueue);
AZStd::string errorMessage = failedJob->error.message;
AZ::TickBus::QueueFunction([requestId, errorMessage]()
@ -230,11 +230,11 @@ namespace AWSMetrics
});
});
requestJob->parameters.data = AZStd::move(metricsQueue);
requestJob->parameters.m_metricsQueue = AZStd::move(metricsQueue);
requestJob->Start();
}
void MetricsManager::OnResponseReceived(const MetricsQueue& metricsEventsInRequest, const ServiceAPI::MetricsEventSuccessResponsePropertyEvents& responseRecords)
void MetricsManager::OnResponseReceived(const MetricsQueue& metricsEventsInRequest, const ServiceAPI::PostMetricsEventsResponseEntries& responseEntries)
{
MetricsQueue metricsEventsForRetry;
int numMetricsEventsInRequest = metricsEventsInRequest.GetNumMetrics();
@ -242,7 +242,7 @@ namespace AWSMetrics
{
MetricsEvent metricsEvent = metricsEventsInRequest[index];
if (responseRecords.size() > 0 && responseRecords[index].result == AwsMetricsSuccessResponseRecordResult)
if (responseEntries.size() > 0 && responseEntries[index].m_result == AwsMetricsPostMetricsEventsResponseEntrySuccessResult)
{
// The metrics event is sent to the backend successfully.
if (metricsEvent.GetNumFailures() == 0)

@ -60,9 +60,8 @@ namespace AWSMetrics
//! Update the global stats and add qualified failed metrics events back to the buffer for retry.
//! @param metricsEventsInRequest Metrics events in the original request.
//! @param responseRecords Response records from the call. Each record in the list contains the result for sending the corresponding metrics event.
void OnResponseReceived(const MetricsQueue& metricsEventsInRequest, const ServiceAPI::MetricsEventSuccessResponsePropertyEvents& responseRecords =
ServiceAPI::MetricsEventSuccessResponsePropertyEvents());
//! @param responseEntries Response list for all the processed metrics events.
void OnResponseReceived(const MetricsQueue& metricsEventsInRequest, const ServiceAPI::PostMetricsEventsResponseEntries& responseEntries = ServiceAPI::PostMetricsEventsResponseEntries());
//! Implementation for flush all metrics buffered in memory.
void FlushMetricsAsync();

@ -42,43 +42,43 @@ namespace AWSMetrics
TEST_F(AWSMetricsServiceApiTest, OnJsonKey_MetricsEventSuccessResponseRecord_AcceptValidKeys)
{
ServiceAPI::MetricsEventSuccessResponseRecord responseRecord;
responseRecord.result = "ok";
ServiceAPI::PostMetricsEventsResponseEntry responseRecord;
responseRecord.m_result = "ok";
EXPECT_CALL(JsonReader, Accept(responseRecord.result)).Times(1);
EXPECT_CALL(JsonReader, Accept(responseRecord.errorCode)).Times(1);
EXPECT_CALL(JsonReader, Accept(responseRecord.m_result)).Times(1);
EXPECT_CALL(JsonReader, Accept(responseRecord.m_errorCode)).Times(1);
EXPECT_CALL(JsonReader, Ignore()).Times(1);
responseRecord.OnJsonKey(AwsMetricsSuccessResponseRecordKeyResult, JsonReader);
responseRecord.OnJsonKey(AwsMetricsSuccessResponseRecordKeyErrorCode, JsonReader);
responseRecord.OnJsonKey(AwsMetricsPostMetricsEventsResponseEntryKeyResult, JsonReader);
responseRecord.OnJsonKey(AwsMetricsPostMetricsEventsResponseEntryKeyErrorCode, JsonReader);
responseRecord.OnJsonKey("other", JsonReader);
}
TEST_F(AWSMetricsServiceApiTest, OnJsonKeyWithEvents_MetricsEventSuccessResponseRecord_AcceptValidKeys)
{
// Verifiy that JsonReader accepts valid JSON keys in each event record from a success reponse
ServiceAPI::MetricsEventSuccessResponseRecord responseRecord;
responseRecord.result = "ok";
ServiceAPI::PostMetricsEventsResponseEntry responseRecord;
responseRecord.m_result = "Ok";
ServiceAPI::MetricsEventSuccessResponse response;
response.events.emplace_back(responseRecord);
response.failedRecordCount = 0;
response.total = 1;
ServiceAPI::PostMetricsEventsResponse response;
response.m_responseEntries.emplace_back(responseRecord);
response.m_failedRecordCount = 0;
response.m_total = 1;
EXPECT_CALL(JsonReader, Accept(response.failedRecordCount)).Times(1);
EXPECT_CALL(JsonReader, Accept(response.total)).Times(1);
EXPECT_CALL(JsonReader, Accept(response.m_failedRecordCount)).Times(1);
EXPECT_CALL(JsonReader, Accept(response.m_total)).Times(1);
EXPECT_CALL(JsonReader, Accept(::testing::An<AWSCore::JsonArrayHandler>())).Times(1);
EXPECT_CALL(JsonReader, Ignore()).Times(1);
response.OnJsonKey(AwsMetricsSuccessResponseKeyFailedRecordCount, JsonReader);
response.OnJsonKey(AwsMetricsSuccessResponseKeyTotal, JsonReader);
response.OnJsonKey(AwsMetricsSuccessResponseKeyEvents, JsonReader);
response.OnJsonKey(AwsMetricsPostMetricsEventsResponseKeyFailedRecordCount, JsonReader);
response.OnJsonKey(AwsMetricsPostMetricsEventsResponseKeyTotal, JsonReader);
response.OnJsonKey(AwsMetricsPostMetricsEventsResponseKeyEvents, JsonReader);
response.OnJsonKey("other", JsonReader);
}
TEST_F(AWSMetricsServiceApiTest, OnJsonKey_Error_AcceptValidKeys)
{
ServiceAPI::Error error;
ServiceAPI::PostMetricsEventsError error;
error.message = "error message";
error.type = "404";
@ -86,16 +86,16 @@ namespace AWSMetrics
EXPECT_CALL(JsonReader, Accept(error.type)).Times(1);
EXPECT_CALL(JsonReader, Ignore()).Times(1);
error.OnJsonKey(AwsMetricsErrorKeyMessage, JsonReader);
error.OnJsonKey(AwsMetricsErrorKeyType, JsonReader);
error.OnJsonKey(AwsMetricsPostMetricsEventsErrorKeyMessage, JsonReader);
error.OnJsonKey(AwsMetricsPostMetricsEventsErrorKeyType, JsonReader);
error.OnJsonKey("other", JsonReader);
}
TEST_F(AWSMetricsServiceApiTest, BuildRequestBody_PostProducerEventsRequest_SerializedMetricsQueue)
{
ServiceAPI::PostProducerEventsRequest request;
request.parameters.data = MetricsQueue();
request.parameters.data.AddMetrics(MetricsEventBuilder().Build());
ServiceAPI::PostMetricsEventsRequest request;
request.parameters.m_metricsQueue = MetricsQueue();
request.parameters.m_metricsQueue.AddMetrics(MetricsEventBuilder().Build());
AWSCore::RequestBuilder requestBuilder{};
EXPECT_TRUE(request.parameters.BuildRequest(requestBuilder));
@ -104,6 +104,6 @@ namespace AWSMetrics
std::istreambuf_iterator<AZStd::string::value_type> eos;
AZStd::string bodyString{ std::istreambuf_iterator<AZStd::string::value_type>(*bodyContent), eos };
EXPECT_TRUE(bodyString.contains(AZStd::string::format("{\"%s\":[{\"event_timestamp\":", AwsMetricsRequestParameterKeyEvents)));
EXPECT_TRUE(bodyString.contains(AZStd::string::format("{\"%s\":[{\"event_timestamp\":", AwsMetricsPostMetricsEventsRequestParameterKeyEvents)));
}
}

@ -430,14 +430,14 @@ namespace AWSMetrics
ReplaceLocalFileIOWithMockIO();
}
TEST_F(MetricsManagerTest, OnResponseReceived_WithResponseRecords_RetryFailedMetrics)
TEST_F(MetricsManagerTest, OnResponseReceived_WithResponseEntries_RetryFailedMetrics)
{
// Reset the config file to change the max queue size setting.
ResetClientConfig(false, (double)TestMetricsEventSizeInBytes * (MaxNumMetricsEvents + 1) / MbToBytes,
DefaultFlushPeriodInSeconds, 1);
MetricsQueue metricsEvents;
ServiceAPI::MetricsEventSuccessResponsePropertyEvents responseRecords;
ServiceAPI::PostMetricsEventsResponseEntries responseEntries;
for (int index = 0; index < MaxNumMetricsEvents; ++index)
{
MetricsEvent newEvent;
@ -445,19 +445,19 @@ namespace AWSMetrics
metricsEvents.AddMetrics(newEvent);
ServiceAPI::MetricsEventSuccessResponseRecord responseRecord;
ServiceAPI::PostMetricsEventsResponseEntry responseEntry;
if (index % 2 == 0)
{
responseRecord.errorCode = "Error";
responseEntry.m_errorCode = "Error";
}
else
{
responseRecord.result = "Ok";
responseEntry.m_result = "Ok";
}
responseRecords.emplace_back(responseRecord);
responseEntries.emplace_back(responseEntry);
}
m_metricsManager->OnResponseReceived(metricsEvents, responseRecords);
m_metricsManager->OnResponseReceived(metricsEvents, responseEntries);
const GlobalStatistics& stats = m_metricsManager->GetGlobalStatistics();
EXPECT_EQ(stats.m_numEvents, MaxNumMetricsEvents);
@ -471,7 +471,7 @@ namespace AWSMetrics
ASSERT_EQ(m_metricsManager->GetNumBufferedMetrics(), MaxNumMetricsEvents / 2);
}
TEST_F(MetricsManagerTest, OnResponseReceived_NoResponseRecords_RetryAllMetrics)
TEST_F(MetricsManagerTest, OnResponseReceived_NoResponseEntries_RetryAllMetrics)
{
// Reset the config file to change the max queue size setting.
ResetClientConfig(false, (double)TestMetricsEventSizeInBytes * (MaxNumMetricsEvents + 1) / MbToBytes,

@ -3,7 +3,7 @@
"info": {
"title": "AWSMetricsServiceApi",
"description": "Service API for the data analytics pipeline defined by the AWS Metrics Gem",
"version": "1.0.0"
"version": "1.0.1"
},
"x-amazon-apigateway-request-validators": {
"all": {
@ -68,7 +68,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MetricsEventSuccessResponse"
"$ref": "#/components/schemas/PostMetricsEventsResponse"
}
}
}
@ -78,7 +78,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
"$ref": "#/components/schemas/PostMetricsEventsError"
}
}
}
@ -88,17 +88,17 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
"$ref": "#/components/schemas/PostMetricsEventsError"
}
}
}
},
"500": {
"description": "Internal Server Error",
"description": "Internal Server PostMetricsEventsError",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
"$ref": "#/components/schemas/PostMetricsEventsError"
}
}
}
@ -109,7 +109,7 @@
},
"components": {
"schemas": {
"Error": {
"PostMetricsEventsError": {
"type": "object",
"properties": {
"message": {
@ -184,18 +184,18 @@
}
}
},
"MetricsEventSuccessResponse": {
"PostMetricsEventsResponse": {
"title": "Metrics Event Success Response Schema",
"type": "object",
"properties": {
"failed_record_count": {
"type": "number",
"description": "Number of events that failed to be saved to metrics events stream"
"description": "Number of events that failed to be sent to the backend"
},
"events": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MetricsEventSuccessResponseRecord"
"$ref": "#/components/schemas/PostMetricsEventsResponseEntry"
}
},
"total": {
@ -204,16 +204,16 @@
}
}
},
"MetricsEventSuccessResponseRecord": {
"PostMetricsEventsResponseEntry": {
"type": "object",
"properties": {
"error_code": {
"type": "string",
"description": "The error code from the metrics events stream. Value set if Result is Error"
"description": "Error code if the individual metrics event failed to be sent"
},
"result": {
"type": "string",
"description": "Processing result for the input record"
"description": "Result for the processed individual metrics event. Expected value: \"Error\" or \"Ok\""
}
}
}

@ -120,7 +120,7 @@ namespace AZ
// Register Precompiled Shader Builder
AssetBuilderSDK::AssetBuilderDesc precompiledShaderBuilderDescriptor;
precompiledShaderBuilderDescriptor.m_name = "Precompiled Shader Builder";
precompiledShaderBuilderDescriptor.m_version = 10; // ATOM-15472
precompiledShaderBuilderDescriptor.m_version = 11; // ATOM-15740
precompiledShaderBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", AZ::PrecompiledShaderBuilder::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
precompiledShaderBuilderDescriptor.m_busId = azrtti_typeid<PrecompiledShaderBuilder>();
precompiledShaderBuilderDescriptor.m_createJobFunction = AZStd::bind(&PrecompiledShaderBuilder::CreateJobs, &m_precompiledShaderBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);

@ -68,20 +68,23 @@ namespace AZ
{
AZStd::vector<AssetBuilderSDK::JobDependency> jobDependencyList;
// setup dependencies on the root azshadervariant asset file names
for (const auto& rootShaderVariantAsset : precompiledShaderAsset.m_rootShaderVariantAssets)
// setup dependencies on the root azshadervariant asset file names, for each supervariant
for (const auto& supervariant : precompiledShaderAsset.m_supervariants)
{
AZStd::string rootShaderVariantAssetPath = RPI::AssetUtils::ResolvePathReference(request.m_sourceFile.c_str(), rootShaderVariantAsset->m_rootShaderVariantAssetFileName);
AssetBuilderSDK::SourceFileDependency sourceDependency;
sourceDependency.m_sourceFileDependencyPath = rootShaderVariantAssetPath;
response.m_sourceFileDependencyList.push_back(sourceDependency);
AssetBuilderSDK::JobDependency jobDependency;
jobDependency.m_jobKey = "azshadervariant";
jobDependency.m_platformIdentifier = platformInfo.m_identifier;
jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order;
jobDependency.m_sourceFile = sourceDependency;
jobDependencyList.push_back(jobDependency);
for (const auto& rootShaderVariantAsset : supervariant->m_rootShaderVariantAssets)
{
AZStd::string rootShaderVariantAssetPath = RPI::AssetUtils::ResolvePathReference(request.m_sourceFile.c_str(), rootShaderVariantAsset->m_rootShaderVariantAssetFileName);
AssetBuilderSDK::SourceFileDependency sourceDependency;
sourceDependency.m_sourceFileDependencyPath = rootShaderVariantAssetPath;
response.m_sourceFileDependencyList.push_back(sourceDependency);
AssetBuilderSDK::JobDependency jobDependency;
jobDependency.m_jobKey = "azshadervariant";
jobDependency.m_platformIdentifier = platformInfo.m_identifier;
jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order;
jobDependency.m_sourceFile = sourceDependency;
jobDependencyList.push_back(jobDependency);
}
}
AssetBuilderSDK::JobDescriptor job;
@ -137,33 +140,37 @@ namespace AZ
AssetBuilderSDK::JobProduct jobProduct;
// load the variant product assets
// load the variant product assets, for each supervariant
// these are the dependency root variant asset products that were processed prior to running this job
RPI::ShaderAssetCreator::ShaderRootVariantAssets rootVariantProductAssets;
for (AZStd::unique_ptr<RPI::RootShaderVariantAssetSourceData>& rootShaderVariantAsset : precompiledShaderAsset.m_rootShaderVariantAssets)
RPI::ShaderAssetCreator::ShaderSupervariants supervariants;
for (const auto& supervariant : precompiledShaderAsset.m_supervariants)
{
// retrieve the variant asset
auto assetOutcome = RPI::AssetUtils::LoadAsset<RPI::ShaderVariantAsset>(request.m_fullPath, rootShaderVariantAsset->m_rootShaderVariantAssetFileName, 0);
if (!assetOutcome)
RPI::ShaderAssetCreator::ShaderRootVariantAssets rootVariantProductAssets;
for (const auto& rootShaderVariantAsset : supervariant->m_rootShaderVariantAssets)
{
AZ_Error(PrecompiledShaderBuilderName, false, "Failed to retrieve Variant asset for file [%s]", rootShaderVariantAsset->m_rootShaderVariantAssetFileName.c_str());
return;
}
// retrieve the variant asset
auto assetOutcome = RPI::AssetUtils::LoadAsset<RPI::ShaderVariantAsset>(request.m_fullPath, rootShaderVariantAsset->m_rootShaderVariantAssetFileName, 0);
if (!assetOutcome)
{
AZ_Error(PrecompiledShaderBuilderName, false, "Failed to retrieve Variant asset for file [%s]", rootShaderVariantAsset->m_rootShaderVariantAssetFileName.c_str());
return;
}
rootVariantProductAssets.push_back(AZStd::make_pair(RHI::APIType{ rootShaderVariantAsset->m_apiName.GetCStr() }, assetOutcome.GetValue()));
rootVariantProductAssets.push_back(AZStd::make_pair(RHI::APIType{ rootShaderVariantAsset->m_apiName.GetCStr() }, assetOutcome.GetValue()));
AssetBuilderSDK::ProductDependency productDependency;
productDependency.m_dependencyId = assetOutcome.GetValue().GetId();
productDependency.m_flags = AZ::Data::ProductDependencyInfo::CreateFlags(AZ::Data::AssetLoadBehavior::PreLoad);
jobProduct.m_dependencies.push_back(productDependency);
}
AssetBuilderSDK::ProductDependency productDependency;
productDependency.m_dependencyId = assetOutcome.GetValue().GetId();
productDependency.m_flags = AZ::Data::ProductDependencyInfo::CreateFlags(AZ::Data::AssetLoadBehavior::PreLoad);
jobProduct.m_dependencies.push_back(productDependency);
supervariants.push_back({ supervariant->m_name, rootVariantProductAssets });
}
// use the ShaderAssetCreator to clone the shader asset, which will update the embedded Srg and Variant asset UUIDs
// Note that the Srg and Variant assets do not have embedded asset references and are processed with the RC Copy functionality
RPI::ShaderAssetCreator shaderAssetCreator;
shaderAssetCreator.Clone(Uuid::CreateRandom(),
*shaderAsset,
rootVariantProductAssets);
shaderAssetCreator.Clone(Uuid::CreateRandom(), *shaderAsset, supervariants);
Data::Asset<RPI::ShaderAsset> outputShaderAsset;
if (!shaderAssetCreator.End(outputShaderAsset))

@ -7,21 +7,28 @@
"ShaderAssetFileName": "diffuseprobegridblenddistance.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridblenddistance_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridblenddistance_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridblenddistance_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridblenddistance_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridblenddistance_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridblenddistance_null_0.azshadervariant"
}
]
}
]
}

@ -7,21 +7,28 @@
"ShaderAssetFileName": "diffuseprobegridblendirradiance.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridblendirradiance_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridblendirradiance_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridblendirradiance_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridblendirradiance_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridblendirradiance_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridblendirradiance_null_0.azshadervariant"
}
]
}
]
}

@ -5,23 +5,30 @@
"ClassData":
{
"ShaderAssetFileName": "diffuseprobegridborderupdatecolumn.azshader",
"PlatformIdentifiers":
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdatecolumn_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdatecolumn_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdatecolumn_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdatecolumn_null_0.azshadervariant"
}
]
}
]
}

@ -2,26 +2,31 @@
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PrecompiledShaderAssetSourceData",
"ClassData":
{
"ClassData": {
"ShaderAssetFileName": "diffuseprobegridborderupdaterow.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"PlatformIdentifiers": [
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdaterow_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdaterow_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdaterow_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdaterow_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdaterow_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridborderupdaterow_null_0.azshadervariant"
}
]
}
]
}

@ -7,21 +7,28 @@
"ShaderAssetFileName": "diffuseprobegridclassification.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridclassification_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridclassification_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridclassification_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridclassification_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridclassification_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridclassification_null_0.azshadervariant"
}
]
}
]
}

@ -2,27 +2,33 @@
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PrecompiledShaderAssetSourceData",
"ClassData":
"ClassData":
{
"ShaderAssetFileName": "diffuseprobegridraytracing.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"PlatformIdentifiers": [
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracing_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracing_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracing_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracing_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracing_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracing_null_0.azshadervariant"
}
]
}
]
}
}
}

@ -2,27 +2,34 @@
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PrecompiledShaderAssetSourceData",
"ClassData":
"ClassData":
{
"ShaderAssetFileName": "diffuseprobegridraytracingclosesthit.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingclosesthit_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingclosesthit_null_0.azshadervariant"
}
]
}
]
}
}
}

@ -2,26 +2,33 @@
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PrecompiledShaderAssetSourceData",
"ClassData":
"ClassData":
{
"ShaderAssetFileName": "diffuseprobegridraytracingmiss.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingmiss_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingmiss_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingmiss_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingmiss_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingmiss_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridraytracingmiss_null_0.azshadervariant"
}
]
}
]
}

@ -2,27 +2,34 @@
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PrecompiledShaderAssetSourceData",
"ClassData":
"ClassData":
{
"ShaderAssetFileName": "diffuseprobegridrelocation.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridrelocation_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridrelocation_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridrelocation_null_0.azshadervariant"
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridrelocation_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridrelocation_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridrelocation_null_0.azshadervariant"
}
]
}
]
}
}
}

@ -7,22 +7,29 @@
"ShaderAssetFileName": "diffuseprobegridrender.azshader",
"PlatformIdentifiers":
[
"pc", "linux"
"pc",
"linux"
],
"RootShaderVariantAssets":
"Supervariants":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridrender_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridrender_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridrender_null_0.azshadervariant"
}
"Name": "",
"RootShaderVariantAssets":
[
{
"APIName": "dx12",
"RootShaderVariantAssetFileName": "diffuseprobegridrender_dx12_0.azshadervariant"
},
{
"APIName": "vulkan",
"RootShaderVariantAssetFileName": "diffuseprobegridrender_vulkan_0.azshadervariant"
},
{
"APIName": "null",
"RootShaderVariantAssetFileName": "diffuseprobegridrender_null_0.azshadervariant"
}
]
}
]
}
}
}

@ -17,14 +17,14 @@ namespace AZ
namespace RPI
{
//! This asset contains is loaded from a Json file and contains information about
//! This asset is loaded from a Json file and contains information about
//! precompiled shader variants and their associated API name.
struct RootShaderVariantAssetSourceData final
struct PrecompiledRootShaderVariantAssetSourceData final
: public Data::AssetData
{
public:
AZ_RTTI(RootShaderVariantAssetSourceData, "{661EF8A7-7BAC-41B6-AD5C-C7249B2390AD}");
AZ_CLASS_ALLOCATOR(RootShaderVariantAssetSourceData, SystemAllocator, 0);
AZ_RTTI(PrecompiledRootShaderVariantAssetSourceData, "{661EF8A7-7BAC-41B6-AD5C-C7249B2390AD}");
AZ_CLASS_ALLOCATOR(PrecompiledRootShaderVariantAssetSourceData, SystemAllocator, 0);
static void Reflect(ReflectContext* context);
@ -32,7 +32,22 @@ namespace AZ
AZStd::string m_rootShaderVariantAssetFileName;
};
//! This asset contains is loaded from a Json file and contains information about
//! This asset is loaded from a Json file and contains information about
//! precompiled shader supervariants
struct PrecompiledSupervariantSourceData final
: public Data::AssetData
{
public:
AZ_RTTI(PrecompiledSupervariantSourceData, "{630BDF15-CE7C-4E2C-882E-4F7AF09C8BB6}");
AZ_CLASS_ALLOCATOR(PrecompiledSupervariantSourceData, SystemAllocator, 0);
static void Reflect(ReflectContext* context);
AZ::Name m_name;
AZStd::vector<AZStd::unique_ptr<PrecompiledRootShaderVariantAssetSourceData>> m_rootShaderVariantAssets;
};
//! This asset is loaded from a Json file and contains information about
//! precompiled shader assets.
struct PrecompiledShaderAssetSourceData final
: public Data::AssetData
@ -45,7 +60,7 @@ namespace AZ
AZStd::string m_shaderAssetFileName;
AZStd::vector<AZStd::string> m_platformIdentifiers;
AZStd::vector<AZStd::unique_ptr<RootShaderVariantAssetSourceData>> m_rootShaderVariantAssets;
AZStd::vector<AZStd::unique_ptr<PrecompiledSupervariantSourceData>> m_supervariants;
};
} // namespace RPI
} // namespace AZ

@ -75,11 +75,20 @@ namespace AZ
bool End(Data::Asset<ShaderAsset>& shaderAsset);
//! Clones an existing ShaderAsset nd replaces the referenced Srg and Variant assets
using ShaderRootVariantAssets = AZStd::vector<AZStd::pair<AZ::Crc32, Data::Asset<RPI::ShaderVariantAsset>>>;
//! Clones an existing ShaderAsset and replaces the ShaderVariant assets
using ShaderRootVariantAssetPair = AZStd::pair<AZ::Crc32, Data::Asset<RPI::ShaderVariantAsset>>;
using ShaderRootVariantAssets = AZStd::vector<ShaderRootVariantAssetPair>;
struct ShaderSupervariant
{
AZ::Name m_name;
ShaderRootVariantAssets m_rootVariantAssets;
};
using ShaderSupervariants = AZStd::vector<ShaderSupervariant>;
void Clone(const Data::AssetId& assetId,
const ShaderAsset& sourceShaderAsset,
const ShaderRootVariantAssets& rootVariantAssets);
const ShaderSupervariants& supervariants);
private:

@ -14,29 +14,43 @@ namespace AZ
{
namespace RPI
{
void RootShaderVariantAssetSourceData::Reflect(ReflectContext* context)
void PrecompiledRootShaderVariantAssetSourceData::Reflect(ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<RootShaderVariantAssetSourceData>()
serializeContext->Class<PrecompiledRootShaderVariantAssetSourceData>()
->Version(0)
->Field("APIName", &RootShaderVariantAssetSourceData::m_apiName)
->Field("RootShaderVariantAssetFileName", &RootShaderVariantAssetSourceData::m_rootShaderVariantAssetFileName)
->Field("APIName", &PrecompiledRootShaderVariantAssetSourceData::m_apiName)
->Field("RootShaderVariantAssetFileName", &PrecompiledRootShaderVariantAssetSourceData::m_rootShaderVariantAssetFileName)
;
}
}
void PrecompiledSupervariantSourceData::Reflect(ReflectContext* context)
{
PrecompiledRootShaderVariantAssetSourceData::Reflect(context);
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<PrecompiledSupervariantSourceData>()
->Version(0)
->Field("Name", &PrecompiledSupervariantSourceData::m_name)
->Field("RootShaderVariantAssets", &PrecompiledSupervariantSourceData::m_rootShaderVariantAssets)
;
}
}
void PrecompiledShaderAssetSourceData::Reflect(ReflectContext* context)
{
RootShaderVariantAssetSourceData::Reflect(context);
PrecompiledSupervariantSourceData::Reflect(context);
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<PrecompiledShaderAssetSourceData>()
->Version(1) // ATOM-15472
->Version(2) // ATOM-15740
->Field("ShaderAssetFileName", &PrecompiledShaderAssetSourceData::m_shaderAssetFileName)
->Field("PlatformIdentifiers", &PrecompiledShaderAssetSourceData::m_platformIdentifiers)
->Field("RootShaderVariantAssets", &PrecompiledShaderAssetSourceData::m_rootShaderVariantAssets)
->Field("Supervariants", &PrecompiledShaderAssetSourceData::m_supervariants)
;
}
}

@ -382,7 +382,7 @@ namespace AZ
return EndCommon(shaderAsset);
}
void ShaderAssetCreator::Clone(const Data::AssetId& assetId, const ShaderAsset& sourceShaderAsset, [[maybe_unused]] const ShaderRootVariantAssets& rootVariantAssets)
void ShaderAssetCreator::Clone(const Data::AssetId& assetId, const ShaderAsset& sourceShaderAsset, [[maybe_unused]] const ShaderSupervariants& supervariants)
{
BeginCommon(assetId);
@ -392,38 +392,60 @@ namespace AZ
m_asset->m_shaderOptionGroupLayout = sourceShaderAsset.m_shaderOptionGroupLayout;
m_asset->m_buildTimestamp = sourceShaderAsset.m_buildTimestamp;
// copy root variant assets
// copy the perAPIShaderData
for (auto& perAPIShaderData : sourceShaderAsset.m_perAPIShaderData)
{
// find the matching ShaderVariantAsset
AZ::Data::Asset<ShaderVariantAsset> foundVariantAsset;
for (const auto& variantAsset : rootVariantAssets)
if (perAPIShaderData.m_supervariants.empty())
{
if (variantAsset.first == perAPIShaderData.m_APIType)
{
foundVariantAsset = variantAsset.second;
break;
}
ReportWarning("Attempting to clone a shader asset that has no supervariants for API [%d]", perAPIShaderData.m_APIType);
continue;
}
if (!foundVariantAsset)
if (perAPIShaderData.m_supervariants.size() != supervariants.size())
{
ReportWarning("Failed to find variant asset for API [%d]", perAPIShaderData.m_APIType);
ReportError("Incorrect number of supervariants provided to ShaderAssetCreator::Clone");
return;
}
m_asset->m_perAPIShaderData.push_back(perAPIShaderData);
if (m_asset->m_perAPIShaderData.back().m_supervariants.empty())
{
ReportWarning("Attempting to clone a shader asset that has no supervariants for API [%d]", perAPIShaderData.m_APIType);
}
else
// set the supervariants for this API
for (auto& supervariant : m_asset->m_perAPIShaderData.back().m_supervariants)
{
// currently we only support one supervariant when cloning
// [GFX TODO][ATOM-15740] Support multiple supervariants in ShaderAssetCreator::Clone
m_asset->m_perAPIShaderData.back().m_supervariants[0].m_rootShaderVariantAsset = foundVariantAsset;
// find the matching Supervariant by name from the incoming list
ShaderSupervariants::const_iterator itFoundSuperVariant = AZStd::find_if(
supervariants.begin(),
supervariants.end(),
[&supervariant](const ShaderSupervariant& shaderSupervariant)
{
return supervariant.m_name == shaderSupervariant.m_name;
});
if (itFoundSuperVariant == supervariants.end())
{
ReportError("Failed to find supervariant [%s]", supervariant.m_name.GetCStr());
return;
}
// find the matching ShaderVariantAsset for this API
ShaderRootVariantAssets::const_iterator itFoundRootShaderVariantAsset = AZStd::find_if(
itFoundSuperVariant->m_rootVariantAssets.begin(),
itFoundSuperVariant->m_rootVariantAssets.end(),
[&perAPIShaderData](const ShaderRootVariantAssetPair& rootShaderVariantAsset)
{
return perAPIShaderData.m_APIType == rootShaderVariantAsset.first;
});
if (itFoundRootShaderVariantAsset == itFoundSuperVariant->m_rootVariantAssets.end())
{
ReportWarning("Failed to find root shader variant asset for API [%d] Supervariant [%s]", perAPIShaderData.m_APIType, supervariant.m_name.GetCStr());
}
else
{
supervariant.m_rootShaderVariantAsset = itFoundRootShaderVariantAsset->second;
}
}
}
}
} // namespace RPI
} // namespace AZ

@ -9,17 +9,14 @@
#pragma once
#if !defined(Q_MOC_RUN)
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QByteArray>
#include <QWidget>
AZ_POP_DISABLE_WARNING
#endif
namespace AzToolsFramework
@ -27,49 +24,50 @@ namespace AzToolsFramework
namespace AssetBrowser
{
class AssetBrowserFilterModel;
class CompositeFilter;
class AssetBrowserEntry;
class ProductAssetBrowserEntry;
class SourceAssetBrowserEntry;
}
}
} // namespace AzToolsFramework
namespace Ui
{
class MaterialBrowserWidget;
class AtomToolsAssetBrowser;
}
namespace MaterialEditor
namespace AtomToolsFramework
{
//! Provides a tree view of all available materials and other assets exposed by the MaterialEditor.
class MaterialBrowserWidget
//! Extends the standard asset browser with custom filters and multiselect behavior
class AtomToolsAssetBrowser
: public QWidget
, protected AZ::TickBus::Handler
, protected AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
{
Q_OBJECT
public:
MaterialBrowserWidget(QWidget* parent = nullptr);
~MaterialBrowserWidget();
AtomToolsAssetBrowser(QWidget* parent = nullptr);
~AtomToolsAssetBrowser();
private:
AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const;
void SetFilterState(const AZStd::string& category, const AZStd::string& displayName, bool enabled);
void SetOpenHandler(AZStd::function<void(const AZStd::string&)> openHandler);
void SelectEntries(const AZStd::string& absolutePath);
void OpenSelectedEntries();
void OpenOptionsMenu();
// AtomToolsDocumentNotificationBus::Handler implementation
void OnDocumentOpened(const AZ::Uuid& documentId) override;
protected:
AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const;
void UpdateFilter();
void UpdatePreview();
void TogglePreview();
// AZ::TickBus::Handler
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
void OpenOptionsMenu();
QScopedPointer<Ui::MaterialBrowserWidget> m_ui;
QScopedPointer<Ui::AtomToolsAssetBrowser> m_ui;
AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* m_filterModel = nullptr;
//! if new asset is being created with this path it will automatically be selected
//! If an asset is opened with this path it will automatically be selected
AZStd::string m_pathToSelect;
QByteArray m_materialBrowserState;
QByteArray m_browserState;
AZStd::function<void(const AZStd::string&)> m_openHandler;
};
} // namespace MaterialEditor
} // namespace AtomToolsFramework

@ -0,0 +1,28 @@
/*
* 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 <AtomToolsFramework/Application/AtomToolsApplication.h>
namespace AtomToolsFramework
{
class AtomToolsDocumentApplication
: public AtomToolsApplication
{
public:
AZ_TYPE_INFO(AtomToolsDocumentApplication, "{F4B43677-EB95-4CBB-8B8E-9EF4247E6F0D}");
using Base = AtomToolsApplication;
AtomToolsDocumentApplication(int* argc, char*** argv);
// AtomToolsApplication overrides...
void ProcessCommandLine(const AZ::CommandLine& commandLine) override;
};
} // namespace AtomToolsFramework

@ -38,5 +38,5 @@ namespace AtomToolsFramework
QFileInfo GetOpenFileInfo(const AZStd::vector<AZ::Data::AssetType>& assetTypes);
QFileInfo GetUniqueFileInfo(const QString& initialPath);
QFileInfo GetDuplicationFileInfo(const QString& initialPath);
bool LaunchTool(const QString& baseName, const QString& extension, const QStringList& arguments);
bool LaunchTool(const QString& baseName, const QStringList& arguments);
} // namespace AtomToolsFramework

@ -8,6 +8,7 @@
#pragma once
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h>
#include <AtomToolsFramework/Window/AtomToolsMainWindowRequestBus.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzQtComponents/Components/DockMainWindow.h>
@ -53,6 +54,8 @@ namespace AtomToolsFramework
QMenu* m_menuView = {};
QMenu* m_menuHelp = {};
AtomToolsFramework::AtomToolsAssetBrowser* m_assetBrowser = {};
AZStd::unordered_map<AZStd::string, AzQtComponents::StyledDockWidget*> m_dockWidgets;
AZStd::unordered_map<AZStd::string, QAction*> m_dockActions;
};

@ -6,13 +6,9 @@
*
*/
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AssetBrowser/ui_AtomToolsAssetBrowser.h>
#include <AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
@ -21,41 +17,32 @@
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
#include <Window/MaterialBrowserWidget.h>
#include <Window/ui_MaterialBrowserWidget.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QAction>
#include <QByteArray>
#include <QCursor>
#include <QDesktopServices>
#include <QList>
#include <QMenu>
#include <QMessageBox>
#include <QPushButton>
#include <QUrl>
AZ_POP_DISABLE_WARNING
namespace MaterialEditor
namespace AtomToolsFramework
{
MaterialBrowserWidget::MaterialBrowserWidget(QWidget* parent)
AtomToolsAssetBrowser::AtomToolsAssetBrowser(QWidget* parent)
: QWidget(parent)
, m_ui(new Ui::MaterialBrowserWidget)
, m_ui(new Ui::AtomToolsAssetBrowser)
{
using namespace AzToolsFramework::AssetBrowser;
m_ui->setupUi(this);
m_ui->m_searchWidget->Setup(true, true);
m_ui->m_searchWidget->SetFilterState("", AZ::RPI::StreamingImageAsset::Group, true);
m_ui->m_searchWidget->SetFilterState("", AZ::RPI::MaterialAsset::Group, true);
m_ui->m_searchWidget->setMinimumSize(QSize(150, 0));
m_ui->m_viewOptionButton->setIcon(QIcon(":/Icons/View.svg"));
m_ui->m_viewOptionButton->setIcon(QIcon(":/Icons/view.svg"));
m_ui->m_splitter->setSizes(QList<int>() << 400 << 200);
m_ui->m_splitter->setStretchFactor(0, 1);
connect(m_ui->m_viewOptionButton, &QPushButton::clicked, this, &MaterialBrowserWidget::OpenOptionsMenu);
// Get the asset browser model
AssetBrowserModel* assetBrowserModel = nullptr;
AssetBrowserComponentRequestBus::BroadcastResult(assetBrowserModel, &AssetBrowserComponentRequests::GetAssetBrowserModel);
@ -73,38 +60,82 @@ namespace MaterialEditor
// Maintains the tree expansion state between runs
m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_main");
connect(m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel, &AssetBrowserFilterModel::filterUpdatedSlot);
connect(m_filterModel, &AssetBrowserFilterModel::filterChanged, this, [this]()
connect(m_filterModel, &AssetBrowserFilterModel::filterChanged, this, &AtomToolsAssetBrowser::UpdateFilter);
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::activated, this, &AtomToolsAssetBrowser::OpenSelectedEntries);
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, this, &AtomToolsAssetBrowser::UpdatePreview);
connect(m_ui->m_viewOptionButton, &QPushButton::clicked, this, &AtomToolsAssetBrowser::OpenOptionsMenu);
connect(
m_ui->m_searchWidget->GetFilter().data(), &AssetBrowserEntryFilter::updatedSignal, m_filterModel,
&AssetBrowserFilterModel::filterUpdatedSlot);
}
AtomToolsAssetBrowser::~AtomToolsAssetBrowser()
{
// Maintains the tree expansion state between runs
m_ui->m_assetBrowserTreeViewWidget->SaveState();
AZ::TickBus::Handler::BusDisconnect();
}
void AtomToolsAssetBrowser::SetFilterState(const AZStd::string& category, const AZStd::string& displayName, bool enabled)
{
m_ui->m_searchWidget->SetFilterState(category.c_str(), displayName.c_str(), enabled);
}
void AtomToolsAssetBrowser::SetOpenHandler(AZStd::function<void(const AZStd::string&)> openHandler)
{
m_openHandler = openHandler;
}
void AtomToolsAssetBrowser::SelectEntries(const AZStd::string& absolutePath)
{
if (!absolutePath.empty())
{
const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty();
constexpr bool selectFirstFilteredIndex = true;
m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex);
});
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::activated, this, &MaterialBrowserWidget::OpenSelectedEntries);
connect(m_ui->m_assetBrowserTreeViewWidget, &AssetBrowserTreeView::selectionChangedSignal, [this]() {
const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
if (!selectedAssets.empty())
// Selecting a new asset in the browser is not guaranteed to happen immediately.
// The asset browser model notifications are sent before the model is updated.
// Instead of relying on the notifications, queue the selection and process it on tick until this change occurs.
m_pathToSelect = absolutePath;
AzFramework::StringFunc::Path::Normalize(m_pathToSelect);
AZ::TickBus::Handler::BusConnect();
}
}
void AtomToolsAssetBrowser::OpenSelectedEntries()
{
const AZStd::vector<AssetBrowserEntry*> entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
const int multiSelectPromptThreshold = 10;
if (entries.size() >= multiSelectPromptThreshold)
{
QMessageBox::StandardButton result = QMessageBox::question(
QApplication::activeWindow(),
tr("Attemptng to open %1 files").arg(entries.size()),
tr("Would you like to open anyway?"),
QMessageBox::Yes | QMessageBox::No);
if (result == QMessageBox::No)
{
m_ui->m_previewerFrame->Display(selectedAssets.front());
return;
}
else
}
for (const AssetBrowserEntry* entry : entries)
{
if (entry && entry->GetEntryType() != AssetBrowserEntry::AssetEntryType::Folder && m_openHandler)
{
m_ui->m_previewerFrame->Clear();
m_openHandler(entry->GetFullPath().c_str());
}
});
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect();
}
}
MaterialBrowserWidget::~MaterialBrowserWidget()
void AtomToolsAssetBrowser::OpenOptionsMenu()
{
// Maintains the tree expansion state between runs
m_ui->m_assetBrowserTreeViewWidget->SaveState();
AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect();
QMenu menu;
QAction* action = menu.addAction(tr("Show Asset Preview"), this, &AtomToolsAssetBrowser::TogglePreview);
action->setCheckable(true);
action->setChecked(m_ui->m_previewerFrame->isVisible());
menu.exec(QCursor::pos());
}
AzToolsFramework::AssetBrowser::FilterConstType MaterialBrowserWidget::CreateFilter() const
AzToolsFramework::AssetBrowser::FilterConstType AtomToolsAssetBrowser::CreateFilter() const
{
using namespace AzToolsFramework::AssetBrowser;
@ -125,59 +156,42 @@ namespace MaterialEditor
return finalFilter;
}
void MaterialBrowserWidget::OpenSelectedEntries()
void AtomToolsAssetBrowser::UpdateFilter()
{
const AZStd::vector<AssetBrowserEntry*> entries = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
const bool hasFilter = !m_ui->m_searchWidget->GetFilterString().isEmpty();
constexpr bool selectFirstFilteredIndex = true;
m_ui->m_assetBrowserTreeViewWidget->UpdateAfterFilter(hasFilter, selectFirstFilteredIndex);
}
const int multiSelectPromptThreshold = 10;
if (entries.size() >= multiSelectPromptThreshold)
void AtomToolsAssetBrowser::UpdatePreview()
{
const auto& selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
if (!selectedAssets.empty())
{
if (QMessageBox::question(
QApplication::activeWindow(),
QString("Attemptng to open %1 files").arg(entries.size()),
"Would you like to open anyway?",
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
{
return;
}
m_ui->m_previewerFrame->Display(selectedAssets.front());
}
for (const AssetBrowserEntry* entry : entries)
else
{
if (entry)
{
if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialSourceData::Extension))
{
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath());
}
else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), AZ::RPI::MaterialTypeSourceData::Extension))
{
//ignore AZ::RPI::MaterialTypeSourceData::Extension
}
else
{
QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str()));
}
}
m_ui->m_previewerFrame->Clear();
}
}
void MaterialBrowserWidget::OnDocumentOpened(const AZ::Uuid& documentId)
void AtomToolsAssetBrowser::TogglePreview()
{
AZStd::string absolutePath;
AtomToolsFramework::AtomToolsDocumentRequestBus::EventResult(absolutePath, documentId, &AtomToolsFramework::AtomToolsDocumentRequestBus::Events::GetAbsolutePath);
if (!absolutePath.empty())
const bool isPreviewFrameVisible = m_ui->m_previewerFrame->isVisible();
m_ui->m_previewerFrame->setVisible(!isPreviewFrameVisible);
if (isPreviewFrameVisible)
{
// Selecting a new asset in the browser is not guaranteed to happen immediately.
// The asset browser model notifications are sent before the model is updated.
// Instead of relying on the notifications, queue the selection and process it on tick until this change occurs.
m_pathToSelect = absolutePath;
AzFramework::StringFunc::Path::Normalize(m_pathToSelect);
AZ::TickBus::Handler::BusConnect();
m_browserState = m_ui->m_splitter->saveState();
m_ui->m_splitter->setSizes(QList({ 1, 0 }));
}
else
{
m_ui->m_splitter->restoreState(m_browserState);
}
}
void MaterialBrowserWidget::OnTick(float deltaTime, AZ::ScriptTimePoint time)
void AtomToolsAssetBrowser::OnTick(float deltaTime, AZ::ScriptTimePoint time)
{
AZ_UNUSED(time);
AZ_UNUSED(deltaTime);
@ -188,7 +202,7 @@ namespace MaterialEditor
AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(
&AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Events::SelectFileAtPath, m_pathToSelect);
// Iterate over the selected entries to verify if the selection was made
// Iterate over the selected entries to verify if the selection was made
for (const AssetBrowserEntry* entry : m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets())
{
if (entry)
@ -205,31 +219,6 @@ namespace MaterialEditor
}
}
}
} // namespace AtomToolsFramework
void MaterialBrowserWidget::OpenOptionsMenu()
{
QMenu menu;
QAction* action = new QAction("Show Asset Preview", this);
action->setCheckable(true);
action->setChecked(m_ui->m_previewerFrame->isVisible());
connect(action, &QAction::triggered, [this]() {
bool isPreviewFrameVisible = m_ui->m_previewerFrame->isVisible();
m_ui->m_previewerFrame->setVisible(!isPreviewFrameVisible);
if (isPreviewFrameVisible)
{
m_materialBrowserState = m_ui->m_splitter->saveState();
m_ui->m_splitter->setSizes(QList({ 1, 0 }));
}
else
{
m_ui->m_splitter->restoreState(m_materialBrowserState);
}
});
menu.addAction(action);
menu.exec(QCursor::pos());
}
} // namespace MaterialEditor
#include <Window/moc_MaterialBrowserWidget.cpp>
#include <AtomToolsFramework/AssetBrowser/moc_AtomToolsAssetBrowser.cpp>

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>Icons/view.svg</file>
</qresource>
</RCC>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MaterialBrowserWidget</class>
<widget class="QWidget" name="MaterialBrowserWidget">
<class>AtomToolsAssetBrowser</class>
<widget class="QWidget" name="AtomToolsAssetBrowser">
<property name="geometry">
<rect>
<x>0</x>

@ -0,0 +1,33 @@
/*
* 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 <AtomToolsFramework/Document/AtomToolsDocumentApplication.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
namespace AtomToolsFramework
{
AtomToolsDocumentApplication::AtomToolsDocumentApplication(int* argc, char*** argv)
: Base(argc, argv)
{
}
void AtomToolsDocumentApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{
// Process command line options for opening documents on startup
size_t openDocumentCount = commandLine.GetNumMiscValues();
for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex)
{
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str());
AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
}
Base::ProcessCommandLine(commandLine);
}
} // namespace AtomToolsFramework

@ -414,6 +414,8 @@ namespace AtomToolsFramework
m_actionPreviousTab->setEnabled(m_tabWidget->count() > 1);
m_actionNextTab->setEnabled(m_tabWidget->count() > 1);
m_assetBrowser->SelectEntries(absolutePath);
activateWindow();
raise();

@ -168,13 +168,13 @@ namespace AtomToolsFramework
return duplicateFileInfo;
}
bool LaunchTool(const QString& baseName, const QString& extension, const QStringList& arguments)
bool LaunchTool(const QString& baseName, const QStringList& arguments)
{
AZ::IO::FixedMaxPath engineRoot = AZ::Utils::GetEnginePath();
AZ_Assert(!engineRoot.empty(), "Cannot query Engine Path");
AZ::IO::FixedMaxPath launchPath = AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory())
/ (baseName + extension).toUtf8().constData();
AZ::IO::FixedMaxPath launchPath =
AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) / (baseName + AZ_TRAIT_OS_EXECUTABLE_EXTENSION).toUtf8().constData();
return QProcess::startDetached(launchPath.c_str(), arguments, engineRoot.c_str());
}

@ -8,6 +8,7 @@
#include <AtomToolsFramework/Window/AtomToolsMainWindow.h>
#include <AzToolsFramework/API/EditorPythonRunnerRequestsBus.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <QFileDialog>
#include <QMenu>
@ -40,6 +41,11 @@ namespace AtomToolsFramework
centralWidget->setLayout(centralWidgetLayout);
setCentralWidget(centralWidget);
m_assetBrowser = new AtomToolsFramework::AtomToolsAssetBrowser(this);
AddDockWidget("Asset Browser", m_assetBrowser, Qt::BottomDockWidgetArea, Qt::Horizontal);
AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
SetDockWidgetVisible("Python Terminal", false);
AtomToolsMainWindowRequestBus::Handler::BusConnect();
}

@ -8,10 +8,12 @@
set(FILES
Include/AtomToolsFramework/Application/AtomToolsApplication.h
Include/AtomToolsFramework/AssetBrowser/AtomToolsAssetBrowser.h
Include/AtomToolsFramework/Communication/LocalServer.h
Include/AtomToolsFramework/Communication/LocalSocket.h
Include/AtomToolsFramework/Debug/TraceRecorder.h
Include/AtomToolsFramework/Document/AtomToolsDocument.h
Include/AtomToolsFramework/Document/AtomToolsDocumentApplication.h
Include/AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemSettings.h
Include/AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h
@ -36,10 +38,14 @@ set(FILES
Include/AtomToolsFramework/Window/AtomToolsMainWindowFactoryRequestBus.h
Include/AtomToolsFramework/Window/AtomToolsMainWindowNotificationBus.h
Source/Application/AtomToolsApplication.cpp
Source/AssetBrowser/AtomToolsAssetBrowser.cpp
Source/AssetBrowser/AtomToolsAssetBrowser.qrc
Source/AssetBrowser/AtomToolsAssetBrowser.ui
Source/Communication/LocalServer.cpp
Source/Communication/LocalSocket.cpp
Source/Debug/TraceRecorder.cpp
Source/Document/AtomToolsDocument.cpp
Source/Document/AtomToolsDocumentApplication.cpp
Source/Document/AtomToolsDocumentMainWindow.cpp
Source/Document/AtomToolsDocumentSystemSettings.cpp
Source/Document/AtomToolsDocumentSystemComponent.cpp

@ -9,7 +9,6 @@
#include <Atom/Document/MaterialDocumentModule.h>
#include <Atom/Viewport/MaterialViewportModule.h>
#include <Atom/Window/MaterialEditorWindowModule.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <MaterialEditorApplication.h>
#include <MaterialEditor_Traits_Platform.h>
@ -37,7 +36,7 @@ namespace MaterialEditor
}
MaterialEditorApplication::MaterialEditorApplication(int* argc, char*** argv)
: AtomToolsApplication(argc, argv)
: Base(argc, argv)
{
QApplication::setApplicationName("O3DE Material Editor");
@ -58,19 +57,4 @@ namespace MaterialEditor
{
return AZStd::vector<AZStd::string>({ "passes/", "config/", "MaterialEditor/" });
}
void MaterialEditorApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{
// Process command line options for opening one or more material documents on startup
size_t openDocumentCount = commandLine.GetNumMiscValues();
for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex)
{
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
}
Base::ProcessCommandLine(commandLine);
}
} // namespace MaterialEditor

@ -8,30 +8,27 @@
#pragma once
#include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h>
namespace MaterialEditor
{
class MaterialThumbnailRenderer;
class MaterialEditorApplication
: public AtomToolsFramework::AtomToolsApplication
: public AtomToolsFramework::AtomToolsDocumentApplication
{
public:
AZ_TYPE_INFO(MaterialEditor::MaterialEditorApplication, "{30F90CA5-1253-49B5-8143-19CEE37E22BB}");
using Base = AtomToolsFramework::AtomToolsApplication;
using Base = AtomToolsFramework::AtomToolsDocumentApplication;
MaterialEditorApplication(int* argc, char*** argv);
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application
// AzFramework::Application overrides...
void CreateStaticModules(AZStd::vector<AZ::Module*>& outModules) override;
const char* GetCurrentConfigurationName() const override;
private:
void ProcessCommandLine(const AZ::CommandLine& commandLine) override;
// AtomToolsFramework::AtomToolsApplication overrides...
AZStd::string GetBuildTargetName() const override;
AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override;
};

@ -21,6 +21,5 @@
<file>Icons/shadow.svg</file>
<file>Icons/skybox.svg</file>
<file>Icons/toneMapping.svg</file>
<file>Icons/View.svg</file>
</qresource>
</RCC>

@ -8,15 +8,16 @@
#include <Atom/Document/MaterialDocumentRequestBus.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RPI.Edit/Material/MaterialSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/Window/MaterialEditorWindowSettings.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <Viewport/MaterialViewportWidget.h>
#include <Window/CreateMaterialDialog/CreateMaterialDialog.h>
#include <Window/HelpDialog/HelpDialog.h>
#include <Window/MaterialBrowserWidget.h>
#include <Window/MaterialEditorWindow.h>
#include <Window/MaterialInspector/MaterialInspector.h>
#include <Window/PerformanceMonitor/PerformanceMonitorWidget.h>
@ -27,14 +28,16 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnin
#include <QApplication>
#include <QByteArray>
#include <QCloseEvent>
#include <QDesktopServices>
#include <QFileDialog>
#include <QUrl>
#include <QWindow>
AZ_POP_DISABLE_WARNING
namespace MaterialEditor
{
MaterialEditorWindow::MaterialEditorWindow(QWidget* parent /* = 0 */)
: AtomToolsFramework::AtomToolsDocumentMainWindow(parent)
: Base(parent)
{
resize(1280, 1024);
@ -72,15 +75,30 @@ namespace MaterialEditor
m_materialViewport->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
centralWidget()->layout()->addWidget(m_materialViewport);
AddDockWidget("Asset Browser", new MaterialBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical);
AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Horizontal);
AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Horizontal);
AddDockWidget("Performance Monitor", new PerformanceMonitorWidget, Qt::RightDockWidgetArea, Qt::Horizontal);
AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
m_assetBrowser->SetFilterState("", AZ::RPI::StreamingImageAsset::Group, true);
m_assetBrowser->SetFilterState("", AZ::RPI::MaterialAsset::Group, true);
m_assetBrowser->SetOpenHandler([](const AZStd::string& absolutePath) {
if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::MaterialSourceData::Extension))
{
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath);
return;
}
if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::MaterialTypeSourceData::Extension))
{
return;
}
QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str()));
});
AddDockWidget("Inspector", new MaterialInspector, Qt::RightDockWidgetArea, Qt::Vertical);
AddDockWidget("Viewport Settings", new ViewportSettingsInspector, Qt::LeftDockWidgetArea, Qt::Vertical);
AddDockWidget("Performance Monitor", new PerformanceMonitorWidget, Qt::BottomDockWidgetArea, Qt::Horizontal);
SetDockWidgetVisible("Viewport Settings", false);
SetDockWidgetVisible("Performance Monitor", false);
SetDockWidgetVisible("Python Terminal", false);
// Restore geometry and show the window
mainWindowWrapper->showFromSettings();

@ -21,7 +21,6 @@ namespace MaterialEditor
{
//! MaterialEditorWindow is the main class. Its responsibility is limited to initializing and connecting
//! its panels, managing selection of assets, and performing high-level actions like saving. It contains...
//! 1) MaterialBrowser - The user browses for Material (.material) assets.
//! 2) MaterialViewport - The user can see the selected Material applied to a model.
//! 3) MaterialPropertyInspector - The user edits the properties of the selected Material.
class MaterialEditorWindow
@ -48,7 +47,7 @@ namespace MaterialEditor
void closeEvent(QCloseEvent* closeEvent) override;
MaterialViewportWidget* m_materialViewport = nullptr;
MaterialEditorToolBar* m_toolBar = nullptr;
MaterialViewportWidget* m_materialViewport = {};
MaterialEditorToolBar* m_toolBar = {};
};
} // namespace MaterialEditor

@ -14,6 +14,7 @@ void InitMaterialEditorResources()
//Must register qt resources from other modules
Q_INIT_RESOURCE(MaterialEditor);
Q_INIT_RESOURCE(InspectorWidget);
Q_INIT_RESOURCE(AtomToolsAssetBrowser);
}
namespace MaterialEditor

@ -15,9 +15,6 @@ set(FILES
Source/Window/MaterialEditorWindow.cpp
Source/Window/MaterialEditorWindowModule.cpp
Source/Window/MaterialEditorWindowSettings.cpp
Source/Window/MaterialBrowserWidget.h
Source/Window/MaterialBrowserWidget.cpp
Source/Window/MaterialBrowserWidget.ui
Source/Window/MaterialEditor.qrc
Source/Window/MaterialEditor.qss
Source/Window/MaterialEditorWindowComponent.h

@ -42,7 +42,6 @@ ly_add_target(
NAME ShaderManagementConsole.Window STATIC
NAMESPACE Gem
AUTOMOC
AUTOUIC
AUTORCC
FILES_CMAKE
shadermanagementconsolewindow_files.cmake

@ -8,7 +8,6 @@
#include <Atom/Document/ShaderManagementConsoleDocumentModule.h>
#include <Atom/Window/ShaderManagementConsoleWindowModule.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <ShaderManagementConsoleApplication.h>
#include <ShaderManagementConsole_Traits_Platform.h>
@ -36,7 +35,7 @@ namespace ShaderManagementConsole
}
ShaderManagementConsoleApplication::ShaderManagementConsoleApplication(int* argc, char*** argv)
: AtomToolsApplication(argc, argv)
: Base(argc, argv)
{
QApplication::setApplicationName("O3DE Shader Management Console");
@ -56,20 +55,4 @@ namespace ShaderManagementConsole
{
return AZStd::vector<AZStd::string>({ "passes/", "config/" });
}
void ShaderManagementConsoleApplication::ProcessCommandLine(const AZ::CommandLine& commandLine)
{
// Process command line options for opening one or more documents on startup
size_t openDocumentCount = commandLine.GetNumMiscValues();
for (size_t openDocumentIndex = 0; openDocumentIndex < openDocumentCount; ++openDocumentIndex)
{
const AZStd::string openDocumentPath = commandLine.GetMiscValue(openDocumentIndex);
AZ_Printf(GetBuildTargetName().c_str(), "Opening document: %s", openDocumentPath.c_str());
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, openDocumentPath);
}
Base::ProcessCommandLine(commandLine);
}
} // namespace ShaderManagementConsole

@ -8,28 +8,25 @@
#pragma once
#include <AtomToolsFramework/Application/AtomToolsApplication.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentApplication.h>
namespace ShaderManagementConsole
{
class ShaderManagementConsoleApplication
: public AtomToolsFramework::AtomToolsApplication
: public AtomToolsFramework::AtomToolsDocumentApplication
{
public:
AZ_TYPE_INFO(ShaderManagementConsole::ShaderManagementConsoleApplication, "{A31B1AEB-4DA3-49CD-884A-CC998FF7546F}");
using Base = AtomToolsFramework::AtomToolsApplication;
using Base = AtomToolsFramework::AtomToolsDocumentApplication;
ShaderManagementConsoleApplication(int* argc, char*** argv);
//////////////////////////////////////////////////////////////////////////
// AzFramework::Application
// AzFramework::Application overrides...
void CreateStaticModules(AZStd::vector<AZ::Module*>& outModules) override;
const char* GetCurrentConfigurationName() const override;
private:
void ProcessCommandLine(const AZ::CommandLine& commandLine);
// AtomToolsFramework::AtomToolsApplication overrides...
AZStd::string GetBuildTargetName() const override;
AZStd::vector<AZStd::string> GetCriticalAssetFilters() const override;
};

@ -1,69 +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
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AtomToolsFramework/Document/AtomToolsDocumentNotificationBus.h>
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
#include <AzToolsFramework/AssetBrowser/Entries/AssetBrowserEntry.h>
#include <AzToolsFramework/AssetBrowser/Search/Filter.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QWidget>
AZ_POP_DISABLE_WARNING
#endif
namespace AzToolsFramework
{
namespace AssetBrowser
{
class AssetBrowserFilterModel;
class CompositeFilter;
class AssetBrowserEntry;
class ProductAssetBrowserEntry;
class SourceAssetBrowserEntry;
}
}
namespace Ui
{
class ShaderManagementConsoleBrowserWidget;
}
namespace ShaderManagementConsole
{
//! Provides a tree view of all available assets
class ShaderManagementConsoleBrowserWidget
: public QWidget
, public AzToolsFramework::AssetBrowser::AssetBrowserModelNotificationBus::Handler
, public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler
{
Q_OBJECT
public:
ShaderManagementConsoleBrowserWidget(QWidget* parent = nullptr);
~ShaderManagementConsoleBrowserWidget();
private:
AzToolsFramework::AssetBrowser::FilterConstType CreateFilter() const;
void OpenSelectedEntries();
QScopedPointer<Ui::ShaderManagementConsoleBrowserWidget> m_ui;
AzToolsFramework::AssetBrowser::AssetBrowserFilterModel* m_filterModel = nullptr;
//! if new asset is being created with this path it will automatically be selected
AZStd::string m_pathToSelect;
// AssetBrowserModelNotificationBus::Handler implementation
void EntryAdded(const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) override;
// AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler implementation
void OnDocumentOpened(const AZ::Uuid& documentId) override;
};
} // namespace ShaderManagementConsole

@ -1,168 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ShaderManagementConsoleBrowserWidget</class>
<widget class="QWidget" name="ShaderManagementConsoleBrowserWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>691</width>
<height>554</height>
</rect>
</property>
<property name="windowTitle">
<string>Asset Browser</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="minimumSize">
<size>
<width>1</width>
<height>1</height>
</size>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>671</width>
<height>534</height>
</rect>
</property>
<layout class="QVBoxLayout" name="scrollAreaVerticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="m_headerLayout">
<item>
<widget class="AzToolsFramework::AssetBrowser::SearchWidget" name="m_searchWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="m_splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QWidget" name="m_leftLayout" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">vertical-align: top</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="AzToolsFramework::AssetBrowser::AssetBrowserTreeView" name="m_assetBrowserTreeViewWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="previewWidgetWrapper">
<layout class="QVBoxLayout" name="m_rightLayout">
<item>
<widget class="AzToolsFramework::AssetBrowser::PreviewerFrame" name="m_previewerFrame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AzToolsFramework::AssetBrowser::SearchWidget</class>
<extends>QWidget</extends>
<header>AzToolsFramework/AssetBrowser/Search/SearchWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>AzToolsFramework::AssetBrowser::AssetBrowserTreeView</class>
<extends>QTreeView</extends>
<header>AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h</header>
</customwidget>
<customwidget>
<class>AzToolsFramework::AssetBrowser::PreviewerFrame</class>
<extends>QFrame</extends>
<header>AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

@ -7,23 +7,25 @@
*/
#include <Atom/Document/ShaderManagementConsoleDocumentRequestBus.h>
#include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
#include <AtomToolsFramework/Util/Util.h>
#include <AzCore/Name/Name.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <Window/ShaderManagementConsoleWindow.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QDesktopServices>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QTableView>
#include <QUrl>
#include <QWindow>
AZ_POP_DISABLE_WARNING
namespace ShaderManagementConsole
{
ShaderManagementConsoleWindow::ShaderManagementConsoleWindow(QWidget* parent /* = 0 */)
: AtomToolsFramework::AtomToolsDocumentMainWindow(parent)
: Base(parent)
{
resize(1280, 1024);
@ -41,10 +43,17 @@ namespace ShaderManagementConsole
m_toolBar->setObjectName("ToolBar");
addToolBar(m_toolBar);
AddDockWidget("Asset Browser", new ShaderManagementConsoleBrowserWidget, Qt::BottomDockWidgetArea, Qt::Vertical);
AddDockWidget("Python Terminal", new AzToolsFramework::CScriptTermDialog, Qt::BottomDockWidgetArea, Qt::Horizontal);
m_assetBrowser->SetFilterState("", AZ::RPI::ShaderAsset::Group, true);
m_assetBrowser->SetOpenHandler([](const AZStd::string& absolutePath) {
if (AzFramework::StringFunc::Path::IsExtension(absolutePath.c_str(), AZ::RPI::ShaderVariantListSourceData::Extension))
{
AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Broadcast(
&AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Events::OpenDocument, absolutePath);
return;
}
SetDockWidgetVisible("Python Terminal", false);
QDesktopServices::openUrl(QUrl::fromLocalFile(absolutePath.c_str()));
});
// Restore geometry and show the window
mainWindowWrapper->showFromSettings();

@ -14,9 +14,7 @@
#include <AtomToolsFramework/Document/AtomToolsDocumentMainWindow.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <Window/ShaderManagementConsoleBrowserWidget.h>
#include <Window/ToolBar/ShaderManagementConsoleToolBar.h>
#include <QStandardItemModel>
AZ_POP_DISABLE_WARNING
#endif
@ -40,6 +38,6 @@ namespace ShaderManagementConsole
protected:
QWidget* CreateDocumentTabView(const AZ::Uuid& documentId) override;
ShaderManagementConsoleToolBar* m_toolBar = nullptr;
ShaderManagementConsoleToolBar* m_toolBar = {};
};
} // namespace ShaderManagementConsole

@ -9,10 +9,20 @@
#include <Atom/Window/ShaderManagementConsoleWindowModule.h>
#include <Window/ShaderManagementConsoleWindowComponent.h>
void InitShaderManagementConsoleResources()
{
// Must register qt resources from other modules
Q_INIT_RESOURCE(ShaderManagementConsole);
Q_INIT_RESOURCE(InspectorWidget);
Q_INIT_RESOURCE(AtomToolsAssetBrowser);
}
namespace ShaderManagementConsole
{
ShaderManagementConsoleWindowModule::ShaderManagementConsoleWindowModule()
{
InitShaderManagementConsoleResources();
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
m_descriptors.insert(m_descriptors.end(), {
ShaderManagementConsoleWindowComponent::CreateDescriptor(),
@ -25,4 +35,4 @@ namespace ShaderManagementConsole
azrtti_typeid<ShaderManagementConsoleWindowComponent>(),
};
}
}
} // namespace ShaderManagementConsole

@ -14,9 +14,6 @@ set(FILES
Source/Window/ShaderManagementConsoleWindow.h
Source/Window/ShaderManagementConsoleWindow.cpp
Source/Window/ShaderManagementConsoleWindowModule.cpp
Source/Window/ShaderManagementConsoleBrowserWidget.h
Source/Window/ShaderManagementConsoleBrowserWidget.cpp
Source/Window/ShaderManagementConsoleBrowserWidget.ui
Source/Window/ShaderManagementConsole.qrc
Source/Window/ShaderManagementConsoleWindowComponent.h
Source/Window/ShaderManagementConsoleWindowComponent.cpp

@ -143,7 +143,7 @@ namespace AZ
arguments.append(QString("--project-path=%1").arg(projectPath.c_str()));
}
AtomToolsFramework::LaunchTool("MaterialEditor", AZ_TRAIT_OS_EXECUTABLE_EXTENSION, arguments);
AtomToolsFramework::LaunchTool("MaterialEditor", arguments);
}
void EditorMaterialSystemComponent::OpenMaterialInspector(

@ -62,7 +62,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
protected:
//////////////////////////////////////////////////////////////////////////

@ -77,7 +77,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override;
//////////////////////////////////////////////////////////////////////////

@ -69,7 +69,7 @@ namespace GradientSignal
// GradientRequestBus overrides...
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
// AZ::Data::AssetBus overrides...
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;

@ -64,7 +64,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override;
protected:

@ -69,7 +69,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override;
protected:

@ -99,7 +99,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override;
protected:

@ -70,7 +70,7 @@ namespace GradientSignal
// GradientRequestBus overrides...
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
private:
PerlinGradientConfig m_configuration;

@ -73,7 +73,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override;
protected:

@ -61,7 +61,7 @@ namespace GradientSignal
// GradientRequestBus overrides...
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
private:
RandomGradientConfig m_configuration;

@ -64,7 +64,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override;
protected:

@ -69,7 +69,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
protected:
//////////////////////////////////////////////////////////////////////////

@ -71,7 +71,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
bool IsEntityInHierarchy(const AZ::EntityId& entityId) const override;
protected:

@ -90,7 +90,7 @@ namespace GradientSignal
//////////////////////////////////////////////////////////////////////////
// GradientRequestBus
float GetValue(const GradientSampleParams& sampleParams) const override;
void GetValues(AZStd::span<AZ::Vector3> positions, AZStd::span<float> outValues) const override;
void GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const override;
protected:
//////////////////////////////////////////////////////////////////////////

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

Loading…
Cancel
Save