Nodes: Panel declarations for grouping sockets #108649
|
@ -561,6 +561,18 @@ void ntreeSetSocketInterfacePanel(bNodeTree *ntree, bNodeSocket *sock, bNodeSock
|
|||
/** \name Node Tree Socket Panels
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Check if a panel is part of the node tree.
|
||||
* \return True if the panel is part of the node tree.
|
||||
*/
|
||||
bool ntreeContainsSocketPanel(const bNodeTree *ntree, const bNodeSocketPanel *panel);
|
||||
|
||||
/**
|
||||
* Index of a panel in the node tree.
|
||||
LukasTonne marked this conversation as resolved
Outdated
|
||||
* \return Index of the panel in the node tree or -1 if the tree does not contain the panel.
|
||||
*/
|
||||
int ntreeGetSocketPanelIndex(const bNodeTree *ntree, const bNodeSocketPanel *panel);
|
||||
|
||||
/**
|
||||
* Find a socket panel by its unique ID.
|
||||
* \param id: Unique ID of the panel within the node tree.
|
||||
|
|
|
@ -516,12 +516,12 @@ inline blender::Span<bNode *> bNodeTree::root_frames() const
|
|||
return this->runtime->root_frames;
|
||||
}
|
||||
|
||||
inline blender::Span<bNodeSocketPanel> bNodeTree::socket_panels() const
|
||||
inline blender::Span<bNodeSocketPanel *> bNodeTree::socket_panels() const
|
||||
{
|
||||
return blender::Span(socket_panels_array, socket_panels_num);
|
||||
}
|
||||
|
||||
inline blender::MutableSpan<bNodeSocketPanel> bNodeTree::socket_panels_for_write()
|
||||
inline blender::MutableSpan<bNodeSocketPanel *> bNodeTree::socket_panels_for_write()
|
||||
{
|
||||
return blender::MutableSpan(socket_panels_array, socket_panels_num);
|
||||
}
|
||||
|
|
|
@ -643,10 +643,10 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
|
|||
write_node_socket_interface(writer, sock);
|
||||
}
|
||||
|
||||
BLO_write_struct_array(
|
||||
writer, bNodeSocketPanel, ntree->socket_panels_num, ntree->socket_panels_array);
|
||||
for (const bNodeSocketPanel &panel : ntree->socket_panels()) {
|
||||
BLO_write_string(writer, panel.name);
|
||||
BLO_write_pointer_array(writer, ntree->socket_panels_num, ntree->socket_panels_array);
|
||||
for (const bNodeSocketPanel *panel : ntree->socket_panels()) {
|
||||
BLO_write_struct(writer, bNodeSocketPanel, panel);
|
||||
BLO_write_string(writer, panel->name);
|
||||
}
|
||||
|
||||
BKE_previewimg_blend_write(writer, ntree->preview);
|
||||
|
@ -869,9 +869,10 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
|
|||
BLO_read_data_address(reader, &link->tosock);
|
||||
}
|
||||
|
||||
BLO_read_data_address(reader, &ntree->socket_panels_array);
|
||||
for (bNodeSocketPanel &panel : ntree->socket_panels_for_write()) {
|
||||
BLO_read_data_address(reader, &panel.name);
|
||||
BLO_read_pointer_array(reader, reinterpret_cast<void **>(&ntree->socket_panels_array));
|
||||
for (const int i : IndexRange(ntree->socket_panels_num)) {
|
||||
BLO_read_data_address(reader, &ntree->socket_panels_array[i]);
|
||||
BLO_read_data_address(reader, &ntree->socket_panels_array[i]->name);
|
||||
}
|
||||
|
||||
/* TODO: should be dealt by new generic cache handling of IDs... */
|
||||
|
@ -3682,25 +3683,25 @@ void ntreeEnsureSocketInterfacePanelOrder(bNodeTree *ntree)
|
|||
/* XXX Hack: store panel index in panel_id temporarily for sorting. */
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->inputs) {
|
||||
const bNodeSocketPanel *panel = ntreeFindSocketPanelByID(ntree, iosock->panel_id);
|
||||
iosock->panel_id = panel == nullptr ? -1 : (int)(panel - ntree->socket_panels_array);
|
||||
iosock->panel_id = ntreeGetSocketPanelIndex(ntree, panel);
|
||||
}
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->outputs) {
|
||||
const bNodeSocketPanel *panel = ntreeFindSocketPanelByID(ntree, iosock->panel_id);
|
||||
iosock->panel_id = panel == nullptr ? -1 : (int)(panel - ntree->socket_panels_array);
|
||||
iosock->panel_id = ntreeGetSocketPanelIndex(ntree, panel);
|
||||
}
|
||||
BLI_listbase_sort(&ntree->inputs, blender::bke::node_socket_panel_cmp);
|
||||
BLI_listbase_sort(&ntree->outputs, blender::bke::node_socket_panel_cmp);
|
||||
/* Restore panel_id. */
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->inputs) {
|
||||
if (iosock->panel_id >= 0) {
|
||||
const bNodeSocketPanel &panel = ntree->socket_panels()[iosock->panel_id];
|
||||
iosock->panel_id = panel.identifier;
|
||||
const bNodeSocketPanel *panel = ntree->socket_panels()[iosock->panel_id];
|
||||
iosock->panel_id = panel->identifier;
|
||||
}
|
||||
}
|
||||
LISTBASE_FOREACH (bNodeSocket *, iosock, &ntree->outputs) {
|
||||
if (iosock->panel_id >= 0) {
|
||||
const bNodeSocketPanel &panel = ntree->socket_panels()[iosock->panel_id];
|
||||
iosock->panel_id = panel.identifier;
|
||||
const bNodeSocketPanel *panel = ntree->socket_panels()[iosock->panel_id];
|
||||
iosock->panel_id = panel->identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3816,11 +3817,21 @@ void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
|
|||
BKE_ntree_update_tag_interface(ntree);
|
||||
}
|
||||
|
||||
bool ntreeContainsSocketPanel(const bNodeTree *ntree, const bNodeSocketPanel *panel)
|
||||
{
|
||||
return ntree->socket_panels().contains(const_cast<bNodeSocketPanel *>(panel));
|
||||
}
|
||||
|
||||
int ntreeGetSocketPanelIndex(const bNodeTree *ntree, const bNodeSocketPanel *panel)
|
||||
{
|
||||
return ntree->socket_panels().first_index_try(const_cast<bNodeSocketPanel *>(panel));
|
||||
}
|
||||
|
||||
bNodeSocketPanel *ntreeFindSocketPanelByID(bNodeTree *ntree, int id)
|
||||
{
|
||||
for (bNodeSocketPanel &panel : ntree->socket_panels_for_write()) {
|
||||
if (panel.identifier == id) {
|
||||
return &panel;
|
||||
for (bNodeSocketPanel *panel : ntree->socket_panels_for_write()) {
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
IMO IMO `__func__` for the allocation string is nicer than specifying one manually. It just takes up less visual space. I've also seen other developers preferring that too.
|
||||
if (panel->identifier == id) {
|
||||
return panel;
|
||||
}
|
||||
}
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
Don't have a strong preference, but this seems a bit more idiomatic and clear to me: Don't have a strong preference, but this seems a bit more idiomatic and clear to me:
` std::copy(old_categories.begin(), old_categories.end(), new_categories.data());`
|
||||
return nullptr;
|
||||
|
@ -3828,22 +3839,24 @@ bNodeSocketPanel *ntreeFindSocketPanelByID(bNodeTree *ntree, int id)
|
|||
|
||||
bNodeSocketPanel *ntreeAddSocketPanel(bNodeTree *ntree, const char *name, int flag)
|
||||
{
|
||||
bNodeSocketPanel *old_panels_array = ntree->socket_panels_array;
|
||||
const Span<bNodeSocketPanel> old_panels = ntree->socket_panels();
|
||||
ntree->socket_panels_array = MEM_cnew_array<bNodeSocketPanel>(ntree->socket_panels_num + 1,
|
||||
__func__);
|
||||
bNodeSocketPanel **old_panels_array = ntree->socket_panels_array;
|
||||
const Span<bNodeSocketPanel *> old_panels = ntree->socket_panels();
|
||||
ntree->socket_panels_array = MEM_cnew_array<bNodeSocketPanel *>(ntree->socket_panels_num + 1,
|
||||
__func__);
|
||||
++ntree->socket_panels_num;
|
||||
const MutableSpan<bNodeSocketPanel> new_panels = ntree->socket_panels_for_write();
|
||||
const MutableSpan<bNodeSocketPanel *> new_panels = ntree->socket_panels_for_write();
|
||||
|
||||
std::copy(old_panels.begin(), old_panels.end(), new_panels.data());
|
||||
bNodeSocketPanel &new_panel = new_panels[new_panels.size() - 1];
|
||||
new_panel = {BLI_strdup(name), flag, ntree->next_socket_panel_identifier++};
|
||||
|
||||
bNodeSocketPanel *new_panel = MEM_cnew<bNodeSocketPanel>(__func__);
|
||||
*new_panel = {BLI_strdup(name), flag, ntree->next_socket_panel_identifier++};
|
||||
new_panels[new_panels.size() - 1] = new_panel;
|
||||
|
||||
MEM_SAFE_FREE(old_panels_array);
|
||||
|
||||
/* No need to sort sockets, nothing is using the new panel yet */
|
||||
|
||||
return &new_panel;
|
||||
return new_panel;
|
||||
}
|
||||
|
||||
bNodeSocketPanel *ntreeInsertSocketPanel(bNodeTree *ntree, const char *name, int flag, int index)
|
||||
|
@ -3852,47 +3865,51 @@ bNodeSocketPanel *ntreeInsertSocketPanel(bNodeTree *ntree, const char *name, int
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bNodeSocketPanel *old_panels_array = ntree->socket_panels_array;
|
||||
const Span<bNodeSocketPanel> old_panels = ntree->socket_panels();
|
||||
ntree->socket_panels_array = MEM_cnew_array<bNodeSocketPanel>(ntree->socket_panels_num + 1,
|
||||
__func__);
|
||||
bNodeSocketPanel **old_panels_array = ntree->socket_panels_array;
|
||||
const Span<bNodeSocketPanel *> old_panels = ntree->socket_panels();
|
||||
ntree->socket_panels_array = MEM_cnew_array<bNodeSocketPanel *>(ntree->socket_panels_num + 1,
|
||||
__func__);
|
||||
++ntree->socket_panels_num;
|
||||
const MutableSpan<bNodeSocketPanel> new_panels = ntree->socket_panels_for_write();
|
||||
const MutableSpan<bNodeSocketPanel *> new_panels = ntree->socket_panels_for_write();
|
||||
|
||||
Span old_panels_front = old_panels.take_front(index);
|
||||
Span old_panels_back = old_panels.drop_front(index);
|
||||
std::copy(old_panels_front.begin(), old_panels_front.end(), new_panels.data());
|
||||
std::copy(
|
||||
old_panels_back.begin(), old_panels_back.end(), new_panels.drop_front(index + 1).data());
|
||||
bNodeSocketPanel &new_panel = new_panels[index];
|
||||
new_panel = {BLI_strdup(name), flag, ntree->next_socket_panel_identifier++};
|
||||
|
||||
bNodeSocketPanel *new_panel = MEM_cnew<bNodeSocketPanel>(__func__);
|
||||
*new_panel = {BLI_strdup(name), flag, ntree->next_socket_panel_identifier++};
|
||||
new_panels[index] = new_panel;
|
||||
|
||||
MEM_SAFE_FREE(old_panels_array);
|
||||
|
||||
/* No need to sort sockets, nothing is using the new panel yet */
|
||||
|
||||
return &new_panel;
|
||||
return new_panel;
|
||||
}
|
||||
|
||||
void ntreeRemoveSocketPanel(bNodeTree *ntree, bNodeSocketPanel *panel)
|
||||
{
|
||||
const int index = panel - ntree->socket_panels_array;
|
||||
if (!ntree->socket_panels().contains_ptr(panel)) {
|
||||
const int index = ntreeGetSocketPanelIndex(ntree, panel);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bNodeSocketPanel *old_panels_array = ntree->socket_panels_array;
|
||||
const Span<bNodeSocketPanel> old_panels = ntree->socket_panels();
|
||||
ntree->socket_panels_array = MEM_cnew_array<bNodeSocketPanel>(ntree->socket_panels_num - 1,
|
||||
__func__);
|
||||
bNodeSocketPanel **old_panels_array = ntree->socket_panels_array;
|
||||
const Span<bNodeSocketPanel *> old_panels = ntree->socket_panels();
|
||||
ntree->socket_panels_array = MEM_cnew_array<bNodeSocketPanel *>(ntree->socket_panels_num - 1,
|
||||
__func__);
|
||||
--ntree->socket_panels_num;
|
||||
const MutableSpan<bNodeSocketPanel> new_panels = ntree->socket_panels_for_write();
|
||||
const MutableSpan<bNodeSocketPanel *> new_panels = ntree->socket_panels_for_write();
|
||||
|
||||
Span old_panels_front = old_panels.take_front(index);
|
||||
Span old_panels_back = old_panels.drop_front(index + 1);
|
||||
std::copy(old_panels_front.begin(), old_panels_front.end(), new_panels.data());
|
||||
std::copy(old_panels_back.begin(), old_panels_back.end(), new_panels.drop_front(index).data());
|
||||
|
||||
MEM_SAFE_FREE(panel->name);
|
||||
MEM_SAFE_FREE(panel);
|
||||
MEM_SAFE_FREE(old_panels_array);
|
||||
|
||||
ntreeEnsureSocketInterfacePanelOrder(ntree);
|
||||
|
@ -3900,6 +3917,10 @@ void ntreeRemoveSocketPanel(bNodeTree *ntree, bNodeSocketPanel *panel)
|
|||
|
||||
void ntreeClearSocketPanels(bNodeTree *ntree)
|
||||
{
|
||||
for (bNodeSocketPanel *panel : ntree->socket_panels_for_write()) {
|
||||
MEM_SAFE_FREE(panel->name);
|
||||
MEM_SAFE_FREE(panel);
|
||||
}
|
||||
MEM_SAFE_FREE(ntree->socket_panels_array);
|
||||
ntree->socket_panels_array = nullptr;
|
||||
ntree->socket_panels_num = 0;
|
||||
|
@ -3909,24 +3930,25 @@ void ntreeClearSocketPanels(bNodeTree *ntree)
|
|||
|
||||
void ntreeMoveSocketPanel(bNodeTree *ntree, bNodeSocketPanel *panel, int new_index)
|
||||
{
|
||||
if (!ntree->socket_panels().contains_ptr(panel)) {
|
||||
const int old_index = ntreeGetSocketPanelIndex(ntree, panel);
|
||||
if (old_index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const MutableSpan<bNodeSocketPanel> panels = ntree->socket_panels_for_write();
|
||||
const int old_index = panel - ntree->socket_panels_array;
|
||||
const MutableSpan<bNodeSocketPanel *> panels = ntree->socket_panels_for_write();
|
||||
if (old_index == new_index) {
|
||||
return;
|
||||
}
|
||||
else if (old_index < new_index) {
|
||||
const Span<bNodeSocketPanel> moved_panels = panels.slice(old_index + 1, new_index - old_index);
|
||||
const bNodeSocketPanel tmp = panels[old_index];
|
||||
const Span<bNodeSocketPanel *> moved_panels = panels.slice(old_index + 1,
|
||||
new_index - old_index);
|
||||
bNodeSocketPanel *tmp = panels[old_index];
|
||||
std::copy(moved_panels.begin(), moved_panels.end(), panels.drop_front(old_index).data());
|
||||
panels[new_index] = tmp;
|
||||
}
|
||||
else /* old_index > new_index */ {
|
||||
const Span<bNodeSocketPanel> moved_panels = panels.slice(new_index, old_index - new_index);
|
||||
const bNodeSocketPanel tmp = panels[old_index];
|
||||
const Span<bNodeSocketPanel *> moved_panels = panels.slice(new_index, old_index - new_index);
|
||||
bNodeSocketPanel *tmp = panels[old_index];
|
||||
std::copy_backward(
|
||||
moved_panels.begin(), moved_panels.end(), panels.drop_front(old_index + 1).data());
|
||||
panels[new_index] = tmp;
|
||||
|
|
|
@ -605,7 +605,7 @@ typedef struct bNodeTree {
|
|||
struct PreviewImage *preview;
|
||||
|
||||
/* UI panels for sockets */
|
||||
struct bNodeSocketPanel *socket_panels_array;
|
||||
struct bNodeSocketPanel **socket_panels_array;
|
||||
int socket_panels_num;
|
||||
int active_socket_panel;
|
||||
int next_socket_panel_identifier;
|
||||
|
@ -675,8 +675,8 @@ typedef struct bNodeTree {
|
|||
blender::Span<const bNodeSocket *> interface_inputs() const;
|
||||
blender::Span<const bNodeSocket *> interface_outputs() const;
|
||||
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
`panels()` should return `Span<const bNodePanel *>`, so a `const bNodeSocket *` doesn't give you a mutable `bNodePanel`
|
||||
blender::Span<bNodeSocketPanel> socket_panels() const;
|
||||
blender::MutableSpan<bNodeSocketPanel> socket_panels_for_write();
|
||||
blender::Span<bNodeSocketPanel *> socket_panels() const;
|
||||
blender::MutableSpan<bNodeSocketPanel *> socket_panels_for_write();
|
||||
#endif
|
||||
} bNodeTree;
|
||||
|
||||
|
|
|
@ -3188,12 +3188,9 @@ static void rna_NodeSocketInterface_panel_set(PointerRNA *ptr,
|
|||
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
|
||||
bNodeSocketPanel *panel = (bNodeSocketPanel *)value.data;
|
||||
|
||||
if (panel != NULL) {
|
||||
const int64_t index = panel - ntree->socket_panels_array;
|
||||
if (index < 0 || index >= ntree->socket_panels_num) {
|
||||
BKE_report(reports, RPT_ERROR, "Panel is not in the node tree interface");
|
||||
return;
|
||||
}
|
||||
if (panel && !ntreeContainsSocketPanel(ntree, panel)) {
|
||||
BKE_report(reports, RPT_ERROR, "Panel is not in the node tree interface");
|
||||
return;
|
||||
}
|
||||
|
||||
ntreeSetSocketInterfacePanel(ntree, socket, panel);
|
||||
|
@ -3203,16 +3200,8 @@ static bool rna_NodeSocketInterface_panel_poll(PointerRNA *ptr, PointerRNA value
|
|||
{
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
|
||||
bNodeSocketPanel *panel = (bNodeSocketPanel *)value.data;
|
||||
if (panel == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const int64_t index = panel - ntree->socket_panels_array;
|
||||
if (index < 0 || index >= ntree->socket_panels_num) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return panel == NULL || ntreeContainsSocketPanel(ntree, panel);
|
||||
LukasTonne marked this conversation as resolved
Outdated
Hans Goudey
commented
Super picky but this newline isn't helpful IMO, better to more closely connect the variable declaration and the null check. Super picky but this newline isn't helpful IMO, better to more closely connect the variable declaration and the null check.
|
||||
}
|
||||
|
||||
static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
|
||||
|
@ -3393,7 +3382,7 @@ static void rna_NodeTree_socket_panels_move(bNodeTree *ntree,
|
|||
return;
|
||||
}
|
||||
|
||||
ntreeMoveSocketPanel(ntree, &ntree->socket_panels_array[from_index], to_index);
|
||||
ntreeMoveSocketPanel(ntree, ntree->socket_panels_array[from_index], to_index);
|
||||
|
||||
BKE_ntree_update_tag_interface(ntree);
|
||||
ED_node_tree_propagate_change(NULL, bmain, ntree);
|
||||
|
@ -3407,7 +3396,7 @@ static PointerRNA rna_NodeTree_active_socket_panel_get(PointerRNA *ptr)
|
|||
if (ntree->active_socket_panel >= 0 &&
|
||||
ntree->active_socket_panel < ntree->socket_panels_num)
|
||||
{
|
||||
panel = &ntree->socket_panels_array[ntree->active_socket_panel];
|
||||
panel = ntree->socket_panels_array[ntree->active_socket_panel];
|
||||
}
|
||||
|
||||
PointerRNA r_ptr;
|
||||
|
@ -3421,7 +3410,7 @@ static void rna_NodeTree_active_socket_panel_set(PointerRNA *ptr,
|
|||
{
|
||||
bNodeSocketPanel *panel = (bNodeSocketPanel *)value.data;
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->data;
|
||||
ntree->active_socket_panel = panel - ntree->socket_panels_array;
|
||||
ntree->active_socket_panel = ntreeGetSocketPanelIndex(ntree, panel);
|
||||
}
|
||||
|
||||
/* ******** Node Types ******** */
|
||||
|
|
Loading…
Reference in New Issue
There's meant to be a colon after the name here:
\param name: