Nodes: Moved group interface panel code to python.

The node group interface panels were still implemented in C.
Now they ported over to python for easier maintenance.

Differential Revision: https://developer.blender.org/D11834
This commit is contained in:
2021-07-09 07:57:29 +01:00
parent d0c5c67e94
commit 07faa3c5ac
6 changed files with 95 additions and 258 deletions

View File

@@ -694,6 +694,97 @@ class NODE_UL_interface_sockets(bpy.types.UIList):
layout.template_node_socket(color=color)
class NodeTreeInterfacePanel:
def draw_socket_list(self, context, in_out, sockets_propname, active_socket_propname):
layout = self.layout
snode = context.space_data
tree = snode.edit_tree
sockets = getattr(tree, sockets_propname)
active_socket_index = getattr(tree, active_socket_propname)
active_socket = sockets[active_socket_index] if active_socket_index >= 0 else None
split = layout.row()
split.template_list("NODE_UL_interface_sockets", in_out, tree, sockets_propname, tree, active_socket_propname)
ops_col = split.column()
add_remove_col = ops_col.column(align=True)
props = add_remove_col.operator("node.tree_socket_add", icon='ADD', text="")
props.in_out = in_out
props = add_remove_col.operator("node.tree_socket_remove", icon='REMOVE', text="")
props.in_out = in_out
ops_col.separator()
up_down_col = ops_col.column(align=True)
props = up_down_col.operator("node.tree_socket_move", icon='TRIA_UP', text="")
props.in_out = in_out
props.direction = 'UP'
props = up_down_col.operator("node.tree_socket_move", icon='TRIA_DOWN', text="")
props.in_out = in_out
props.direction = 'DOWN'
if active_socket is not None:
# Mimicking property split.
layout.use_property_split = False
layout.use_property_decorate = False
layout_row = layout.row(align=True)
layout_split = layout_row.split(factor=0.4, align=True)
label_column = layout_split.column(align=True)
label_column.alignment = 'RIGHT'
# Menu to change the socket type.
label_column.label(text="Type")
property_row = layout_split.row(align=True)
props = property_row.operator_menu_enum(
"node.tree_socket_change_type",
"socket_type",
text=active_socket.bl_label if active_socket.bl_label else active_socket.bl_idname
)
props.in_out = in_out
layout.use_property_split = True
layout.use_property_decorate = False
layout.prop(active_socket, "name")
# Display descriptions only for Geometry Nodes, since it's only used in the modifier panel.
if tree.type == 'GEOMETRY':
layout.prop(active_socket, "description")
active_socket.draw(context, layout)
class NODE_PT_node_tree_interface_inputs(NodeTreeInterfacePanel, Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_category = "Group"
bl_label = "Inputs"
@classmethod
def poll(cls, context):
snode = context.space_data
return snode.edit_tree is not None
def draw(self, context):
self.draw_socket_list(context, "IN", "inputs", "active_input")
class NODE_PT_node_tree_interface_outputs(NodeTreeInterfacePanel, Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_category = "Group"
bl_label = "Outputs"
@classmethod
def poll(cls, context):
snode = context.space_data
return snode.edit_tree is not None
def draw(self, context):
self.draw_socket_list(context, "OUT", "outputs", "active_output")
# Grease Pencil properties
class NODE_PT_annotation(AnnotationDataPanel, Panel):
bl_space_type = 'NODE_EDITOR'
@@ -752,6 +843,8 @@ classes = (
NODE_PT_quality,
NODE_PT_annotation,
NODE_UL_interface_sockets,
NODE_PT_node_tree_interface_inputs,
NODE_PT_node_tree_interface_outputs,
node_panel(EEVEE_MATERIAL_PT_settings),
node_panel(MATERIAL_PT_viewport),

View File

@@ -40,7 +40,6 @@ set(INC
set(SRC
drawnode.cc
node_add.cc
node_buttons.c
node_draw.cc
node_edit.cc
node_geometry_attribute_search.cc

View File

@@ -1,250 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2009 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup spnode
*/
#include "MEM_guardedalloc.h"
#include "DNA_node_types.h"
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLT_translation.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_node.h"
#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "ED_screen.h"
#include "UI_resources.h"
#include "node_intern.h" /* own include */
/* ******************* node space & buttons ************** */
#if 0
/* poll for active nodetree */
static bool active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
return (snode && snode->nodetree);
}
#endif
static bool node_sockets_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
return (snode && snode->nodetree && G.debug_value == 777);
}
static void node_sockets_panel(const bContext *C, Panel *panel)
{
SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */
bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */
bNode *node = nodeGetActive(ntree);
if (node == NULL) {
return;
}
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
char name[UI_MAX_NAME_STR];
BLI_snprintf(name, sizeof(name), "%s:", socket->name);
uiLayout *split = uiLayoutSplit(panel->layout, 0.35f, false);
uiItemL(split, name, ICON_NONE);
uiTemplateNodeLink(split, (bContext *)C, ntree, node, socket);
}
}
static bool node_tree_interface_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
return (snode && snode->edittree &&
(snode->edittree->inputs.first || snode->edittree->outputs.first));
}
static bNodeSocket *node_tree_find_active_socket(bNodeTree *ntree, const eNodeSocketInOut in_out)
{
ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
LISTBASE_FOREACH (bNodeSocket *, socket, sockets) {
if (socket->flag & SELECT) {
return socket;
}
}
return NULL;
}
static void draw_socket_list(const bContext *C,
uiLayout *layout,
bNodeTree *ntree,
const eNodeSocketInOut in_out)
{
PointerRNA tree_ptr;
RNA_id_pointer_create((ID *)ntree, &tree_ptr);
uiLayout *split = uiLayoutRow(layout, false);
uiLayout *list_col = uiLayoutColumn(split, true);
uiTemplateList(list_col,
(bContext *)C,
"NODE_UL_interface_sockets",
(in_out == SOCK_IN) ? "inputs" : "outputs",
&tree_ptr,
(in_out == SOCK_IN) ? "inputs" : "outputs",
&tree_ptr,
(in_out == SOCK_IN) ? "active_input" : "active_output",
NULL,
0,
0,
0,
0,
false,
false);
PointerRNA opptr;
uiLayout *ops_col = uiLayoutColumn(split, false);
uiLayout *add_remove_col = uiLayoutColumn(ops_col, true);
wmOperatorType *ot = WM_operatortype_find("NODE_OT_tree_socket_add", false);
uiItemFullO_ptr(add_remove_col, ot, "", ICON_ADD, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_enum_set(&opptr, "in_out", in_out);
ot = WM_operatortype_find("NODE_OT_tree_socket_remove", false);
uiItemFullO_ptr(add_remove_col, ot, "", ICON_REMOVE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_enum_set(&opptr, "in_out", in_out);
uiItemS(ops_col);
uiLayout *up_down_col = uiLayoutColumn(ops_col, true);
ot = WM_operatortype_find("NODE_OT_tree_socket_move", false);
uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_enum_set(&opptr, "direction", 1);
RNA_enum_set(&opptr, "in_out", in_out);
uiItemFullO_ptr(up_down_col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_enum_set(&opptr, "direction", 2);
RNA_enum_set(&opptr, "in_out", in_out);
bNodeSocket *socket = node_tree_find_active_socket(ntree, in_out);
if (socket != NULL) {
PointerRNA socket_ptr;
RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, socket, &socket_ptr);
{
/* Mimicking property split */
uiLayoutSetPropSep(layout, false);
uiLayoutSetPropDecorate(layout, false);
uiLayout *layout_row = uiLayoutRow(layout, true);
uiLayout *layout_split = uiLayoutSplit(layout_row, 0.4f, true);
uiLayout *label_column = uiLayoutColumn(layout_split, true);
uiLayoutSetAlignment(label_column, UI_LAYOUT_ALIGN_RIGHT);
/* Menu to change the socket type. */
uiItemL(label_column, "Type", ICON_NONE);
uiLayout *property_row = uiLayoutRow(layout_split, true);
PointerRNA props_ptr;
uiItemMenuEnumFullO(property_row,
(bContext *)C,
"NODE_OT_tree_socket_change_type",
"socket_type",
nodeSocketTypeLabel(socket->typeinfo),
ICON_NONE,
&props_ptr);
RNA_enum_set(&props_ptr, "in_out", in_out);
}
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
uiItemR(layout, &socket_ptr, "name", 0, NULL, ICON_NONE);
/* Display descriptions only for Geometry Nodes, since it's only used in the modifier panel. */
if (ntree->type == NTREE_GEOMETRY) {
uiItemR(layout, &socket_ptr, "description", 0, NULL, ICON_NONE);
}
if (socket->typeinfo->interface_draw) {
socket->typeinfo->interface_draw((bContext *)C, layout, &socket_ptr);
}
}
}
static void node_tree_interface_inputs_panel(const bContext *C, Panel *panel)
{
SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */
bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */
draw_socket_list(C, panel->layout, ntree, SOCK_IN);
}
static void node_tree_interface_outputs_panel(const bContext *C, Panel *panel)
{
SpaceNode *snode = CTX_wm_space_node(C); /* NULL checked in poll function. */
bNodeTree *ntree = snode->edittree; /* NULL checked in poll function. */
draw_socket_list(C, panel->layout, ntree, SOCK_OUT);
}
/* ******************* node buttons registration ************** */
void node_buttons_register(ARegionType *art)
{
{
PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
strcpy(pt->idname, "NODE_PT_sockets");
strcpy(pt->category, N_("Node"));
strcpy(pt->label, N_("Sockets"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_sockets_panel;
pt->poll = node_sockets_poll;
pt->flag |= PANEL_TYPE_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
}
{
PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
strcpy(pt->idname, "NODE_PT_node_tree_interface_inputs");
strcpy(pt->category, N_("Group"));
strcpy(pt->label, N_("Inputs"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_tree_interface_inputs_panel;
pt->poll = node_tree_interface_poll;
BLI_addtail(&art->paneltypes, pt);
}
{
PanelType *pt = MEM_callocN(sizeof(PanelType), __func__);
strcpy(pt->idname, "NODE_PT_node_tree_interface_outputs");
strcpy(pt->category, N_("Group"));
strcpy(pt->label, N_("Outputs"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = node_tree_interface_outputs_panel;
pt->poll = node_tree_interface_poll;
BLI_addtail(&art->paneltypes, pt);
}
}

View File

@@ -140,9 +140,6 @@ void node_to_view(const struct bNode *node, float x, float y, float *rx, float *
void node_to_updated_rect(const struct bNode *node, rctf *r_rect);
void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry);
/* node_buttons.c */
void node_buttons_register(struct ARegionType *art);
/* node_toolbar.c */
void node_toolbar_register(struct ARegionType *art);

View File

@@ -1098,8 +1098,6 @@ void ED_spacetype_node(void)
art->draw = node_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
node_buttons_register(art);
/* regions: toolbar */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tools region");
art->regionid = RGN_TYPE_TOOLS;

View File

@@ -3205,7 +3205,7 @@ static void rna_NodeSocketInterfaceStandard_draw(ID *id,
struct uiLayout *layout)
{
PointerRNA ptr;
RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
RNA_pointer_create(id, &RNA_NodeSocketInterface, sock, &ptr);
sock->typeinfo->interface_draw(C, layout, &ptr);
}
@@ -3215,7 +3215,7 @@ static void rna_NodeSocketInterfaceStandard_draw_color(ID *id,
float r_color[4])
{
PointerRNA ptr;
RNA_pointer_create(id, &RNA_NodeSocket, sock, &ptr);
RNA_pointer_create(id, &RNA_NodeSocketInterface, sock, &ptr);
sock->typeinfo->interface_draw_color(C, &ptr, r_color);
}