Merge branch 'upstream/development' into LYN-8514_AutomatedReviewServerLogChecks
This commit is contained in:
@@ -130,10 +130,11 @@ namespace AZStd::Internal
|
||||
|
||||
|
||||
//! Constructors
|
||||
constexpr fixed_trivial_storage() = default;
|
||||
fixed_trivial_storage() = default;
|
||||
|
||||
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");
|
||||
size_t index{};
|
||||
@@ -141,20 +142,19 @@ namespace AZStd::Internal
|
||||
{
|
||||
m_data[index++] = element;
|
||||
}
|
||||
resize_no_construct(ilist.size());
|
||||
}
|
||||
|
||||
constexpr pointer data() noexcept
|
||||
pointer data() noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
constexpr const_pointer data() const noexcept
|
||||
const_pointer data() const noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
//! Number of elements currently stored.
|
||||
constexpr size_type size() const noexcept
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
@@ -164,12 +164,12 @@ namespace AZStd::Internal
|
||||
return Capacity;
|
||||
}
|
||||
//! Is the storage empty?
|
||||
constexpr bool empty() const noexcept
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
//! Is the storage full?
|
||||
constexpr bool full() const noexcept
|
||||
bool full() const noexcept
|
||||
{
|
||||
return size() == capacity();
|
||||
}
|
||||
@@ -186,7 +186,7 @@ namespace AZStd::Internal
|
||||
//! Increases size of the storage by one.
|
||||
//! Always fails for empty storage.
|
||||
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");
|
||||
reference new_element = *(data() + size());
|
||||
@@ -196,7 +196,7 @@ namespace AZStd::Internal
|
||||
}
|
||||
//! Removes the last element of the storage.
|
||||
//! 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");
|
||||
resize_no_construct(size() - 1);
|
||||
@@ -205,7 +205,7 @@ namespace AZStd::Internal
|
||||
//! removing elements (unsafe).
|
||||
//!
|
||||
//! 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");
|
||||
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 is a no-op for trivial types
|
||||
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.
|
||||
//! This does not modify the size of the storage
|
||||
//! This is a no-op for trivial types
|
||||
constexpr void unsafe_destroy_all() noexcept
|
||||
void unsafe_destroy_all() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
T m_data[Capacity]{};
|
||||
T m_data[Capacity];
|
||||
size_type m_size{};
|
||||
};
|
||||
|
||||
@@ -245,7 +245,7 @@ namespace AZStd::Internal
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
|
||||
constexpr fixed_non_trivial_storage() = default;
|
||||
fixed_non_trivial_storage() = default;
|
||||
|
||||
~fixed_non_trivial_storage() noexcept
|
||||
{
|
||||
@@ -253,7 +253,7 @@ namespace AZStd::Internal
|
||||
}
|
||||
|
||||
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");
|
||||
for (const U& element : ilist)
|
||||
@@ -272,7 +272,7 @@ namespace AZStd::Internal
|
||||
}
|
||||
|
||||
//! Number of elements currently stored.
|
||||
constexpr size_type size() const noexcept
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
@@ -282,12 +282,12 @@ namespace AZStd::Internal
|
||||
return Capacity;
|
||||
}
|
||||
//! Is the storage empty?
|
||||
constexpr bool empty() const noexcept
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
//! Is the storage full?
|
||||
constexpr bool full() const noexcept
|
||||
bool full() const noexcept
|
||||
{
|
||||
return size() == capacity();
|
||||
}
|
||||
@@ -325,7 +325,7 @@ namespace AZStd::Internal
|
||||
//! removing elements (unsafe).
|
||||
//!
|
||||
//! 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");
|
||||
m_size = aznumeric_cast<size_type>(new_size);
|
||||
@@ -402,23 +402,23 @@ namespace AZStd
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
AZStd::uninitialized_fill_n(data(), numElements, value);
|
||||
}
|
||||
|
||||
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));
|
||||
AZStd::uninitialized_copy(first, last, data());
|
||||
}
|
||||
|
||||
|
||||
constexpr fixed_vector(const fixed_vector& rhs)
|
||||
fixed_vector(const fixed_vector& rhs)
|
||||
{
|
||||
resize_no_construct(rhs.size());
|
||||
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
|
||||
// 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
|
||||
constexpr fixed_vector(fixed_vector&& rhs)
|
||||
fixed_vector(fixed_vector&& rhs)
|
||||
{
|
||||
resize_no_construct(rhs.size());
|
||||
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
|
||||
template <typename VectorContainer, typename = AZStd::enable_if_t<!AZStd::is_same_v<VectorContainer, fixed_vector>
|
||||
&& !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>
|
||||
|| 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)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr fixed_vector& operator=(const fixed_vector& rhs)
|
||||
fixed_vector& operator=(const fixed_vector& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
{
|
||||
@@ -475,7 +475,7 @@ namespace AZStd
|
||||
return assign_helper(rhs);
|
||||
}
|
||||
|
||||
constexpr fixed_vector& operator=(fixed_vector&& rhs)
|
||||
fixed_vector& operator=(fixed_vector&& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
{
|
||||
@@ -487,23 +487,23 @@ namespace AZStd
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
constexpr iterator begin() { return iterator(data()); }
|
||||
constexpr const_iterator begin() const { return const_iterator(data()); }
|
||||
constexpr const_iterator cbegin() const { return const_iterator(data()); }
|
||||
constexpr iterator end() { return iterator(data() + size()); }
|
||||
constexpr const_iterator end() const { return const_iterator(data() + size()); }
|
||||
constexpr const_iterator cend() const { return const_iterator(data() + size()); }
|
||||
constexpr reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
constexpr const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||
constexpr const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
|
||||
constexpr reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
constexpr const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
||||
constexpr const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
|
||||
iterator begin() { return iterator(data()); }
|
||||
const_iterator begin() const { return const_iterator(data()); }
|
||||
const_iterator cbegin() const { return const_iterator(data()); }
|
||||
iterator end() { return iterator(data() + size()); }
|
||||
const_iterator end() const { return const_iterator(data() + size()); }
|
||||
const_iterator cend() const { return const_iterator(data() + size()); }
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||
const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
|
||||
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
|
||||
|
||||
// bring in fixed_vector_storage functions into scope
|
||||
using base_type::data;
|
||||
@@ -514,7 +514,7 @@ namespace AZStd
|
||||
// extension method
|
||||
using base_type::resize_no_construct;
|
||||
|
||||
constexpr size_type size() const noexcept
|
||||
size_type size() const noexcept
|
||||
{
|
||||
return base_type::size();
|
||||
}
|
||||
@@ -527,12 +527,12 @@ namespace AZStd
|
||||
return base_type::max_size();
|
||||
}
|
||||
|
||||
constexpr void resize(size_type newSize)
|
||||
void resize(size_type newSize)
|
||||
{
|
||||
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();
|
||||
if (dataSize < newSize)
|
||||
@@ -547,7 +547,7 @@ namespace AZStd
|
||||
|
||||
// Removes unused capacity - For fixed_vector this only asserts
|
||||
// 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
|
||||
AZSTD_CONTAINER_ASSERT(newCapacity <= capacity(),
|
||||
@@ -556,79 +556,79 @@ namespace AZStd
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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");
|
||||
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");
|
||||
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");
|
||||
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");
|
||||
return *(data() + position);
|
||||
}
|
||||
|
||||
constexpr reference front()
|
||||
reference front()
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
||||
return *data();
|
||||
}
|
||||
constexpr const_reference front() const
|
||||
const_reference front() const
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::front - container is empty!");
|
||||
return *data();
|
||||
}
|
||||
constexpr reference back()
|
||||
reference back()
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
||||
return *(data() + size() - 1);
|
||||
}
|
||||
constexpr const_reference back() const
|
||||
const_reference back() const
|
||||
{
|
||||
AZSTD_CONTAINER_ASSERT(!empty(), "AZStd::fixed_vector<>::back - container is empty!");
|
||||
return *(data() + size() - 1);
|
||||
}
|
||||
|
||||
constexpr void push_back(const_reference value)
|
||||
void push_back(const_reference value)
|
||||
{
|
||||
emplace_back(value);
|
||||
}
|
||||
|
||||
constexpr void assign(size_type numElements, const_reference value)
|
||||
void assign(size_type numElements, const_reference value)
|
||||
{
|
||||
clear();
|
||||
insert(end(), numElements, value);
|
||||
}
|
||||
|
||||
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();
|
||||
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());
|
||||
}
|
||||
|
||||
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(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)...);
|
||||
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");
|
||||
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");
|
||||
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)
|
||||
{
|
||||
@@ -708,24 +708,24 @@ namespace AZStd
|
||||
}
|
||||
|
||||
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.
|
||||
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());
|
||||
};
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
constexpr iterator erase(const_iterator elementIter)
|
||||
iterator erase(const_iterator elementIter)
|
||||
{
|
||||
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");
|
||||
iterator dataStart = begin();
|
||||
@@ -741,12 +741,12 @@ namespace AZStd
|
||||
return dataStart + offset;
|
||||
}
|
||||
|
||||
constexpr void clear()
|
||||
void clear()
|
||||
{
|
||||
base_type::unsafe_destroy_all();
|
||||
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.
|
||||
// The strategy is to extend the smaller fixed_vector to be the size
|
||||
@@ -776,12 +776,12 @@ namespace AZStd
|
||||
}
|
||||
|
||||
// Validate container status.
|
||||
constexpr bool validate() const
|
||||
bool validate() const
|
||||
{
|
||||
return size() <= max_size();
|
||||
}
|
||||
// Validate iterator.
|
||||
constexpr int validate_iterator(const_iterator iter) const
|
||||
int validate_iterator(const_iterator iter) const
|
||||
{
|
||||
const_pointer start = data();
|
||||
const_pointer end = data() + size();
|
||||
@@ -799,19 +799,19 @@ namespace AZStd
|
||||
}
|
||||
|
||||
// pushes back an empty without a provided instance.
|
||||
constexpr void push_back()
|
||||
void push_back()
|
||||
{
|
||||
emplace_back();
|
||||
}
|
||||
|
||||
constexpr void leak_and_reset()
|
||||
void leak_and_reset()
|
||||
{
|
||||
resize_no_construct(0);
|
||||
}
|
||||
|
||||
private:
|
||||
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>
|
||||
|| AZStd::is_const_v<VectorContainer>;
|
||||
@@ -872,7 +872,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
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);
|
||||
if (numElements == 0)
|
||||
@@ -923,7 +923,7 @@ namespace AZStd
|
||||
}
|
||||
|
||||
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();
|
||||
size_type offset = AZStd::distance(dataStart, insertPos);
|
||||
|
||||
@@ -753,7 +753,7 @@ namespace UnitTest
|
||||
|
||||
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 };
|
||||
EXPECT_EQ(sourceVector, copyConstructVector);
|
||||
@@ -768,32 +768,32 @@ namespace UnitTest
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_F(Arrays, FixedVectorComparisonOperatorsSucceedAsExpected)
|
||||
{
|
||||
constexpr AZStd::fixed_vector<int, 32> testVector{ 1,2,3,4,5 };
|
||||
constexpr AZStd::fixed_vector<int, 32> equalVector{ 1,2,3,4,5 };
|
||||
constexpr AZStd::fixed_vector<int, 32> notEqualVectorDifferentSize{ 1,2,3,4,5,6 };
|
||||
constexpr 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> testVector{ 1,2,3,4,5 };
|
||||
AZStd::fixed_vector<int, 32> equalVector{ 1,2,3,4,5 };
|
||||
AZStd::fixed_vector<int, 32> notEqualVectorDifferentSize{ 1,2,3,4,5,6 };
|
||||
AZStd::fixed_vector<int, 32> lessVector{ 1,2,3,4,4 };
|
||||
AZStd::fixed_vector<int, 32> greaterVectorDifferentSize{ 1,2,3,4,5, 1 };
|
||||
|
||||
static_assert(testVector == equalVector);
|
||||
static_assert(testVector != notEqualVectorDifferentSize);
|
||||
static_assert(testVector != lessVector);
|
||||
static_assert(lessVector < testVector);
|
||||
static_assert(lessVector < greaterVectorDifferentSize);
|
||||
static_assert(lessVector <= lessVector);
|
||||
static_assert(lessVector <= testVector);
|
||||
static_assert(lessVector <= greaterVectorDifferentSize);
|
||||
static_assert(testVector > lessVector);
|
||||
static_assert(testVector > lessVector);
|
||||
static_assert(notEqualVectorDifferentSize > testVector);
|
||||
static_assert(testVector >= testVector);
|
||||
static_assert(testVector >= lessVector);
|
||||
static_assert(greaterVectorDifferentSize > lessVector);
|
||||
EXPECT_EQ(testVector, equalVector);
|
||||
EXPECT_NE(testVector, notEqualVectorDifferentSize);
|
||||
EXPECT_NE(testVector, lessVector);
|
||||
EXPECT_LT(lessVector, testVector);
|
||||
EXPECT_LT(lessVector, greaterVectorDifferentSize);
|
||||
EXPECT_LE(lessVector, lessVector);
|
||||
EXPECT_LE(lessVector, testVector);
|
||||
EXPECT_LE(lessVector, greaterVectorDifferentSize);
|
||||
EXPECT_GT(testVector, lessVector);
|
||||
EXPECT_GT(testVector, lessVector);
|
||||
EXPECT_GT(notEqualVectorDifferentSize, testVector);
|
||||
EXPECT_GE(testVector, testVector);
|
||||
EXPECT_GE(testVector, lessVector);
|
||||
EXPECT_GT(greaterVectorDifferentSize, lessVector);
|
||||
}
|
||||
|
||||
TEST_F(Arrays, VectorSwap)
|
||||
|
||||
@@ -239,12 +239,14 @@ namespace AzToolsFramework
|
||||
, m_isInIsolationMode(false)
|
||||
{
|
||||
ToolsApplicationRequests::Bus::Handler::BusConnect();
|
||||
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusConnect();
|
||||
|
||||
m_undoCache.RegisterToUndoCacheInterface();
|
||||
}
|
||||
|
||||
ToolsApplication::~ToolsApplication()
|
||||
{
|
||||
AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect();
|
||||
ToolsApplicationRequests::Bus::Handler::BusDisconnect();
|
||||
Stop();
|
||||
}
|
||||
@@ -566,6 +568,12 @@ namespace AzToolsFramework
|
||||
void ToolsApplication::MarkEntitySelected(AZ::EntityId entityId)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_Assert(entityId.IsValid(), "Invalid entity Id being marked as selected.");
|
||||
|
||||
EntityIdList::iterator foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
||||
@@ -585,6 +593,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EntityIdList entitiesSelected;
|
||||
entitiesSelected.reserve(entitiesToSelect.size());
|
||||
|
||||
@@ -608,6 +621,12 @@ namespace AzToolsFramework
|
||||
void ToolsApplication::MarkEntityDeselected(AZ::EntityId entityId)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto foundIter = AZStd::find(m_selectedEntities.begin(), m_selectedEntities.end(), entityId);
|
||||
if (foundIter != m_selectedEntities.end())
|
||||
{
|
||||
@@ -625,6 +644,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ToolsApplicationEvents::Bus::Broadcast(&ToolsApplicationEvents::BeforeEntitySelectionChanged);
|
||||
|
||||
EntityIdSet entitySetToDeselect(entitiesToDeselect.begin(), entitiesToDeselect.end());
|
||||
@@ -679,6 +703,11 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
if (m_freezeSelectionUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We're setting the selection set as a batch from an external caller.
|
||||
// * Filter out any unselectable entities
|
||||
// * 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()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzToolsFramework/API/EditorEntityAPI.h>
|
||||
#include <AzToolsFramework/Application/EditorEntityManager.h>
|
||||
#include <AzToolsFramework/Commands/PreemptiveUndoCache.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicNotificationBus.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -29,6 +30,7 @@ namespace AzToolsFramework
|
||||
class ToolsApplication
|
||||
: public AzFramework::Application
|
||||
, public ToolsApplicationRequests::Bus::Handler
|
||||
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
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 ConsistencyCheckUndoCache();
|
||||
AZ::Aabb m_selectionBounds;
|
||||
@@ -181,6 +191,7 @@ namespace AzToolsFramework
|
||||
bool m_isDuringUndoRedo;
|
||||
bool m_isInIsolationMode;
|
||||
EntityIdSet m_isolatedEntityIdSet;
|
||||
bool m_freezeSelectionUpdates = false;
|
||||
|
||||
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);
|
||||
if (orderItr != m_savedOrderInfo.end() && orderItr->second.first == parentId)
|
||||
{
|
||||
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)
|
||||
bool isPrefabEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
// If prefabs are enabled, rely on the component to do a sanity check instead of restoring the order from the model
|
||||
if (!isPrefabEnabled)
|
||||
{
|
||||
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
|
||||
|
||||
+93
-17
@@ -8,11 +8,17 @@
|
||||
#include "EditorEntitySortComponent.h"
|
||||
#include "EditorEntityInfoBus.h"
|
||||
#include "EditorEntityHelpers.h"
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Debug/Profiler.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/Json/RegistrationContext.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
#include <AzFramework/API/ApplicationAPI.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");
|
||||
|
||||
@@ -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)
|
||||
@@ -167,9 +179,6 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -187,6 +196,10 @@ namespace AzToolsFramework
|
||||
else
|
||||
{
|
||||
EntityOrderArray::iterator insertPosition = GetFirstSelectedEntityPosition();
|
||||
if (insertPosition != m_childEntityOrderArray.end())
|
||||
{
|
||||
++insertPosition;
|
||||
}
|
||||
retval = AddChildEntityInternal(entityId, false, insertPosition);
|
||||
}
|
||||
|
||||
@@ -220,9 +233,6 @@ namespace AzToolsFramework
|
||||
|
||||
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 false;
|
||||
@@ -272,6 +282,12 @@ namespace AzToolsFramework
|
||||
void EditorEntitySortComponent::OnPrefabInstancePropagationEnd()
|
||||
{
|
||||
m_ignoreIncomingOrderChanges = false;
|
||||
|
||||
if (m_shouldSanityCheckStateAfterPropagation)
|
||||
{
|
||||
SanitizeOrderEntryArray();
|
||||
m_shouldSanityCheckStateAfterPropagation = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorEntitySortComponent::MarkDirtyAndSendChangedEvent()
|
||||
@@ -280,14 +296,8 @@ namespace AzToolsFramework
|
||||
// one of the event listeners needs to build the InstanceDataHierarchy
|
||||
m_entityOrderIsDirty = true;
|
||||
|
||||
// Force an immediate update for prefabs, which won't receive PrepareSave
|
||||
bool isPrefabEnabled = false;
|
||||
AzFramework::ApplicationRequests::Bus::BroadcastResult(
|
||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (isPrefabEnabled)
|
||||
{
|
||||
PrepareSave();
|
||||
}
|
||||
// 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());
|
||||
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
||||
}
|
||||
|
||||
@@ -308,9 +318,8 @@ namespace AzToolsFramework
|
||||
isPrefabEnabled, &AzFramework::ApplicationRequests::IsPrefabSystemEnabled);
|
||||
if (isPrefabEnabled)
|
||||
{
|
||||
PostLoad();
|
||||
m_shouldSanityCheckStateAfterPropagation = true;
|
||||
}
|
||||
|
||||
// Send out that the order for our entity is now updated
|
||||
EditorEntitySortNotificationBus::Event(GetEntityId(), &EditorEntitySortNotificationBus::Events::ChildEntityOrderArrayUpdated);
|
||||
}
|
||||
@@ -336,6 +345,73 @@ namespace AzToolsFramework
|
||||
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()
|
||||
{
|
||||
// Clear out the vector to be rebuilt from persistent id
|
||||
@@ -383,7 +459,7 @@ namespace AzToolsFramework
|
||||
firstSelectedEntityPos = selectedEntityPos < firstSelectedEntityPos ? selectedEntityPos : firstSelectedEntityPos;
|
||||
}
|
||||
|
||||
return firstSelectedEntityPos == m_childEntityOrderArray.end() ? m_childEntityOrderArray.begin() : firstSelectedEntityPos;
|
||||
return firstSelectedEntityPos;
|
||||
}
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace AzToolsFramework
|
||||
, public EditorEntityContextNotificationBus::Handler
|
||||
, public AzToolsFramework::Prefab::PrefabPublicNotificationBus::Handler
|
||||
{
|
||||
friend class JsonEditorEntitySortComponentSerializer;
|
||||
|
||||
public:
|
||||
AZ_COMPONENT(EditorEntitySortComponent, "{6EA1E03D-68B2-466D-97F7-83998C8C27F0}", EditorComponentBase);
|
||||
|
||||
@@ -64,6 +66,8 @@ namespace AzToolsFramework
|
||||
void PrepareSave();
|
||||
void PostLoad();
|
||||
|
||||
void SanitizeOrderEntryArray();
|
||||
|
||||
class EntitySortSerializationEvents
|
||||
: 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_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
|
||||
|
||||
+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/PrefabSystemComponentInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Template/Template.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicRequestBus.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -244,10 +245,10 @@ namespace AzToolsFramework
|
||||
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);
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequests::SetSelectedEntities, selectedEntityIds);
|
||||
}
|
||||
|
||||
m_updatingTemplateInstancesInQueue = false;
|
||||
|
||||
@@ -28,6 +28,9 @@ namespace AzToolsFramework
|
||||
inline static const char* EntityIdName = "Id";
|
||||
inline static const char* EntitiesName = "Entities";
|
||||
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.
|
||||
|
||||
@@ -212,7 +212,17 @@ namespace AzToolsFramework::Prefab
|
||||
|
||||
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
|
||||
@@ -366,7 +376,7 @@ namespace AzToolsFramework::Prefab
|
||||
size_t index = 0;
|
||||
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);
|
||||
if (instance.has_value())
|
||||
@@ -404,7 +414,7 @@ namespace AzToolsFramework::Prefab
|
||||
return;
|
||||
}
|
||||
|
||||
for (const AZ::EntityId containerEntityId : instances)
|
||||
for (const AZ::EntityId& containerEntityId : instances)
|
||||
{
|
||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||
|
||||
@@ -423,7 +433,7 @@ namespace AzToolsFramework::Prefab
|
||||
return;
|
||||
}
|
||||
|
||||
for (const AZ::EntityId containerEntityId : instances)
|
||||
for (const AZ::EntityId& containerEntityId : instances)
|
||||
{
|
||||
InstanceOptionalReference instance = GetReferenceFromContainerEntityId(containerEntityId);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/JSON/stringbuffer.h>
|
||||
#include <AzCore/JSON/writer.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Utils/TypeHash.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
@@ -29,6 +30,7 @@
|
||||
#include <AzToolsFramework/Prefab/PrefabUndo.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabUndoHelpers.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntitySortComponent.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
@@ -595,8 +597,41 @@ namespace AzToolsFramework
|
||||
|
||||
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;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBeforeUpdate, entityOwningInstance);
|
||||
instanceDomBeforeUpdate.CopyFrom(instanceDomFromRoot.value().get(), instanceDomBeforeUpdate.GetAllocator());
|
||||
|
||||
ScopedUndoBatch undoBatch("Add Entity");
|
||||
|
||||
@@ -674,6 +709,9 @@ namespace AzToolsFramework
|
||||
bool isInstanceContainerEntity = IsInstanceContainerEntity(entityId) && !IsLevelInstanceContainerEntity(entityId);
|
||||
bool isNewParentOwnedByDifferentInstance = false;
|
||||
|
||||
bool isInFocusTree = m_prefabFocusPublicInterface->IsOwningPrefabInFocusHierarchy(entityId);
|
||||
bool isOwnedByFocusedPrefabInstance = m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId);
|
||||
|
||||
if (beforeParentId != afterParentId)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
@@ -1648,6 +1686,144 @@ namespace AzToolsFramework
|
||||
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,
|
||||
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
||||
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<EntityAlias, EntityAlias>& oldAliasToNewAliasMap)
|
||||
@@ -1705,6 +1881,73 @@ namespace AzToolsFramework
|
||||
PrefabDom entityDomAfter(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
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
|
||||
rapidjson::Value aliasName(newEntityAlias.c_str(), static_cast<rapidjson::SizeType>(newEntityAlias.length()), domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
|
||||
@@ -78,6 +78,8 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) 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
|
||||
|
||||
-1
@@ -1599,7 +1599,6 @@ namespace AzToolsFramework
|
||||
for (size_t entityIndex = 1; entityIndex < m_selectedEntityIds.size(); ++entityIndex)
|
||||
{
|
||||
entity = GetSelectedEntityById(m_selectedEntityIds[entityIndex]);
|
||||
AZ_Assert(entity, "Entity id selected for display but no such entity exists");
|
||||
if (!entity)
|
||||
{
|
||||
continue;
|
||||
|
||||
+1
-4
@@ -150,10 +150,7 @@ namespace AzToolsFramework
|
||||
TypeBeingHandled actualValue = instance;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -148,6 +148,8 @@ set(FILES
|
||||
Entity/EditorEntitySortBus.h
|
||||
Entity/EditorEntitySortComponent.cpp
|
||||
Entity/EditorEntitySortComponent.h
|
||||
Entity/EditorEntitySortComponentSerializer.cpp
|
||||
Entity/EditorEntitySortComponentSerializer.h
|
||||
Entity/EditorEntityTransformBus.h
|
||||
Entity/PrefabEditorEntityOwnershipInterface.h
|
||||
Entity/PrefabEditorEntityOwnershipService.h
|
||||
|
||||
Reference in New Issue
Block a user