Cleanup: extract low level dna array utilities to separate file
This simplifies reusing those functions outside of the context of node sockets. Pull Request: https://projects.blender.org/blender/blender/pulls/117418
This commit is contained in:
parent
02fc4d6481
commit
c7e674d40f
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup DNA
|
||||
*
|
||||
* Contains functions that help dealing with arrays that are stored in DNA. Due to the constraints
|
||||
* of DNA, all structs are trivial from the language's point of view (`std::is_trivial_v`).
|
||||
* However, semantically, these types may have non-trivial copy-constructors and destructors.
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_index_range.hh"
|
||||
|
||||
namespace blender::dna::array {
|
||||
|
||||
/**
|
||||
* Removes an element from the array and shifts the elements after it towards the front.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void remove_index(
|
||||
T **items, int *items_num, int *active_index, const int index, void (*destruct_item)(T *))
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < *items_num);
|
||||
|
||||
const int old_items_num = *items_num;
|
||||
const int new_items_num = old_items_num - 1;
|
||||
|
||||
T *old_items = *items;
|
||||
T *new_items = MEM_cnew_array<T>(new_items_num, __func__);
|
||||
|
||||
std::copy_n(old_items, index, new_items);
|
||||
std::copy_n(old_items + index + 1, old_items_num - index - 1, new_items + index);
|
||||
|
||||
destruct_item(&old_items[index]);
|
||||
MEM_freeN(old_items);
|
||||
|
||||
*items = new_items;
|
||||
*items_num = new_items_num;
|
||||
|
||||
if (active_index) {
|
||||
const int old_active_index = active_index ? *active_index : 0;
|
||||
const int new_active_index = std::max(
|
||||
0, old_active_index == new_items_num ? new_items_num - 1 : old_active_index);
|
||||
*active_index = new_active_index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements from an array and frees it.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void clear(T **items, int *items_num, int *active_index, void (*destruct_item)(T *))
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
for (const int i : IndexRange(*items_num)) {
|
||||
destruct_item(&(*items)[i]);
|
||||
}
|
||||
MEM_SAFE_FREE(*items);
|
||||
*items_num = 0;
|
||||
if (active_index) {
|
||||
*active_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves one element from one index to another, moving other elements if necessary.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void move_index(T *items, const int items_num, const int from_index, const int to_index)
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
BLI_assert(from_index >= 0);
|
||||
BLI_assert(from_index < items_num);
|
||||
BLI_assert(to_index >= 0);
|
||||
BLI_assert(to_index < items_num);
|
||||
UNUSED_VARS_NDEBUG(items_num);
|
||||
|
||||
if (from_index == to_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (from_index < to_index) {
|
||||
const T tmp = items[from_index];
|
||||
for (int i = from_index; i < to_index; i++) {
|
||||
items[i] = items[i + 1];
|
||||
}
|
||||
items[to_index] = tmp;
|
||||
}
|
||||
else if (from_index > to_index) {
|
||||
const T tmp = items[from_index];
|
||||
for (int i = from_index; i > to_index; i--) {
|
||||
items[i] = items[i - 1];
|
||||
}
|
||||
items[to_index] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::dna::array
|
|
@ -3324,7 +3324,7 @@ static void rna_Node_ItemArray_remove(ID *id,
|
|||
return;
|
||||
}
|
||||
const int remove_index = item_to_remove - *ref.items;
|
||||
blender::nodes::socket_items::remove_item(
|
||||
blender::dna::array::remove_index(
|
||||
ref.items, ref.items_num, ref.active_index, remove_index, Accessor::destruct_item);
|
||||
|
||||
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
|
||||
|
@ -3336,8 +3336,7 @@ static void rna_Node_ItemArray_remove(ID *id,
|
|||
template<typename Accessor> static void rna_Node_ItemArray_clear(ID *id, bNode *node, Main *bmain)
|
||||
{
|
||||
blender::nodes::socket_items::SocketItemsRef ref = Accessor::get_items_from_node(*node);
|
||||
blender::nodes::socket_items::clear_items(
|
||||
ref.items, ref.items_num, ref.active_index, Accessor::destruct_item);
|
||||
blender::dna::array::clear(ref.items, ref.items_num, ref.active_index, Accessor::destruct_item);
|
||||
|
||||
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
|
||||
BKE_ntree_update_tag_node_property(ntree, node);
|
||||
|
@ -3354,7 +3353,7 @@ static void rna_Node_ItemArray_move(
|
|||
if (from_index < 0 || to_index < 0 || from_index >= items_num || to_index >= items_num) {
|
||||
return;
|
||||
}
|
||||
blender::nodes::socket_items::move_item(*ref.items, items_num, from_index, to_index);
|
||||
blender::dna::array::move_index(*ref.items, items_num, from_index, to_index);
|
||||
|
||||
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
|
||||
BKE_ntree_update_tag_node_property(ntree, node);
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "DNA_array_utils.hh"
|
||||
|
||||
#include "NOD_socket.hh"
|
||||
|
||||
namespace blender::nodes::socket_items {
|
||||
|
@ -53,94 +55,6 @@ inline bNode *find_node_by_item(bNodeTree &ntree, const typename Accessor::ItemT
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Low level utility to remove an item from the array and to shift the elements after it.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void remove_item(T **items,
|
||||
int *items_num,
|
||||
int *active_index,
|
||||
const int remove_index,
|
||||
void (*destruct_item)(T *))
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
BLI_assert(remove_index >= 0);
|
||||
BLI_assert(remove_index < *items_num);
|
||||
|
||||
const int old_items_num = *items_num;
|
||||
const int new_items_num = old_items_num - 1;
|
||||
|
||||
T *old_items = *items;
|
||||
T *new_items = MEM_cnew_array<T>(new_items_num, __func__);
|
||||
|
||||
std::copy_n(old_items, remove_index, new_items);
|
||||
std::copy_n(
|
||||
old_items + remove_index + 1, old_items_num - remove_index - 1, new_items + remove_index);
|
||||
|
||||
destruct_item(&old_items[remove_index]);
|
||||
MEM_SAFE_FREE(old_items);
|
||||
|
||||
*items = new_items;
|
||||
*items_num = new_items_num;
|
||||
|
||||
if (active_index) {
|
||||
const int old_active_index = active_index ? *active_index : 0;
|
||||
const int new_active_index = std::max(
|
||||
0, old_active_index == new_items_num ? new_items_num - 1 : old_active_index);
|
||||
*active_index = new_active_index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Low level utility to remove all elements from an items array.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void clear_items(T **items, int *items_num, int *active_index, void (*destruct_item)(T *))
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
for (const int i : blender::IndexRange(*items_num)) {
|
||||
destruct_item(&(*items)[i]);
|
||||
}
|
||||
MEM_SAFE_FREE(*items);
|
||||
*items_num = 0;
|
||||
if (active_index) {
|
||||
*active_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Low level utility to move one item from one index to another.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void move_item(T *items, const int items_num, const int from_index, const int to_index)
|
||||
{
|
||||
static_assert(std::is_trivial_v<T>);
|
||||
BLI_assert(from_index >= 0);
|
||||
BLI_assert(from_index < items_num);
|
||||
BLI_assert(to_index >= 0);
|
||||
BLI_assert(to_index < items_num);
|
||||
UNUSED_VARS_NDEBUG(items_num);
|
||||
|
||||
if (from_index == to_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (from_index < to_index) {
|
||||
const T tmp = items[from_index];
|
||||
for (int i = from_index; i < to_index; i++) {
|
||||
items[i] = items[i + 1];
|
||||
}
|
||||
items[to_index] = tmp;
|
||||
}
|
||||
else if (from_index > to_index) {
|
||||
const T tmp = items[from_index];
|
||||
for (int i = from_index; i > to_index; i--) {
|
||||
items[i] = items[i - 1];
|
||||
}
|
||||
items[to_index] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruct all the items and the free the array itself.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue