Merge branch 'upstream/development' into LYN-8514_AutomatedReviewServerLogChecks
This commit is contained in:
+11
-10
@@ -95,7 +95,8 @@ def EntityOutliner_EntityOrdering():
|
|||||||
entity_outliner_model.dropMimeData(
|
entity_outliner_model.dropMimeData(
|
||||||
mime_data, QtCore.Qt.MoveAction, target_row, 0, target_index.parent()
|
mime_data, QtCore.Qt.MoveAction, target_row, 0, target_index.parent()
|
||||||
)
|
)
|
||||||
QtWidgets.QApplication.processEvents()
|
# Wait after move to let events (i.e. prefab propagation) process
|
||||||
|
general.idle_wait(1.0)
|
||||||
|
|
||||||
# Move an entity before another entity in the order by dragging the source above the target
|
# Move an entity before another entity in the order by dragging the source above the target
|
||||||
move_entity_before = lambda source_name, target_name: _move_entity(
|
move_entity_before = lambda source_name, target_name: _move_entity(
|
||||||
@@ -119,24 +120,24 @@ def EntityOutliner_EntityOrdering():
|
|||||||
|
|
||||||
# Our new entity should be given a name with a number automatically
|
# Our new entity should be given a name with a number automatically
|
||||||
new_entity = f"Entity{i+1}"
|
new_entity = f"Entity{i+1}"
|
||||||
# The new entity should be added to the top of its parent entity
|
# The new entity should be added to the bottom of its parent entity
|
||||||
expected_order = [new_entity] + expected_order
|
expected_order = expected_order + [new_entity]
|
||||||
|
|
||||||
verify_entities_sorted(expected_order)
|
verify_entities_sorted(expected_order)
|
||||||
|
|
||||||
# 3) Move "Entity1" to the top of the order
|
# 3) Move "Entity5" to the top of the order
|
||||||
move_entity_before("Entity1", "Entity5")
|
move_entity_before("Entity5", "Entity1")
|
||||||
expected_order = ["Entity1", "Entity5", "Entity4", "Entity3", "Entity2"]
|
expected_order = ["Entity5", "Entity1", "Entity2", "Entity3", "Entity4"]
|
||||||
verify_entities_sorted(expected_order)
|
verify_entities_sorted(expected_order)
|
||||||
|
|
||||||
# 4) Move "Entity4" to the bottom of the order
|
# 4) Move "Entity2" to the bottom of the order
|
||||||
move_entity_after("Entity4", "Entity2")
|
move_entity_after("Entity2", "Entity4")
|
||||||
expected_order = ["Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
|
expected_order = ["Entity5", "Entity1", "Entity3", "Entity4", "Entity2"]
|
||||||
verify_entities_sorted(expected_order)
|
verify_entities_sorted(expected_order)
|
||||||
|
|
||||||
# 5) Add another new entity, ensure the rest of the order is unchanged
|
# 5) Add another new entity, ensure the rest of the order is unchanged
|
||||||
create_entity()
|
create_entity()
|
||||||
expected_order = ["Entity6", "Entity1", "Entity5", "Entity3", "Entity2", "Entity4"]
|
expected_order = ["Entity5", "Entity1", "Entity3", "Entity4", "Entity2", "Entity6"]
|
||||||
verify_entities_sorted(expected_order)
|
verify_entities_sorted(expected_order)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ ly_add_source_properties(
|
|||||||
PROPERTY COMPILE_DEFINITIONS
|
PROPERTY COMPILE_DEFINITIONS
|
||||||
VALUES
|
VALUES
|
||||||
O3DE_COPYRIGHT_YEAR=${LY_VERSION_COPYRIGHT_YEAR}
|
O3DE_COPYRIGHT_YEAR=${LY_VERSION_COPYRIGHT_YEAR}
|
||||||
LY_BUILD=${LY_VERSION_BUILD_NUMBER}
|
LY_VERSION_BUILD_NUMBER=${LY_VERSION_BUILD_NUMBER}
|
||||||
${LY_PAL_TOOLS_DEFINES}
|
${LY_PAL_TOOLS_DEFINES}
|
||||||
)
|
)
|
||||||
ly_add_source_properties(
|
ly_add_source_properties(
|
||||||
|
|||||||
@@ -911,13 +911,9 @@ namespace
|
|||||||
QWidget* g_splashScreen = nullptr;
|
QWidget* g_splashScreen = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FormatVersion(const SFileVersion& v)
|
QString FormatVersion([[maybe_unused]] const SFileVersion& v)
|
||||||
{
|
{
|
||||||
#if defined(LY_BUILD)
|
return QObject::tr("Version %1").arg(LY_VERSION_BUILD_NUMBER);
|
||||||
return QObject::tr("Version %1.%2.%3.%4 - Build %5").arg(v[3]).arg(v[2]).arg(v[1]).arg(v[0]).arg(LY_BUILD);
|
|
||||||
#else
|
|
||||||
return QObject::tr("Version %1.%2.%3.%4").arg(v[3]).arg(v[2]).arg(v[1]).arg(v[0]);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FormatRichTextCopyrightNotice()
|
QString FormatRichTextCopyrightNotice()
|
||||||
|
|||||||
@@ -130,10 +130,11 @@ namespace AZStd::Internal
|
|||||||
|
|
||||||
|
|
||||||
//! Constructors
|
//! Constructors
|
||||||
constexpr fixed_trivial_storage() = default;
|
fixed_trivial_storage() = default;
|
||||||
|
|
||||||
template <typename U, typename = enable_if_t<is_convertible_v<U, T>>>
|
template <typename U, typename = enable_if_t<is_convertible_v<U, T>>>
|
||||||
constexpr fixed_trivial_storage(AZStd::initializer_list<U> ilist) noexcept
|
fixed_trivial_storage(AZStd::initializer_list<U> ilist) noexcept
|
||||||
|
: m_size(aznumeric_caster(ilist.size()))
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(ilist.size() <= capacity(), "Initializer list cannot be larger than storage capacity");
|
AZSTD_CONTAINER_ASSERT(ilist.size() <= capacity(), "Initializer list cannot be larger than storage capacity");
|
||||||
size_t index{};
|
size_t index{};
|
||||||
@@ -141,20 +142,19 @@ namespace AZStd::Internal
|
|||||||
{
|
{
|
||||||
m_data[index++] = element;
|
m_data[index++] = element;
|
||||||
}
|
}
|
||||||
resize_no_construct(ilist.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr pointer data() noexcept
|
pointer data() noexcept
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
constexpr const_pointer data() const noexcept
|
const_pointer data() const noexcept
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Number of elements currently stored.
|
//! Number of elements currently stored.
|
||||||
constexpr size_type size() const noexcept
|
size_type size() const noexcept
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
@@ -164,12 +164,12 @@ namespace AZStd::Internal
|
|||||||
return Capacity;
|
return Capacity;
|
||||||
}
|
}
|
||||||
//! Is the storage empty?
|
//! Is the storage empty?
|
||||||
constexpr bool empty() const noexcept
|
bool empty() const noexcept
|
||||||
{
|
{
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
//! Is the storage full?
|
//! Is the storage full?
|
||||||
constexpr bool full() const noexcept
|
bool full() const noexcept
|
||||||
{
|
{
|
||||||
return size() == capacity();
|
return size() == capacity();
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ namespace AZStd::Internal
|
|||||||
//! Increases size of the storage by one.
|
//! Increases size of the storage by one.
|
||||||
//! Always fails for empty storage.
|
//! Always fails for empty storage.
|
||||||
template <typename... Args, typename = enable_if_t<is_constructible_v<T, Args...>>>
|
template <typename... Args, typename = enable_if_t<is_constructible_v<T, Args...>>>
|
||||||
constexpr reference emplace_back(Args&&... args) noexcept
|
reference emplace_back(Args&&... args) noexcept
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(!full(), "emplace_back cannot be invoked on full storage");
|
AZSTD_CONTAINER_ASSERT(!full(), "emplace_back cannot be invoked on full storage");
|
||||||
reference new_element = *(data() + size());
|
reference new_element = *(data() + size());
|
||||||
@@ -196,7 +196,7 @@ namespace AZStd::Internal
|
|||||||
}
|
}
|
||||||
//! Removes the last element of the storage.
|
//! Removes the last element of the storage.
|
||||||
//! Precondition: size is not empty
|
//! Precondition: size is not empty
|
||||||
constexpr void pop_back() noexcept
|
void pop_back() noexcept
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(!empty(), "pop_back cannot be invoked on empty storage");
|
AZSTD_CONTAINER_ASSERT(!empty(), "pop_back cannot be invoked on empty storage");
|
||||||
resize_no_construct(size() - 1);
|
resize_no_construct(size() - 1);
|
||||||
@@ -205,7 +205,7 @@ namespace AZStd::Internal
|
|||||||
//! removing elements (unsafe).
|
//! removing elements (unsafe).
|
||||||
//!
|
//!
|
||||||
//! Updates the size of the container while checking that the new size is less than capacity
|
//! Updates the size of the container while checking that the new size is less than capacity
|
||||||
constexpr void resize_no_construct(size_t new_size) noexcept
|
void resize_no_construct(size_t new_size) noexcept
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(new_size <= capacity(), "New size cannot be larger than capacity");
|
AZSTD_CONTAINER_ASSERT(new_size <= capacity(), "New size cannot be larger than capacity");
|
||||||
m_size = aznumeric_cast<size_type>(new_size);
|
m_size = aznumeric_cast<size_type>(new_size);
|
||||||
@@ -215,19 +215,19 @@ namespace AZStd::Internal
|
|||||||
//! This does not modify the size of the storage
|
//! This does not modify the size of the storage
|
||||||
//! This is a no-op for trivial types
|
//! This is a no-op for trivial types
|
||||||
template <typename InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
template <typename InputIt, typename = enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||||
constexpr void unsafe_destroy(InputIt, InputIt) noexcept
|
void unsafe_destroy(InputIt, InputIt) noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destructs all elements of the storage.
|
//! Destructs all elements of the storage.
|
||||||
//! This does not modify the size of the storage
|
//! This does not modify the size of the storage
|
||||||
//! This is a no-op for trivial types
|
//! This is a no-op for trivial types
|
||||||
constexpr void unsafe_destroy_all() noexcept
|
void unsafe_destroy_all() noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T m_data[Capacity]{};
|
T m_data[Capacity];
|
||||||
size_type m_size{};
|
size_type m_size{};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ namespace AZStd::Internal
|
|||||||
using reference = T&;
|
using reference = T&;
|
||||||
using const_reference = const T&;
|
using const_reference = const T&;
|
||||||
|
|
||||||
constexpr fixed_non_trivial_storage() = default;
|
fixed_non_trivial_storage() = default;
|
||||||
|
|
||||||
~fixed_non_trivial_storage() noexcept
|
~fixed_non_trivial_storage() noexcept
|
||||||
{
|
{
|
||||||
@@ -253,7 +253,7 @@ namespace AZStd::Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename = enable_if_t<is_convertible_v<U, T>>>
|
template <typename U, typename = enable_if_t<is_convertible_v<U, T>>>
|
||||||
constexpr fixed_non_trivial_storage(AZStd::initializer_list<U> ilist) noexcept(noexcept(emplace_back(AZStd::declval<U>())))
|
fixed_non_trivial_storage(AZStd::initializer_list<U> ilist) noexcept(noexcept(emplace_back(AZStd::declval<U>())))
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(ilist.size() <= capacity(), "Initializer list cannot be larger than storage capacity");
|
AZSTD_CONTAINER_ASSERT(ilist.size() <= capacity(), "Initializer list cannot be larger than storage capacity");
|
||||||
for (const U& element : ilist)
|
for (const U& element : ilist)
|
||||||
@@ -272,7 +272,7 @@ namespace AZStd::Internal
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Number of elements currently stored.
|
//! Number of elements currently stored.
|
||||||
constexpr size_type size() const noexcept
|
size_type size() const noexcept
|
||||||
{
|
{
|
||||||
return m_size;
|
return m_size;
|
||||||
}
|
}
|
||||||
@@ -282,12 +282,12 @@ namespace AZStd::Internal
|
|||||||
return Capacity;
|
return Capacity;
|
||||||
}
|
}
|
||||||
//! Is the storage empty?
|
//! Is the storage empty?
|
||||||
constexpr bool empty() const noexcept
|
bool empty() const noexcept
|
||||||
{
|
{
|
||||||
return size() == 0;
|
return size() == 0;
|
||||||
}
|
}
|
||||||
//! Is the storage full?
|
//! Is the storage full?
|
||||||
constexpr bool full() const noexcept
|
bool full() const noexcept
|
||||||
{
|
{
|
||||||
return size() == capacity();
|
return size() == capacity();
|
||||||
}
|
}
|
||||||
@@ -325,7 +325,7 @@ namespace AZStd::Internal
|
|||||||
//! removing elements (unsafe).
|
//! removing elements (unsafe).
|
||||||
//!
|
//!
|
||||||
//! Updates the size of the container while checking that the new size is less than capacity
|
//! Updates the size of the container while checking that the new size is less than capacity
|
||||||
constexpr void resize_no_construct(size_t new_size) noexcept
|
void resize_no_construct(size_t new_size) noexcept
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(new_size <= capacity(), "New size cannot be larger than capacity");
|
AZSTD_CONTAINER_ASSERT(new_size <= capacity(), "New size cannot be larger than capacity");
|
||||||
m_size = aznumeric_cast<size_type>(new_size);
|
m_size = aznumeric_cast<size_type>(new_size);
|
||||||
@@ -402,23 +402,23 @@ namespace AZStd
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
// 23.2.4.1 construct/copy/destroy
|
// 23.2.4.1 construct/copy/destroy
|
||||||
constexpr fixed_vector() = default;
|
fixed_vector() = default;
|
||||||
|
|
||||||
constexpr explicit fixed_vector(size_type numElements, const_reference value = value_type())
|
explicit fixed_vector(size_type numElements, const_reference value = value_type())
|
||||||
{
|
{
|
||||||
resize_no_construct(numElements);
|
resize_no_construct(numElements);
|
||||||
AZStd::uninitialized_fill_n(data(), numElements, value);
|
AZStd::uninitialized_fill_n(data(), numElements, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||||
constexpr fixed_vector(InputIt first, InputIt last)
|
fixed_vector(InputIt first, InputIt last)
|
||||||
{
|
{
|
||||||
resize_no_construct(AZStd::distance(first, last));
|
resize_no_construct(AZStd::distance(first, last));
|
||||||
AZStd::uninitialized_copy(first, last, data());
|
AZStd::uninitialized_copy(first, last, data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
constexpr fixed_vector(const fixed_vector& rhs)
|
fixed_vector(const fixed_vector& rhs)
|
||||||
{
|
{
|
||||||
resize_no_construct(rhs.size());
|
resize_no_construct(rhs.size());
|
||||||
AZStd::uninitialized_copy(rhs.data(), rhs.data() + rhs.size(), data());
|
AZStd::uninitialized_copy(rhs.data(), rhs.data() + rhs.size(), data());
|
||||||
@@ -428,7 +428,7 @@ namespace AZStd
|
|||||||
// It performs an AZStd::move on each of the fixed_vector elements instead
|
// It performs an AZStd::move on each of the fixed_vector elements instead
|
||||||
// of swapping pointers to the allocted memory address
|
// of swapping pointers to the allocted memory address
|
||||||
// as it is unable to perform that operations due to the storage being baked into the container
|
// as it is unable to perform that operations due to the storage being baked into the container
|
||||||
constexpr fixed_vector(fixed_vector&& rhs)
|
fixed_vector(fixed_vector&& rhs)
|
||||||
{
|
{
|
||||||
resize_no_construct(rhs.size());
|
resize_no_construct(rhs.size());
|
||||||
AZStd::uninitialized_move(rhs.data(), rhs.data() + rhs.size(), data());
|
AZStd::uninitialized_move(rhs.data(), rhs.data() + rhs.size(), data());
|
||||||
@@ -440,7 +440,7 @@ namespace AZStd
|
|||||||
// into a fixed_vector given that the type in question isn't the same type as this fixed_vector type
|
// into a fixed_vector given that the type in question isn't the same type as this fixed_vector type
|
||||||
template <typename VectorContainer, typename = AZStd::enable_if_t<!AZStd::is_same_v<VectorContainer, fixed_vector>
|
template <typename VectorContainer, typename = AZStd::enable_if_t<!AZStd::is_same_v<VectorContainer, fixed_vector>
|
||||||
&& !AZStd::is_convertible_v<VectorContainer, size_type>>>
|
&& !AZStd::is_convertible_v<VectorContainer, size_type>>>
|
||||||
constexpr fixed_vector(VectorContainer&& rhs)
|
fixed_vector(VectorContainer&& rhs)
|
||||||
{
|
{
|
||||||
constexpr bool is_const_or_lvalue_reference = AZStd::is_lvalue_reference_v<VectorContainer>
|
constexpr bool is_const_or_lvalue_reference = AZStd::is_lvalue_reference_v<VectorContainer>
|
||||||
|| AZStd::is_const_v<VectorContainer>;
|
|| AZStd::is_const_v<VectorContainer>;
|
||||||
@@ -459,12 +459,12 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr fixed_vector(AZStd::initializer_list<value_type> ilist)
|
fixed_vector(AZStd::initializer_list<value_type> ilist)
|
||||||
: base_type(ilist)
|
: base_type(ilist)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr fixed_vector& operator=(const fixed_vector& rhs)
|
fixed_vector& operator=(const fixed_vector& rhs)
|
||||||
{
|
{
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
{
|
{
|
||||||
@@ -475,7 +475,7 @@ namespace AZStd
|
|||||||
return assign_helper(rhs);
|
return assign_helper(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr fixed_vector& operator=(fixed_vector&& rhs)
|
fixed_vector& operator=(fixed_vector&& rhs)
|
||||||
{
|
{
|
||||||
if (this == &rhs)
|
if (this == &rhs)
|
||||||
{
|
{
|
||||||
@@ -487,23 +487,23 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename VectorContainer>
|
template <typename VectorContainer>
|
||||||
constexpr AZStd::enable_if_t<!AZStd::is_same_v<AZStd::remove_cvref_t<VectorContainer>, fixed_vector>, fixed_vector>& operator=(VectorContainer&& rhs)
|
AZStd::enable_if_t<!AZStd::is_same_v<AZStd::remove_cvref_t<VectorContainer>, fixed_vector>, fixed_vector>& operator=(VectorContainer&& rhs)
|
||||||
{
|
{
|
||||||
return assign_helper(AZStd::forward<VectorContainer>(rhs));
|
return assign_helper(AZStd::forward<VectorContainer>(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator begin() { return iterator(data()); }
|
iterator begin() { return iterator(data()); }
|
||||||
constexpr const_iterator begin() const { return const_iterator(data()); }
|
const_iterator begin() const { return const_iterator(data()); }
|
||||||
constexpr const_iterator cbegin() const { return const_iterator(data()); }
|
const_iterator cbegin() const { return const_iterator(data()); }
|
||||||
constexpr iterator end() { return iterator(data() + size()); }
|
iterator end() { return iterator(data() + size()); }
|
||||||
constexpr const_iterator end() const { return const_iterator(data() + size()); }
|
const_iterator end() const { return const_iterator(data() + size()); }
|
||||||
constexpr const_iterator cend() const { return const_iterator(data() + size()); }
|
const_iterator cend() const { return const_iterator(data() + size()); }
|
||||||
constexpr reverse_iterator rbegin() { return reverse_iterator(end()); }
|
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||||
constexpr const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||||
constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
|
const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
|
||||||
constexpr reverse_iterator rend() { return reverse_iterator(begin()); }
|
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||||
constexpr const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
||||||
constexpr const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
|
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
|
||||||
|
|
||||||
// bring in fixed_vector_storage functions into scope
|
// bring in fixed_vector_storage functions into scope
|
||||||
using base_type::data;
|
using base_type::data;
|
||||||
@@ -514,7 +514,7 @@ namespace AZStd
|
|||||||
// extension method
|
// extension method
|
||||||
using base_type::resize_no_construct;
|
using base_type::resize_no_construct;
|
||||||
|
|
||||||
constexpr size_type size() const noexcept
|
size_type size() const noexcept
|
||||||
{
|
{
|
||||||
return base_type::size();
|
return base_type::size();
|
||||||
}
|
}
|
||||||
@@ -527,12 +527,12 @@ namespace AZStd
|
|||||||
return base_type::max_size();
|
return base_type::max_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void resize(size_type newSize)
|
void resize(size_type newSize)
|
||||||
{
|
{
|
||||||
return resize(newSize, value_type{});
|
return resize(newSize, value_type{});
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void resize(size_type newSize, const_reference value)
|
void resize(size_type newSize, const_reference value)
|
||||||
{
|
{
|
||||||
size_type dataSize = size();
|
size_type dataSize = size();
|
||||||
if (dataSize < newSize)
|
if (dataSize < newSize)
|
||||||
@@ -547,7 +547,7 @@ namespace AZStd
|
|||||||
|
|
||||||
// Removes unused capacity - For fixed_vector this only asserts
|
// Removes unused capacity - For fixed_vector this only asserts
|
||||||
// that the supplied capacity is not longer than the fixed_vector capacity
|
// that the supplied capacity is not longer than the fixed_vector capacity
|
||||||
constexpr void reserve(size_type newCapacity)
|
void reserve(size_type newCapacity)
|
||||||
{
|
{
|
||||||
// No-op - Implemented to provide consistent std::vector
|
// No-op - Implemented to provide consistent std::vector
|
||||||
AZSTD_CONTAINER_ASSERT(newCapacity <= capacity(),
|
AZSTD_CONTAINER_ASSERT(newCapacity <= capacity(),
|
||||||
@@ -556,79 +556,79 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Removes unused capacity - For fixed_vector this does nothing
|
// Removes unused capacity - For fixed_vector this does nothing
|
||||||
constexpr void shrink_to_fit()
|
void shrink_to_fit()
|
||||||
{
|
{
|
||||||
// No-op - Implemented to provide consistent std::vector
|
// No-op - Implemented to provide consistent std::vector
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr reference at(size_type position)
|
reference at(size_type position)
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||||
return *(data() + position);
|
return *(data() + position);
|
||||||
}
|
}
|
||||||
constexpr const_reference at(size_type position) const
|
const_reference at(size_type position) const
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||||
return *(data() + position);
|
return *(data() + position);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr reference operator[](size_type position)
|
reference operator[](size_type position)
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||||
return *(data() + position);
|
return *(data() + position);
|
||||||
}
|
}
|
||||||
constexpr const_reference operator[](size_type position) const
|
const_reference operator[](size_type position) const
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
AZSTD_CONTAINER_ASSERT(position < size(), "AZStd::fixed_vector<>::at - position is out of range");
|
||||||
return *(data() + position);
|
return *(data() + position);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr reference front()
|
reference front()
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
||||||
return *data();
|
return *data();
|
||||||
}
|
}
|
||||||
constexpr const_reference front() const
|
const_reference front() const
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
||||||
return *data();
|
return *data();
|
||||||
}
|
}
|
||||||
constexpr reference back()
|
reference back()
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
||||||
return *(data() + size() - 1);
|
return *(data() + size() - 1);
|
||||||
}
|
}
|
||||||
constexpr const_reference back() const
|
const_reference back() const
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
||||||
return *(data() + size() - 1);
|
return *(data() + size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void push_back(const_reference value)
|
void push_back(const_reference value)
|
||||||
{
|
{
|
||||||
emplace_back(value);
|
emplace_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void assign(size_type numElements, const_reference value)
|
void assign(size_type numElements, const_reference value)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
insert(end(), numElements, value);
|
insert(end(), numElements, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
template <class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||||
constexpr void assign(InputIt first, InputIt last)
|
void assign(InputIt first, InputIt last)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
insert(end(), first, last);
|
insert(end(), first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void assign(AZStd::initializer_list<value_type> ilist)
|
void assign(AZStd::initializer_list<value_type> ilist)
|
||||||
{
|
{
|
||||||
assign(ilist.begin(), ilist.end());
|
assign(ilist.begin(), ilist.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args, typename = AZStd::enable_if_t<is_constructible_v<T, Args...>>>
|
template <typename... Args, typename = AZStd::enable_if_t<is_constructible_v<T, Args...>>>
|
||||||
constexpr iterator emplace(const_iterator insertPos, Args&&... args)
|
iterator emplace(const_iterator insertPos, Args&&... args)
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(!full(), "Cannot emplace on a full fixed_vector");
|
AZSTD_CONTAINER_ASSERT(!full(), "Cannot emplace on a full fixed_vector");
|
||||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||||
@@ -645,18 +645,18 @@ namespace AZStd
|
|||||||
AZStd::construct_at(insertPosPtr, AZStd::forward<Args>(args)...);
|
AZStd::construct_at(insertPosPtr, AZStd::forward<Args>(args)...);
|
||||||
return iterator(insertPosPtr);
|
return iterator(insertPosPtr);
|
||||||
}
|
}
|
||||||
constexpr iterator insert(const_iterator insertPos, const_reference value)
|
iterator insert(const_iterator insertPos, const_reference value)
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||||
return emplace(insertPos, value);
|
return emplace(insertPos, value);
|
||||||
}
|
}
|
||||||
constexpr iterator insert(const_iterator insertPos, value_type&& value)
|
iterator insert(const_iterator insertPos, value_type&& value)
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||||
return emplace(insertPos, AZStd::move(value));
|
return emplace(insertPos, AZStd::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void insert(const_iterator insertPos, size_type numElements, const_reference value)
|
void insert(const_iterator insertPos, size_type numElements, const_reference value)
|
||||||
{
|
{
|
||||||
if (numElements == 0)
|
if (numElements == 0)
|
||||||
{
|
{
|
||||||
@@ -708,24 +708,24 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
template<class InputIt, typename = AZStd::enable_if_t<Internal::is_input_iterator_v<InputIt>>>
|
||||||
constexpr void insert(const_iterator insertPos, InputIt first, InputIt last)
|
void insert(const_iterator insertPos, InputIt first, InputIt last)
|
||||||
{
|
{
|
||||||
// specialize for iterator categories.
|
// specialize for iterator categories.
|
||||||
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
AZSTD_CONTAINER_ASSERT(insertPos >= cbegin() && insertPos <= cend(), "insert position must be in range of container");
|
||||||
insert_iter(insertPos, first, last, typename iterator_traits<InputIt>::iterator_category());
|
insert_iter(insertPos, first, last, typename iterator_traits<InputIt>::iterator_category());
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr void insert(const_iterator insertPos, AZStd::initializer_list<value_type> ilist)
|
void insert(const_iterator insertPos, AZStd::initializer_list<value_type> ilist)
|
||||||
{
|
{
|
||||||
insert(insertPos, ilist.begin(), ilist.end());
|
insert(insertPos, ilist.begin(), ilist.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator erase(const_iterator elementIter)
|
iterator erase(const_iterator elementIter)
|
||||||
{
|
{
|
||||||
return erase(elementIter, elementIter + 1);
|
return erase(elementIter, elementIter + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr iterator erase(const_iterator first, const_iterator last)
|
iterator erase(const_iterator first, const_iterator last)
|
||||||
{
|
{
|
||||||
AZSTD_CONTAINER_ASSERT(first >= cbegin() && last <= cend(), "erase iterator must be inside the range of fixed_vector container");
|
AZSTD_CONTAINER_ASSERT(first >= cbegin() && last <= cend(), "erase iterator must be inside the range of fixed_vector container");
|
||||||
iterator dataStart = begin();
|
iterator dataStart = begin();
|
||||||
@@ -741,12 +741,12 @@ namespace AZStd
|
|||||||
return dataStart + offset;
|
return dataStart + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
base_type::unsafe_destroy_all();
|
base_type::unsafe_destroy_all();
|
||||||
resize_no_construct(0);
|
resize_no_construct(0);
|
||||||
}
|
}
|
||||||
constexpr void swap(fixed_vector& rhs)
|
void swap(fixed_vector& rhs)
|
||||||
{
|
{
|
||||||
// Fixed containers cannot swap pointers, they need to do full copies.
|
// Fixed containers cannot swap pointers, they need to do full copies.
|
||||||
// The strategy is to extend the smaller fixed_vector to be the size
|
// The strategy is to extend the smaller fixed_vector to be the size
|
||||||
@@ -776,12 +776,12 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate container status.
|
// Validate container status.
|
||||||
constexpr bool validate() const
|
bool validate() const
|
||||||
{
|
{
|
||||||
return size() <= max_size();
|
return size() <= max_size();
|
||||||
}
|
}
|
||||||
// Validate iterator.
|
// Validate iterator.
|
||||||
constexpr int validate_iterator(const_iterator iter) const
|
int validate_iterator(const_iterator iter) const
|
||||||
{
|
{
|
||||||
const_pointer start = data();
|
const_pointer start = data();
|
||||||
const_pointer end = data() + size();
|
const_pointer end = data() + size();
|
||||||
@@ -799,19 +799,19 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pushes back an empty without a provided instance.
|
// pushes back an empty without a provided instance.
|
||||||
constexpr void push_back()
|
void push_back()
|
||||||
{
|
{
|
||||||
emplace_back();
|
emplace_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void leak_and_reset()
|
void leak_and_reset()
|
||||||
{
|
{
|
||||||
resize_no_construct(0);
|
resize_no_construct(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename VectorContainer>
|
template <typename VectorContainer>
|
||||||
constexpr fixed_vector& assign_helper(VectorContainer&& rhs)
|
fixed_vector& assign_helper(VectorContainer&& rhs)
|
||||||
{
|
{
|
||||||
constexpr bool is_const_or_lvalue_reference = AZStd::is_lvalue_reference_v<VectorContainer>
|
constexpr bool is_const_or_lvalue_reference = AZStd::is_lvalue_reference_v<VectorContainer>
|
||||||
|| AZStd::is_const_v<VectorContainer>;
|
|| AZStd::is_const_v<VectorContainer>;
|
||||||
@@ -872,7 +872,7 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Iterator>
|
template<class Iterator>
|
||||||
constexpr void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const forward_iterator_tag&)
|
void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const forward_iterator_tag&)
|
||||||
{
|
{
|
||||||
size_type numElements = AZStd::distance(first, last);
|
size_type numElements = AZStd::distance(first, last);
|
||||||
if (numElements == 0)
|
if (numElements == 0)
|
||||||
@@ -923,7 +923,7 @@ namespace AZStd
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Iterator>
|
template<class Iterator>
|
||||||
constexpr void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const input_iterator_tag&)
|
void insert_iter(const_iterator insertPos, Iterator first, Iterator last, const input_iterator_tag&)
|
||||||
{
|
{
|
||||||
iterator dataStart = data();
|
iterator dataStart = data();
|
||||||
size_type offset = AZStd::distance(dataStart, insertPos);
|
size_type offset = AZStd::distance(dataStart, insertPos);
|
||||||
|
|||||||
@@ -753,7 +753,7 @@ namespace UnitTest
|
|||||||
|
|
||||||
TEST_F(Arrays, FixedVectorCanCopyAndMoveWithDifferentCapacity)
|
TEST_F(Arrays, FixedVectorCanCopyAndMoveWithDifferentCapacity)
|
||||||
{
|
{
|
||||||
constexpr AZStd::fixed_vector<int, 32> sourceVector{ 1,2,3,4,5 };
|
AZStd::fixed_vector<int, 32> sourceVector{ 1,2,3,4,5 };
|
||||||
|
|
||||||
AZStd::fixed_vector<int, 8> copyConstructVector{ sourceVector };
|
AZStd::fixed_vector<int, 8> copyConstructVector{ sourceVector };
|
||||||
EXPECT_EQ(sourceVector, copyConstructVector);
|
EXPECT_EQ(sourceVector, copyConstructVector);
|
||||||
@@ -768,32 +768,32 @@ namespace UnitTest
|
|||||||
|
|
||||||
AZStd::fixed_vector<int, 16> moveAssignVector = AZStd::move(moveConstructVector);
|
AZStd::fixed_vector<int, 16> moveAssignVector = AZStd::move(moveConstructVector);
|
||||||
|
|
||||||
constexpr AZStd::fixed_vector expectedVector{ 1,2,3,4,5,6 };
|
AZStd::fixed_vector expectedVector{ 1,2,3,4,5,6 };
|
||||||
EXPECT_EQ(expectedVector, moveAssignVector);
|
EXPECT_EQ(expectedVector, moveAssignVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(Arrays, FixedVectorComparisonOperatorsSucceedAsExpected)
|
TEST_F(Arrays, FixedVectorComparisonOperatorsSucceedAsExpected)
|
||||||
{
|
{
|
||||||
constexpr AZStd::fixed_vector<int, 32> testVector{ 1,2,3,4,5 };
|
AZStd::fixed_vector<int, 32> testVector{ 1,2,3,4,5 };
|
||||||
constexpr AZStd::fixed_vector<int, 32> equalVector{ 1,2,3,4,5 };
|
AZStd::fixed_vector<int, 32> equalVector{ 1,2,3,4,5 };
|
||||||
constexpr AZStd::fixed_vector<int, 32> notEqualVectorDifferentSize{ 1,2,3,4,5,6 };
|
AZStd::fixed_vector<int, 32> notEqualVectorDifferentSize{ 1,2,3,4,5,6 };
|
||||||
constexpr AZStd::fixed_vector<int, 32> lessVector{ 1,2,3,4,4 };
|
AZStd::fixed_vector<int, 32> lessVector{ 1,2,3,4,4 };
|
||||||
constexpr AZStd::fixed_vector<int, 32> greaterVectorDifferentSize{ 1,2,3,4,5, 1 };
|
AZStd::fixed_vector<int, 32> greaterVectorDifferentSize{ 1,2,3,4,5, 1 };
|
||||||
|
|
||||||
static_assert(testVector == equalVector);
|
EXPECT_EQ(testVector, equalVector);
|
||||||
static_assert(testVector != notEqualVectorDifferentSize);
|
EXPECT_NE(testVector, notEqualVectorDifferentSize);
|
||||||
static_assert(testVector != lessVector);
|
EXPECT_NE(testVector, lessVector);
|
||||||
static_assert(lessVector < testVector);
|
EXPECT_LT(lessVector, testVector);
|
||||||
static_assert(lessVector < greaterVectorDifferentSize);
|
EXPECT_LT(lessVector, greaterVectorDifferentSize);
|
||||||
static_assert(lessVector <= lessVector);
|
EXPECT_LE(lessVector, lessVector);
|
||||||
static_assert(lessVector <= testVector);
|
EXPECT_LE(lessVector, testVector);
|
||||||
static_assert(lessVector <= greaterVectorDifferentSize);
|
EXPECT_LE(lessVector, greaterVectorDifferentSize);
|
||||||
static_assert(testVector > lessVector);
|
EXPECT_GT(testVector, lessVector);
|
||||||
static_assert(testVector > lessVector);
|
EXPECT_GT(testVector, lessVector);
|
||||||
static_assert(notEqualVectorDifferentSize > testVector);
|
EXPECT_GT(notEqualVectorDifferentSize, testVector);
|
||||||
static_assert(testVector >= testVector);
|
EXPECT_GE(testVector, testVector);
|
||||||
static_assert(testVector >= lessVector);
|
EXPECT_GE(testVector, lessVector);
|
||||||
static_assert(greaterVectorDifferentSize > lessVector);
|
EXPECT_GT(greaterVectorDifferentSize, lessVector);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(Arrays, VectorSwap)
|
TEST_F(Arrays, VectorSwap)
|
||||||
|
|||||||
@@ -239,12 +239,14 @@ namespace AzToolsFramework
|
|||||||
, m_isInIsolationMode(false)
|
, m_isInIsolationMode(false)
|
||||||
{
|
{
|
||||||
ToolsApplicationRequests::Bus::Handler::BusConnect();
|
ToolsApplicationRequests::Bus::Handler::BusConnect();
|
||||||
|
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
|
||||||
|
|
||||||
m_undoCache.RegisterToUndoCacheInterface();
|
m_undoCache.RegisterToUndoCacheInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolsApplication::~ToolsApplication()
|
ToolsApplication::~ToolsApplication()
|
||||||
{
|
{
|
||||||
|
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect();
|
||||||
ToolsApplicationRequests::Bus::Handler::BusDisconnect();
|
ToolsApplicationRequests::Bus::Handler::BusDisconnect();
|
||||||
Stop();
|
Stop();
|
||||||
}
|
}
|
||||||
@@ -566,6 +568,12 @@ namespace AzToolsFramework
|
|||||||
void ToolsApplication::MarkEntitySelected(AZ::EntityId entityId)
|
void ToolsApplication::MarkEntitySelected(AZ::EntityId entityId)
|
||||||
{
|
{
|
||||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||||
|
|
||||||
|
if (m_freezeSelectionUpdates)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AZ_Assert(entityId.IsValid(), "Invalid entity Id being marked as selected.");
|
AZ_Assert(entityId.IsValid(), "Invalid entity Id being marked as selected.");
|
||||||
|
|
||||||
EntityIdList::iterator foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
EntityIdList::iterator foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
||||||
@@ -585,6 +593,11 @@ namespace AzToolsFramework
|
|||||||
{
|
{
|
||||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||||
|
|
||||||
|
if (m_freezeSelectionUpdates)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EntityIdList entitiesSelected;
|
EntityIdList entitiesSelected;
|
||||||
entitiesSelected.reserve(entitiesToSelect.size());
|
entitiesSelected.reserve(entitiesToSelect.size());
|
||||||
|
|
||||||
@@ -608,6 +621,12 @@ namespace AzToolsFramework
|
|||||||
void ToolsApplication::MarkEntityDeselected(AZ::EntityId entityId)
|
void ToolsApplication::MarkEntityDeselected(AZ::EntityId entityId)
|
||||||
{
|
{
|
||||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||||
|
|
||||||
|
if (m_freezeSelectionUpdates)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
auto foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
||||||
if (foundIter != m_selectedEntities.end())
|
if (foundIter != m_selectedEntities.end())
|
||||||
{
|
{
|
||||||
@@ -625,6 +644,11 @@ namespace AzToolsFramework
|
|||||||
{
|
{
|
||||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||||
|
|
||||||
|
if (m_freezeSelectionUpdates)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ToolsApplicationEvents::Bus::Broadcast(&ToolsApplicationEvents::BeforeEntitySelectionChanged);
|
ToolsApplicationEvents::Bus::Broadcast(&ToolsApplicationEvents::BeforeEntitySelectionChanged);
|
||||||
|
|
||||||
EntityIdSet entitySetToDeselect(entitiesToDeselect.begin(), entitiesToDeselect.end());
|
EntityIdSet entitySetToDeselect(entitiesToDeselect.begin(), entitiesToDeselect.end());
|
||||||
@@ -679,6 +703,11 @@ namespace AzToolsFramework
|
|||||||
{
|
{
|
||||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||||
|
|
||||||
|
if (m_freezeSelectionUpdates)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We're setting the selection set as a batch from an external caller.
|
// We're setting the selection set as a batch from an external caller.
|
||||||
// * Filter out any unselectable entities
|
// * Filter out any unselectable entities
|
||||||
// * Calculate selection/deselection delta so we can notify specific entities only on change.
|
// * Calculate selection/deselection delta so we can notify specific entities only on change.
|
||||||
@@ -1569,6 +1598,16 @@ namespace AzToolsFramework
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ToolsApplication::OnPrefabInstancePropagationBegin()
|
||||||
|
{
|
||||||
|
m_freezeSelectionUpdates = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToolsApplication::OnPrefabInstancePropagationEnd()
|
||||||
|
{
|
||||||
|
m_freezeSelectionUpdates = false;
|
||||||
|
}
|
||||||
|
|
||||||
void ToolsApplication::CreateUndosForDirtyEntities()
|
void ToolsApplication::CreateUndosForDirtyEntities()
|
||||||
{
|
{
|
||||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <AzToolsFramework/API/EditorEntityAPI.h>
|
#include <AzToolsFramework/API/EditorEntityAPI.h>
|
||||||
#include <AzToolsFramework/Application/EditorEntityManager.h>
|
#include <AzToolsFramework/Application/EditorEntityManager.h>
|
||||||
#include <AzToolsFramework/Commands/PreemptiveUndoCache.h>
|
#include <AzToolsFramework/Commands/PreemptiveUndoCache.h>
|
||||||
|
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ namespace AzToolsFramework
|
|||||||
class ToolsApplication
|
class ToolsApplication
|
||||||
: public AzFramework::Application
|
: public AzFramework::Application
|
||||||
, public ToolsApplicationRequests::Bus::Handler
|
, public ToolsApplicationRequests::Bus::Handler
|
||||||
|
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AZ_RTTI(ToolsApplication, "{2895561E-BE90-4CC3-8370-DD46FCF74C01}", AzFramework::Application);
|
AZ_RTTI(ToolsApplication, "{2895561E-BE90-4CC3-8370-DD46FCF74C01}", AzFramework::Application);
|
||||||
@@ -169,6 +171,14 @@ namespace AzToolsFramework
|
|||||||
};
|
};
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// PrefabPublicNotificationBus::Handler
|
||||||
|
|
||||||
|
void OnPrefabInstancePropagationBegin() override;
|
||||||
|
void OnPrefabInstancePropagationEnd() override;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void CreateUndosForDirtyEntities();
|
void CreateUndosForDirtyEntities();
|
||||||
void ConsistencyCheckUndoCache();
|
void ConsistencyCheckUndoCache();
|
||||||
AZ::Aabb m_selectionBounds;
|
AZ::Aabb m_selectionBounds;
|
||||||
@@ -181,6 +191,7 @@ namespace AzToolsFramework
|
|||||||
bool m_isDuringUndoRedo;
|
bool m_isDuringUndoRedo;
|
||||||
bool m_isInIsolationMode;
|
bool m_isInIsolationMode;
|
||||||
EntityIdSet m_isolatedEntityIdSet;
|
EntityIdSet m_isolatedEntityIdSet;
|
||||||
|
bool m_freezeSelectionUpdates = false;
|
||||||
|
|
||||||
EditorEntityAPI* m_editorEntityAPI = nullptr;
|
EditorEntityAPI* m_editorEntityAPI = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -449,16 +449,23 @@ namespace AzToolsFramework
|
|||||||
AZStd::unordered_map<AZ::EntityId, AZStd::pair<AZ::EntityId, AZ::u64>>::const_iterator orderItr = m_savedOrderInfo.find(childId);
|
AZStd::unordered_map<AZ::EntityId, AZStd::pair<AZ::EntityId, AZ::u64>>::const_iterator orderItr = m_savedOrderInfo.find(childId);
|
||||||
if (orderItr != m_savedOrderInfo.end() && orderItr->second.first == parentId)
|
if (orderItr != m_savedOrderInfo.end() && orderItr->second.first == parentId)
|
||||||
{
|
{
|
||||||
bool sortOrderUpdated = AzToolsFramework::RecoverEntitySortInfo(parentId, childId, orderItr->second.second);
|
bool isPrefabEnabled = false;
|
||||||
m_savedOrderInfo.erase(childId);
|
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||||
|
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||||
// force notify the child sort order changed on the parent entity info, but only if the restore didn't actually modify
|
// If prefabs are enabled, rely on the component to do a sanity check instead of restoring the order from the model
|
||||||
// the order internally (and sent ChildEntityOrderArrayUpdated). that may seem heavy handed, and it is, but necessary
|
if (!isPrefabEnabled)
|
||||||
// to combat scenarios when the initial override detection returns a false positive (see comment about IDH comparisons
|
|
||||||
// in OnChildSortOrderChanged) and the slice instance source-to-live mapping hasn't been fully reconstructed yet.
|
|
||||||
if (!sortOrderUpdated)
|
|
||||||
{
|
{
|
||||||
parentInfo.OnChildSortOrderChanged();
|
bool sortOrderUpdated = AzToolsFramework::RecoverEntitySortInfo(parentId, childId, orderItr->second.second);
|
||||||
|
m_savedOrderInfo.erase(childId);
|
||||||
|
|
||||||
|
// force notify the child sort order changed on the parent entity info, but only if the restore didn't actually modify
|
||||||
|
// the order internally (and sent ChildEntityOrderArrayUpdated). that may seem heavy handed, and it is, but necessary
|
||||||
|
// to combat scenarios when the initial override detection returns a false positive (see comment about IDH comparisons
|
||||||
|
// in OnChildSortOrderChanged) and the slice instance source-to-live mapping hasn't been fully reconstructed yet.
|
||||||
|
if (!sortOrderUpdated)
|
||||||
|
{
|
||||||
|
parentInfo.OnChildSortOrderChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
+93
-17
@@ -8,11 +8,17 @@
|
|||||||
#include "EditorEntitySortComponent.h"
|
#include "EditorEntitySortComponent.h"
|
||||||
#include "EditorEntityInfoBus.h"
|
#include "EditorEntityInfoBus.h"
|
||||||
#include "EditorEntityHelpers.h"
|
#include "EditorEntityHelpers.h"
|
||||||
|
#include <AzCore/Component/TransformBus.h>
|
||||||
#include <AzCore/Debug/Profiler.h>
|
#include <AzCore/Debug/Profiler.h>
|
||||||
#include <AzCore/Serialization/EditContext.h>
|
#include <AzCore/Serialization/EditContext.h>
|
||||||
|
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||||
#include <AzCore/std/sort.h>
|
#include <AzCore/std/sort.h>
|
||||||
#include <AzFramework/API/ApplicationAPI.h>
|
#include <AzFramework/API/ApplicationAPI.h>
|
||||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||||
|
#include <AzToolsFramework/Prefab/PrefabPublicRequestBus.h>
|
||||||
|
#include <AzToolsFramework/Undo/UndoSystem.h>
|
||||||
|
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||||
|
#include <AzToolsFramework/Entity/EditorEntitySortComponentSerializer.h>
|
||||||
|
|
||||||
static_assert(sizeof(AZ::u64) == sizeof(AZ::EntityId), "We use AZ::EntityId for Persistent ID, which is a u64 under the hood. These must be the same size otherwise the persistent id will have to be rewritten");
|
static_assert(sizeof(AZ::u64) == sizeof(AZ::EntityId), "We use AZ::EntityId for Persistent ID, which is a u64 under the hood. These must be the same size otherwise the persistent id will have to be rewritten");
|
||||||
|
|
||||||
@@ -51,6 +57,12 @@ namespace AzToolsFramework
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AZ::JsonRegistrationContext* jsonRegistration = azrtti_cast<AZ::JsonRegistrationContext*>(context);
|
||||||
|
if (jsonRegistration)
|
||||||
|
{
|
||||||
|
jsonRegistration->Serializer<JsonEditorEntitySortComponentSerializer>()->HandlesType<EditorEntitySortComponent>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorEntitySortComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
void EditorEntitySortComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||||
@@ -167,9 +179,6 @@ namespace AzToolsFramework
|
|||||||
}
|
}
|
||||||
|
|
||||||
MarkDirtyAndSendChangedEvent();
|
MarkDirtyAndSendChangedEvent();
|
||||||
|
|
||||||
// Use the ToolsApplication to mark the entity dirty, this will only do something if we already have an undo batch
|
|
||||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::AddDirtyEntity, GetEntityId());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -187,6 +196,10 @@ namespace AzToolsFramework
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
EntityOrderArray::iterator insertPosition = GetFirstSelectedEntityPosition();
|
EntityOrderArray::iterator insertPosition = GetFirstSelectedEntityPosition();
|
||||||
|
if (insertPosition != m_childEntityOrderArray.end())
|
||||||
|
{
|
||||||
|
++insertPosition;
|
||||||
|
}
|
||||||
retval = AddChildEntityInternal(entityId, false, insertPosition);
|
retval = AddChildEntityInternal(entityId, false, insertPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,9 +233,6 @@ namespace AzToolsFramework
|
|||||||
|
|
||||||
MarkDirtyAndSendChangedEvent();
|
MarkDirtyAndSendChangedEvent();
|
||||||
|
|
||||||
// Use the ToolsApplication to mark the entity dirty, this will only do something if we already have an undo batch
|
|
||||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::AddDirtyEntity, GetEntityId());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -272,6 +282,12 @@ namespace AzToolsFramework
|
|||||||
void EditorEntitySortComponent::OnPrefabInstancePropagationEnd()
|
void EditorEntitySortComponent::OnPrefabInstancePropagationEnd()
|
||||||
{
|
{
|
||||||
m_ignoreIncomingOrderChanges = false;
|
m_ignoreIncomingOrderChanges = false;
|
||||||
|
|
||||||
|
if (m_shouldSanityCheckStateAfterPropagation)
|
||||||
|
{
|
||||||
|
SanitizeOrderEntryArray();
|
||||||
|
m_shouldSanityCheckStateAfterPropagation = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorEntitySortComponent::MarkDirtyAndSendChangedEvent()
|
void EditorEntitySortComponent::MarkDirtyAndSendChangedEvent()
|
||||||
@@ -280,14 +296,8 @@ namespace AzToolsFramework
|
|||||||
// one of the event listeners needs to build the InstanceDataHierarchy
|
// one of the event listeners needs to build the InstanceDataHierarchy
|
||||||
m_entityOrderIsDirty = true;
|
m_entityOrderIsDirty = true;
|
||||||
|
|
||||||
// Force an immediate update for prefabs, which won't receive PrepareSave
|
// Use the ToolsApplication to mark the entity dirty, this will only do something if we already have an undo batch
|
||||||
bool isPrefabEnabled = false;
|
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::AddDirtyEntity, GetEntityId());
|
||||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
|
||||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
|
||||||
if (isPrefabEnabled)
|
|
||||||
{
|
|
||||||
PrepareSave();
|
|
||||||
}
|
|
||||||
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,9 +318,8 @@ namespace AzToolsFramework
|
|||||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||||
if (isPrefabEnabled)
|
if (isPrefabEnabled)
|
||||||
{
|
{
|
||||||
PostLoad();
|
m_shouldSanityCheckStateAfterPropagation = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send out that the order for our entity is now updated
|
// Send out that the order for our entity is now updated
|
||||||
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
||||||
}
|
}
|
||||||
@@ -336,6 +345,73 @@ namespace AzToolsFramework
|
|||||||
m_entityOrderIsDirty = false;
|
m_entityOrderIsDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorEntitySortComponent::SanitizeOrderEntryArray()
|
||||||
|
{
|
||||||
|
bool shouldEmitDirtyState = false;
|
||||||
|
|
||||||
|
// Remove invalid and duplicate entries that point at non-existent entities
|
||||||
|
AZStd::unordered_set<AZ::EntityId> duplicateIds;
|
||||||
|
for (auto it = m_childEntityOrderArray.begin(); it != m_childEntityOrderArray.end();)
|
||||||
|
{
|
||||||
|
if (!it->IsValid() || GetEntityById(*it) == nullptr || duplicateIds.contains(*it))
|
||||||
|
{
|
||||||
|
it = m_childEntityOrderArray.erase(it);
|
||||||
|
shouldEmitDirtyState = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
duplicateIds.insert(*it);
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append any missing children
|
||||||
|
EntityIdList children;
|
||||||
|
AZ::TransformBus::EventResult(children, GetEntityId(), &AZ::TransformBus::Events::GetChildren);
|
||||||
|
for (auto it = m_childEntityOrderArray.begin(); it != m_childEntityOrderArray.end(); ++it)
|
||||||
|
{
|
||||||
|
if (auto removedChildrenIt = AZStd::remove(children.begin(), children.end(), *it); removedChildrenIt != children.end())
|
||||||
|
{
|
||||||
|
children.erase(removedChildrenIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AZStd::sort(children.begin(), children.end(), [](AZ::EntityId lhs, AZ::EntityId rhs)
|
||||||
|
{
|
||||||
|
return GetEntityById(lhs)->GetName() < GetEntityById(rhs)->GetName();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!children.empty())
|
||||||
|
{
|
||||||
|
shouldEmitDirtyState = true;
|
||||||
|
EntityOrderArray::iterator insertPosition = GetFirstSelectedEntityPosition();
|
||||||
|
if (insertPosition != m_childEntityOrderArray.end())
|
||||||
|
{
|
||||||
|
++insertPosition;
|
||||||
|
}
|
||||||
|
m_childEntityOrderArray.insert(insertPosition, children.begin(), children.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear out the vector to be rebuilt from persistent id
|
||||||
|
m_childEntityOrderEntryArray.resize(m_childEntityOrderArray.size());
|
||||||
|
for (size_t i = 0; i < m_childEntityOrderArray.size(); ++i)
|
||||||
|
{
|
||||||
|
m_childEntityOrderEntryArray[i] = {
|
||||||
|
m_childEntityOrderArray[i],
|
||||||
|
static_cast<AZ::u64>(i)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
RebuildEntityOrderCache();
|
||||||
|
|
||||||
|
if (shouldEmitDirtyState)
|
||||||
|
{
|
||||||
|
ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::Bus::Events::AddDirtyEntity, GetEntityId());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_entityOrderIsDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
void EditorEntitySortComponent::PostLoad()
|
void EditorEntitySortComponent::PostLoad()
|
||||||
{
|
{
|
||||||
// Clear out the vector to be rebuilt from persistent id
|
// Clear out the vector to be rebuilt from persistent id
|
||||||
@@ -383,7 +459,7 @@ namespace AzToolsFramework
|
|||||||
firstSelectedEntityPos = selectedEntityPos < firstSelectedEntityPos ? selectedEntityPos : firstSelectedEntityPos;
|
firstSelectedEntityPos = selectedEntityPos < firstSelectedEntityPos ? selectedEntityPos : firstSelectedEntityPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstSelectedEntityPos == m_childEntityOrderArray.end() ? m_childEntityOrderArray.begin() : firstSelectedEntityPos;
|
return firstSelectedEntityPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace AzToolsFramework
|
} // namespace AzToolsFramework
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ namespace AzToolsFramework
|
|||||||
, public EditorEntityContextNotificationBus::Handler
|
, public EditorEntityContextNotificationBus::Handler
|
||||||
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
||||||
{
|
{
|
||||||
|
friend class JsonEditorEntitySortComponentSerializer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AZ_COMPONENT(EditorEntitySortComponent, "{6EA1E03D-68B2-466D-97F7-83998C8C27F0}", EditorComponentBase);
|
AZ_COMPONENT(EditorEntitySortComponent, "{6EA1E03D-68B2-466D-97F7-83998C8C27F0}", EditorComponentBase);
|
||||||
|
|
||||||
@@ -64,6 +66,8 @@ namespace AzToolsFramework
|
|||||||
void PrepareSave();
|
void PrepareSave();
|
||||||
void PostLoad();
|
void PostLoad();
|
||||||
|
|
||||||
|
void SanitizeOrderEntryArray();
|
||||||
|
|
||||||
class EntitySortSerializationEvents
|
class EntitySortSerializationEvents
|
||||||
: public AZ::SerializeContext::IEventHandler
|
: public AZ::SerializeContext::IEventHandler
|
||||||
{
|
{
|
||||||
@@ -112,6 +116,7 @@ namespace AzToolsFramework
|
|||||||
|
|
||||||
bool m_entityOrderIsDirty = true; ///< This flag indicates our stored serialization order data is out of date and must be rebuilt before serialization occurs
|
bool m_entityOrderIsDirty = true; ///< This flag indicates our stored serialization order data is out of date and must be rebuilt before serialization occurs
|
||||||
bool m_ignoreIncomingOrderChanges = false; ///< This is set when prefab propagation occurs so that non-authored order changes can be ignored
|
bool m_ignoreIncomingOrderChanges = false; ///< This is set when prefab propagation occurs so that non-authored order changes can be ignored
|
||||||
|
bool m_shouldSanityCheckStateAfterPropagation = false; //< This is set after activation, to queue a cleanup of any invalid state after the next prefab propagation.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} // namespace AzToolsFramework
|
} // namespace AzToolsFramework
|
||||||
|
|||||||
+137
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||||
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
|
||||||
|
#include <AzCore/std/sort.h>
|
||||||
|
#include <AzToolsFramework/Entity/EditorEntitySortComponent.h>
|
||||||
|
#include <AzToolsFramework/Entity/EditorEntitySortComponentSerializer.h>
|
||||||
|
|
||||||
|
namespace AzToolsFramework::Components
|
||||||
|
{
|
||||||
|
AZ_CLASS_ALLOCATOR_IMPL(JsonEditorEntitySortComponentSerializer, AZ::SystemAllocator, 0);
|
||||||
|
|
||||||
|
AZ::JsonSerializationResult::Result JsonEditorEntitySortComponentSerializer::Load(
|
||||||
|
void* outputValue,
|
||||||
|
[[maybe_unused]] const AZ::Uuid& outputValueTypeId,
|
||||||
|
const rapidjson::Value& inputValue,
|
||||||
|
AZ::JsonDeserializerContext& context)
|
||||||
|
{
|
||||||
|
namespace JSR = AZ::JsonSerializationResult;
|
||||||
|
|
||||||
|
AZ_Assert(
|
||||||
|
azrtti_typeid<EditorEntitySortComponent>() == outputValueTypeId,
|
||||||
|
"Unable to deserialize EditorEntitySortComponent from json because the provided type is %s.",
|
||||||
|
outputValueTypeId.ToString<AZStd::string>().c_str());
|
||||||
|
|
||||||
|
EditorEntitySortComponent* sortComponentInstance = reinterpret_cast<EditorEntitySortComponent*>(outputValue);
|
||||||
|
AZ_Assert(sortComponentInstance, "Output value for JsonEditorEntitySortComponentSerializer can't be null.");
|
||||||
|
|
||||||
|
JSR::ResultCode result(JSR::Tasks::ReadField);
|
||||||
|
{
|
||||||
|
JSR::ResultCode componentIdLoadResult = ContinueLoadingFromJsonObjectField(
|
||||||
|
&sortComponentInstance->m_id, azrtti_typeid<decltype(sortComponentInstance->m_id)>(), inputValue,
|
||||||
|
"Id", context);
|
||||||
|
|
||||||
|
result.Combine(componentIdLoadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
sortComponentInstance->m_childEntityOrderArray.clear();
|
||||||
|
JSR::ResultCode enryLoadResult = ContinueLoadingFromJsonObjectField(
|
||||||
|
&sortComponentInstance->m_childEntityOrderArray,
|
||||||
|
azrtti_typeid<decltype(sortComponentInstance->m_childEntityOrderArray)>(), inputValue, "Child Entity Order",
|
||||||
|
context);
|
||||||
|
|
||||||
|
// Migrate ChildEntityOrderEntryArray -> ChildEntityOrderArray
|
||||||
|
if (sortComponentInstance->m_childEntityOrderArray.empty())
|
||||||
|
{
|
||||||
|
enryLoadResult = ContinueLoadingFromJsonObjectField(
|
||||||
|
&sortComponentInstance->m_childEntityOrderEntryArray,
|
||||||
|
azrtti_typeid<decltype(sortComponentInstance->m_childEntityOrderEntryArray)>(), inputValue,
|
||||||
|
"ChildEntityOrderEntryArray", context);
|
||||||
|
|
||||||
|
AZStd::sort(
|
||||||
|
sortComponentInstance->m_childEntityOrderEntryArray.begin(),
|
||||||
|
sortComponentInstance->m_childEntityOrderEntryArray.end(),
|
||||||
|
[](const EditorEntitySortComponent::EntityOrderEntry& lhs,
|
||||||
|
const EditorEntitySortComponent::EntityOrderEntry& rhs) -> bool
|
||||||
|
{
|
||||||
|
return lhs.m_sortIndex < rhs.m_sortIndex;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort by index and copy to the order array, any duplicates or invalid entries will be cleaned up by the sanitization pass
|
||||||
|
sortComponentInstance->m_childEntityOrderArray.resize(sortComponentInstance->m_childEntityOrderEntryArray.size());
|
||||||
|
for (size_t i = 0; i < sortComponentInstance->m_childEntityOrderEntryArray.size(); ++i)
|
||||||
|
{
|
||||||
|
sortComponentInstance->m_childEntityOrderArray[i] = sortComponentInstance->m_childEntityOrderEntryArray[i].m_entityId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sortComponentInstance->RebuildEntityOrderCache();
|
||||||
|
|
||||||
|
result.Combine(enryLoadResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Report(
|
||||||
|
result,
|
||||||
|
result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded EditorEntitySortComponent information."
|
||||||
|
: "Failed to load EditorEntitySortComponent information.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AZ::JsonSerializationResult::Result JsonEditorEntitySortComponentSerializer::Store(
|
||||||
|
rapidjson::Value& outputValue,
|
||||||
|
const void* inputValue,
|
||||||
|
const void* defaultValue,
|
||||||
|
[[maybe_unused]] const AZ::Uuid& valueTypeId,
|
||||||
|
AZ::JsonSerializerContext& context)
|
||||||
|
{
|
||||||
|
namespace JSR = AZ::JsonSerializationResult;
|
||||||
|
|
||||||
|
AZ_Assert(
|
||||||
|
azrtti_typeid<EditorEntitySortComponent>() == valueTypeId,
|
||||||
|
"Unable to Serialize EditorEntitySortComponent because the provided type is %s.",
|
||||||
|
valueTypeId.ToString<AZStd::string>().c_str());
|
||||||
|
|
||||||
|
const EditorEntitySortComponent* sortComponentInstance = reinterpret_cast<const EditorEntitySortComponent*>(inputValue);
|
||||||
|
AZ_Assert(sortComponentInstance, "Input value for JsonEditorEntitySortComponentSerializer can't be null.");
|
||||||
|
const EditorEntitySortComponent* defaultsortComponentInstance =
|
||||||
|
reinterpret_cast<const EditorEntitySortComponent*>(defaultValue);
|
||||||
|
|
||||||
|
JSR::ResultCode result(JSR::Tasks::WriteValue);
|
||||||
|
{
|
||||||
|
AZ::ScopedContextPath subPathName(context, "m_id");
|
||||||
|
const AZ::ComponentId* componentId = &sortComponentInstance->m_id;
|
||||||
|
const AZ::ComponentId* defaultComponentId =
|
||||||
|
defaultsortComponentInstance ? &defaultsortComponentInstance->m_id : nullptr;
|
||||||
|
|
||||||
|
JSR::ResultCode resultComponentId = ContinueStoringToJsonObjectField(
|
||||||
|
outputValue, "Id", componentId, defaultComponentId, azrtti_typeid<decltype(sortComponentInstance->m_id)>(),
|
||||||
|
context);
|
||||||
|
|
||||||
|
result.Combine(resultComponentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
AZ::ScopedContextPath subPathName(context, "m_childEntityOrderArray");
|
||||||
|
const EntityOrderArray* childEntityOrderArray = &sortComponentInstance->m_childEntityOrderArray;
|
||||||
|
const EntityOrderArray* defaultChildEntityOrderArray =
|
||||||
|
defaultsortComponentInstance ? &defaultsortComponentInstance->m_childEntityOrderArray : nullptr;
|
||||||
|
|
||||||
|
JSR::ResultCode resultParentEntityId = ContinueStoringToJsonObjectField(
|
||||||
|
outputValue, "Child Entity Order", childEntityOrderArray, defaultChildEntityOrderArray,
|
||||||
|
azrtti_typeid<decltype(sortComponentInstance->m_childEntityOrderArray)>(), context);
|
||||||
|
|
||||||
|
result.Combine(resultParentEntityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Report(
|
||||||
|
result,
|
||||||
|
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored EditorEntitySortComponent information."
|
||||||
|
: "Failed to store EditorEntitySortComponent information.");
|
||||||
|
}
|
||||||
|
} // namespace AzToolsFramework::Components
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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/Memory/Memory.h>
|
||||||
|
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||||
|
|
||||||
|
namespace AzToolsFramework::Components
|
||||||
|
{
|
||||||
|
class JsonEditorEntitySortComponentSerializer
|
||||||
|
: public AZ::BaseJsonSerializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AZ_RTTI(JsonEditorEntitySortComponentSerializer, "{5104782E-B34F-4D87-B1DF-BDFB1AF20D58}", BaseJsonSerializer);
|
||||||
|
AZ_CLASS_ALLOCATOR_DECL;
|
||||||
|
|
||||||
|
AZ::JsonSerializationResult::Result Load(
|
||||||
|
void* outputValue, const AZ::Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
|
||||||
|
AZ::JsonDeserializerContext& context) override;
|
||||||
|
|
||||||
|
AZ::JsonSerializationResult::Result Store(
|
||||||
|
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const AZ::Uuid& valueTypeId,
|
||||||
|
AZ::JsonSerializerContext& context) override;
|
||||||
|
};
|
||||||
|
} // namespace AzToolsFramework::Components
|
||||||
+3
-2
@@ -20,6 +20,7 @@
|
|||||||
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
||||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||||
#include <AzToolsFramework/Prefab/Template/Template.h>
|
#include <AzToolsFramework/Prefab/Template/Template.h>
|
||||||
|
#include <AzToolsFramework/Prefab/PrefabPublicRequestBus.h>
|
||||||
|
|
||||||
namespace AzToolsFramework
|
namespace AzToolsFramework
|
||||||
{
|
{
|
||||||
@@ -244,10 +245,10 @@ namespace AzToolsFramework
|
|||||||
selectedEntityIds.erase(entityIdIterator--);
|
selectedEntityIds.erase(entityIdIterator--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds);
|
|
||||||
|
|
||||||
// Notify Propagation has ended
|
// Notify Propagation has ended, then update selection (which is frozen during propagation, so this order matters)
|
||||||
PrefabPublicNotificationBus::Broadcast(&PrefabPublicNotifications::OnPrefabInstancePropagationEnd);
|
PrefabPublicNotificationBus::Broadcast(&PrefabPublicNotifications::OnPrefabInstancePropagationEnd);
|
||||||
|
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_updatingTemplateInstancesInQueue = false;
|
m_updatingTemplateInstancesInQueue = false;
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ namespace AzToolsFramework
|
|||||||
inline static const char* EntityIdName = "Id";
|
inline static const char* EntityIdName = "Id";
|
||||||
inline static const char* EntitiesName = "Entities";
|
inline static const char* EntitiesName = "Entities";
|
||||||
inline static const char* ContainerEntityName = "ContainerEntity";
|
inline static const char* ContainerEntityName = "ContainerEntity";
|
||||||
|
inline static const char* ComponentsName = "Components";
|
||||||
|
inline static const char* EntityOrderName = "Child Entity Order";
|
||||||
|
inline static const char* TypeName = "$type";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find Prefab value from given parent value and target value's name.
|
* Find Prefab value from given parent value and target value's name.
|
||||||
|
|||||||
@@ -212,7 +212,17 @@ namespace AzToolsFramework::Prefab
|
|||||||
|
|
||||||
AZ::EntityId PrefabFocusHandler::GetFocusedPrefabContainerEntityId([[maybe_unused]] AzFramework::EntityContextId entityContextId) const
|
AZ::EntityId PrefabFocusHandler::GetFocusedPrefabContainerEntityId([[maybe_unused]] AzFramework::EntityContextId entityContextId) const
|
||||||
{
|
{
|
||||||
return m_focusedInstanceContainerEntityId;
|
if (m_focusedInstanceContainerEntityId.IsValid())
|
||||||
|
{
|
||||||
|
return m_focusedInstanceContainerEntityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto instance = GetReferenceFromContainerEntityId(m_focusedInstanceContainerEntityId); instance.has_value())
|
||||||
|
{
|
||||||
|
return instance->get().GetContainerEntityId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return AZ::EntityId();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PrefabFocusHandler::IsOwningPrefabBeingFocused(AZ::EntityId entityId) const
|
bool PrefabFocusHandler::IsOwningPrefabBeingFocused(AZ::EntityId entityId) const
|
||||||
@@ -366,7 +376,7 @@ namespace AzToolsFramework::Prefab
|
|||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
size_t maxIndex = m_instanceFocusHierarchy.size() - 1;
|
size_t maxIndex = m_instanceFocusHierarchy.size() - 1;
|
||||||
|
|
||||||
for (const AZ::EntityId containerEntityId : m_instanceFocusHierarchy)
|
for (const AZ::EntityId& containerEntityId : m_instanceFocusHierarchy)
|
||||||
{
|
{
|
||||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||||
if (instance.has_value())
|
if (instance.has_value())
|
||||||
@@ -404,7 +414,7 @@ namespace AzToolsFramework::Prefab
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const AZ::EntityId containerEntityId : instances)
|
for (const AZ::EntityId& containerEntityId : instances)
|
||||||
{
|
{
|
||||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||||
|
|
||||||
@@ -423,7 +433,7 @@ namespace AzToolsFramework::Prefab
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const AZ::EntityId containerEntityId : instances)
|
for (const AZ::EntityId& containerEntityId : instances)
|
||||||
{
|
{
|
||||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <AzCore/Component/TransformBus.h>
|
#include <AzCore/Component/TransformBus.h>
|
||||||
#include <AzCore/JSON/stringbuffer.h>
|
#include <AzCore/JSON/stringbuffer.h>
|
||||||
#include <AzCore/JSON/writer.h>
|
#include <AzCore/JSON/writer.h>
|
||||||
|
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||||
#include <AzCore/Utils/TypeHash.h>
|
#include <AzCore/Utils/TypeHash.h>
|
||||||
|
|
||||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#include <AzToolsFramework/Prefab/PrefabUndo.h>
|
#include <AzToolsFramework/Prefab/PrefabUndo.h>
|
||||||
#include <AzToolsFramework/Prefab/PrefabUndoHelpers.h>
|
#include <AzToolsFramework/Prefab/PrefabUndoHelpers.h>
|
||||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||||
|
#include <AzToolsFramework/Entity/EditorEntitySortComponent.h>
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
@@ -595,8 +597,41 @@ namespace AzToolsFramework
|
|||||||
|
|
||||||
Instance& entityOwningInstance = owningInstanceOfParentEntity->get();
|
Instance& entityOwningInstance = owningInstanceOfParentEntity->get();
|
||||||
|
|
||||||
|
// Get the template for our owning instance from the root prefab DOM and use that to generate our patch
|
||||||
|
AZStd::vector<InstanceOptionalConstReference> pathOfInstances;
|
||||||
|
|
||||||
|
InstanceOptionalReference rootInstance = owningInstanceOfParentEntity;
|
||||||
|
while (rootInstance->get().GetParentInstance() != AZStd::nullopt)
|
||||||
|
{
|
||||||
|
pathOfInstances.emplace_back(rootInstance);
|
||||||
|
rootInstance = rootInstance->get().GetParentInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
AZStd::string aliasPathResult = "";
|
||||||
|
for (auto instanceIter = pathOfInstances.rbegin(); instanceIter != pathOfInstances.rend(); ++instanceIter)
|
||||||
|
{
|
||||||
|
aliasPathResult.append("/Instances/");
|
||||||
|
aliasPathResult.append((*instanceIter)->get().GetInstanceAlias());
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefabDomPath rootPrefabDomPath(aliasPathResult.c_str());
|
||||||
|
|
||||||
|
PrefabDom& rootPrefabTemplateDom = m_prefabSystemComponentInterface->FindTemplateDom(rootInstance->get().GetTemplateId());
|
||||||
|
|
||||||
|
auto instanceDomFromRootValue = rootPrefabDomPath.Get(rootPrefabTemplateDom);
|
||||||
|
if (!instanceDomFromRootValue)
|
||||||
|
{
|
||||||
|
return AZ::Failure<AZStd::string>("Could not load Instance DOM from the top level ancestor's DOM.");
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefabDomValueReference instanceDomFromRoot = *instanceDomFromRootValue;
|
||||||
|
if (!instanceDomFromRoot.has_value())
|
||||||
|
{
|
||||||
|
return AZ::Failure<AZStd::string>("Could not load Instance DOM from the top level ancestor's DOM.");
|
||||||
|
}
|
||||||
|
|
||||||
PrefabDom instanceDomBeforeUpdate;
|
PrefabDom instanceDomBeforeUpdate;
|
||||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBeforeUpdate, entityOwningInstance);
|
instanceDomBeforeUpdate.CopyFrom(instanceDomFromRoot.value().get(), instanceDomBeforeUpdate.GetAllocator());
|
||||||
|
|
||||||
ScopedUndoBatch undoBatch("Add Entity");
|
ScopedUndoBatch undoBatch("Add Entity");
|
||||||
|
|
||||||
@@ -674,6 +709,9 @@ namespace AzToolsFramework
|
|||||||
bool isInstanceContainerEntity = IsInstanceContainerEntity(entityId) && !IsLevelInstanceContainerEntity(entityId);
|
bool isInstanceContainerEntity = IsInstanceContainerEntity(entityId) && !IsLevelInstanceContainerEntity(entityId);
|
||||||
bool isNewParentOwnedByDifferentInstance = false;
|
bool isNewParentOwnedByDifferentInstance = false;
|
||||||
|
|
||||||
|
bool isInFocusTree = m_prefabFocusPublicInterface->IsOwningPrefabInFocusHierarchy(entityId);
|
||||||
|
bool isOwnedByFocusedPrefabInstance = m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId);
|
||||||
|
|
||||||
if (beforeParentId != afterParentId)
|
if (beforeParentId != afterParentId)
|
||||||
{
|
{
|
||||||
// If the entity parent changed, verify if the owning instance changed too
|
// If the entity parent changed, verify if the owning instance changed too
|
||||||
@@ -727,7 +765,7 @@ namespace AzToolsFramework
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isInstanceContainerEntity)
|
if (isInFocusTree && !isOwnedByFocusedPrefabInstance)
|
||||||
{
|
{
|
||||||
if (isNewParentOwnedByDifferentInstance)
|
if (isNewParentOwnedByDifferentInstance)
|
||||||
{
|
{
|
||||||
@@ -1648,6 +1686,144 @@ namespace AzToolsFramework
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrefabPublicHandler::AddNewEntityToSortOrder(
|
||||||
|
Instance& owningInstance,
|
||||||
|
PrefabDom& domToAddEntityUnder,
|
||||||
|
const EntityAlias& parentEntityAlias,
|
||||||
|
const EntityAlias& entityToAddAlias)
|
||||||
|
{
|
||||||
|
// Find the parent entity to get its sort order component
|
||||||
|
auto findParentEntity = [&]() -> rapidjson::Value*
|
||||||
|
{
|
||||||
|
if (auto containerEntityIter = domToAddEntityUnder.FindMember(PrefabDomUtils::ContainerEntityName);
|
||||||
|
containerEntityIter != domToAddEntityUnder.MemberEnd())
|
||||||
|
{
|
||||||
|
if (parentEntityAlias == containerEntityIter->value[PrefabDomUtils::EntityIdName].GetString())
|
||||||
|
{
|
||||||
|
return &containerEntityIter->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto entitiesIter = domToAddEntityUnder.FindMember(PrefabDomUtils::EntitiesName);
|
||||||
|
entitiesIter != domToAddEntityUnder.MemberEnd())
|
||||||
|
{
|
||||||
|
for (auto entityIter = entitiesIter->value.MemberBegin(); entityIter != entitiesIter->value.MemberEnd(); ++entityIter)
|
||||||
|
{
|
||||||
|
if (parentEntityAlias == entityIter->value[PrefabDomUtils::EntityIdName].GetString())
|
||||||
|
{
|
||||||
|
return &entityIter->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
rapidjson::Value* parentEntityValue = findParentEntity();
|
||||||
|
if (parentEntityValue == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the list of selected entities, we'll insert our duplicated entities after the last selected
|
||||||
|
// sibling in their parent's list, e.g. for:
|
||||||
|
// - Entity1
|
||||||
|
// - Entity2 (selected)
|
||||||
|
// - Entity3
|
||||||
|
// - Entity4 (selected)
|
||||||
|
// - Entity5
|
||||||
|
// Our duplicate selection command would create duplicate Entity2 and Entity4 and insert them after Entity4:
|
||||||
|
// - Entity1
|
||||||
|
// - Entity2
|
||||||
|
// - Entity3
|
||||||
|
// - Entity4
|
||||||
|
// - Entity2 (new, selected after duplicate)
|
||||||
|
// - Entity4 (new, selected after duplicate)
|
||||||
|
// - Entity5
|
||||||
|
AzToolsFramework::EntityIdList selectedEntities;
|
||||||
|
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
|
||||||
|
selectedEntities, &AzToolsFramework::ToolsApplicationRequests::GetSelectedEntities);
|
||||||
|
|
||||||
|
// Find the EditorEntitySortComponent DOM
|
||||||
|
auto componentsIter = parentEntityValue->FindMember(PrefabDomUtils::ComponentsName);
|
||||||
|
if (componentsIter == parentEntityValue->MemberEnd())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto componentIter = componentsIter->value.MemberBegin(); componentIter != componentIter->value.MemberEnd();
|
||||||
|
++componentIter)
|
||||||
|
{
|
||||||
|
// Check the component type
|
||||||
|
auto typeFieldIter = componentIter->value.FindMember(PrefabDomUtils::TypeName);
|
||||||
|
if (typeFieldIter == componentIter->value.MemberEnd())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AZ::JsonDeserializerSettings jsonDeserializerSettings;
|
||||||
|
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||||
|
AZ::JsonSerialization::LoadTypeId(typeId, typeFieldIter->value);
|
||||||
|
|
||||||
|
if (typeId != azrtti_typeid<Components::EditorEntitySortComponent>())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for the entity order field
|
||||||
|
auto orderMembersIter = componentIter->value.FindMember(PrefabDomUtils::EntityOrderName);
|
||||||
|
if (orderMembersIter == componentIter->value.MemberEnd() || !orderMembersIter->value.IsArray())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan for the last selected entity in the list (if any) to determine where to add our entries
|
||||||
|
rapidjson::Value newOrder(rapidjson::kArrayType);
|
||||||
|
auto insertValuesAfter = orderMembersIter->value.End();
|
||||||
|
for (auto orderMemberIter = orderMembersIter->value.Begin(); orderMemberIter != orderMembersIter->value.End();
|
||||||
|
++orderMemberIter)
|
||||||
|
{
|
||||||
|
if (!orderMemberIter->IsString())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const char* value = orderMemberIter->GetString();
|
||||||
|
for (AZ::EntityId selectedEntity : selectedEntities)
|
||||||
|
{
|
||||||
|
auto alias = owningInstance.GetEntityAlias(selectedEntity);
|
||||||
|
if (alias.has_value() && alias.value().get() == value)
|
||||||
|
{
|
||||||
|
insertValuesAfter = orderMemberIter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct our new array with the new order - insertion may happen at end, so check for that in the loop itself
|
||||||
|
for (auto orderMemberIter = orderMembersIter->value.Begin();; ++orderMemberIter)
|
||||||
|
{
|
||||||
|
if (orderMemberIter != orderMembersIter->value.End())
|
||||||
|
{
|
||||||
|
newOrder.PushBack(orderMemberIter->Move(), domToAddEntityUnder.GetAllocator());
|
||||||
|
}
|
||||||
|
if (orderMemberIter == insertValuesAfter)
|
||||||
|
{
|
||||||
|
newOrder.PushBack(
|
||||||
|
rapidjson::Value(entityToAddAlias.c_str(), domToAddEntityUnder.GetAllocator()),
|
||||||
|
domToAddEntityUnder.GetAllocator());
|
||||||
|
}
|
||||||
|
if (orderMemberIter == orderMembersIter->value.End())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the order with our newly constructed one
|
||||||
|
orderMembersIter->value.Swap(newOrder);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PrefabPublicHandler::DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
|
void PrefabPublicHandler::DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
|
||||||
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
||||||
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<EntityAlias, EntityAlias>& oldAliasToNewAliasMap)
|
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<EntityAlias, EntityAlias>& oldAliasToNewAliasMap)
|
||||||
@@ -1705,6 +1881,73 @@ namespace AzToolsFramework
|
|||||||
PrefabDom entityDomAfter(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
PrefabDom entityDomAfter(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||||
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
|
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
|
||||||
|
|
||||||
|
EntityAlias parentEntityAlias;
|
||||||
|
if (auto componentsIter = entityDomAfter.FindMember(PrefabDomUtils::ComponentsName);
|
||||||
|
componentsIter != entityDomAfter.MemberEnd())
|
||||||
|
{
|
||||||
|
auto checkComponent = [&](const rapidjson::Value& value) -> bool
|
||||||
|
{
|
||||||
|
if (!value.IsObject())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the component type
|
||||||
|
auto typeFieldIter = value.FindMember(PrefabDomUtils::TypeName);
|
||||||
|
if (typeFieldIter == value.MemberEnd())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AZ::JsonDeserializerSettings jsonDeserializerSettings;
|
||||||
|
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||||
|
AZ::JsonSerialization::LoadTypeId(typeId, typeFieldIter->value);
|
||||||
|
|
||||||
|
// Prefabs get serialized with the Editor transform component type, check for that
|
||||||
|
if (typeId != azrtti_typeid<Components::TransformComponent>())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto parentEntityIter = value.FindMember("Parent Entity");
|
||||||
|
parentEntityIter != value.MemberEnd())
|
||||||
|
{
|
||||||
|
parentEntityAlias = parentEntityIter->value.GetString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (componentsIter->value.IsObject())
|
||||||
|
{
|
||||||
|
for (auto componentIter = componentsIter->value.MemberBegin(); componentIter != componentsIter->value.MemberEnd();
|
||||||
|
++componentIter)
|
||||||
|
{
|
||||||
|
if (checkComponent(componentIter->value))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (componentsIter->value.IsArray())
|
||||||
|
{
|
||||||
|
for (auto componentIter = componentsIter->value.Begin(); componentIter != componentsIter->value.End();
|
||||||
|
++componentIter)
|
||||||
|
{
|
||||||
|
if (checkComponent(*componentIter))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert our entity into its parent's sort order
|
||||||
|
if (!parentEntityAlias.empty())
|
||||||
|
{
|
||||||
|
AddNewEntityToSortOrder(commonOwningInstance, domToAddDuplicatedEntitiesUnder, parentEntityAlias, newEntityAlias);
|
||||||
|
}
|
||||||
|
|
||||||
// Add the new Entity DOM to the Entities member of the instance
|
// Add the new Entity DOM to the Entities member of the instance
|
||||||
rapidjson::Value aliasName(newEntityAlias.c_str(), static_cast<rapidjson::SizeType>(newEntityAlias.length()), domToAddDuplicatedEntitiesUnder.GetAllocator());
|
rapidjson::Value aliasName(newEntityAlias.c_str(), static_cast<rapidjson::SizeType>(newEntityAlias.length()), domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||||
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, domToAddDuplicatedEntitiesUnder.GetAllocator());
|
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ namespace AzToolsFramework
|
|||||||
|
|
||||||
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
|
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
|
||||||
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
|
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
|
||||||
|
void AddNewEntityToSortOrder(Instance& owningInstance, PrefabDom& domToAddEntityUnder,
|
||||||
|
const EntityAlias& parentEntityAlias, const EntityAlias& entityToAddAlias);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Duplicate a list of entities owned by a common owning instance by directly
|
* Duplicate a list of entities owned by a common owning instance by directly
|
||||||
|
|||||||
-1
@@ -1599,7 +1599,6 @@ namespace AzToolsFramework
|
|||||||
for (size_t entityIndex = 1; entityIndex < m_selectedEntityIds.size(); ++entityIndex)
|
for (size_t entityIndex = 1; entityIndex < m_selectedEntityIds.size(); ++entityIndex)
|
||||||
{
|
{
|
||||||
entity = GetSelectedEntityById(m_selectedEntityIds[entityIndex]);
|
entity = GetSelectedEntityById(m_selectedEntityIds[entityIndex]);
|
||||||
AZ_Assert(entity, "Entity id selected for display but no such entity exists");
|
|
||||||
if (!entity)
|
if (!entity)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
+1
-4
@@ -150,10 +150,7 @@ namespace AzToolsFramework
|
|||||||
TypeBeingHandled actualValue = instance;
|
TypeBeingHandled actualValue = instance;
|
||||||
for (int idx = 0; idx < m_common.GetElementCount(); ++idx)
|
for (int idx = 0; idx < m_common.GetElementCount(); ++idx)
|
||||||
{
|
{
|
||||||
if (elements[idx]->wasValueEditedByUser())
|
actualValue.SetElement(idx, static_cast<float>(elements[idx]->getValue()));
|
||||||
{
|
|
||||||
actualValue.SetElement(idx, static_cast<float>(elements[idx]->getValue()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
instance = actualValue;
|
instance = actualValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ set(FILES
|
|||||||
Entity/EditorEntitySortBus.h
|
Entity/EditorEntitySortBus.h
|
||||||
Entity/EditorEntitySortComponent.cpp
|
Entity/EditorEntitySortComponent.cpp
|
||||||
Entity/EditorEntitySortComponent.h
|
Entity/EditorEntitySortComponent.h
|
||||||
|
Entity/EditorEntitySortComponentSerializer.cpp
|
||||||
|
Entity/EditorEntitySortComponentSerializer.h
|
||||||
Entity/EditorEntityTransformBus.h
|
Entity/EditorEntityTransformBus.h
|
||||||
Entity/PrefabEditorEntityOwnershipInterface.h
|
Entity/PrefabEditorEntityOwnershipInterface.h
|
||||||
Entity/PrefabEditorEntityOwnershipService.h
|
Entity/PrefabEditorEntityOwnershipService.h
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
// Attempt to use the Ninja build system if it is installed (described in the o3de documentation) if possible,
|
// Attempt to use the Ninja build system if it is installed (described in the o3de documentation) if possible,
|
||||||
// otherwise default to the the default for Linux (Unix Makefiles)
|
// otherwise default to the the default for Linux (Unix Makefiles)
|
||||||
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment());
|
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"});
|
||||||
QString cmakeGenerator = (whichNinjaResult.IsSuccess()) ? "Ninja Multi-Config" : "Unix Makefiles";
|
QString cmakeGenerator = (whichNinjaResult.IsSuccess()) ? "Ninja Multi-Config" : "Unix Makefiles";
|
||||||
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
|
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
AZ::Outcome<QStringList, QString> ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const
|
AZ::Outcome<QStringList, QString> ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const
|
||||||
{
|
{
|
||||||
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment());
|
auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"});
|
||||||
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
|
bool compileProfileOnBuild = (whichNinjaResult.IsSuccess());
|
||||||
QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix);
|
QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix);
|
||||||
QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher";
|
QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher";
|
||||||
|
|||||||
@@ -19,16 +19,15 @@ namespace O3DE::ProjectManager
|
|||||||
// The list of clang C/C++ compiler command lines to validate on the host Linux system
|
// The list of clang C/C++ compiler command lines to validate on the host Linux system
|
||||||
const QStringList SupportedClangVersions = {"13", "12", "11", "10", "9", "8", "7", "6.0"};
|
const QStringList SupportedClangVersions = {"13", "12", "11", "10", "9", "8", "7", "6.0"};
|
||||||
|
|
||||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment()
|
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
|
||||||
{
|
{
|
||||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
return AZ::Success();
|
||||||
return AZ::Success(currentEnvironment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
||||||
{
|
{
|
||||||
// Validate that cmake is installed and is in the command line
|
// Validate that cmake is installed and is in the command line
|
||||||
auto whichCMakeResult = ProjectUtils::ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, QProcessEnvironment::systemEnvironment());
|
auto whichCMakeResult = ProjectUtils::ExecuteCommandResult("which", QStringList{ProjectCMakeCommand});
|
||||||
if (!whichCMakeResult.IsSuccess())
|
if (!whichCMakeResult.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(QObject::tr("CMake not found. <br><br>"
|
return AZ::Failure(QObject::tr("CMake not found. <br><br>"
|
||||||
@@ -39,8 +38,8 @@ namespace O3DE::ProjectManager
|
|||||||
// Look for the first compatible version of clang. The list below will contain the known clang compilers that have been tested for O3DE.
|
// Look for the first compatible version of clang. The list below will contain the known clang compilers that have been tested for O3DE.
|
||||||
for (const QString& supportClangVersion : SupportedClangVersions)
|
for (const QString& supportClangVersion : SupportedClangVersions)
|
||||||
{
|
{
|
||||||
auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment());
|
auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang-%1").arg(supportClangVersion)});
|
||||||
auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang++-%1").arg(supportClangVersion)}, QProcessEnvironment::systemEnvironment());
|
auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{QString("clang++-%1").arg(supportClangVersion)});
|
||||||
if (whichClangResult.IsSuccess() && whichClangPPResult.IsSuccess())
|
if (whichClangResult.IsSuccess() && whichClangPPResult.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Success(QString("clang-%1").arg(supportClangVersion));
|
return AZ::Success(QString("clang-%1").arg(supportClangVersion));
|
||||||
@@ -54,7 +53,7 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
|
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
|
||||||
{
|
{
|
||||||
AZ::Outcome processEnvResult = GetCommandLineProcessEnvironment();
|
AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
|
||||||
if (!processEnvResult.IsSuccess())
|
if (!processEnvResult.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(processEnvResult.GetError());
|
return AZ::Failure(processEnvResult.GetError());
|
||||||
@@ -68,7 +67,6 @@ namespace O3DE::ProjectManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.setProcessEnvironment(processEnvResult.GetValue());
|
|
||||||
|
|
||||||
// if the project build path is relative, it should be relative to the project path
|
// if the project build path is relative, it should be relative to the project path
|
||||||
process.setWorkingDirectory(projectPath);
|
process.setWorkingDirectory(projectPath);
|
||||||
@@ -88,7 +86,6 @@ namespace O3DE::ProjectManager
|
|||||||
return ExecuteCommandResultModalDialog(
|
return ExecuteCommandResultModalDialog(
|
||||||
QString("%1/python/get_python.sh").arg(engineRoot),
|
QString("%1/python/get_python.sh").arg(engineRoot),
|
||||||
{},
|
{},
|
||||||
QProcessEnvironment::systemEnvironment(),
|
|
||||||
QObject::tr("Running get_python script..."));
|
QObject::tr("Running get_python script..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,16 +19,14 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
AZ::Outcome<QString, QString> QueryInstalledCmakeFullPath()
|
AZ::Outcome<QString, QString> QueryInstalledCmakeFullPath()
|
||||||
{
|
{
|
||||||
auto environmentRequest = ProjectUtils::GetCommandLineProcessEnvironment();
|
auto environmentRequest = ProjectUtils::SetupCommandLineProcessEnvironment();
|
||||||
if (!environmentRequest.IsSuccess())
|
if (!environmentRequest.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(environmentRequest.GetError());
|
return AZ::Failure(environmentRequest.GetError());
|
||||||
}
|
}
|
||||||
auto currentEnvironment = environmentRequest.GetValue();
|
|
||||||
|
|
||||||
auto queryCmakeInstalled = ProjectUtils::ExecuteCommandResult("which",
|
auto queryCmakeInstalled = ProjectUtils::ExecuteCommandResult("which",
|
||||||
QStringList{ProjectCMakeCommand},
|
QStringList{ProjectCMakeCommand});
|
||||||
currentEnvironment);
|
|
||||||
if (!queryCmakeInstalled.IsSuccess())
|
if (!queryCmakeInstalled.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
|
return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
|
||||||
|
|||||||
@@ -18,28 +18,36 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
namespace ProjectUtils
|
namespace ProjectUtils
|
||||||
{
|
{
|
||||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment()
|
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
|
||||||
{
|
{
|
||||||
// For CMake on Mac, if its installed through home-brew, then it will be installed
|
// For CMake on Mac, if its installed through home-brew, then it will be installed
|
||||||
// under /usr/local/bin, which may not be in the system PATH environment.
|
// under /usr/local/bin, which may not be in the system PATH environment.
|
||||||
// Add that path for the command line process so that it will be able to locate
|
// Add that path for the command line process so that it will be able to locate
|
||||||
// a home-brew installed version of CMake
|
// a home-brew installed version of CMake
|
||||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
QString pathEnv = qEnvironmentVariable("PATH");
|
||||||
QString pathValue = currentEnvironment.value("PATH");
|
QStringList pathEnvList = pathEnv.split(":");
|
||||||
pathValue += ":/usr/local/bin";
|
if (!pathEnvList.contains("/usr/local/bin"))
|
||||||
currentEnvironment.insert("PATH", pathValue);
|
{
|
||||||
return AZ::Success(currentEnvironment);
|
pathEnv += ":/usr/local/bin";
|
||||||
|
if (!qputenv("PATH", pathEnv.toStdString().c_str()))
|
||||||
|
{
|
||||||
|
return AZ::Failure(QObject::tr("Failed to set PATH environment variable"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AZ::Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
||||||
{
|
{
|
||||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
|
||||||
QString pathValue = currentEnvironment.value("PATH");
|
if (!processEnvResult.IsSuccess())
|
||||||
pathValue += ":/usr/local/bin";
|
{
|
||||||
currentEnvironment.insert("PATH", pathValue);
|
return AZ::Failure(processEnvResult.GetError());
|
||||||
|
}
|
||||||
|
|
||||||
// Validate that we have cmake installed first
|
// Validate that we have cmake installed first
|
||||||
auto queryCmakeInstalled = ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, currentEnvironment);
|
auto queryCmakeInstalled = ExecuteCommandResult("which", QStringList{ProjectCMakeCommand});
|
||||||
if (!queryCmakeInstalled.IsSuccess())
|
if (!queryCmakeInstalled.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
|
return AZ::Failure(QObject::tr("Unable to detect CMake on this host."));
|
||||||
@@ -47,7 +55,7 @@ namespace O3DE::ProjectManager
|
|||||||
QString cmakeInstalledPath = queryCmakeInstalled.GetValue().split("\n")[0];
|
QString cmakeInstalledPath = queryCmakeInstalled.GetValue().split("\n")[0];
|
||||||
|
|
||||||
// Query the version of the installed cmake
|
// Query the version of the installed cmake
|
||||||
auto queryCmakeVersionQuery = ExecuteCommandResult(cmakeInstalledPath, QStringList{"-version"}, currentEnvironment);
|
auto queryCmakeVersionQuery = ExecuteCommandResult(cmakeInstalledPath, QStringList{"-version"});
|
||||||
if (!queryCmakeVersionQuery.IsSuccess())
|
if (!queryCmakeVersionQuery.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(QObject::tr("Unable to determine the version of CMake on this host."));
|
return AZ::Failure(QObject::tr("Unable to determine the version of CMake on this host."));
|
||||||
@@ -55,7 +63,7 @@ namespace O3DE::ProjectManager
|
|||||||
AZ_TracePrintf("Project Manager", "Cmake version %s detected.", queryCmakeVersionQuery.GetValue().split("\n")[0].toUtf8().constData());
|
AZ_TracePrintf("Project Manager", "Cmake version %s detected.", queryCmakeVersionQuery.GetValue().split("\n")[0].toUtf8().constData());
|
||||||
|
|
||||||
// Query for the version of xcodebuild (if installed)
|
// Query for the version of xcodebuild (if installed)
|
||||||
auto queryXcodeBuildVersion = ExecuteCommandResult("xcodebuild", QStringList{"-version"}, currentEnvironment);
|
auto queryXcodeBuildVersion = ExecuteCommandResult("xcodebuild", QStringList{"-version"});
|
||||||
if (!queryCmakeInstalled.IsSuccess())
|
if (!queryCmakeInstalled.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(QObject::tr("Unable to detect XCodeBuilder on this host."));
|
return AZ::Failure(QObject::tr("Unable to detect XCodeBuilder on this host."));
|
||||||
@@ -104,7 +112,6 @@ namespace O3DE::ProjectManager
|
|||||||
return ExecuteCommandResultModalDialog(
|
return ExecuteCommandResultModalDialog(
|
||||||
QString("%1/python/get_python.sh").arg(engineRoot),
|
QString("%1/python/get_python.sh").arg(engineRoot),
|
||||||
{},
|
{},
|
||||||
QProcessEnvironment::systemEnvironment(),
|
|
||||||
QObject::tr("Running get_python script..."));
|
QObject::tr("Running get_python script..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace O3DE::ProjectManager
|
|||||||
{
|
{
|
||||||
namespace ProjectUtils
|
namespace ProjectUtils
|
||||||
{
|
{
|
||||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment()
|
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment()
|
||||||
{
|
{
|
||||||
// Use the engine path to insert a path for cmake
|
// Use the engine path to insert a path for cmake
|
||||||
auto engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
auto engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo();
|
||||||
@@ -31,26 +31,34 @@ namespace O3DE::ProjectManager
|
|||||||
}
|
}
|
||||||
auto engineInfo = engineInfoResult.GetValue();
|
auto engineInfo = engineInfoResult.GetValue();
|
||||||
|
|
||||||
QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment());
|
// Append cmake path to the current environment PATH incase it is missing, since if
|
||||||
|
// we are starting CMake itself the current application needs to find it using Path
|
||||||
// Append cmake path to PATH incase it is missing
|
// This also takes affect for all child processes.
|
||||||
QDir cmakePath(engineInfo.m_path);
|
QDir cmakePath(engineInfo.m_path);
|
||||||
cmakePath.cd("cmake/runtime/bin");
|
cmakePath.cd("cmake/runtime/bin");
|
||||||
QString pathValue = currentEnvironment.value("PATH");
|
QString pathEnv = qEnvironmentVariable("Path");
|
||||||
pathValue += ";" + cmakePath.path();
|
QStringList pathEnvList = pathEnv.split(";");
|
||||||
currentEnvironment.insert("PATH", pathValue);
|
if (!pathEnvList.contains(cmakePath.path()))
|
||||||
return AZ::Success(currentEnvironment);
|
{
|
||||||
|
pathEnv += ";" + cmakePath.path();
|
||||||
|
if (!qputenv("Path", pathEnv.toStdString().c_str()))
|
||||||
|
{
|
||||||
|
return AZ::Failure(QObject::tr("Failed to set Path environment variable"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AZ::Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
AZ::Outcome<QString, QString> FindSupportedCompilerForPlatform()
|
||||||
{
|
{
|
||||||
// Validate that cmake is installed
|
// Validate that cmake is installed
|
||||||
auto cmakeProcessEnvResult = GetCommandLineProcessEnvironment();
|
auto cmakeProcessEnvResult = SetupCommandLineProcessEnvironment();
|
||||||
if (!cmakeProcessEnvResult.IsSuccess())
|
if (!cmakeProcessEnvResult.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(cmakeProcessEnvResult.GetError());
|
return AZ::Failure(cmakeProcessEnvResult.GetError());
|
||||||
}
|
}
|
||||||
auto cmakeVersionQueryResult = ExecuteCommandResult("cmake", QStringList{"--version"}, cmakeProcessEnvResult.GetValue());
|
auto cmakeVersionQueryResult = ExecuteCommandResult("cmake", QStringList{"--version"});
|
||||||
if (!cmakeVersionQueryResult.IsSuccess())
|
if (!cmakeVersionQueryResult.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(QObject::tr("CMake not found. \n\n"
|
return AZ::Failure(QObject::tr("CMake not found. \n\n"
|
||||||
@@ -104,7 +112,7 @@ namespace O3DE::ProjectManager
|
|||||||
|
|
||||||
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
|
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath)
|
||||||
{
|
{
|
||||||
AZ::Outcome processEnvResult = GetCommandLineProcessEnvironment();
|
AZ::Outcome processEnvResult = SetupCommandLineProcessEnvironment();
|
||||||
if (!processEnvResult.IsSuccess())
|
if (!processEnvResult.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(processEnvResult.GetError());
|
return AZ::Failure(processEnvResult.GetError());
|
||||||
@@ -118,7 +126,6 @@ namespace O3DE::ProjectManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.setProcessEnvironment(processEnvResult.GetValue());
|
|
||||||
|
|
||||||
// if the project build path is relative, it should be relative to the project path
|
// if the project build path is relative, it should be relative to the project path
|
||||||
process.setWorkingDirectory(projectPath);
|
process.setWorkingDirectory(projectPath);
|
||||||
@@ -139,7 +146,6 @@ namespace O3DE::ProjectManager
|
|||||||
return ExecuteCommandResultModalDialog(
|
return ExecuteCommandResultModalDialog(
|
||||||
"cmd.exe",
|
"cmd.exe",
|
||||||
QStringList{"/c", batPath},
|
QStringList{"/c", batPath},
|
||||||
QProcessEnvironment::systemEnvironment(),
|
|
||||||
QObject::tr("Running get_python script..."));
|
QObject::tr("Running get_python script..."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +163,7 @@ namespace O3DE::ProjectManager
|
|||||||
.arg(shortcutPath)
|
.arg(shortcutPath)
|
||||||
.arg(targetPath)
|
.arg(targetPath)
|
||||||
.arg(arguments.join(' '));
|
.arg(arguments.join(' '));
|
||||||
auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg}, QProcessEnvironment::systemEnvironment());
|
auto createShortcutResult = ExecuteCommandResult(cmd, QStringList{"-Command", arg});
|
||||||
if (!createShortcutResult.IsSuccess())
|
if (!createShortcutResult.IsSuccess())
|
||||||
{
|
{
|
||||||
return AZ::Failure(QObject::tr("Failed to create desktop shortcut %1 <br><br>"
|
return AZ::Failure(QObject::tr("Failed to create desktop shortcut %1 <br><br>"
|
||||||
|
|||||||
@@ -117,18 +117,16 @@ namespace O3DE::ProjectManager
|
|||||||
// Show some kind of progress with very approximate estimates
|
// Show some kind of progress with very approximate estimates
|
||||||
UpdateProgress(++m_progressEstimate);
|
UpdateProgress(++m_progressEstimate);
|
||||||
|
|
||||||
auto currentEnvironmentRequest = ProjectUtils::GetCommandLineProcessEnvironment();
|
auto currentEnvironmentRequest = ProjectUtils::SetupCommandLineProcessEnvironment();
|
||||||
if (!currentEnvironmentRequest.IsSuccess())
|
if (!currentEnvironmentRequest.IsSuccess())
|
||||||
{
|
{
|
||||||
QStringToAZTracePrint(currentEnvironmentRequest.GetError());
|
QStringToAZTracePrint(currentEnvironmentRequest.GetError());
|
||||||
return AZ::Failure(currentEnvironmentRequest.GetError());
|
return AZ::Failure(currentEnvironmentRequest.GetError());
|
||||||
}
|
}
|
||||||
QProcessEnvironment currentEnvironment = currentEnvironmentRequest.GetValue();
|
|
||||||
|
|
||||||
m_configProjectProcess = new QProcess(this);
|
m_configProjectProcess = new QProcess(this);
|
||||||
m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
|
m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
|
||||||
m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
|
m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
|
||||||
m_configProjectProcess->setProcessEnvironment(currentEnvironment);
|
|
||||||
|
|
||||||
auto cmakeGenerateArgumentsResult = ConstructCmakeGenerateProjectArguments(engineInfo.m_thirdPartyPath);
|
auto cmakeGenerateArgumentsResult = ConstructCmakeGenerateProjectArguments(engineInfo.m_thirdPartyPath);
|
||||||
if (!cmakeGenerateArgumentsResult.IsSuccess())
|
if (!cmakeGenerateArgumentsResult.IsSuccess())
|
||||||
@@ -181,7 +179,6 @@ namespace O3DE::ProjectManager
|
|||||||
m_buildProjectProcess = new QProcess(this);
|
m_buildProjectProcess = new QProcess(this);
|
||||||
m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
|
m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels);
|
||||||
m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
|
m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path);
|
||||||
m_buildProjectProcess->setProcessEnvironment(currentEnvironment);
|
|
||||||
|
|
||||||
auto cmakeBuildArgumentsResult = ConstructCmakeBuildCommandArguments();
|
auto cmakeBuildArgumentsResult = ConstructCmakeBuildCommandArguments();
|
||||||
if (!cmakeBuildArgumentsResult.IsSuccess())
|
if (!cmakeBuildArgumentsResult.IsSuccess())
|
||||||
|
|||||||
@@ -520,12 +520,10 @@ namespace O3DE::ProjectManager
|
|||||||
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
|
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
|
||||||
const QString& cmd,
|
const QString& cmd,
|
||||||
const QStringList& arguments,
|
const QStringList& arguments,
|
||||||
const QProcessEnvironment& processEnv,
|
|
||||||
const QString& title)
|
const QString& title)
|
||||||
{
|
{
|
||||||
QString resultOutput;
|
QString resultOutput;
|
||||||
QProcess execProcess;
|
QProcess execProcess;
|
||||||
execProcess.setProcessEnvironment(processEnv);
|
|
||||||
execProcess.setProcessChannelMode(QProcess::MergedChannels);
|
execProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
QProgressDialog dialog(title, QObject::tr("Cancel"), /*minimum=*/0, /*maximum=*/0);
|
QProgressDialog dialog(title, QObject::tr("Cancel"), /*minimum=*/0, /*maximum=*/0);
|
||||||
@@ -611,11 +609,9 @@ namespace O3DE::ProjectManager
|
|||||||
AZ::Outcome<QString, QString> ExecuteCommandResult(
|
AZ::Outcome<QString, QString> ExecuteCommandResult(
|
||||||
const QString& cmd,
|
const QString& cmd,
|
||||||
const QStringList& arguments,
|
const QStringList& arguments,
|
||||||
const QProcessEnvironment& processEnv,
|
|
||||||
int commandTimeoutSeconds /*= ProjectCommandLineTimeoutSeconds*/)
|
int commandTimeoutSeconds /*= ProjectCommandLineTimeoutSeconds*/)
|
||||||
{
|
{
|
||||||
QProcess execProcess;
|
QProcess execProcess;
|
||||||
execProcess.setProcessEnvironment(processEnv);
|
|
||||||
execProcess.setProcessChannelMode(QProcess::MergedChannels);
|
execProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
execProcess.start(cmd, arguments);
|
execProcess.start(cmd, arguments);
|
||||||
if (!execProcess.waitForStarted())
|
if (!execProcess.waitForStarted())
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ namespace O3DE::ProjectManager
|
|||||||
AZ::Outcome<QString, QString> ExecuteCommandResult(
|
AZ::Outcome<QString, QString> ExecuteCommandResult(
|
||||||
const QString& cmd,
|
const QString& cmd,
|
||||||
const QStringList& arguments,
|
const QStringList& arguments,
|
||||||
const QProcessEnvironment& processEnv,
|
|
||||||
int commandTimeoutSeconds = ProjectCommandLineTimeoutSeconds);
|
int commandTimeoutSeconds = ProjectCommandLineTimeoutSeconds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,10 +60,9 @@ namespace O3DE::ProjectManager
|
|||||||
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
|
AZ::Outcome<QString, QString> ExecuteCommandResultModalDialog(
|
||||||
const QString& cmd,
|
const QString& cmd,
|
||||||
const QStringList& arguments,
|
const QStringList& arguments,
|
||||||
const QProcessEnvironment& processEnv,
|
|
||||||
const QString& title);
|
const QString& title);
|
||||||
|
|
||||||
AZ::Outcome<QProcessEnvironment, QString> GetCommandLineProcessEnvironment();
|
AZ::Outcome<void, QString> SetupCommandLineProcessEnvironment();
|
||||||
AZ::Outcome<QString, QString> GetProjectBuildPath(const QString& projectPath);
|
AZ::Outcome<QString, QString> GetProjectBuildPath(const QString& projectPath);
|
||||||
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath);
|
AZ::Outcome<void, QString> OpenCMakeGUI(const QString& projectPath);
|
||||||
AZ::Outcome<QString, QString> RunGetPythonScript(const QString& enginePath);
|
AZ::Outcome<QString, QString> RunGetPythonScript(const QString& enginePath);
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ ly_create_alias(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/Platform/${PAL_PLATFORM_NAME}/PAL_traits_editor_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
|
||||||
|
|
||||||
ly_add_target(
|
ly_add_target(
|
||||||
NAME AWSCore.Editor.Static STATIC
|
NAME AWSCore.Editor.Static STATIC
|
||||||
NAMESPACE Gem
|
NAMESPACE Gem
|
||||||
@@ -97,22 +100,31 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
|||||||
Gem::AWSCore.Editor.Static
|
Gem::AWSCore.Editor.Static
|
||||||
)
|
)
|
||||||
|
|
||||||
# This target is not a real gem module
|
if (PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL)
|
||||||
# It is not meant to be loaded by the ModuleManager in C++
|
|
||||||
ly_add_target(
|
# This target is not a real gem module
|
||||||
NAME AWSCore.ResourceMappingTool MODULE
|
# It is not meant to be loaded by the ModuleManager in C++
|
||||||
NAMESPACE Gem
|
ly_add_target(
|
||||||
OUTPUT_SUBDIRECTORY AWSCoreEditorQtBin
|
NAME AWSCore.ResourceMappingTool MODULE
|
||||||
FILES_CMAKE
|
NAMESPACE Gem
|
||||||
awscore_resourcemappingtool_files.cmake
|
OUTPUT_SUBDIRECTORY AWSCoreEditorQtBin
|
||||||
INCLUDE_DIRECTORIES
|
FILES_CMAKE
|
||||||
PRIVATE
|
awscore_resourcemappingtool_files.cmake
|
||||||
Include/Private
|
INCLUDE_DIRECTORIES
|
||||||
BUILD_DEPENDENCIES
|
PRIVATE
|
||||||
PRIVATE
|
Include/Private
|
||||||
Gem::AWSCore.Editor.Static
|
BUILD_DEPENDENCIES
|
||||||
)
|
PRIVATE
|
||||||
ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappingTool)
|
Gem::AWSCore.Editor.Static
|
||||||
|
RUNTIME_DEPENDENCIES
|
||||||
|
3rdParty::pyside2
|
||||||
|
|
||||||
|
)
|
||||||
|
ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappingTool)
|
||||||
|
|
||||||
|
ly_install_directory(DIRECTORIES Tools/ResourceMappingTool)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
# Builders and Tools (such as the Editor use AWSCore.Editor) use the .Editor module above.
|
# Builders and Tools (such as the Editor use AWSCore.Editor) use the .Editor module above.
|
||||||
ly_create_alias(
|
ly_create_alias(
|
||||||
|
|||||||
@@ -13,6 +13,8 @@
|
|||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "AWSCoreEditor_Traits_Platform.h"
|
||||||
|
|
||||||
namespace AWSCore
|
namespace AWSCore
|
||||||
{
|
{
|
||||||
class AWSCoreResourceMappingToolAction
|
class AWSCoreResourceMappingToolAction
|
||||||
@@ -22,7 +24,7 @@ namespace AWSCore
|
|||||||
static constexpr const char AWSCoreResourceMappingToolActionName[] = "AWSCoreResourceMappingToolAction";
|
static constexpr const char AWSCoreResourceMappingToolActionName[] = "AWSCoreResourceMappingToolAction";
|
||||||
static constexpr const char ResourceMappingToolDirectoryPath[] = "Gems/AWSCore/Code/Tools/ResourceMappingTool";
|
static constexpr const char ResourceMappingToolDirectoryPath[] = "Gems/AWSCore/Code/Tools/ResourceMappingTool";
|
||||||
static constexpr const char ResourceMappingToolLogDirectoryPath[] = "user/log/";
|
static constexpr const char ResourceMappingToolLogDirectoryPath[] = "user/log/";
|
||||||
static constexpr const char EngineWindowsPythonEntryScriptPath[] = "python/python.cmd";
|
static constexpr const char EngineWindowsPythonEntryScriptPath[] = AWSCORE_EDITOR_PYTHON_COMMAND;
|
||||||
|
|
||||||
AWSCoreResourceMappingToolAction(const QString& text, QObject* parent = nullptr);
|
AWSCoreResourceMappingToolAction(const QString& text, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 0
|
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 1
|
||||||
|
#define AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT ""
|
||||||
|
#define AWSCORE_EDITOR_PYTHON_COMMAND "python/python.sh"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# 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(PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL TRUE)
|
||||||
@@ -8,3 +8,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 0
|
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 0
|
||||||
|
#define AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT ""
|
||||||
|
#define AWSCORE_EDITOR_PYTHON_COMMAND "python/python.sh"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# 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(PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL FALSE)
|
||||||
@@ -8,3 +8,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 1
|
#define AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED 1
|
||||||
|
#define AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT "debug "
|
||||||
|
#define AWSCORE_EDITOR_PYTHON_COMMAND "python/python.cmd"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
# 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(PAL_TRAIT_ENABLE_RESOURCE_MAPPING_TOOL TRUE)
|
||||||
@@ -58,7 +58,7 @@ namespace AWSCore
|
|||||||
if (m_isDebug)
|
if (m_isDebug)
|
||||||
{
|
{
|
||||||
return AZStd::string::format(
|
return AZStd::string::format(
|
||||||
"\"%s\" debug -B \"%s\" --binaries-path \"%s\" --debug --profile \"%s\" --config-path \"%s\" --log-path \"%s\"",
|
"\"%s\" " AWSCORE_EDITOR_PYTHON_DEBUG_ARGUMENT "-B \"%s\" --binaries-path \"%s\" --debug --profile \"%s\" --config-path \"%s\" --log-path \"%s\"",
|
||||||
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(),
|
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(),
|
||||||
profileName.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str());
|
profileName.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,16 @@ Follow cmake instructions to configure your project, for example:
|
|||||||
```
|
```
|
||||||
$ python\python.cmd debug Gems\AWSCore\Code\Tools\ResourceMappingTool\resource_mapping_tool.py --binaries_path <PATH_TO_BUILD_FOLDER>\bin\debug\AWSCoreEditorQtBin
|
$ python\python.cmd debug Gems\AWSCore\Code\Tools\ResourceMappingTool\resource_mapping_tool.py --binaries_path <PATH_TO_BUILD_FOLDER>\bin\debug\AWSCoreEditorQtBin
|
||||||
```
|
```
|
||||||
|
* Linux
|
||||||
|
* release mode
|
||||||
|
```
|
||||||
|
$ python/python.sh Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py --binaries_path <PATH_TO_BUILD_FOLDER>/bin/profile/AWSCoreEditorQtBin
|
||||||
|
```
|
||||||
|
* debug mode
|
||||||
|
```
|
||||||
|
$ python/python.sh Gems/AWSCore/Code/Tools/ResourceMappingTool/resource_mapping_tool.py --binaries_path <PATH_TO_BUILD_FOLDER>/bin/debug/AWSCoreEditorQtBin
|
||||||
|
```
|
||||||
|
|
||||||
* Note - Editor is integrated with the same engine python environment to launch Resource Mapping Tool. If it is failed to launch the tool
|
* Note - Editor is integrated with the same engine python environment to launch Resource Mapping Tool. If it is failed to launch the tool
|
||||||
in Editor, please follow above steps to make sure expected scripts/binaries are present.
|
in Editor, please follow above steps to make sure expected scripts/binaries are present.
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ argument_parser.add_argument('--debug', action='store_true', help='Execute on de
|
|||||||
argument_parser.add_argument('--log-path', help='Path to resource mapping tool logging directory '
|
argument_parser.add_argument('--log-path', help='Path to resource mapping tool logging directory '
|
||||||
'(if not provided, logging file will be located at tool directory)')
|
'(if not provided, logging file will be located at tool directory)')
|
||||||
argument_parser.add_argument('--profile', default='default', help='Named AWS profile to use for querying AWS resources')
|
argument_parser.add_argument('--profile', default='default', help='Named AWS profile to use for querying AWS resources')
|
||||||
|
|
||||||
arguments: Namespace = argument_parser.parse_args()
|
arguments: Namespace = argument_parser.parse_args()
|
||||||
|
|
||||||
# logging setup
|
# logging setup
|
||||||
|
|||||||
+13
-2
@@ -5,6 +5,7 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
|||||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import platform
|
||||||
from typing import List
|
from typing import List
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from unittest.mock import (ANY, call, MagicMock, patch)
|
from unittest.mock import (ANY, call, MagicMock, patch)
|
||||||
@@ -27,14 +28,24 @@ class TestEnvironmentUtils(TestCase):
|
|||||||
self.addCleanup(os_pathsep_patcher.stop)
|
self.addCleanup(os_pathsep_patcher.stop)
|
||||||
self._mock_os_pathsep: MagicMock = os_pathsep_patcher.start()
|
self._mock_os_pathsep: MagicMock = os_pathsep_patcher.start()
|
||||||
|
|
||||||
def test_setup_qt_environment_global_flag_is_set(self) -> None:
|
@patch('os.path.exists')
|
||||||
|
@patch('ctypes.CDLL')
|
||||||
|
def test_setup_qt_environment_global_flag_is_set(self, mock_os_path_exists, mock_ctype_cdll) -> None:
|
||||||
|
mock_os_path_exists.return_value = True
|
||||||
environment_utils.setup_qt_environment("dummy")
|
environment_utils.setup_qt_environment("dummy")
|
||||||
self._mock_os_environ.copy.assert_called_once()
|
self._mock_os_environ.copy.assert_called_once()
|
||||||
self._mock_os_pathsep.join.assert_called_once()
|
self._mock_os_pathsep.join.assert_called_once()
|
||||||
assert environment_utils.is_qt_linked() is True
|
assert environment_utils.is_qt_linked() is True
|
||||||
|
if platform.system() == 'Linux':
|
||||||
|
mock_os_path_exists.assert_called()
|
||||||
|
|
||||||
def test_cleanup_qt_environment_global_flag_is_set(self) -> None:
|
@patch('os.path.exists')
|
||||||
|
@patch('ctypes.CDLL')
|
||||||
|
def test_cleanup_qt_environment_global_flag_is_set(self, mock_os_path_exists, mock_ctype_cdll) -> None:
|
||||||
|
mock_os_path_exists.return_value = True
|
||||||
environment_utils.setup_qt_environment("dummy")
|
environment_utils.setup_qt_environment("dummy")
|
||||||
assert environment_utils.is_qt_linked() is True
|
assert environment_utils.is_qt_linked() is True
|
||||||
environment_utils.cleanup_qt_environment()
|
environment_utils.cleanup_qt_environment()
|
||||||
assert environment_utils.is_qt_linked() is False
|
assert environment_utils.is_qt_linked() is False
|
||||||
|
if platform.system() == 'Linux':
|
||||||
|
mock_os_path_exists.assert_called()
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
from utils import file_utils
|
from utils import file_utils
|
||||||
@@ -38,6 +39,20 @@ def setup_qt_environment(bin_path: str) -> None:
|
|||||||
new_path = os.pathsep.join([binaries_path, path])
|
new_path = os.pathsep.join([binaries_path, path])
|
||||||
os.environ['PATH'] = new_path
|
os.environ['PATH'] = new_path
|
||||||
|
|
||||||
|
# On Linux, we need to load pyside2 and related modules as well
|
||||||
|
if platform.system() == 'Linux':
|
||||||
|
import ctypes
|
||||||
|
|
||||||
|
preload_shared_libs = [f'{bin_path}/libpyside2.abi3.so.5.14',
|
||||||
|
f'{bin_path}/libQt5Widgets.so.5']
|
||||||
|
|
||||||
|
for preload_shared_lib in preload_shared_libs:
|
||||||
|
if not os.path.exists(preload_shared_lib):
|
||||||
|
logger.error(f"Cannot find required shared library at {preload_shared_lib}")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
ctypes.CDLL(preload_shared_lib)
|
||||||
|
|
||||||
global qt_binaries_linked
|
global qt_binaries_linked
|
||||||
qt_binaries_linked = True
|
qt_binaries_linked = True
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,16 @@
|
|||||||
|
|
||||||
#include <PrefabGroup/ProceduralAssetHandler.h>
|
#include <PrefabGroup/ProceduralAssetHandler.h>
|
||||||
#include <AzCore/Asset/AssetTypeInfoBus.h>
|
#include <AzCore/Asset/AssetTypeInfoBus.h>
|
||||||
|
#include <AzCore/Serialization/Json/JsonUtils.h>
|
||||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||||
#include <AzFramework/FileFunc/FileFunc.h>
|
#include <AzFramework/FileFunc/FileFunc.h>
|
||||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
#include <AzQtComponents/Components/Widgets/FileDialog.h>
|
||||||
|
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||||
|
#include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h>
|
||||||
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
||||||
|
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||||
#include <AzToolsFramework/Prefab/Procedural/ProceduralPrefabAsset.h>
|
#include <AzToolsFramework/Prefab/Procedural/ProceduralPrefabAsset.h>
|
||||||
#include <AzCore/Serialization/Json/JsonUtils.h>
|
#include <QMenu>
|
||||||
|
|
||||||
namespace AZ::Prefab
|
namespace AZ::Prefab
|
||||||
{
|
{
|
||||||
@@ -21,6 +25,7 @@ namespace AZ::Prefab
|
|||||||
|
|
||||||
class PrefabGroupAssetHandler::AssetTypeInfoHandler final
|
class PrefabGroupAssetHandler::AssetTypeInfoHandler final
|
||||||
: public AZ::AssetTypeInfoBus::Handler
|
: public AZ::AssetTypeInfoBus::Handler
|
||||||
|
, protected AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AZ_CLASS_ALLOCATOR(AssetTypeInfoHandler, AZ::SystemAllocator, 0);
|
AZ_CLASS_ALLOCATOR(AssetTypeInfoHandler, AZ::SystemAllocator, 0);
|
||||||
@@ -31,15 +36,21 @@ namespace AZ::Prefab
|
|||||||
const char* GetGroup() const override;
|
const char* GetGroup() const override;
|
||||||
const char* GetBrowserIcon() const override;
|
const char* GetBrowserIcon() const override;
|
||||||
void GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions) override;
|
void GetAssetTypeExtensions(AZStd::vector<AZStd::string>& extensions) override;
|
||||||
|
|
||||||
|
// AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler
|
||||||
|
void AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>& entries) override;
|
||||||
|
bool SaveAsAuthoredPrefab(const AZ::Data::AssetId& assetId, const char* destinationFilename);
|
||||||
};
|
};
|
||||||
|
|
||||||
PrefabGroupAssetHandler::AssetTypeInfoHandler::AssetTypeInfoHandler()
|
PrefabGroupAssetHandler::AssetTypeInfoHandler::AssetTypeInfoHandler()
|
||||||
{
|
{
|
||||||
AZ::AssetTypeInfoBus::Handler::BusConnect(azrtti_typeid<ProceduralPrefabAsset>());
|
AZ::AssetTypeInfoBus::Handler::BusConnect(azrtti_typeid<ProceduralPrefabAsset>());
|
||||||
|
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrefabGroupAssetHandler::AssetTypeInfoHandler::~AssetTypeInfoHandler()
|
PrefabGroupAssetHandler::AssetTypeInfoHandler::~AssetTypeInfoHandler()
|
||||||
{
|
{
|
||||||
|
AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect();
|
||||||
AZ::AssetTypeInfoBus::Handler::BusDisconnect(azrtti_typeid<ProceduralPrefabAsset>());
|
AZ::AssetTypeInfoBus::Handler::BusDisconnect(azrtti_typeid<ProceduralPrefabAsset>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +79,84 @@ namespace AZ::Prefab
|
|||||||
extensions.push_back(PrefabGroupAssetHandler::s_Extension);
|
extensions.push_back(PrefabGroupAssetHandler::s_Extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrefabGroupAssetHandler::AssetTypeInfoHandler::AddContextMenuActions(
|
||||||
|
[[maybe_unused]] QWidget* caller,
|
||||||
|
QMenu* menu,
|
||||||
|
const AZStd::vector<AzToolsFramework::AssetBrowser::AssetBrowserEntry*>& entries)
|
||||||
|
{
|
||||||
|
using namespace AzToolsFramework::AssetBrowser;
|
||||||
|
auto entryIt = AZStd::find_if
|
||||||
|
(
|
||||||
|
entries.begin(),
|
||||||
|
entries.end(),
|
||||||
|
[](const AssetBrowserEntry* entry) -> bool
|
||||||
|
{
|
||||||
|
return entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (entryIt == entries.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ((*entryIt)->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
|
||||||
|
{
|
||||||
|
ProductAssetBrowserEntry* product = azrtti_cast<ProductAssetBrowserEntry*>(*entryIt);
|
||||||
|
if (product->GetAssetType() == azrtti_typeid<ProceduralPrefabAsset>())
|
||||||
|
{
|
||||||
|
AZ::Data::AssetId assetId = product->GetAssetId();
|
||||||
|
menu->addAction("Save as Prefab...", [assetId, this]()
|
||||||
|
{
|
||||||
|
QString filePath = AzQtComponents::FileDialog::GetSaveFileName(nullptr, QString("Save to file"), "", QString("Prefab file (*.prefab)"));
|
||||||
|
if (filePath.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (SaveAsAuthoredPrefab(assetId, filePath.toUtf8().data()))
|
||||||
|
{
|
||||||
|
AZ_Printf("Prefab", "Prefab was saved to a .prefab file %s", filePath.toUtf8().data());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PrefabGroupAssetHandler::AssetTypeInfoHandler::SaveAsAuthoredPrefab(const AZ::Data::AssetId& assetId, const char* destinationFilename)
|
||||||
|
{
|
||||||
|
using namespace AzToolsFramework::Prefab;
|
||||||
|
using namespace AZ::Data;
|
||||||
|
|
||||||
|
auto procPrefabAsset = AssetManager::Instance().GetAsset<ProceduralPrefabAsset>(assetId, AssetLoadBehavior::Default);
|
||||||
|
const auto status = AssetManager::Instance().BlockUntilLoadComplete(procPrefabAsset);
|
||||||
|
if (status != AssetData::AssetStatus::Ready)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* prefabLoaderInterface = AZ::Interface<PrefabLoaderInterface>::Get();
|
||||||
|
if (!prefabLoaderInterface)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto templateId = procPrefabAsset.GetAs<ProceduralPrefabAsset>()->GetTemplateId();
|
||||||
|
AZStd::string outputJson;
|
||||||
|
if (prefabLoaderInterface->SaveTemplateToString(templateId, outputJson) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto fileMode = AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath | AZ::IO::OpenMode::ModeText;
|
||||||
|
AZ::IO::FileIOStream outputFileStream;
|
||||||
|
if (outputFileStream.Open(destinationFilename, fileMode) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFileStream.Write(outputJson.size(), outputJson.data());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// PrefabGroupAssetHandler
|
// PrefabGroupAssetHandler
|
||||||
|
|
||||||
AZStd::string_view PrefabGroupAssetHandler::s_Extension{ "procprefab" };
|
AZStd::string_view PrefabGroupAssetHandler::s_Extension{ "procprefab" };
|
||||||
|
|||||||
-92
@@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
||||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ScriptEventReferencesComponent.h"
|
|
||||||
|
|
||||||
namespace ScriptEvents
|
|
||||||
{
|
|
||||||
namespace Components
|
|
||||||
{
|
|
||||||
void ScriptEventReferencesComponent::Reflect(AZ::ReflectContext* context)
|
|
||||||
{
|
|
||||||
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
||||||
{
|
|
||||||
// The Script Event References component is no longer necessary, as all Script Event assets
|
|
||||||
// will be properly loaded as needed.
|
|
||||||
serializeContext->ClassDeprecate("ScriptEventReferencesComponent", "{D0F440AC-32D4-49EC-8B93-860B188266A6}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptEventReferencesComponent::Activate()
|
|
||||||
{
|
|
||||||
for (auto& scriptEventReferences : m_scriptEventAssets)
|
|
||||||
{
|
|
||||||
const auto& asset = scriptEventReferences.GetAsset();
|
|
||||||
if (asset)
|
|
||||||
{
|
|
||||||
if (!AZ::Data::AssetBus::MultiHandler::BusIsConnectedId(asset.GetId()))
|
|
||||||
{
|
|
||||||
AZ::Data::AssetBus::MultiHandler::BusConnect(asset.GetId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the asset if it's not ready
|
|
||||||
if (!asset.IsReady())
|
|
||||||
{
|
|
||||||
AZ::Data::AssetInfo assetInfo;
|
|
||||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(assetInfo, &AZ::Data::AssetCatalogRequests::GetAssetInfoById, asset.GetId());
|
|
||||||
if (assetInfo.m_assetId.IsValid())
|
|
||||||
{
|
|
||||||
AZ::Data::AssetManager::Instance().GetAsset(asset.GetId(), azrtti_typeid<ScriptEventsAsset>(), AZ::Data::AssetLoadBehavior::Default)
|
|
||||||
.BlockUntilLoadComplete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AZ_Warning("Script Events", false, "ScriptEventReferencesComponent could not find Script Event asset: %s", scriptEventReferences.GetDefinition() ? scriptEventReferences.GetDefinition()->GetName().c_str() : scriptEventReferences.GetAsset().GetId().ToString<AZStd::string>().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptEventReferencesComponent::Deactivate()
|
|
||||||
{
|
|
||||||
for (auto& scriptEventReferences : m_scriptEventAssets)
|
|
||||||
{
|
|
||||||
const auto& asset = scriptEventReferences.GetAsset();
|
|
||||||
if (asset)
|
|
||||||
{
|
|
||||||
AZ::Data::AssetBus::MultiHandler::BusDisconnect(asset.GetId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptEventReferencesComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
|
||||||
{
|
|
||||||
provided.push_back(AZ_CRC("ScriptEventReference", 0x3df92d40));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptEventReferencesComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
|
||||||
{
|
|
||||||
incompatible.push_back(AZ_CRC("ScriptEventReference", 0x3df92d40));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptEventReferencesComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
|
||||||
{
|
|
||||||
dependent.push_back(AZ_CRC("LuaScriptService", 0x21d76c4b));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptEventReferencesComponent::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
|
||||||
{
|
|
||||||
if (ScriptEventsAsset* scriptEventAsset = asset.GetAs<ScriptEventsAsset>())
|
|
||||||
{
|
|
||||||
scriptEventAsset->m_definition.RegisterInternal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-44
@@ -1,44 +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
|
|
||||||
|
|
||||||
#include <ScriptEvents/ScriptEventsAssetRef.h>
|
|
||||||
#include <AzCore/Asset/AssetCommon.h>
|
|
||||||
|
|
||||||
namespace ScriptEvents
|
|
||||||
{
|
|
||||||
namespace Components
|
|
||||||
{
|
|
||||||
class ScriptEventReferencesComponent
|
|
||||||
: public AZ::Component
|
|
||||||
, private AZ::Data::AssetBus::MultiHandler
|
|
||||||
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
AZ_COMPONENT(ScriptEventReferencesComponent, "{D0F440AC-32D4-49EC-8B93-860B188266A6}", AZ::Component);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
// AZ::Component
|
|
||||||
void Init() override {}
|
|
||||||
void Activate() override;
|
|
||||||
void Deactivate() override;
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
|
||||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
|
||||||
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
|
|
||||||
|
|
||||||
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
|
||||||
static void Reflect(AZ::ReflectContext* reflection);
|
|
||||||
|
|
||||||
AZStd::vector<ScriptEvents::ScriptEventsAssetRef> m_scriptEventAssets;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <ScriptEvents/ScriptEventsGem.h>
|
#include <ScriptEvents/ScriptEventsGem.h>
|
||||||
#include <Source/Editor/ScriptEventsSystemEditorComponent.h>
|
#include <Source/Editor/ScriptEventsSystemEditorComponent.h>
|
||||||
|
|
||||||
#include <ScriptEvents/Components/ScriptEventReferencesComponent.h>
|
|
||||||
#include <Builder/ScriptEventsBuilderComponent.h>
|
#include <Builder/ScriptEventsBuilderComponent.h>
|
||||||
#include <ScriptEvents/ScriptEventsBus.h>
|
#include <ScriptEvents/ScriptEventsBus.h>
|
||||||
|
|
||||||
@@ -74,7 +73,6 @@ namespace ScriptEvents
|
|||||||
|
|
||||||
m_descriptors.insert(m_descriptors.end(), {
|
m_descriptors.insert(m_descriptors.end(), {
|
||||||
ScriptEventsEditor::ScriptEventEditorSystemComponent::CreateDescriptor(),
|
ScriptEventsEditor::ScriptEventEditorSystemComponent::CreateDescriptor(),
|
||||||
ScriptEvents::Components::ScriptEventReferencesComponent::CreateDescriptor(),
|
|
||||||
ScriptEventsBuilder::ScriptEventsBuilderComponent::CreateDescriptor(),
|
ScriptEventsBuilder::ScriptEventsBuilderComponent::CreateDescriptor(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
#include <ScriptEvents/ScriptEventsGem.h>
|
#include <ScriptEvents/ScriptEventsGem.h>
|
||||||
|
|
||||||
#include <ScriptEvents/Components/ScriptEventReferencesComponent.h>
|
|
||||||
|
|
||||||
namespace ScriptEvents
|
namespace ScriptEvents
|
||||||
{
|
{
|
||||||
ScriptEventsModule::ScriptEventsModule()
|
ScriptEventsModule::ScriptEventsModule()
|
||||||
@@ -23,8 +21,7 @@ namespace ScriptEvents
|
|||||||
ScriptEventModuleConfigurationRequestBus::Handler::BusConnect();
|
ScriptEventModuleConfigurationRequestBus::Handler::BusConnect();
|
||||||
|
|
||||||
m_descriptors.insert(m_descriptors.end(), {
|
m_descriptors.insert(m_descriptors.end(), {
|
||||||
ScriptEvents::ScriptEventsSystemComponent::CreateDescriptor(),
|
ScriptEvents::ScriptEventsSystemComponent::CreateDescriptor()
|
||||||
ScriptEvents::Components::ScriptEventReferencesComponent::CreateDescriptor(),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,4 @@ set(FILES
|
|||||||
Include/ScriptEvents/Internal/BehaviorContextBinding/ScriptEventsBindingBus.h
|
Include/ScriptEvents/Internal/BehaviorContextBinding/ScriptEventsBindingBus.h
|
||||||
Include/ScriptEvents/Internal/BehaviorContextBinding/ScriptEventBinding.h
|
Include/ScriptEvents/Internal/BehaviorContextBinding/ScriptEventBinding.h
|
||||||
Include/ScriptEvents/Internal/BehaviorContextBinding/ScriptEventBinding.cpp
|
Include/ScriptEvents/Internal/BehaviorContextBinding/ScriptEventBinding.cpp
|
||||||
Include/ScriptEvents/Components/ScriptEventReferencesComponent.h
|
|
||||||
Include/ScriptEvents/Components/ScriptEventReferencesComponent.cpp
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,5 +2,10 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"materialType": "PbrTerrain.materialtype",
|
"materialType": "PbrTerrain.materialtype",
|
||||||
"parentMaterial": "",
|
"parentMaterial": "",
|
||||||
"propertyLayoutVersion": 1
|
"propertyLayoutVersion": 1,
|
||||||
|
"properties": {
|
||||||
|
"baseColor": {
|
||||||
|
"color": [ 0.18, 0.18, 0.18 ]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"baseColor": [
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"displayName": "Color",
|
||||||
|
"description": "Color is displayed as sRGB but the values are stored as linear color.",
|
||||||
|
"type": "Color",
|
||||||
|
"defaultValue": [ 1.0, 1.0, 1.0 ],
|
||||||
|
"connection": {
|
||||||
|
"type": "ShaderInput",
|
||||||
|
"name": "m_baseColor"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"settings": [
|
"settings": [
|
||||||
{
|
{
|
||||||
"id": "detailTextureMultiplier",
|
"id": "detailTextureMultiplier",
|
||||||
|
|||||||
@@ -93,10 +93,6 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
|||||||
|
|
||||||
ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial
|
ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial
|
||||||
{
|
{
|
||||||
float m_detailTextureMultiplier;
|
|
||||||
float m_detailFadeDistance;
|
|
||||||
float m_detailFadeLength;
|
|
||||||
|
|
||||||
Sampler m_sampler
|
Sampler m_sampler
|
||||||
{
|
{
|
||||||
AddressU = Wrap;
|
AddressU = Wrap;
|
||||||
@@ -109,22 +105,11 @@ ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial
|
|||||||
|
|
||||||
// Base Color
|
// Base Color
|
||||||
float3 m_baseColor;
|
float3 m_baseColor;
|
||||||
float m_baseColorFactor;
|
|
||||||
Texture2D m_baseColorMap;
|
|
||||||
|
|
||||||
// Normal
|
// Detail Material Properties
|
||||||
Texture2D m_normalMap;
|
float m_detailTextureMultiplier;
|
||||||
bool m_flipNormalX;
|
float m_detailFadeDistance;
|
||||||
bool m_flipNormalY;
|
float m_detailFadeLength;
|
||||||
float m_normalFactor;
|
|
||||||
|
|
||||||
// Roughness
|
|
||||||
Texture2D m_roughnessMap;
|
|
||||||
float m_roughnessFactor;
|
|
||||||
|
|
||||||
// Specular
|
|
||||||
Texture2D m_specularF0Map;
|
|
||||||
float m_specularF0Factor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
option bool o_useTerrainSmoothing = false;
|
option bool o_useTerrainSmoothing = false;
|
||||||
|
|||||||
@@ -57,7 +57,30 @@ DetailSurface GetDefaultDetailSurface()
|
|||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WeightDetailSurface(inout DetailSurface surface, in float weight)
|
||||||
|
{
|
||||||
|
surface.m_color *= weight;
|
||||||
|
surface.m_normal *= weight;
|
||||||
|
surface.m_roughness *= weight;
|
||||||
|
surface.m_specularF0 *= weight;
|
||||||
|
surface.m_metalness *= weight;
|
||||||
|
surface.m_occlusion *= weight;
|
||||||
|
surface.m_height *= weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddDetailSurface(inout DetailSurface surface, in DetailSurface surfaceToAdd)
|
||||||
|
{
|
||||||
|
surface.m_color += surfaceToAdd.m_color;
|
||||||
|
surface.m_normal += surfaceToAdd.m_normal;
|
||||||
|
surface.m_roughness += surfaceToAdd.m_roughness;
|
||||||
|
surface.m_specularF0 += surfaceToAdd.m_specularF0;
|
||||||
|
surface.m_metalness += surfaceToAdd.m_metalness;
|
||||||
|
surface.m_occlusion += surfaceToAdd.m_occlusion;
|
||||||
|
surface.m_height += surfaceToAdd.m_height;
|
||||||
|
}
|
||||||
|
|
||||||
// Detail material index getters
|
// Detail material index getters
|
||||||
|
|
||||||
uint GetDetailColorIndex(TerrainSrg::DetailMaterialData materialData)
|
uint GetDetailColorIndex(TerrainSrg::DetailMaterialData materialData)
|
||||||
{
|
{
|
||||||
return materialData.m_colorNormalImageIndices & 0x0000FFFF;
|
return materialData.m_colorNormalImageIndices & 0x0000FFFF;
|
||||||
@@ -95,22 +118,22 @@ uint GetDetailHeightIndex(TerrainSrg::DetailMaterialData materialData)
|
|||||||
|
|
||||||
// Detail material value getters
|
// Detail material value getters
|
||||||
|
|
||||||
float3 GetDetailColor(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
float3 GetDetailColor(TerrainSrg::DetailMaterialData materialData, float2 uv, float2 ddx, float2 ddy)
|
||||||
{
|
{
|
||||||
float3 color = materialData.m_baseColor;
|
float3 color = materialData.m_baseColor;
|
||||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureBaseColor) > 0)
|
if ((materialData.m_flags & DetailTextureFlags::UseTextureBaseColor) > 0)
|
||||||
{
|
{
|
||||||
color = TerrainSrg::m_detailTextures[GetDetailColorIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).rgb;
|
color = TerrainSrg::m_detailTextures[GetDetailColorIndex(materialData)].SampleGrad(TerrainMaterialSrg::m_sampler, uv, ddx, ddy).rgb;
|
||||||
}
|
}
|
||||||
return color * materialData.m_baseColorFactor;
|
return color * materialData.m_baseColorFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
float3 GetDetailNormal(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
float3 GetDetailNormal(TerrainSrg::DetailMaterialData materialData, float2 uv, float2 ddx, float2 ddy)
|
||||||
{
|
{
|
||||||
float2 normal = float2(0.0, 0.0);
|
float2 normal = float2(0.0, 0.0);
|
||||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureNormal) > 0)
|
if ((materialData.m_flags & DetailTextureFlags::UseTextureNormal) > 0)
|
||||||
{
|
{
|
||||||
normal = TerrainSrg::m_detailTextures[GetDetailNormalIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).rg;
|
normal = TerrainSrg::m_detailTextures[GetDetailNormalIndex(materialData)].SampleGrad(TerrainMaterialSrg::m_sampler, uv, ddx, ddy).rg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// X and Y are inverted here to be consistent with SampleNormalXY in NormalInput.azsli.
|
// X and Y are inverted here to be consistent with SampleNormalXY in NormalInput.azsli.
|
||||||
@@ -125,53 +148,53 @@ float3 GetDetailNormal(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
|||||||
return GetTangentSpaceNormal(normal, materialData.m_normalFactor);
|
return GetTangentSpaceNormal(normal, materialData.m_normalFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDetailRoughness(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
float GetDetailRoughness(TerrainSrg::DetailMaterialData materialData, float2 uv, float2 ddx, float2 ddy)
|
||||||
{
|
{
|
||||||
float roughness = materialData.m_roughnessScale;
|
float roughness = materialData.m_roughnessScale;
|
||||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureRoughness) > 0)
|
if ((materialData.m_flags & DetailTextureFlags::UseTextureRoughness) > 0)
|
||||||
{
|
{
|
||||||
roughness = TerrainSrg::m_detailTextures[GetDetailRoughnessIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
roughness = TerrainSrg::m_detailTextures[GetDetailRoughnessIndex(materialData)].SampleGrad(TerrainMaterialSrg::m_sampler, uv, ddx, ddy).r;
|
||||||
roughness = materialData.m_roughnessBias + roughness * materialData.m_roughnessScale;
|
roughness = materialData.m_roughnessBias + roughness * materialData.m_roughnessScale;
|
||||||
}
|
}
|
||||||
return roughness;
|
return roughness;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDetailMetalness(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
float GetDetailMetalness(TerrainSrg::DetailMaterialData materialData, float2 uv, float2 ddx, float2 ddy)
|
||||||
{
|
{
|
||||||
float metalness = 1.0;
|
float metalness = 1.0;
|
||||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureMetallic) > 0)
|
if ((materialData.m_flags & DetailTextureFlags::UseTextureMetallic) > 0)
|
||||||
{
|
{
|
||||||
metalness = TerrainSrg::m_detailTextures[GetDetailMetalnessIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
metalness = TerrainSrg::m_detailTextures[GetDetailMetalnessIndex(materialData)].SampleGrad(TerrainMaterialSrg::m_sampler, uv, ddx, ddy).r;
|
||||||
}
|
}
|
||||||
return metalness * materialData.m_metalFactor;
|
return metalness * materialData.m_metalFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDetailSpecularF0(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
float GetDetailSpecularF0(TerrainSrg::DetailMaterialData materialData, float2 uv, float2 ddx, float2 ddy)
|
||||||
{
|
{
|
||||||
float specularF0 = 1.0;
|
float specularF0 = 1.0;
|
||||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureSpecularF0) > 0)
|
if ((materialData.m_flags & DetailTextureFlags::UseTextureSpecularF0) > 0)
|
||||||
{
|
{
|
||||||
specularF0 = TerrainSrg::m_detailTextures[GetDetailSpecularF0Index(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
specularF0 = TerrainSrg::m_detailTextures[GetDetailSpecularF0Index(materialData)].SampleGrad(TerrainMaterialSrg::m_sampler, uv, ddx, ddy).r;
|
||||||
}
|
}
|
||||||
return specularF0 * materialData.m_specularF0Factor;
|
return specularF0 * materialData.m_specularF0Factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDetailOcclusion(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
float GetDetailOcclusion(TerrainSrg::DetailMaterialData materialData, float2 uv, float2 ddx, float2 ddy)
|
||||||
{
|
{
|
||||||
float occlusion = 1.0;
|
float occlusion = 1.0;
|
||||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureOcclusion) > 0)
|
if ((materialData.m_flags & DetailTextureFlags::UseTextureOcclusion) > 0)
|
||||||
{
|
{
|
||||||
occlusion = TerrainSrg::m_detailTextures[GetDetailOcclusionIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
occlusion = TerrainSrg::m_detailTextures[GetDetailOcclusionIndex(materialData)].SampleGrad(TerrainMaterialSrg::m_sampler, uv, ddx, ddy).r;
|
||||||
}
|
}
|
||||||
return occlusion * materialData.m_occlusionFactor;
|
return occlusion * materialData.m_occlusionFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDetailHeight(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
float GetDetailHeight(TerrainSrg::DetailMaterialData materialData, float2 uv, float2 ddx, float2 ddy)
|
||||||
{
|
{
|
||||||
float height = materialData.m_heightFactor;
|
float height = materialData.m_heightFactor;
|
||||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureHeight) > 0)
|
if ((materialData.m_flags & DetailTextureFlags::UseTextureHeight) > 0)
|
||||||
{
|
{
|
||||||
height = TerrainSrg::m_detailTextures[GetDetailHeightIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
height = TerrainSrg::m_detailTextures[GetDetailHeightIndex(materialData)].SampleGrad(TerrainMaterialSrg::m_sampler, uv, ddx, ddy).r;
|
||||||
height = materialData.m_heightOffset + height * materialData.m_heightFactor;
|
height = materialData.m_heightOffset + height * materialData.m_heightFactor;
|
||||||
}
|
}
|
||||||
return height;
|
return height;
|
||||||
@@ -181,15 +204,19 @@ void GetDetailSurfaceForMaterial(inout DetailSurface surface, uint materialId, f
|
|||||||
{
|
{
|
||||||
TerrainSrg::DetailMaterialData detailMaterialData = TerrainSrg::m_detailMaterialData[materialId];
|
TerrainSrg::DetailMaterialData detailMaterialData = TerrainSrg::m_detailMaterialData[materialId];
|
||||||
|
|
||||||
surface.m_color = GetDetailColor(detailMaterialData, uv);
|
float2 uvDdx = ddx(uv);
|
||||||
surface.m_normal = GetDetailNormal(detailMaterialData, uv);
|
float2 uvDdy = ddy(uv);
|
||||||
surface.m_roughness = GetDetailRoughness(detailMaterialData, uv);
|
|
||||||
surface.m_specularF0 = GetDetailSpecularF0(detailMaterialData, uv);
|
surface.m_color = GetDetailColor(detailMaterialData, uv, uvDdx, uvDdy);
|
||||||
surface.m_metalness = GetDetailMetalness(detailMaterialData, uv);
|
surface.m_normal = GetDetailNormal(detailMaterialData, uv, uvDdx, uvDdy);
|
||||||
surface.m_occlusion = GetDetailOcclusion(detailMaterialData, uv);
|
surface.m_roughness = GetDetailRoughness(detailMaterialData, uv, uvDdx, uvDdy);
|
||||||
surface.m_height = GetDetailHeight(detailMaterialData, uv);
|
surface.m_specularF0 = GetDetailSpecularF0(detailMaterialData, uv, uvDdx, uvDdy);
|
||||||
|
surface.m_metalness = GetDetailMetalness(detailMaterialData, uv, uvDdx, uvDdy);
|
||||||
|
surface.m_occlusion = GetDetailOcclusion(detailMaterialData, uv, uvDdx, uvDdy);
|
||||||
|
surface.m_height = GetDetailHeight(detailMaterialData, uv, uvDdx, uvDdy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debugs the detail material by choosing a random color per material ID and rendering it without blending.
|
||||||
void GetDebugDetailSurface(inout DetailSurface surface, uint material1, uint material2, float blend, float2 idUv)
|
void GetDebugDetailSurface(inout DetailSurface surface, uint material1, uint material2, float blend, float2 idUv)
|
||||||
{
|
{
|
||||||
float3 material1Color = float3(0.1, 0.1, 0.1);
|
float3 material1Color = float3(0.1, 0.1, 0.1);
|
||||||
@@ -210,7 +237,7 @@ void GetDebugDetailSurface(inout DetailSurface surface, uint material1, uint mat
|
|||||||
surface.m_color = lerp(material1Color, material2Color, blend);
|
surface.m_color = lerp(material1Color, material2Color, blend);
|
||||||
float seamBlend = 0.0;
|
float seamBlend = 0.0;
|
||||||
const float halfLineWidth = 1.0 / 2048.0;
|
const float halfLineWidth = 1.0 / 2048.0;
|
||||||
if (any(abs(idUv) % 1.0 < halfLineWidth) || any(abs(idUv) % 1.0 > 1.0 - halfLineWidth))
|
if (any(frac(abs(idUv)) < halfLineWidth) || any(frac(abs(idUv)) > 1.0 - halfLineWidth))
|
||||||
{
|
{
|
||||||
seamBlend = 1.0;
|
seamBlend = 1.0;
|
||||||
}
|
}
|
||||||
@@ -225,26 +252,114 @@ void GetDebugDetailSurface(inout DetailSurface surface, uint material1, uint mat
|
|||||||
surface.m_height = 0.5;
|
surface.m_height = 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetDetailSurface(inout DetailSurface surface, float2 idUv, float2 uv)
|
//Blend a single detail material sample (with two possible material ids) onto a DetailSurface.
|
||||||
|
void BlendDetailMaterial(inout DetailSurface surface, uint material1, uint material2, float blend, float2 detailUv, float weight)
|
||||||
{
|
{
|
||||||
uint4 material1 = TerrainSrg::m_detailMaterialIdImage.GatherRed(TerrainSrg::DetailSampler, idUv, 0).xyzw;
|
DetailSurface tempSurface;
|
||||||
uint4 material2 = TerrainSrg::m_detailMaterialIdImage.GatherGreen(TerrainSrg::DetailSampler, idUv, 0).xyzw;
|
GetDetailSurfaceForMaterial(tempSurface, material1, detailUv);
|
||||||
|
WeightDetailSurface(tempSurface, weight * (1.0 - blend));
|
||||||
|
AddDetailSurface(surface, tempSurface);
|
||||||
|
if (material2 != 0xFF)
|
||||||
|
{
|
||||||
|
GetDetailSurfaceForMaterial(tempSurface, material2, detailUv);
|
||||||
|
WeightDetailSurface(tempSurface, weight * blend);
|
||||||
|
AddDetailSurface(surface, tempSurface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const float maxBlendAmount = 0xFF;
|
/*
|
||||||
|
Populates a DetailSurface with material data gathered form the 4 nearest samples to detailMaterialIdUv. The weight
|
||||||
|
of each detail material's contribution is calculated based on the distance to the center point for that sample (for
|
||||||
|
instance, if detailMaterialIdUv falls perfectly in-between all 4 samples, then each sample will be weighed at 25%).
|
||||||
|
Each sample can have two different detail materials defined with a blend value to determine their relative contribution.
|
||||||
|
The detailUv is used for sampling the textures of each detail material.
|
||||||
|
*/
|
||||||
|
bool GetDetailSurface(inout DetailSurface surface, float2 detailMaterialIdUv, float2 detailUv)
|
||||||
|
{
|
||||||
|
float2 textureSize;
|
||||||
|
TerrainSrg::m_detailMaterialIdImage.GetDimensions(textureSize.x, textureSize.y);
|
||||||
|
|
||||||
|
float2 detailMaterialIdCoord = detailMaterialIdUv * textureSize; // uv -> pixel coordinate
|
||||||
|
|
||||||
|
// detailMaterialIdCoord could be negative, so add textureSize to ensure it is positive
|
||||||
|
detailMaterialIdCoord += textureSize;
|
||||||
|
|
||||||
|
// The detail material id texture wraps since the "center" point can be anywhere in the texture, so mod by texturesize
|
||||||
|
int2 detailMaterailIdTopLeft = int2(detailMaterialIdCoord) % textureSize;
|
||||||
|
int2 detailMaterailIdBottomRight = (int2(detailMaterialIdCoord) + 1) % textureSize;
|
||||||
|
|
||||||
|
// Using Load() to gather the nearest 4 samples (Gather4() isn't used because of precision issues with uvs).
|
||||||
|
uint4 s1 = TerrainSrg::m_detailMaterialIdImage.Load(int3(detailMaterailIdTopLeft.x, detailMaterailIdBottomRight.y, 0));
|
||||||
|
uint4 s2 = TerrainSrg::m_detailMaterialIdImage.Load(int3(detailMaterailIdBottomRight, 0));
|
||||||
|
uint4 s3 = TerrainSrg::m_detailMaterialIdImage.Load(int3(detailMaterailIdBottomRight.x, detailMaterailIdTopLeft.y, 0));
|
||||||
|
uint4 s4 = TerrainSrg::m_detailMaterialIdImage.Load(int3(detailMaterailIdTopLeft, 0));
|
||||||
|
|
||||||
|
uint4 material1 = uint4(s1.x, s2.x, s3.x, s4.x);
|
||||||
|
uint4 material2 = uint4(s1.y, s2.y, s3.y, s4.y);
|
||||||
|
|
||||||
// convert integer of 0-255 to float of 0-1.
|
// convert integer of 0-255 to float of 0-1.
|
||||||
float4 blends = float4(TerrainSrg::m_detailMaterialIdImage.GatherBlue(TerrainSrg::DetailSampler, idUv, 0).xyzw) / maxBlendAmount;
|
const float maxBlendAmount = 0xFF;
|
||||||
|
float4 blends = float4(s1.z, s2.z, s3.z, s4.z) / maxBlendAmount;
|
||||||
|
|
||||||
|
// Calculate weight based on proximity to detail material samples
|
||||||
|
float2 gatherWeight = frac(detailMaterialIdCoord);
|
||||||
|
// Adjust the gather weight for better interpolation by (3x^2 - 2x^3). This helps avoid diamond-shaped artifacts in binlinear filtering.
|
||||||
|
gatherWeight = gatherWeight * gatherWeight * (3.0 - 2.0 * gatherWeight);
|
||||||
|
|
||||||
if (o_debugDetailMaterialIds)
|
if (o_debugDetailMaterialIds)
|
||||||
{
|
{
|
||||||
|
float2 idUv = (detailMaterialIdCoord + gatherWeight - 0.5) / textureSize;
|
||||||
GetDebugDetailSurface(surface, material1.x, material2.x, blends.x, idUv);
|
GetDebugDetailSurface(surface, material1.x, material2.x, blends.x, idUv);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (material1.x == 0xFF)
|
// If any sample has no materials, give up.
|
||||||
|
if (any(material1 == 0xFF))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetDetailSurfaceForMaterial(surface, material1.x, uv);
|
if (all(material1.x == material1.yzw) && all(material2.x == material2.yzw))
|
||||||
|
{
|
||||||
|
// Fast path for same material ids
|
||||||
|
GetDetailSurfaceForMaterial(surface, material1.x, detailUv);
|
||||||
|
if (material2.x != 0xFF)
|
||||||
|
{
|
||||||
|
float4 material2Blends = 1.0 - blends;
|
||||||
|
DetailSurface tempSurface;
|
||||||
|
float weight =
|
||||||
|
((1.0 - gatherWeight.x) * gatherWeight.y * material2Blends.x) +
|
||||||
|
(gatherWeight.x * gatherWeight.y * material2Blends.y) +
|
||||||
|
(gatherWeight.x * (1.0 - gatherWeight.y) * material2Blends.z) +
|
||||||
|
((1.0 - gatherWeight.x) * (1.0 - gatherWeight.y) * material2Blends.w);
|
||||||
|
WeightDetailSurface(surface, weight);
|
||||||
|
GetDetailSurfaceForMaterial(tempSurface, material2.x, detailUv);
|
||||||
|
WeightDetailSurface(tempSurface, 1.0 - weight);
|
||||||
|
AddDetailSurface(surface, tempSurface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
surface = (DetailSurface)0;
|
||||||
|
|
||||||
|
// X
|
||||||
|
float weight = (1.0 - gatherWeight.x) * gatherWeight.y;
|
||||||
|
BlendDetailMaterial(surface, material1.x, material2.x, blends.x, detailUv, weight);
|
||||||
|
|
||||||
|
// Y
|
||||||
|
weight = gatherWeight.x * gatherWeight.y;
|
||||||
|
BlendDetailMaterial(surface, material1.y, material2.y, blends.y, detailUv, weight);
|
||||||
|
|
||||||
|
// Z
|
||||||
|
weight = gatherWeight.x * (1.0 - gatherWeight.y);
|
||||||
|
BlendDetailMaterial(surface, material1.z, material2.z, blends.z, detailUv, weight);
|
||||||
|
|
||||||
|
// W
|
||||||
|
weight = (1.0 - gatherWeight.x) * (1.0 - gatherWeight.y);
|
||||||
|
BlendDetailMaterial(surface, material1.w, material2.w, blends.w, detailUv, weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
surface.m_normal = normalize(surface.m_normal);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,9 +109,10 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN)
|
|||||||
{
|
{
|
||||||
bool flipX = ObjectSrg::m_macroMaterialData[i].m_flipNormalX;
|
bool flipX = ObjectSrg::m_macroMaterialData[i].m_flipNormalX;
|
||||||
bool flipY = ObjectSrg::m_macroMaterialData[i].m_flipNormalY;
|
bool flipY = ObjectSrg::m_macroMaterialData[i].m_flipNormalY;
|
||||||
bool factor = ObjectSrg::m_macroMaterialData[i].m_normalFactor;
|
float factor = ObjectSrg::m_macroMaterialData[i].m_normalFactor;
|
||||||
macroNormal = GetNormalInputTS(ObjectSrg::m_macroNormalMap[i], TerrainMaterialSrg::m_sampler,
|
|
||||||
macroUv, flipX, flipY, CreateIdentity3x3(), true, factor);
|
float2 sampledValue = SampleNormalXY(ObjectSrg::m_macroNormalMap[i], TerrainMaterialSrg::m_sampler, macroUv, flipX, flipY);
|
||||||
|
macroNormal = normalize(GetTangentSpaceNormal_Unnormalized(sampledValue.xy, factor));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -129,7 +130,7 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN)
|
|||||||
// Check to make sure we're inside the detail texture's bounds and within where detail textures should be drawn.
|
// Check to make sure we're inside the detail texture's bounds and within where detail textures should be drawn.
|
||||||
if (detailFactor < 1.0 && all(detailRegionUv > TerrainSrg::m_detailHalfPixelUv) && all(detailRegionUv < 1.0 - TerrainSrg::m_detailHalfPixelUv))
|
if (detailFactor < 1.0 && all(detailRegionUv > TerrainSrg::m_detailHalfPixelUv) && all(detailRegionUv < 1.0 - TerrainSrg::m_detailHalfPixelUv))
|
||||||
{
|
{
|
||||||
detailRegionUv += TerrainSrg::m_detailMaterialIdImageCenter - (0.5);
|
detailRegionUv += TerrainSrg::m_detailMaterialIdImageCenter - 0.5;
|
||||||
hasDetailSurface = GetDetailSurface(detailSurface, detailRegionUv, detailUv);
|
hasDetailSurface = GetDetailSurface(detailSurface, detailRegionUv, detailUv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"Source" : "./TerrainPBR_ForwardPass.azsl",
|
"Source" : "./TerrainPBR_ForwardPass.azsl",
|
||||||
|
|
||||||
|
"CompilerHints" :
|
||||||
|
{
|
||||||
|
"DisableOptimizations" : false,
|
||||||
|
"GenerateDebugInfo" : false
|
||||||
|
},
|
||||||
|
|
||||||
"DepthStencilState" :
|
"DepthStencilState" :
|
||||||
{
|
{
|
||||||
"Depth" :
|
"Depth" :
|
||||||
|
|||||||
@@ -17,16 +17,6 @@ ShaderResourceGroupSemantic SRG_Terrain
|
|||||||
|
|
||||||
ShaderResourceGroup TerrainSrg : SRG_Terrain
|
ShaderResourceGroup TerrainSrg : SRG_Terrain
|
||||||
{
|
{
|
||||||
|
|
||||||
Sampler DetailSampler
|
|
||||||
{
|
|
||||||
AddressU = Wrap;
|
|
||||||
AddressV = Wrap;
|
|
||||||
MinFilter = Point;
|
|
||||||
MagFilter = Point;
|
|
||||||
MipFilter = Point;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DetailMaterialData
|
struct DetailMaterialData
|
||||||
{
|
{
|
||||||
// Uv
|
// Uv
|
||||||
|
|||||||
@@ -40,15 +40,17 @@ namespace Terrain
|
|||||||
|
|
||||||
->DataElement(AZ::Edit::UIHandlers::Default, &TerrainWorldConfig::m_worldMin, "World Bounds (Min)", "")
|
->DataElement(AZ::Edit::UIHandlers::Default, &TerrainWorldConfig::m_worldMin, "World Bounds (Min)", "")
|
||||||
// Temporary constraint until the rest of the Terrain system is updated to support larger worlds.
|
// Temporary constraint until the rest of the Terrain system is updated to support larger worlds.
|
||||||
|
->Attribute(AZ::Edit::Attributes::ChangeValidate, &TerrainWorldConfig::ValidateWorldMin)
|
||||||
->Attribute(AZ::Edit::Attributes::Min, -2048.0f)
|
->Attribute(AZ::Edit::Attributes::Min, -2048.0f)
|
||||||
->Attribute(AZ::Edit::Attributes::Max, 2048.0f)
|
->Attribute(AZ::Edit::Attributes::Max, 2048.0f)
|
||||||
->DataElement(AZ::Edit::UIHandlers::Default, &TerrainWorldConfig::m_worldMax, "World Bounds (Max)", "")
|
->DataElement(AZ::Edit::UIHandlers::Default, &TerrainWorldConfig::m_worldMax, "World Bounds (Max)", "")
|
||||||
// Temporary constraint until the rest of the Terrain system is updated to support larger worlds.
|
// Temporary constraint until the rest of the Terrain system is updated to support larger worlds.
|
||||||
|
->Attribute(AZ::Edit::Attributes::ChangeValidate, &TerrainWorldConfig::ValidateWorldMax)
|
||||||
->Attribute(AZ::Edit::Attributes::Min, -2048.0f)
|
->Attribute(AZ::Edit::Attributes::Min, -2048.0f)
|
||||||
->Attribute(AZ::Edit::Attributes::Max, 2048.0f)
|
->Attribute(AZ::Edit::Attributes::Max, 2048.0f)
|
||||||
->DataElement(
|
->DataElement(
|
||||||
AZ::Edit::UIHandlers::Default, &TerrainWorldConfig::m_heightQueryResolution, "Height Query Resolution (m)", "")
|
AZ::Edit::UIHandlers::Default, &TerrainWorldConfig::m_heightQueryResolution, "Height Query Resolution (m)", "")
|
||||||
;
|
->Attribute(AZ::Edit::Attributes::ChangeValidate, &TerrainWorldConfig::ValidateWorldHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,4 +130,42 @@ namespace Terrain
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
float TerrainWorldConfig::NumberOfSamples(AZ::Vector3* min, AZ::Vector3* max, AZ::Vector2* heightQuery)
|
||||||
|
{
|
||||||
|
float numberOfSamples = ((max->GetX() - min->GetX()) / heightQuery->GetX()) * ((max->GetY() - min->GetY()) / heightQuery->GetY());
|
||||||
|
return numberOfSamples;
|
||||||
|
}
|
||||||
|
|
||||||
|
AZ::Outcome<void, AZStd::string> TerrainWorldConfig::DetermineMessage(float numSamples)
|
||||||
|
{
|
||||||
|
const float maximumSamplesAllowed = 8.0f * 1024.0f * 1024.0f;
|
||||||
|
if (numSamples < maximumSamplesAllowed)
|
||||||
|
{
|
||||||
|
return AZ::Success();
|
||||||
|
}
|
||||||
|
return AZ::Failure(AZStd::string("The number of samples exceeds the maximum allowed."));
|
||||||
|
}
|
||||||
|
|
||||||
|
AZ::Outcome<void, AZStd::string> TerrainWorldConfig::ValidateWorldMin(void* newValue, [[maybe_unused]]const AZ::Uuid& valueType)
|
||||||
|
{
|
||||||
|
AZ::Vector3 minValue = *static_cast<AZ::Vector3*>(newValue);
|
||||||
|
|
||||||
|
return DetermineMessage(NumberOfSamples(&minValue, &m_worldMax, &m_heightQueryResolution));
|
||||||
|
}
|
||||||
|
|
||||||
|
AZ::Outcome<void, AZStd::string> TerrainWorldConfig::ValidateWorldMax(void* newValue, [[maybe_unused]] const AZ::Uuid& valueType)
|
||||||
|
{
|
||||||
|
AZ::Vector3 maxValue = *static_cast<AZ::Vector3*>(newValue);
|
||||||
|
|
||||||
|
return DetermineMessage(NumberOfSamples(&m_worldMin, &maxValue, &m_heightQueryResolution));
|
||||||
|
}
|
||||||
|
|
||||||
|
AZ::Outcome<void, AZStd::string> TerrainWorldConfig::ValidateWorldHeight(void* newValue, [[maybe_unused]] const AZ::Uuid& valueType)
|
||||||
|
{
|
||||||
|
AZ::Vector2 heightValue = *static_cast<AZ::Vector2*>(newValue);
|
||||||
|
|
||||||
|
return DetermineMessage(NumberOfSamples(&m_worldMin, &m_worldMax, &heightValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Terrain
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ namespace Terrain
|
|||||||
AZ::Vector3 m_worldMin{ 0.0f, 0.0f, 0.0f };
|
AZ::Vector3 m_worldMin{ 0.0f, 0.0f, 0.0f };
|
||||||
AZ::Vector3 m_worldMax{ 1024.0f, 1024.0f, 1024.0f };
|
AZ::Vector3 m_worldMax{ 1024.0f, 1024.0f, 1024.0f };
|
||||||
AZ::Vector2 m_heightQueryResolution{ 1.0f, 1.0f };
|
AZ::Vector2 m_heightQueryResolution{ 1.0f, 1.0f };
|
||||||
|
|
||||||
|
private:
|
||||||
|
AZ::Outcome<void, AZStd::string> ValidateWorldMin(void* newValue, const AZ::Uuid& valueType);
|
||||||
|
AZ::Outcome<void, AZStd::string> ValidateWorldMax(void* newValue, const AZ::Uuid& valueType);
|
||||||
|
AZ::Outcome<void, AZStd::string> ValidateWorldHeight(void* newValue, const AZ::Uuid& valueType);
|
||||||
|
float NumberOfSamples(AZ::Vector3* min, AZ::Vector3* max, AZ::Vector2* heightQuery);
|
||||||
|
AZ::Outcome<void, AZStd::string> DetermineMessage(float numSamples);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -27,6 +27,6 @@ namespace Terrain
|
|||||||
static constexpr const char* const s_componentDescription = "Provides height data for a region to the terrain system";
|
static constexpr const char* const s_componentDescription = "Provides height data for a region to the terrain system";
|
||||||
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainHeight.svg";
|
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainHeight.svg";
|
||||||
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainHeight.svg";
|
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainHeight.svg";
|
||||||
static constexpr const char* const s_helpUrl = "";
|
static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/terrain/height_gradient_list/";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,6 @@ namespace Terrain
|
|||||||
static constexpr const char* const s_componentDescription = "Defines a terrain region for use by the terrain system";
|
static constexpr const char* const s_componentDescription = "Defines a terrain region for use by the terrain system";
|
||||||
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainLayerSpawner.svg";
|
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainLayerSpawner.svg";
|
||||||
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainLayerSpawner.svg";
|
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainLayerSpawner.svg";
|
||||||
static constexpr const char* const s_helpUrl = "";
|
static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/terrain/layer_spawner/";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -27,6 +27,6 @@ namespace Terrain
|
|||||||
static constexpr const char* const s_componentDescription = "Provides a mapping between gradients and surface tags for use by the terrain system.";
|
static constexpr const char* const s_componentDescription = "Provides a mapping between gradients and surface tags for use by the terrain system.";
|
||||||
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainSurfaceGradientList.svg";
|
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainSurfaceGradientList.svg";
|
||||||
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainSurfaceGradientList.svg";
|
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainSurfaceGradientList.svg";
|
||||||
static constexpr const char* const s_helpUrl = "";
|
static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/terrain/surface-gradient-list/";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -27,6 +27,6 @@ namespace Terrain
|
|||||||
static constexpr const char* const s_componentDescription = "Provides a mapping between surface tags and render materials.";
|
static constexpr const char* const s_componentDescription = "Provides a mapping between surface tags and render materials.";
|
||||||
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainSurfaceMaterials.svg";
|
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainSurfaceMaterials.svg";
|
||||||
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainSurfaceMaterials.svg";
|
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainSurfaceMaterials.svg";
|
||||||
static constexpr const char* const s_helpUrl = "";
|
static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/terrain/surface-material-list/";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ cmake_policy(SET CMP0012 NEW) # new policy for the if that evaluates a boolean o
|
|||||||
|
|
||||||
function(ly_copy source_file target_directory)
|
function(ly_copy source_file target_directory)
|
||||||
cmake_path(GET source_file FILENAME target_filename)
|
cmake_path(GET source_file FILENAME target_filename)
|
||||||
|
cmake_PATH(GET source_file EXTENSION target_filename_ext)
|
||||||
cmake_path(APPEND target_file "${target_directory}" "${target_filename}")
|
cmake_path(APPEND target_file "${target_directory}" "${target_filename}")
|
||||||
cmake_path(COMPARE "${source_file}" EQUAL "${target_file}" same_location)
|
cmake_path(COMPARE "${source_file}" EQUAL "${target_file}" same_location)
|
||||||
if(NOT ${same_location})
|
if(NOT ${same_location})
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ REM
|
|||||||
REM
|
REM
|
||||||
|
|
||||||
REM To get recursive folder creation
|
REM To get recursive folder creation
|
||||||
SETLOCAL EnableExtensions
|
SETLOCAL EnableExtensions EnableDelayedExpansion
|
||||||
SETLOCAL EnableDelayedExpansion
|
|
||||||
|
|
||||||
where /Q cmake
|
where /Q cmake
|
||||||
IF NOT %ERRORLEVEL%==0 (
|
IF NOT %ERRORLEVEL%==0 (
|
||||||
@@ -22,21 +21,26 @@ IF NOT "%COMMAND_CWD%"=="" (
|
|||||||
CD %COMMAND_CWD%
|
CD %COMMAND_CWD%
|
||||||
)
|
)
|
||||||
|
|
||||||
REM Jenkins reports MSB8029 when TMP/TEMP is not defined, define a dummy folder
|
REM Ending the local environment to be able to propagate the TMP/TEMP variables to the calling script
|
||||||
IF NOT "%TMP%"=="" (
|
ENDLOCAL
|
||||||
IF NOT "%WORKSPACE_TMP%"=="" (
|
|
||||||
SET TMP=%WORKSPACE_TMP%
|
REM Jenkins does not defined TMP
|
||||||
SET TEMP=%WORKSPACE_TMP%
|
IF "%TMP%"=="" (
|
||||||
|
IF "%WORKSPACE%"=="" (
|
||||||
|
SET TMP=%APPDATA%\Local\Temp
|
||||||
|
SET TEMP=%APPDATA%\Local\Temp
|
||||||
) ELSE (
|
) ELSE (
|
||||||
SET TMP=%cd%/temp
|
SET TMP=%WORKSPACE%\Temp
|
||||||
SET TEMP=%cd%/temp
|
SET TEMP=%WORKSPACE%\Temp
|
||||||
|
REM This folder may not be created in the workspace
|
||||||
|
IF NOT EXIST "!TMP!" (
|
||||||
|
MKDIR "!TMP!"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
IF NOT EXIST "!TMP!" (
|
|
||||||
MKDIR "!TMP!"
|
|
||||||
)
|
|
||||||
|
|
||||||
EXIT /b 0
|
EXIT /b 0
|
||||||
|
|
||||||
:error
|
:error
|
||||||
|
ENDLOCAL
|
||||||
EXIT /b 1
|
EXIT /b 1
|
||||||
@@ -17,14 +17,6 @@ IF NOT EXIST %OUTPUT_DIRECTORY% (
|
|||||||
)
|
)
|
||||||
PUSHD %OUTPUT_DIRECTORY%
|
PUSHD %OUTPUT_DIRECTORY%
|
||||||
|
|
||||||
REM Override the temporary directory used by wix to the workspace (if we have a WORKSPACE_TMP)
|
|
||||||
IF NOT "%WORKSPACE_TMP%"=="" (
|
|
||||||
SET "WIX_TEMP=!WORKSPACE_TMP!/wix"
|
|
||||||
IF NOT EXIST "!WIX_TEMP!" (
|
|
||||||
MKDIR "!WIX_TEMP!"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Make sure we are using the CMake version of CPack and not the one that comes with chocolatey
|
REM Make sure we are using the CMake version of CPack and not the one that comes with chocolatey
|
||||||
SET CPACK_PATH=
|
SET CPACK_PATH=
|
||||||
IF "%LY_CMAKE_PATH%"=="" (
|
IF "%LY_CMAKE_PATH%"=="" (
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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 +x
|
||||||
|
|
||||||
|
export GPG_TTY=$(tty) # Required to pass valid tty during ssh sessions
|
||||||
|
file=$1
|
||||||
|
|
||||||
|
# dpkg-sig depends on a valid and trusted GPG private key. This also assumes a private key password has already been cached via gpg-agent
|
||||||
|
# If you do need to pass a password, a gpg argument can be added to the command:
|
||||||
|
# dpkg-sig -k $fingerprint -g "--pinentry-mode loopback --passphrase $pass" --sign builder
|
||||||
|
|
||||||
|
fingerprint=$(gpg --list-keys --with-colons | awk -F: '/fpr:/ {print $10}' | tail -n1) #Get the last certificate in the list, which is the signing cert
|
||||||
|
if [ -z $fingerprint ]; then
|
||||||
|
echo "No valid certs found. Exiting with 1"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Signing with $fingerprint"
|
||||||
|
dpkg-sig -k $fingerprint --sign builder $file
|
||||||
|
dpkg-sig --verify $file && echo "Signing $file complete!"
|
||||||
Reference in New Issue
Block a user