Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-03-19 02:37:04 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-03-19 02:37:04 +0400
commitae25aa22105b060294095357692f2aed4c650ce8 (patch)
tree06548276f86326f21943f8ec7ef92765a97b5ab5 /source/blender/editors
parent29b7b344fc48ed31b1e36818ab4767090691d6e2 (diff)
parent03762409cd4f812d152e42de9c4f9853df91be0b (diff)
svn merge ^/trunk/blender -r55372:55392
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/ED_node.h35
-rw-r--r--source/blender/editors/include/UI_interface.h5
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/include/UI_view2d.h5
-rw-r--r--source/blender/editors/interface/interface_draw.c66
-rw-r--r--source/blender/editors/interface/interface_handlers.c1
-rw-r--r--source/blender/editors/interface/interface_intern.h1
-rw-r--r--source/blender/editors/interface/interface_templates.c64
-rw-r--r--source/blender/editors/interface/interface_widgets.c100
-rw-r--r--source/blender/editors/interface/resources.c14
-rw-r--r--source/blender/editors/interface/view2d.c28
-rw-r--r--source/blender/editors/object/object_add.c2
-rw-r--r--source/blender/editors/object/object_constraint.c2
-rw-r--r--source/blender/editors/render/render_preview.c16
-rw-r--r--source/blender/editors/render/render_shading.c4
-rw-r--r--source/blender/editors/render/render_update.c2
-rw-r--r--source/blender/editors/screen/screen_ops.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c4
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_logic/logic_window.c6
-rw-r--r--source/blender/editors/space_node/drawnode.c967
-rw-r--r--source/blender/editors/space_node/node_add.c199
-rw-r--r--source/blender/editors/space_node/node_buttons.c93
-rw-r--r--source/blender/editors/space_node/node_draw.c578
-rw-r--r--source/blender/editors/space_node/node_edit.c699
-rw-r--r--source/blender/editors/space_node/node_group.c1312
-rw-r--r--source/blender/editors/space_node/node_header.c177
-rw-r--r--source/blender/editors/space_node/node_intern.h38
-rw-r--r--source/blender/editors/space_node/node_ops.c52
-rw-r--r--source/blender/editors/space_node/node_relationships.c215
-rw-r--r--source/blender/editors/space_node/node_select.c77
-rw-r--r--source/blender/editors/space_node/node_templates.c227
-rw-r--r--source/blender/editors/space_node/node_view.c5
-rw-r--r--source/blender/editors/space_node/space_node.c242
-rw-r--r--source/blender/editors/space_view3d/drawobject.c9
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2
38 files changed, 2619 insertions, 2643 deletions
diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h
index 32baa8883e1..448a15334c7 100644
--- a/source/blender/editors/include/ED_node.h
+++ b/source/blender/editors/include/ED_node.h
@@ -39,7 +39,10 @@ struct Tex;
struct bContext;
struct bNodeTree;
struct bNode;
+struct bNodeType;
+struct bNodeSocketType;
struct bNodeTree;
+struct bNodeTreeType;
struct ScrArea;
struct Scene;
struct View2D;
@@ -51,15 +54,30 @@ typedef enum {
NODE_RIGHT = 8
} NodeBorder;
+/* space_node.c */
+int ED_node_tree_path_length(struct SpaceNode *snode);
+void ED_node_tree_path_get(struct SpaceNode *snode, char *value);
+void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length);
+
+void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from);
+void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode);
+void ED_node_tree_pop(struct SpaceNode *snode);
+int ED_node_tree_depth(struct SpaceNode *snode);
+struct bNodeTree *ED_node_tree_get(struct SpaceNode *snode, int level);
+
/* drawnode.c */
void ED_node_init_butfuncs(void);
+void ED_init_custom_node_type(struct bNodeType *ntype);
+void ED_init_custom_node_socket_type(struct bNodeSocketType *stype);
+void ED_init_standard_node_socket_type(struct bNodeSocketType *stype);
+void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype);
void ED_node_sample_set(const float col[4]);
void ED_node_draw_snap(struct View2D *v2d, const float cent[2], float size, NodeBorder border);
/* node_draw.c */
-void ED_node_tree_update(struct SpaceNode *snode, struct Scene *scene);
-void ED_node_changed_update(struct ID *id, struct bNode *node);
-void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
+void ED_node_tree_update(const struct bContext *C);
+void ED_node_tag_update_id(struct ID *id);
+void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree);
void ED_node_sort(struct bNodeTree *ntree);
/* node_relationships.c */
@@ -67,9 +85,14 @@ void ED_node_link_intersect_test(struct ScrArea *sa, int test);
void ED_node_link_insert(struct ScrArea *sa);
/* node_edit.c */
-void ED_node_shader_default(struct Scene *scene, struct ID *id);
-void ED_node_composit_default(struct Scene *sce);
-void ED_node_texture_default(struct Tex *tex);
+void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
+int ED_node_is_compositor(struct SpaceNode *snode);
+int ED_node_is_shader(struct SpaceNode *snode);
+int ED_node_is_texture(struct SpaceNode *snode);
+
+void ED_node_shader_default(const struct bContext *C, struct ID *id);
+void ED_node_composit_default(const struct bContext *C, struct Scene *scene);
+void ED_node_texture_default(const struct bContext *C, struct Tex *tex);
int ED_node_select_check(ListBase *lb);
void ED_node_post_apply_transform(struct bContext *C, struct bNodeTree *ntree);
void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 3c8a9a87fbe..f805b199280 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -259,7 +259,8 @@ typedef enum {
WAVEFORM = (49 << 9),
VECTORSCOPE = (50 << 9),
PROGRESSBAR = (51 << 9),
- SEARCH_MENU_UNLINK = (52 << 9)
+ SEARCH_MENU_UNLINK = (52 << 9),
+ NODESOCKET = (53 << 9)
} eButType;
#define BUTTYPE (63 << 9)
@@ -835,6 +836,8 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
+void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
+void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 2ac66fb1919..fb4e9d2aa6e 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -144,6 +144,7 @@ enum {
TH_NODE,
TH_NODE_IN_OUT,
+ TH_NODE_INTERFACE,
TH_NODE_OPERATOR,
TH_NODE_CONVERTOR,
TH_NODE_GROUP,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 81a0f526049..3743539a9bd 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -167,7 +167,7 @@ View2DGrid *UI_view2d_grid_calc(struct Scene *scene, struct View2D *v2d,
short xunits, short xclamp, short yunits, short yclamp, int winx, int winy);
void UI_view2d_grid_draw(struct View2D *v2d, View2DGrid *grid, int flag);
void UI_view2d_constant_grid_draw(struct View2D *v2d);
-void UI_view2d_multi_grid_draw(struct View2D *v2d, float step, int level_size, int totlevels);
+void UI_view2d_multi_grid_draw(struct View2D *v2d, int colorid, float step, int level_size, int totlevels);
void UI_view2d_grid_size(View2DGrid *grid, float *r_dx, float *r_dy);
void UI_view2d_grid_free(View2DGrid *grid);
@@ -200,6 +200,9 @@ struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
void UI_view2d_getscale(struct View2D *v2d, float *x, float *y);
void UI_view2d_getscale_inverse(struct View2D *v2d, float *x, float *y);
+void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y);
+void UI_view2d_setcenter(struct View2D *v2d, float x, float y);
+
short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
/* cached text drawing in v2d, to allow pixel-aligned draw as post process */
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 5486e12c6bf..7fc5c21f052 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -42,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BKE_colortools.h"
+#include "BKE_node.h"
#include "BKE_texture.h"
#include "BKE_tracking.h"
@@ -1685,6 +1686,71 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
glDisable(GL_BLEND);
}
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *recti)
+{
+ static const float size = 5.0f;
+
+ /* 16 values of sin function */
+ static float si[16] = {
+ 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
+ 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
+ -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
+ -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
+ };
+ /* 16 values of cos function */
+ static float co[16] = {
+ 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
+ -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
+ -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
+ 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
+ };
+
+ unsigned char *col = but->col;
+ int a;
+ GLint scissor[4];
+ rcti scissor_new;
+ float x, y;
+
+ x = 0.5f * (recti->xmin + recti->xmax);
+ y = 0.5f * (recti->ymin + recti->ymax);
+
+ /* need scissor test, can draw outside of boundary */
+ glGetIntegerv(GL_VIEWPORT, scissor);
+ scissor_new.xmin = ar->winrct.xmin + recti->xmin;
+ scissor_new.ymin = ar->winrct.ymin + recti->ymin;
+ scissor_new.xmax = ar->winrct.xmin + recti->xmax;
+ scissor_new.ymax = ar->winrct.ymin + recti->ymax;
+ BLI_rcti_isect(&scissor_new, &ar->winrct, &scissor_new);
+ glScissor(scissor_new.xmin,
+ scissor_new.ymin,
+ BLI_rcti_size_x(&scissor_new),
+ BLI_rcti_size_y(&scissor_new));
+
+ glColor4ubv(col);
+
+ glEnable(GL_BLEND);
+ glBegin(GL_POLYGON);
+ for (a = 0; a < 16; a++)
+ glVertex2f(x + size * si[a], y + size * co[a]);
+ glEnd();
+ glDisable(GL_BLEND);
+
+ glColor4ub(0, 0, 0, 150);
+
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ glBegin(GL_LINE_LOOP);
+ for (a = 0; a < 16; a++)
+ glVertex2f(x + size * si[a], y + size * co[a]);
+ glEnd();
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ glLineWidth(1.0f);
+
+ /* restore scissortest */
+ glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
+}
+
/* ****************************************************** */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 39aef38fadb..54a173af603 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -5434,6 +5434,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case LISTROW:
case BUT_IMAGE:
case PROGRESSBAR:
+ case NODESOCKET:
retval = ui_do_but_EXIT(C, but, data, event);
break;
case HISTOGRAM:
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 6065fcfe574..19b863dd6fa 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -510,6 +510,7 @@ void ui_draw_but_NORMAL(uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_CURVE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
+void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rcti *rect);
/* interface_handlers.c */
extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index afb44101910..f376d42e7a8 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -32,6 +32,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_dynamicpaint_types.h"
+#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
@@ -57,6 +58,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_packedFile.h"
#include "BKE_particle.h"
@@ -3073,3 +3075,65 @@ void uiTemplateColormanagedViewSettings(uiLayout *layout, bContext *UNUSED(C), P
if (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)
uiTemplateCurveMapping(col, &view_transform_ptr, "curve_mapping", 'c', TRUE, 0);
}
+
+/********************************* Component Menu *************************************/
+
+typedef struct ComponentMenuArgs {
+ PointerRNA ptr;
+ char propname[64]; /* XXX arbitrary */
+} ComponentMenuArgs;
+/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
+static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v)
+{
+ ComponentMenuArgs *args = (ComponentMenuArgs *)args_v;
+ uiBlock *block;
+ uiLayout *layout;
+
+ block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
+ uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
+
+ layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, UI_GetStyle()), 0);
+
+ uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
+
+ uiBoundsBlock(block, 6);
+ uiBlockSetDirection(block, UI_DOWN);
+ uiEndBlock(C, block);
+
+ return block;
+}
+void uiTemplateComponentMenu(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name)
+{
+ ComponentMenuArgs *args = MEM_callocN(sizeof(ComponentMenuArgs), "component menu template args");
+ uiBlock *block;
+
+ args->ptr = *ptr;
+ BLI_strncpy(args->propname, propname, sizeof(args->propname));
+
+ block = uiLayoutGetBlock(layout);
+ uiBlockBeginAlign(block);
+
+ uiDefBlockButN(block, component_menu, args, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, "");
+
+ uiBlockEndAlign(block);
+}
+
+/************************* Node Socket Icon **************************/
+
+void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ block = uiLayoutGetBlock(layout);
+ uiBlockBeginAlign(block);
+
+ /* XXX using explicit socket colors is not quite ideal.
+ * Eventually it should be possible to use theme colors for this purpose,
+ * but this requires a better design for extendable color palettes in user prefs.
+ */
+ but = uiDefBut(block, NODESOCKET, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ rgba_float_to_uchar(but->col, color);
+
+ uiBlockEndAlign(block);
+}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 78b6d2541fd..f2e553bd140 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -767,7 +767,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
const unsigned char tcol[4] = {wcol->outline[0],
wcol->outline[1],
wcol->outline[2],
- UCHAR_MAX / WIDGET_AA_JITTER};
+ wcol->outline[3] / WIDGET_AA_JITTER};
widget_verts_to_quad_strip(wtb, wtb->totvert, quad_strip);
@@ -1184,7 +1184,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
but->drawstr[selend_tmp] = ch;
- glColor3ubv((unsigned char *)wcol->item);
+ glColor4ubv((unsigned char *)wcol->item);
glRects(rect->xmin + selsta_draw, rect->ymin + 2, rect->xmin + selwidth_draw, rect->ymax - 2);
}
}
@@ -1224,7 +1224,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
}
}
- glColor3ubv((unsigned char *)wcol->text);
+ glColor4ubv((unsigned char *)wcol->text);
uiStyleFontDrawExt(fstyle, rect, but->drawstr + but->ofs, &font_xofs, &font_yofs);
@@ -1272,6 +1272,7 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* draws text and icons for buttons */
static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
+ float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
if (but == NULL)
@@ -1311,12 +1312,12 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
dualset = UI_BITBUT_TEST(*(((int *)but->poin) + 1), but->bitnr);
}
- widget_draw_icon(but, ICON_DOT, dualset ? 1.0f : 0.25f, rect);
+ widget_draw_icon(but, ICON_DOT, dualset ? alpha : 0.25f, rect);
}
else if (but->type == MENU && (but->flag & UI_BUT_NODE_LINK)) {
int tmp = rect->xmin;
rect->xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
- widget_draw_icon(but, ICON_LAYER_USED, 1.0f, rect);
+ widget_draw_icon(but, ICON_LAYER_USED, alpha, rect);
rect->xmin = tmp;
}
@@ -1324,7 +1325,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
* and offset the text label to accommodate it */
if (but->flag & UI_HAS_ICON) {
- widget_draw_icon(but, but->icon + but->iconadd, 1.0f, rect);
+ widget_draw_icon(but, but->icon + but->iconadd, alpha, rect);
/* icons default draw 0.8f x height */
rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect));
@@ -1342,7 +1343,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rcti temp = *rect;
temp.xmin = temp.xmax - BLI_rcti_size_y(rect);
- widget_draw_icon(but, ICON_X, 1.0f, &temp);
+ widget_draw_icon(but, ICON_X, alpha, &temp);
}
/* always draw text for textbutton cursor */
@@ -1379,12 +1380,12 @@ static struct uiWidgetStateColors wcol_state_colors = {
};
/* uiWidgetColors
- * float outline[3];
- * float inner[4];
- * float inner_sel[4];
- * float item[3];
- * float text[3];
- * float text_sel[3];
+ * char outline[3];
+ * char inner[4];
+ * char inner_sel[4];
+ * char item[3];
+ * char text[3];
+ * char text_sel[3];
*
* short shaded;
* float shadetop, shadedown;
@@ -2873,12 +2874,7 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(
round_box_edges(&wtb, roundboxalign, rect, rad);
widgetbase_draw(&wtb, wcol);
-
- /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects
- * over the top to indicate disabled buttons */
- /* XXX, this doesnt work right since the color applies to buttons outside the box too. */
- glClearColor(wcol->inner[0] / 255.0, wcol->inner[1] / 255.0, wcol->inner[2] / 255.0, 1.0);
-
+
copy_v3_v3_char(wcol->inner, old_col);
}
@@ -2941,24 +2937,6 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
}
-
-static void widget_disabled(const rcti *rect)
-{
- float col[4];
-
- glEnable(GL_BLEND);
-
- /* can't use theme TH_BACK or TH_PANEL... undefined */
- glGetFloatv(GL_COLOR_CLEAR_VALUE, col);
- glColor4f(col[0], col[1], col[2], 0.5f);
-
- /* need -1 and +1 to make it work right for aligned buttons,
- * but problem may be somewhere else? */
- glRectf(rect->xmin - 1, rect->ymin - 1, rect->xmax, rect->ymax + 1);
-
- glDisable(GL_BLEND);
-}
-
static uiWidgetType *widget_type(uiWidgetTypeEnum type)
{
bTheme *btheme = UI_GetTheme();
@@ -3171,6 +3149,23 @@ static int widget_roundbox_set(uiBut *but, rcti *rect)
return roundbox;
}
+/* put all widget colors on half alpha, use local storage */
+static void ui_widget_color_disabled(uiWidgetType *wt)
+{
+ static uiWidgetColors wcol_theme_s;
+
+ wcol_theme_s = *wt->wcol_theme;
+
+ wcol_theme_s.outline[3] *= 0.5;
+ wcol_theme_s.inner[3] *= 0.5;
+ wcol_theme_s.inner_sel[3] *= 0.5;
+ wcol_theme_s.item[3] *= 0.5;
+ wcol_theme_s.text[3] *= 0.5;
+ wcol_theme_s.text_sel[3] *= 0.5;
+
+ wt->wcol_theme = &wcol_theme_s;
+}
+
/* conversion from old to new buttons, so still messy */
void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rcti *rect)
{
@@ -3367,30 +3362,47 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
ui_draw_but_TRACKPREVIEW(ar, but, &tui->wcol_regular, rect);
break;
+ case NODESOCKET:
+ ui_draw_but_NODESOCKET(ar, but, &tui->wcol_regular, rect);
+ break;
+
default:
wt = widget_type(UI_WTYPE_REGULAR);
}
}
if (wt) {
- rcti disablerect = *rect; /* rect gets clipped smaller for text */
+ //rcti disablerect = *rect; /* rect gets clipped smaller for text */
int roundboxalign, state;
+ bool disabled = FALSE;
roundboxalign = widget_roundbox_set(but, rect);
state = but->flag;
if (but->editstr) state |= UI_TEXTINPUT;
+ if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
+ if (but->dt != UI_EMBOSSP)
+ disabled = TRUE;
+
+ if (disabled)
+ ui_widget_color_disabled(wt);
+
wt->state(wt, state);
if (wt->custom)
wt->custom(but, &wt->wcol, rect, state, roundboxalign);
else if (wt->draw)
wt->draw(&wt->wcol, rect, state, roundboxalign);
+
+ if (disabled)
+ glEnable(GL_BLEND);
wt->text(fstyle, &wt->wcol, but, rect);
+ if (disabled)
+ glDisable(GL_BLEND);
- if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
- if (but->dt != UI_EMBOSSP)
- widget_disabled(&disablerect);
+// if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE))
+// if (but->dt != UI_EMBOSSP)
+// widget_disabled(&disablerect);
}
}
@@ -3474,7 +3486,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic
rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1) + 10;
}
- glColor3ubv((unsigned char *)wt->wcol.text);
+ glColor4ubv((unsigned char *)wt->wcol.text);
uiStyleFontDraw(fstyle, rect, name);
/* part text right aligned */
@@ -3541,9 +3553,9 @@ void ui_draw_preview_item(uiFontStyle *fstyle, rcti *rect, const char *name, int
glDisable(GL_BLEND);
if (state == UI_ACTIVE)
- glColor3ubv((unsigned char *)wt->wcol.text);
+ glColor4ubv((unsigned char *)wt->wcol.text);
else
- glColor3ubv((unsigned char *)wt->wcol.text_sel);
+ glColor4ubv((unsigned char *)wt->wcol.text_sel);
uiStyleFontDraw(fstyle, &trect, name);
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 09122737373..658d89abea3 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -395,6 +395,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
cp = ts->syntaxv; break;
case TH_NODE_GROUP:
cp = ts->syntaxc; break;
+ case TH_NODE_INTERFACE:
+ cp = ts->console_output; break;
case TH_NODE_FRAME:
cp = ts->movie; break;
case TH_NODE_MATTE:
@@ -961,7 +963,7 @@ void ui_theme_init_default(void)
rgba_char_args_set_fl(btheme->ttime.grid, 0.36, 0.36, 0.36, 1.0);
rgba_char_args_set(btheme->ttime.shade1, 173, 173, 173, 255); /* sliders */
- /* space node, re-uses syntax color storage */
+ /* space node, re-uses syntax and console color storage */
btheme->tnode = btheme->tv3d;
rgba_char_args_set(btheme->tnode.edge_select, 255, 255, 255, 255); /* wire selected */
rgba_char_args_set(btheme->tnode.syntaxl, 155, 155, 155, 160); /* TH_NODE, backdrop */
@@ -970,6 +972,7 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */
rgba_char_args_set(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */
rgba_char_args_set(btheme->tnode.movie, 155, 155, 155, 160); /* frame */
+ rgba_char_args_set(btheme->tnode.console_output, 190, 190, 80, 255); /* group input/output */
btheme->tnode.noodle_curving = 5;
/* space logic */
@@ -1545,7 +1548,7 @@ void init_userdef_do_versions(void)
rgba_char_args_set(btheme->tv3d.editmesh_active, 255, 255, 255, 128);
}
if (U.coba_weight.tot == 0)
- init_colorband(&U.coba_weight, 1);
+ init_colorband(&U.coba_weight, true);
}
if ((bmain->versionfile < 245) || (bmain->versionfile == 245 && bmain->subversionfile < 11)) {
bTheme *btheme;
@@ -2174,6 +2177,13 @@ void init_userdef_do_versions(void)
}
}
+ if (U.versionfile < 266 || (U.versionfile == 266 && U.subversionfile < 2)) {
+ bTheme *btheme;
+ for (btheme = U.themes.first; btheme; btheme = btheme->next) {
+ rgba_char_args_test_set(btheme->tnode.console_output, 223, 202, 53, 255); /* interface nodes */
+ }
+ }
+
/* NOTE!! from now on use U.versionfile and U.subversionfile */
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 8a6de9a549b..013b6d3c606 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -1368,7 +1368,7 @@ void UI_view2d_constant_grid_draw(View2D *v2d)
}
/* Draw a multi-level grid in given 2d-region */
-void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totlevels)
+void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels)
{
int offset = -10;
float lstep = step;
@@ -1378,7 +1378,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
int i;
float start;
- UI_ThemeColorShade(TH_BACK, offset);
+ UI_ThemeColorShade(colorid, offset);
i = (v2d->cur.xmin >= 0.0f ? -(int)(-v2d->cur.xmin / lstep) : (int)(v2d->cur.xmin / lstep));
start = i * lstep;
@@ -1402,7 +1402,7 @@ void UI_view2d_multi_grid_draw(View2D *v2d, float step, int level_size, int totl
}
/* X and Y axis */
- UI_ThemeColorShade(TH_BACK, offset - 8);
+ UI_ThemeColorShade(colorid, offset - 8);
glVertex2f(0.0f, v2d->cur.ymin);
glVertex2f(0.0f, v2d->cur.ymax);
glVertex2f(v2d->cur.xmin, 0.0f);
@@ -2075,6 +2075,28 @@ void UI_view2d_getscale_inverse(View2D *v2d, float *x, float *y)
if (y) *y = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
}
+/* Simple functions for consistent center offset access.
+ * Used by node editor to shift view center for each individual node tree.
+ */
+void UI_view2d_getcenter(struct View2D *v2d, float *x, float *y)
+{
+ /* get center */
+ if (x) *x = BLI_rctf_cent_x(&v2d->cur);
+ if (y) *y = BLI_rctf_cent_y(&v2d->cur);
+}
+void UI_view2d_setcenter(struct View2D *v2d, float x, float y)
+{
+ /* get delta from current center */
+ float dx = x - BLI_rctf_cent_x(&v2d->cur);
+ float dy = y - BLI_rctf_cent_y(&v2d->cur);
+
+ /* add to cur */
+ BLI_rctf_translate(&v2d->cur, dx, dy);
+
+ /* make sure that 'cur' rect is in a valid state as a result of these changes */
+ UI_view2d_curRect_validate(v2d);
+}
+
/* Check if mouse is within scrollers
* - Returns appropriate code for match
* 'h' = in horizontal scroller
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index dbb0d55a2b1..312cceac77d 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -852,7 +852,7 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op)
rename_id(&la->id, get_lamp_defname(type));
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &la->id);
+ ED_node_shader_default(C, &la->id);
la->use_nodes = TRUE;
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 8e2a87c7c64..9b61fa44955 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -604,7 +604,7 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
list = &pchan->constraints;
else {
//if (G.debug & G_DEBUG)
- //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name+2 : "<None>");
+ //printf("edit_constraint_property_get: No active bone for object '%s'\n", (ob)? ob->id.name + 2 : "<None>");
return NULL;
}
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index dd5b97a68ed..948e272eca0 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -378,8 +378,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
sce->lay = 1 << mat->pr_type;
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(mat->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(origmat->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(mat->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(origmat->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
}
@@ -442,8 +442,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (tex && tex->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(origtex->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(tex->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(origtex->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(tex->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_LA) {
@@ -479,8 +479,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (la && la->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(origla->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(la->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(origla->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(la->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
else if (id_type == ID_WO) {
@@ -497,8 +497,8 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre
if (wrld && wrld->nodetree && sp->pr_method == PR_NODE_RENDER) {
/* two previews, they get copied by wmJob */
- ntreeInitPreview(wrld->nodetree, sp->sizex, sp->sizey);
- ntreeInitPreview(origwrld->nodetree, sp->sizex, sp->sizey);
+ BKE_node_preview_init_tree(wrld->nodetree, sp->sizex, sp->sizey, TRUE);
+ BKE_node_preview_init_tree(origwrld->nodetree, sp->sizex, sp->sizey, TRUE);
}
}
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index decc5b131ae..68766591788 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -385,7 +385,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
ma = BKE_material_add(bmain, "Material");
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &ma->id);
+ ED_node_shader_default(C, &ma->id);
ma->use_nodes = TRUE;
}
}
@@ -487,7 +487,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
wo = add_world(bmain, "World");
if (BKE_scene_use_new_shading_nodes(scene)) {
- ED_node_shader_default(scene, &wo->id);
+ ED_node_shader_default(C, &wo->id);
wo->use_nodes = TRUE;
}
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index a467b053443..d29c711cad0 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -377,7 +377,7 @@ static void texture_changed(Main *bmain, Tex *tex)
if (scene->use_nodes && scene->nodetree) {
for (node = scene->nodetree->nodes.first; node; node = node->next) {
if (node->id == &tex->id)
- ED_node_changed_update(&scene->id, node);
+ ED_node_tag_update_id(&scene->id);
}
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 1906a3259a9..8b69e6e831d 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -47,6 +47,7 @@
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_mask_types.h"
+#include "DNA_node_types.h"
#include "DNA_userdef_types.h"
#include "BKE_context.h"
@@ -54,6 +55,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -252,7 +254,7 @@ int ED_operator_node_active(bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
- if (snode && snode->edittree)
+ if (snode && ntreeIsValid(snode->edittree))
return 1;
return 0;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index d94b9372560..92a55151b66 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -407,7 +407,7 @@ void paint_brush_init_tex(Brush *brush)
if (brush) {
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
}
}
@@ -416,7 +416,7 @@ void paint_brush_exit_tex(Brush *brush)
if (brush) {
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 156be008a96..51500ab8e1c 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4073,7 +4073,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
/* init mtex nodes */
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */
+ ntreeTexBeginExecTree(mtex->tex->nodetree); /* has internal flag to detect it only does it once */
/* TODO: Shouldn't really have to do this at the start of every
* stroke, but sculpt would need some sort of notification when
@@ -4249,7 +4249,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
MTex *mtex = &brush->mtex;
if (mtex->tex && mtex->tex->nodetree)
- ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1);
+ ntreeTexEndExecTree(mtex->tex->nodetree->execdata);
}
static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke))
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 1643921e4dd..bb1310d486a 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -113,7 +113,7 @@ static void buttons_texture_users_find_nodetree(ListBase *users, ID *id,
{
bNode *node;
- if (ntree) {
+ if (ntreeIsValid(ntree)) {
for (node = ntree->nodes.first; node; node = node->next) {
if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
PointerRNA ptr;
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index fa7e888f8d7..816ad9960df 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -2321,7 +2321,7 @@ void logic_buttons(bContext *C, ARegion *ar)
uiItemR(split, &settings_ptr, "show_state_panel", UI_ITEM_R_NO_BG, "", ICON_DISCLOSURE_TRI_RIGHT);
row = uiLayoutRow(split, TRUE);
- uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
+ uiDefButBitS(block, TOG, OB_SHOWCONT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide controllers"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2418,7 +2418,7 @@ void logic_buttons(bContext *C, ARegion *ar)
if ((ob->scavisflag & OB_VIS_SENS) == 0) continue;
row = uiLayoutRow(layout, TRUE);
- uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
+ uiDefButBitS(block, TOG, OB_SHOWSENS, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide sensors"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
@@ -2489,7 +2489,7 @@ void logic_buttons(bContext *C, ARegion *ar)
}
row = uiLayoutRow(layout, TRUE);
- uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name+2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
+ uiDefButBitS(block, TOG, OB_SHOWACT, B_REDR, ob->id.name + 2, (short)(xco - U.widget_unit / 2), yco, (short)(width - 1.5f * U.widget_unit), UI_UNIT_Y, &ob->scaflag, 0, 31, 0, 0, TIP_("Object name, click to show/hide actuators"));
RNA_pointer_create((ID *)ob, &RNA_Object, ob, &object_ptr);
uiLayoutSetContextPointer(row, "object", &object_ptr);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 4a14d6ba6fd..0b02aef2fab 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -43,18 +43,23 @@
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BLF_api.h"
#include "BLF_translation.h"
+#include "NOD_texture.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "BLF_translation.h"
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "ED_node.h"
@@ -68,189 +73,136 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
-/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
+/* ****************** MENU FUNCTIONS ***************** */
-static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
+static void node_add_menu_class(bContext *C, uiLayout *layout, void *arg_nodeclass)
{
- SpaceNode *snode = snode_v;
+ Scene *scene = CTX_data_scene(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree;
+ int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass);
+ int event, compatibility = 0;
- if (snode->treetype == NTREE_SHADER) {
- nodeShaderSynchronizeID(node_v, 1);
- // allqueue(REDRAWBUTSSHADING, 0);
+ ntree = snode->nodetree;
+
+ if (!ntree) {
+ uiItemS(layout);
+ return;
}
-}
-
-static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
- bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock,
- const char *UNUSED(name), int x, int y, int width)
-{
- uiDefBut(block, LABEL, 0, IFACE_(sock->name), x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
-}
-static void node_socket_button_default(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
-{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
+ if (ntree->type == NTREE_SHADER) {
+ if (BKE_scene_use_new_shading_nodes(scene))
+ compatibility = NODE_NEW_SHADING;
+ else
+ compatibility = NODE_OLD_SHADING;
+ }
+
+ if (nodeclass == NODE_CLASS_GROUP) {
+ Main *bmain = CTX_data_main(C);
+ bNodeTree *ngroup;
+ const char *ngroup_type, *node_type;
PointerRNA ptr;
- uiBut *bt;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
- bt = uiDefButR(block, NUM, B_NODE_EXEC, IFACE_(name),
- x, y + 1, width, NODE_DY - 2,
- &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype->nclass != nodeclass || !ntype->ui_name)
+ continue;
+ if (!ntype->poll(ntype, ntree))
+ continue;
+
+ switch (ntree->type) {
+ case NTREE_COMPOSIT:
+ ngroup_type = "CompositorNodeTree";
+ node_type = "CompositorNodeGroup";
+ break;
+ case NTREE_SHADER:
+ ngroup_type = "ShaderNodeTree";
+ node_type = "ShaderNodeGroup";
+ break;
+ case NTREE_TEXTURE:
+ ngroup_type = "TextureNodeTree";
+ node_type = "TextureNodeGroup";
+ break;
+ }
+
+ ptr = uiItemFullO(layout, "NODE_OT_group_make", "New Group", ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "node_type", node_type);
+
+ uiItemS(layout);
+
+ for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) {
+ /* only use group trees of the right type */
+ if (STRNEQ(ngroup->idname, ngroup_type))
+ continue;
+ if (!nodeGroupPoll(ntree, ngroup))
+ continue;
+
+ ptr = uiItemFullO(layout, "NODE_OT_add_group_node", ngroup->id.name + 2, ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "type", ntype->idname);
+ RNA_string_set(&ptr, "grouptree", ngroup->id.name + 2);
+ }
+ NODE_TYPES_END
+ }
+ else if (nodeclass == NODE_DYNAMIC) {
+ /* disabled */
}
-}
-
-static void node_socket_button_string(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
-{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
else {
PointerRNA ptr;
- uiBut *bt;
-
- SpaceNode *snode = CTX_wm_space_node(C);
- const char *ui_name = IFACE_(name);
- float slen;
-
- UI_ThemeColor(TH_TEXT);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect; /* XXX, check for dpis */
- while (slen > (width * 0.5f) && *ui_name) {
- ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect;
- }
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- if (name[0] == '\0')
- slen = 0.0;
- bt = uiDefButR(block, TEX, B_NODE_EXEC, "",
- x, y + 1, width - slen, NODE_DY - 2,
- &ptr, "default_value", 0, 0, 0, -1, -1, "");
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
-
- if (slen > 0.0f)
- uiDefBut(block, LABEL, 0, IFACE_(name), x + (width - slen), y + 2, slen, NODE_DY - 2, NULL, 0, 0, 0, 0, "");
+ NODE_TYPES_BEGIN(ntype)
+ if (ntype->nclass != nodeclass || !ntype->ui_name)
+ continue;
+ if (!ntype->poll(ntype, ntree))
+ continue;
+ if (compatibility && (ntype->compatibility & compatibility) == 0)
+ continue;
+
+ ptr = uiItemFullO(layout, "NODE_OT_add_node", IFACE_(ntype->ui_name), ntype->ui_icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_string_set(&ptr, "type", ntype->idname);
+ NODE_TYPES_END
}
}
-typedef struct SocketComponentMenuArgs {
- PointerRNA ptr;
- int x, y, width;
- uiButHandleFunc cb;
- void *arg1, *arg2;
-} SocketComponentMenuArgs;
-/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
-static uiBlock *socket_component_menu(bContext *C, ARegion *ar, void *args_v)
+static void node_add_menu_foreach_class_cb(void *calldata, int nclass, const char *name)
{
- SocketComponentMenuArgs *args = (SocketComponentMenuArgs *)args_v;
- uiBlock *block;
- uiLayout *layout;
-
- block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
- uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
-
- layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- args->x, args->y + 2, args->width, NODE_DY, UI_GetStyle()), FALSE);
-
- uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NONE);
-
- return block;
+ uiLayout *layout = calldata;
+ uiItemMenuF(layout, IFACE_(name), 0, node_add_menu_class, SET_INT_IN_POINTER(nclass));
}
-static void node_socket_button_components(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+
+static void node_add_menu_default(const bContext *C, uiLayout *layout, bNodeTree *ntree)
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
- else {
- PointerRNA ptr;
- SocketComponentMenuArgs *args;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- args = MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
-
- args->ptr = ptr;
- args->x = x;
- args->y = y;
- args->width = width;
- args->cb = node_sync_cb;
- args->arg1 = CTX_wm_space_node(C);
- args->arg2 = node;
-
- uiDefBlockButN(block, socket_component_menu, args, IFACE_(name), x, y + 1, width, NODE_DY - 2, "");
- }
+ Scene *scene = CTX_data_scene(C);
+
+ if (ntree->typeinfo->foreach_nodeclass)
+ ntree->typeinfo->foreach_nodeclass(scene, layout, node_add_menu_foreach_class_cb);
}
-static void node_socket_button_color(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+/* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
+
+static void node_socket_button_label(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr, PointerRNA *UNUSED(node_ptr))
{
- if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
- node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
- else {
- PointerRNA ptr;
- uiBut *bt;
- int labelw = width - 40;
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-
- bt = uiDefButR(block, COLOR, B_NODE_EXEC, "",
- x, y + 2, (labelw > 0 ? 40 : width), NODE_DY - 2,
- &ptr, "default_value", -1, 0, 0, -1, -1, NULL);
- if (node)
- uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
-
- if (name[0] != '\0' && labelw > 0)
- uiDefBut(block, LABEL, 0, IFACE_(name), x + 40, y + 2, labelw, NODE_DY - 2, NULL, 0, 0, 0, 0, "");
- }
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ uiItemL(layout, sock->name, 0);
}
-/* standard draw function, display the default input value */
-static void node_draw_input_default(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *name, int x, int y, int width)
+static void node_draw_input_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int linked)
{
- bNodeSocketType *stype = ntreeGetSocketType(sock->type);
- if (stype->buttonfunc)
- stype->buttonfunc(C, block, ntree, node, sock, name, x, y, width);
+ bNodeSocket *sock = (bNodeSocket *)ptr->data;
+ if (linked || (sock->flag & SOCK_HIDE_VALUE))
+ node_socket_button_label(C, layout, ptr, node_ptr);
else
- node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
+ sock->typeinfo->draw(C, layout, ptr, node_ptr);
}
-static void node_draw_output_default(const bContext *UNUSED(C), uiBlock *block,
- bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock,
- const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width))
+static void node_draw_output_default(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked))
{
- const char *ui_name = IFACE_(name);
- float slen;
-
- UI_ThemeColor(TH_TEXT);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) ;
- while (slen > NODE_WIDTH(node) && *ui_name) {
- ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
- slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X);
- }
-
- if (*ui_name) {
- uiDefBut(block, LABEL, 0, ui_name,
- (int)(sock->locx - slen), (int)(sock->locy - 9.0f),
- (short)slen, (short)NODE_DY,
- NULL, 0, 0, 0, 0, "");
- }
+ node_socket_button_label(C, layout, ptr, node_ptr);
}
+
/* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
#if 0 /* UNUSED */
@@ -297,25 +249,23 @@ static void node_draw_socket_new(bNodeSocket *sock, float size)
static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- PropertyRNA *prop;
-
- /* first socket stores value */
- prop = RNA_struct_find_property(ptr, "outputs");
- RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- uiLayout *col;
+ bNode *node = ptr->data;
+ /* first output stores value */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- PropertyRNA *prop;
-
- /* first socket stores value */
- prop = RNA_struct_find_property(ptr, "outputs");
- RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
+ uiLayout *col;
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
col = uiLayoutColumn(layout, FALSE);
uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
@@ -399,14 +349,15 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA
static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
- bNode *node = (bNode *)ptr->data;
- bNodeSocket *sock = node->outputs.first; /* first socket stores normal */
+ bNode *node = ptr->data;
+ /* first output stores normal */
+ bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
-
- RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr);
+ RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
+
#if 0 /* not used in 2.5x yet */
static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
{
@@ -491,427 +442,6 @@ static int node_resize_area_default(bNode *node, int x, int y)
/* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
-/* width of socket columns in group display */
-#define NODE_GROUP_FRAME 120
-
-/* based on settings in node, sets drawing rect info. each redraw! */
-/* note: this assumes only 1 group at a time is drawn (linked data) */
-/* in node->totr the entire boundbox for the group is stored */
-static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
-{
- if (!(gnode->flag & NODE_GROUP_EDIT)) {
- node_update_default(C, ntree, gnode);
- }
- else {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNode *node;
- bNodeSocket *sock, *gsock;
- float locx, locy;
- rctf *rect = &gnode->totr;
- const float dpi_fac = UI_DPI_FAC;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float group_header = 26 * dpi_fac;
- int counter;
- int dy;
-
- /* get "global" coords */
- node_to_view(gnode, 0.0f, 0.0f, &locx, &locy);
-
- /* center them, is a bit of abuse of locx and locy though */
- node_update_nodetree(C, ngroup, locx, locy);
-
- rect->xmin = rect->xmax = locx;
- rect->ymin = rect->ymax = locy;
-
- counter = 1;
- for (node = ngroup->nodes.first; node; node = node->next) {
- if (counter) {
- *rect = node->totr;
- counter = 0;
- }
- else
- BLI_rctf_union(rect, &node->totr);
- }
-
- /* add some room for links to group sockets */
- rect->xmin -= 4 * NODE_DY;
- rect->xmax += 4 * NODE_DY;
- rect->ymin -= NODE_DY;
- rect->ymax += NODE_DY;
-
- /* input sockets */
- dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1));
- gsock = ngroup->inputs.first;
- sock = gnode->inputs.first;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- sock->locx = rect->xmin - node_group_frame;
- sock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- gsock->locx = rect->xmin;
- gsock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- gsock = gsock->next;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- gsock->locx = rect->xmin;
- sock->locx = rect->xmin - node_group_frame;
- sock->locy = gsock->locy = dy;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- gsock = gsock->next;
- }
- }
-
- /* output sockets */
- dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1));
- gsock = ngroup->outputs.first;
- sock = gnode->outputs.first;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- sock->locx = rect->xmax + node_group_frame;
- sock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- gsock->locx = rect->xmax;
- gsock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- gsock = gsock->next;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- gsock->locx = rect->xmax;
- sock->locx = rect->xmax + node_group_frame;
- sock->locy = gsock->locy = dy - NODE_DYS;
-
- /* prevent long socket lists from growing out of the group box */
- if (dy - 3 * NODE_DYS < rect->ymin)
- rect->ymin = dy - 3 * NODE_DYS;
- if (dy + 3 * NODE_DYS > rect->ymax)
- rect->ymax = dy + 3 * NODE_DYS;
- dy -= 2 * NODE_DY;
-
- sock = sock->next;
- gsock = gsock->next;
- }
- }
-
- /* Set the block bounds to clip mouse events from underlying nodes.
- * Add margin for header and input/output columns.
- */
- uiExplicitBoundsBlock(gnode->block,
- rect->xmin - node_group_frame,
- rect->ymin,
- rect->xmax + node_group_frame,
- rect->ymax + group_header);
- }
-}
-
-static void update_group_input_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
-{
- bNodeTree *ngroup = (bNodeTree *)ngroup_v;
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- ntreeUpdateTree(ngroup);
-}
-
-static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
-{
- bNodeTree *ngroup = (bNodeTree *)ngroup_v;
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- ntreeUpdateTree(ngroup);
-}
-
-static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock,
- int in_out, float xoffset, float yoffset, short width, short height)
-{
- if (sock->flag & SOCK_DYNAMIC) {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- uiBut *but;
- but = uiDefBut(gnode->block, TEX, 0, "",
- sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
- sock->name, 0, sizeof(sock->name), 0, 0, "");
- if (in_out == SOCK_IN)
- uiButSetFunc(but, update_group_input_cb, snode, ngroup);
- else
- uiButSetFunc(but, update_group_output_cb, snode, ngroup);
- }
- else {
- const char *ui_name = IFACE_(sock->name);
- uiDefBut(gnode->block, LABEL, 0, ui_name,
- sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
- NULL, 0, 0, 0, 0, "");
- }
-}
-
-static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode,
- bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out)
-{
- const float dpi_fac = UI_DPI_FAC;
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type);
- uiBut *bt;
- float offset;
- int draw_value;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float socket_size = NODE_SOCKSIZE;
- const float arrowbutw = 0.8f * UI_UNIT_X;
- const short co_text_w = 72 * dpi_fac;
- const float co_margin = 6.0f * dpi_fac;
- /* layout stuff for buttons on group left frame */
- const float colw = 0.6f * node_group_frame;
- const float col1 = co_margin - node_group_frame;
- const float col2 = col1 + colw + co_margin;
- const float col3 = -arrowbutw - co_margin;
- /* layout stuff for buttons on group right frame */
- const float cor1 = co_margin;
- const float cor2 = cor1 + arrowbutw;
- const float cor3 = cor2 + arrowbutw + co_margin;
-
- /* node and group socket circles */
- if (sock)
- node_socket_circle_draw(ntree, sock, socket_size, sock->flag & SELECT);
- if (gsock)
- node_socket_circle_draw(ngroup, gsock, socket_size, gsock->flag & SELECT);
-
- /* socket name */
- offset = (in_out == SOCK_IN ? col1 : cor3);
- if (!gsock)
- offset += (in_out == SOCK_IN ? node_group_frame : -node_group_frame);
-
- /* draw both name and value button if:
- * 1) input: not internal
- * 2) output: (node type uses const outputs) and (group output is unlinked)
- */
- draw_value = 0;
- switch (in_out) {
- case SOCK_IN:
- draw_value = !(gsock && (gsock->flag & SOCK_INTERNAL));
- break;
- case SOCK_OUT:
- if (gnode->typeinfo->flag & NODE_CONST_OUTPUT)
- draw_value = !(gsock && gsock->link);
- break;
- }
- if (draw_value) {
- /* both name and value buttons */
- if (gsock) {
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0, co_text_w, NODE_DY);
- if (stype->buttonfunc)
- stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "",
- gsock->locx + offset, gsock->locy - NODE_DY, colw);
- }
- else {
- draw_group_socket_name(snode, gnode, sock, in_out, offset, 0, co_text_w, NODE_DY);
- if (stype->buttonfunc)
- stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "",
- sock->locx + offset, sock->locy - NODE_DY, colw);
- }
- }
- else {
- /* only name, no value button */
- if (gsock)
- draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
- else
- draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
- }
-
- if (gsock && (gsock->flag & SOCK_DYNAMIC)) {
- /* up/down buttons */
- offset = (in_out == SOCK_IN ? col2 : cor2);
- uiBlockSetDirection(gnode->block, UI_TOP);
- uiBlockBeginAlign(gnode->block);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP,
- gsock->locx + offset, gsock->locy, arrowbutw, arrowbutw, "");
- if (!gsock->prev || !(gsock->prev->flag & SOCK_DYNAMIC))
- uiButSetFlag(bt, UI_BUT_DISABLED);
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN,
- gsock->locx + offset, gsock->locy - arrowbutw, arrowbutw, arrowbutw, "");
- if (!gsock->next || !(gsock->next->flag & SOCK_DYNAMIC))
- uiButSetFlag(bt, UI_BUT_DISABLED);
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- uiBlockEndAlign(gnode->block);
- uiBlockSetDirection(gnode->block, 0);
-
- /* remove button */
- offset = (in_out == SOCK_IN ? col3 : cor1);
- uiBlockSetEmboss(gnode->block, UI_EMBOSSN);
- bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X,
- gsock->locx + offset, gsock->locy - 0.5f * arrowbutw, arrowbutw, arrowbutw, "");
- RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
- RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
- uiBlockSetEmboss(gnode->block, UI_EMBOSS);
- }
-}
-
-/* groups are, on creation, centered around 0,0 */
-static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
-{
- if (!(gnode->flag & NODE_GROUP_EDIT)) {
- node_draw_default(C, ar, snode, ntree, gnode);
- }
- else {
- bNodeTree *ngroup = (bNodeTree *)gnode->id;
- bNodeSocket *sock, *gsock;
- uiLayout *layout;
- PointerRNA ptr;
- rctf rect = gnode->totr;
- const float dpi_fac = UI_DPI_FAC;
- const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
- const float group_header = 26 * dpi_fac;
-
- int index;
-
- /* backdrop header */
- glEnable(GL_BLEND);
- uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
- UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
- uiDrawBox(GL_POLYGON,
- rect.xmin - node_group_frame, rect.ymax,
- rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
-
- /* backdrop body */
- UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
- uiSetRoundBox(UI_CNR_NONE);
- uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
-
- /* input column */
- UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
- uiSetRoundBox(UI_CNR_BOTTOM_LEFT);
- uiDrawBox(GL_POLYGON, rect.xmin - node_group_frame, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD);
-
- /* output column */
- UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
- uiSetRoundBox(UI_CNR_BOTTOM_RIGHT);
- uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax + node_group_frame, rect.ymax, BASIS_RAD);
-
- /* input column separator */
- glColor4ub(200, 200, 200, 140);
- glBegin(GL_LINES);
- glVertex2f(rect.xmin, rect.ymin);
- glVertex2f(rect.xmin, rect.ymax);
- glEnd();
-
- /* output column separator */
- glColor4ub(200, 200, 200, 140);
- glBegin(GL_LINES);
- glVertex2f(rect.xmax, rect.ymin);
- glVertex2f(rect.xmax, rect.ymax);
- glEnd();
-
- /* group node outline */
- uiSetRoundBox(UI_CNR_ALL);
- glColor4ub(200, 200, 200, 140);
- glEnable(GL_LINE_SMOOTH);
- uiDrawBox(GL_LINE_LOOP,
- rect.xmin - node_group_frame, rect.ymin,
- rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
-
- /* backdrop title */
- UI_ThemeColor(TH_TEXT_HI);
-
- layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
- (int)(rect.xmin + NODE_MARGIN_X), (int)(rect.ymax + (group_header - (2.5f * dpi_fac))),
- min_ii((int)(BLI_rctf_size_x(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle());
- RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr);
- uiTemplateIDBrowse(layout, (bContext *)C, &ptr, "node_tree", NULL, NULL, NULL);
- uiBlockLayoutResolve(gnode->block, NULL, NULL);
-
- /* draw the internal tree nodes and links */
- node_draw_nodetree(C, ar, snode, ngroup);
-
- /* group sockets */
- gsock = ngroup->inputs.first;
- sock = gnode->inputs.first;
- index = 0;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_IN);
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_IN);
- gsock = gsock->next;
- index++;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_IN);
- sock = sock->next;
- gsock = gsock->next;
- index++;
- }
- }
- gsock = ngroup->outputs.first;
- sock = gnode->outputs.first;
- index = 0;
- while (gsock || sock) {
- while (sock && !sock->groupsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_OUT);
- sock = sock->next;
- }
- while (gsock && (!sock || sock->groupsock != gsock)) {
- draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_OUT);
- gsock = gsock->next;
- index++;
- }
- while (sock && gsock && sock->groupsock == gsock) {
- draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_OUT);
- sock = sock->next;
- gsock = gsock->next;
- index++;
- }
- }
-
- uiEndBlock(C, gnode->block);
- uiDrawBlock(C, gnode->block);
- gnode->block = NULL;
- }
-}
static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
@@ -1003,7 +533,8 @@ static void node_draw_frame_label(bNode *node, const float aspect)
BLF_disable(fontid, BLF_ASPECT);
}
-static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *UNUSED(ntree), bNode *node)
+static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode,
+ bNodeTree *UNUSED(ntree), bNode *node, bNodeInstanceKey UNUSED(key))
{
rctf *rct = &node->totr;
int color_id = node_get_colorid(node);
@@ -1118,7 +649,8 @@ static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntr
node->totr.ymin = locy - size;
}
-static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node)
+static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),
+ bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
bNodeSocket *sock;
char showname[128]; /* 128 used below */
@@ -1178,7 +710,7 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
* highlight also if node itself is selected, since we don't display the node body separately!
*/
for (sock = node->inputs.first; sock; sock = sock->next) {
- node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
}
uiEndBlock(C, node->block);
@@ -1205,8 +737,6 @@ static void node_common_set_butfunc(bNodeType *ntype)
switch (ntype->type) {
case NODE_GROUP:
ntype->uifunc = node_uifunc_group;
- ntype->drawfunc = node_draw_group;
- ntype->drawupdatefunc = node_update_group;
break;
case NODE_FRAME:
ntype->drawfunc = node_draw_frame;
@@ -1491,8 +1021,6 @@ static void node_shader_buts_script_details(uiLayout *layout, bContext *C, Point
static void node_shader_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
- /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
-
case SH_NODE_MATERIAL:
case SH_NODE_MATERIAL_EXT:
ntype->uifunc = node_shader_buts_material;
@@ -2092,20 +1620,17 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
}
/* draw function for file output node sockets, displays only sub-path and format, no value button */
-static void node_draw_input_file_output(const bContext *C, uiBlock *block,
- bNodeTree *ntree, bNode *node, bNodeSocket *sock,
- const char *UNUSED(name), int x, int y, int width)
+static void node_draw_input_file_output(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *node_ptr, int UNUSED(linked))
{
- uiLayout *layout, *row;
- PointerRNA nodeptr, inputptr, imfptr;
+ bNodeTree *ntree = ptr->id.data;
+ bNodeSocket *sock = ptr->data;
+ uiLayout *row;
+ PointerRNA inputptr, imfptr;
int imtype;
- int rx, ry;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
- layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y + NODE_DY, width, 20, UI_GetStyle());
row = uiLayoutRow(layout, FALSE);
- imfptr = RNA_pointer_get(&nodeptr, "format");
+ imfptr = RNA_pointer_get(node_ptr, "format");
imtype = RNA_enum_get(&imfptr, "file_format");
if (imtype == R_IMF_IMTYPE_MULTILAYER) {
NodeImageMultiFileSocket *input = sock->storage;
@@ -2117,6 +1642,7 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block,
NodeImageMultiFileSocket *input = sock->storage;
PropertyRNA *imtype_prop;
const char *imtype_name;
+ uiBlock *block;
RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
uiItemL(row, input->path, ICON_NONE);
@@ -2127,12 +1653,11 @@ static void node_draw_input_file_output(const bContext *C, uiBlock *block,
imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
+ block = uiLayoutGetBlock(row);
uiBlockSetEmboss(block, UI_EMBOSSP);
uiItemL(row, imtype_name, ICON_NONE);
uiBlockSetEmboss(block, UI_EMBOSSN);
}
-
- uiBlockLayoutResolve(block, &rx, &ry);
}
static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
@@ -2781,8 +2306,6 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN
static void node_composit_set_butfunc(bNodeType *ntype)
{
switch (ntype->type) {
- /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
-
case CMP_NODE_IMAGE:
ntype->uifunc = node_composit_buts_image;
ntype->uifuncbut = node_composit_buts_image_details;
@@ -2998,8 +2521,6 @@ static void node_composit_set_butfunc(bNodeType *ntype)
case CMP_NODE_TRACKPOS:
ntype->uifunc = node_composit_buts_trackpos;
break;
- default:
- ntype->uifunc = NULL;
}
}
@@ -3158,81 +2679,170 @@ static void node_texture_set_butfunc(bNodeType *ntype)
/* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
-void ED_node_init_butfuncs(void)
+static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTreeType *treetype;
- bNodeType *ntype;
- bNodeSocketType *stype;
- int i;
+ bNodeTree *ntree = ptr->id.data;
+ ED_node_tag_update_nodetree(bmain, ntree);
+}
+
+static void node_socket_template_properties_update(bNodeType *ntype, bNodeSocketTemplate *stemp)
+{
+ StructRNA *srna = ntype->ext.srna;
+ PropertyRNA *prop = RNA_struct_type_find_property(srna, stemp->identifier);
- /* node type ui functions */
- for (i = 0; i < NUM_NTREE_TYPES; ++i) {
- treetype = ntreeGetType(i);
- if (treetype) {
- for (ntype = treetype->node_types.first; ntype; ntype = ntype->next) {
- /* default ui functions */
- ntype->drawfunc = node_draw_default;
- ntype->drawupdatefunc = node_update_default;
- ntype->select_area_func = node_select_area_default;
- ntype->tweak_area_func = node_tweak_area_default;
- ntype->uifunc = NULL;
- ntype->uifuncbut = NULL;
- ntype->drawinputfunc = node_draw_input_default;
- ntype->drawoutputfunc = node_draw_output_default;
- ntype->resize_area_func = node_resize_area_default;
-
- node_common_set_butfunc(ntype);
-
- switch (i) {
- case NTREE_COMPOSIT:
- node_composit_set_butfunc(ntype);
- break;
- case NTREE_SHADER:
- node_shader_set_butfunc(ntype);
- break;
- case NTREE_TEXTURE:
- node_texture_set_butfunc(ntype);
- break;
- }
- }
- }
+ if (prop)
+ RNA_def_property_update_runtime(prop, node_property_update_default);
+}
+
+static void node_template_properties_update(bNodeType *ntype)
+{
+ bNodeSocketTemplate *stemp;
+
+ if (ntype->inputs) {
+ for (stemp = ntype->inputs; stemp->type >= 0; ++stemp)
+ node_socket_template_properties_update(ntype, stemp);
}
+ if (ntype->outputs) {
+ for (stemp = ntype->outputs; stemp->type >= 0; ++stemp)
+ node_socket_template_properties_update(ntype, stemp);
+ }
+}
+
+void ED_node_init_butfuncs(void)
+{
+ /* node type ui functions */
+ NODE_TYPES_BEGIN(ntype)
+ /* default ui functions */
+ ntype->drawfunc = node_draw_default;
+ ntype->drawupdatefunc = node_update_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
+ ntype->uifunc = NULL;
+ ntype->uifuncbut = NULL;
+ ntype->drawinputfunc = node_draw_input_default;
+ ntype->drawoutputfunc = node_draw_output_default;
+ ntype->resize_area_func = node_resize_area_default;
+
+ node_common_set_butfunc(ntype);
+
+ node_composit_set_butfunc(ntype);
+ node_shader_set_butfunc(ntype);
+ node_texture_set_butfunc(ntype);
+
+ /* define update callbacks for socket properties */
+ node_template_properties_update(ntype);
+ NODE_TYPES_END
- /* socket type ui functions */
- for (i = 0; i < NUM_SOCKET_TYPES; ++i) {
- stype = ntreeGetSocketType(i);
- if (stype) {
- switch (stype->type) {
- case SOCK_FLOAT:
- case SOCK_INT:
- case SOCK_BOOLEAN:
- stype->buttonfunc = node_socket_button_default;
- break;
- case SOCK_STRING:
- stype->buttonfunc = node_socket_button_string;
- break;
- case SOCK_VECTOR:
- stype->buttonfunc = node_socket_button_components;
- break;
- case SOCK_RGBA:
- stype->buttonfunc = node_socket_button_color;
- break;
- case SOCK_SHADER:
- stype->buttonfunc = node_socket_button_label;
- break;
- default:
- stype->buttonfunc = NULL;
- }
+ /* tree type icons */
+ ntreeType_Composite->ui_icon = ICON_RENDERLAYERS;
+ ntreeType_Composite->draw_add_menu = node_add_menu_default;
+ ntreeType_Shader->ui_icon = ICON_MATERIAL;
+ ntreeType_Shader->draw_add_menu = node_add_menu_default;
+ ntreeType_Texture->ui_icon = ICON_TEXTURE;
+ ntreeType_Texture->draw_add_menu = node_add_menu_default;
+}
+
+void ED_init_custom_node_type(bNodeType *ntype)
+{
+ /* default ui functions */
+ ntype->drawfunc = node_draw_default;
+ ntype->drawupdatefunc = node_update_default;
+ ntype->drawinputfunc = node_draw_input_default;
+ ntype->drawoutputfunc = node_draw_output_default;
+ ntype->resize_area_func = node_resize_area_default;
+ ntype->select_area_func = node_select_area_default;
+ ntype->tweak_area_func = node_tweak_area_default;
+}
+
+void ED_init_custom_node_socket_type(bNodeSocketType *stype)
+{
+ /* default ui functions */
+ stype->draw = node_socket_button_label;
+}
+
+/* maps standard socket integer type to a color */
+static const float std_node_socket_colors[][4] = {
+ {0.63, 0.63, 0.63, 1.0}, /* SOCK_FLOAT */
+ {0.39, 0.39, 0.78, 1.0}, /* SOCK_VECTOR */
+ {0.78, 0.78, 0.16, 1.0}, /* SOCK_RGBA */
+ {0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
+ {0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
+ {0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
+ {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
+ {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */
+};
+
+/* common color callbacks for standard types */
+static void std_node_socket_draw_color(bContext *UNUSED(C), PointerRNA *ptr, PointerRNA *UNUSED(node_ptr), float *r_color)
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
+}
+static void std_node_socket_interface_draw_color(bContext *UNUSED(C), PointerRNA *ptr, float *r_color)
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ copy_v4_v4(r_color, std_node_socket_colors[type]);
+}
+
+static void std_node_socket_draw(bContext *UNUSED(C), uiLayout *layout, PointerRNA *ptr, PointerRNA *UNUSED(node_ptr))
+{
+ bNodeSocket *sock = ptr->data;
+ int type = sock->typeinfo->type;
+ /*int subtype = sock->typeinfo->subtype;*/
+
+ switch (type) {
+ case SOCK_FLOAT:
+ case SOCK_INT:
+ case SOCK_BOOLEAN:
+ uiItemR(layout, ptr, "default_value", 0, sock->name, 0);
+ break;
+ case SOCK_VECTOR:
+ uiTemplateComponentMenu(layout, ptr, "default_value", sock->name);
+ break;
+ case SOCK_RGBA: {
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
+ /* draw the socket name right of the actual button */
+ uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiItemL(row, sock->name, 0);
+ break;
+ }
+ case SOCK_STRING: {
+ uiLayout *row = uiLayoutRow(layout, true);
+ /* draw the socket name right of the actual button */
+ uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiItemL(row, sock->name, 0);
+ break;
}
}
}
+void ED_init_standard_node_socket_type(bNodeSocketType *stype)
+{
+ stype->draw = std_node_socket_draw;
+ stype->draw_color = std_node_socket_draw_color;
+ stype->interface_draw_color = std_node_socket_interface_draw_color;
+}
+
+static void node_socket_virtual_draw_color(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PointerRNA *UNUSED(node_ptr), float *r_color)
+{
+ /* alpha = 0, empty circle */
+ zero_v4(r_color);
+}
+
+void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
+{
+ stype->draw = node_socket_button_label;
+ stype->draw_color = node_socket_virtual_draw_color;
+}
+
/* ************** Generic drawing ************** */
void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
{
-
- if ((snode->flag & SNODE_BACKDRAW) && snode->treetype == NTREE_COMPOSIT) {
+ if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
void *lock;
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
@@ -3640,18 +3250,13 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
do_triple = TRUE;
}
else {
- int cycle = 0;
-
/* going to give issues once... */
if (link->tosock->flag & SOCK_UNAVAIL)
return;
if (link->fromsock->flag & SOCK_UNAVAIL)
return;
- /* check cyclic */
- if (link->fromnode && link->tonode)
- cycle = (link->fromnode->level < link->tonode->level || link->tonode->level == 0xFFF);
- if (!cycle && (link->flag & NODE_LINK_VALID)) {
+ if (link->flag & NODE_LINK_VALID) {
/* special indicated link, on drop-node */
if (link->flag & NODE_LINKFLAG_HILITE) {
th_col1 = th_col2 = TH_ACTIVE;
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 235d91ecd92..765f2b67549 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -62,62 +62,60 @@
#include "node_intern.h" /* own include */
-/* can be called from menus too, but they should do own undopush and redraws */
-bNode *node_add_node(SpaceNode *snode, Main *bmain, Scene *scene,
- bNodeTemplate *ntemp, float locx, float locy)
+/* XXX Does some additional initialization on top of nodeAddNode
+ * Can be used with both custom and static nodes, if idname==NULL the static int type will be used instead.
+ * Can be called from menus too, but they should do own undopush and redraws.
+ */
+bNode *node_add_node(const bContext *C, const char *idname, int type, float locx, float locy)
{
- bNode *node = NULL, *gnode;
-
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ bNode *node = NULL;
+
node_deselect_all(snode);
-
- node = nodeAddNode(snode->edittree, ntemp);
-
+
+ if (idname)
+ node = nodeAddNode(C, snode->edittree, idname);
+ else
+ node = nodeAddStaticNode(C, snode->edittree, type);
+ BLI_assert(node && node->typeinfo);
+
/* generics */
- if (node) {
- node_select(node);
-
- /* node location is mapped */
- locx /= UI_DPI_FAC;
- locy /= UI_DPI_FAC;
-
- gnode = node_tree_get_editgroup(snode->nodetree);
- // arbitrary y offset of 60 so its visible
- if (gnode) {
- node_from_view(gnode, locx, locy + 60.0f, &node->locx, &node->locy);
- }
- else {
- node->locx = locx;
- node->locy = locy + 60.0f;
+ node->locx = locx;
+ node->locy = locy + 60.0f; // arbitrary.. so its visible, (0,0) is top of node
+ nodeSetSelected(node, TRUE);
+
+ /* node location is mapped */
+ locx /= UI_DPI_FAC;
+ locy /= UI_DPI_FAC;
+
+ node->locx = locx;
+ node->locy = locy + 60.0f;
+
+ ntreeUpdateTree(snode->edittree);
+ ED_node_set_active(bmain, snode->edittree, node);
+
+ if (snode->nodetree->type == NTREE_COMPOSIT) {
+ if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
+ node->id = &scene->id;
}
-
- ntreeUpdateTree(snode->edittree);
- ED_node_set_active(bmain, snode->edittree, node);
-
- if (snode->nodetree->type == NTREE_COMPOSIT) {
- if (ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE)) {
- node->id = &scene->id;
- }
- else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
- node->id = (ID *)scene->clip;
- }
-
- ntreeCompositForceHidden(snode->edittree, scene);
+ else if (ELEM3(node->type, CMP_NODE_MOVIECLIP, CMP_NODE_MOVIEDISTORTION, CMP_NODE_STABILIZE2D)) {
+ node->id = (ID *)scene->clip;
}
-
- if (node->id)
- id_us_plus(node->id);
-
-
- if (snode->flag & SNODE_USE_HIDDEN_PREVIEW)
- node->flag &= ~NODE_PREVIEW;
-
- snode_update(snode, node);
+
+ ntreeCompositForceHidden(snode->edittree, scene);
}
-
+
+ if (node->id)
+ id_us_plus(node->id);
+
+ snode_update(snode, node);
+
if (snode->nodetree->type == NTREE_TEXTURE) {
ntreeTexCheckCyclics(snode->edittree);
}
-
+
return node;
}
@@ -183,9 +181,7 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
/* create the reroute node for this cursock */
if (!reroute_node) {
- bNodeTemplate ntemp;
- ntemp.type = NODE_REROUTE;
- reroute_node = nodeAddNode(ntree, &ntemp);
+ reroute_node = nodeAddStaticNode(C, ntree, NODE_REROUTE);
/* add a single link to/from the reroute node to replace multiple links */
if (in_out == SOCK_OUT) {
@@ -213,18 +209,11 @@ static bNodeSocketLink *add_reroute_do_socket_section(bContext *C, bNodeSocketLi
}
if (num_links > 0) {
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
-
/* average cut point from shared links */
mul_v2_fl(insert_point, 1.0f / num_links);
- if (gnode) {
- node_from_view(gnode, insert_point[0], insert_point[1], &reroute_node->locx, &reroute_node->locy);
- }
- else {
- reroute_node->locx = insert_point[0];
- reroute_node->locy = insert_point[1];
- }
+ reroute_node->locx = insert_point[0];
+ reroute_node->locy = insert_point[1];
}
return socklink;
@@ -266,6 +255,8 @@ static int add_reroute_exec(bContext *C, wmOperator *op)
output_links.first = output_links.last = NULL;
input_links.first = input_links.last = NULL;
for (link = ntree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (add_reroute_intersect_check(link, mcoords, i, insert_point)) {
add_reroute_insert_socket_link(&output_links, link->fromsock, link, insert_point);
add_reroute_insert_socket_link(&input_links, link->tosock, link, insert_point);
@@ -330,12 +321,10 @@ void NODE_OT_add_reroute(wmOperatorType *ot)
static int node_add_file_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
Image *ima = NULL;
- bNodeTemplate ntemp;
+ int type = 0;
/* check input variables */
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
@@ -367,36 +356,35 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
switch (snode->nodetree->type) {
case NTREE_SHADER:
- ntemp.type = SH_NODE_TEX_IMAGE;
+ type = SH_NODE_TEX_IMAGE;
break;
case NTREE_TEXTURE:
- ntemp.type = TEX_NODE_IMAGE;
+ type = TEX_NODE_IMAGE;
break;
case NTREE_COMPOSIT:
- ntemp.type = CMP_NODE_IMAGE;
+ type = CMP_NODE_IMAGE;
break;
default:
return OPERATOR_CANCELLED;
}
-
+
ED_preview_kill_jobs(C);
-
- node = node_add_node(snode, bmain, scene, &ntemp, snode->cursor[0], snode->cursor[1]);
-
+
+ node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]);
+
if (!node) {
BKE_report(op->reports, RPT_WARNING, "Could not add an image node");
return OPERATOR_CANCELLED;
}
-
+
node->id = (ID *)ima;
- id_us_plus(node->id);
-
+
BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
return OPERATOR_FINISHED;
}
@@ -404,11 +392,11 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even
{
ARegion *ar = CTX_wm_region(C);
SpaceNode *snode = CTX_wm_space_node(C);
-
+
/* convert mouse coordinates to v2d space */
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
-
+
if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name"))
return node_add_file_exec(C, op);
else
@@ -435,35 +423,35 @@ void NODE_OT_add_file(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Datablock name to assign");
}
-
/********************** New node tree operator *********************/
static int new_node_tree_exec(bContext *C, wmOperator *op)
{
- SpaceNode *snode;
+ SpaceNode *snode = CTX_wm_space_node(C);
+ Main *bmain = CTX_data_main(C);
bNodeTree *ntree;
- Main *bmain;
PointerRNA ptr, idptr;
PropertyRNA *prop;
- int treetype;
+ const char *idname;
char treename[MAX_ID_NAME - 2] = "NodeTree";
-
- /* retrieve state */
- snode = CTX_wm_space_node(C);
- bmain = CTX_data_main(C);
-
- if (RNA_struct_property_is_set(op->ptr, "type"))
- treetype = RNA_enum_get(op->ptr, "type");
- else
- treetype = snode->treetype;
-
+
+ if (RNA_struct_property_is_set(op->ptr, "type")) {
+ prop = RNA_struct_find_property(op->ptr, "type");
+ RNA_property_enum_identifier(C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &idname);
+ }
+ else if (snode)
+ idname = snode->tree_idname;
+
if (RNA_struct_property_is_set(op->ptr, "name"))
RNA_string_get(op->ptr, "name", treename);
-
- ntree = ntreeAddTree(bmain, treename, treetype, 0);
- if (!ntree)
+
+ if (!ntreeTypeFind(idname)) {
+ BKE_reportf(op->reports, RPT_ERROR, "Node tree type %s undefined", idname);
return OPERATOR_CANCELLED;
-
+ }
+
+ ntree = ntreeAddTree(bmain, treename, idname);
+
/* hook into UI */
uiIDContextProperty(C, &ptr, &prop);
@@ -477,29 +465,36 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &ptr, prop);
}
else if (snode) {
- Scene *scene = CTX_data_scene(C);
snode->nodetree = ntree;
-
- ED_node_tree_update(snode, scene);
+
+ ED_node_tree_update(C);
}
-
+
return OPERATOR_FINISHED;
}
+static EnumPropertyItem *new_node_tree_type_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
+{
+ return rna_node_tree_type_itemf(NULL, NULL, free);
+}
+
void NODE_OT_new_node_tree(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "New Node Tree";
ot->idname = "NODE_OT_new_node_tree";
ot->description = "Create a new node tree";
-
+
/* api callbacks */
ot->exec = new_node_tree_exec;
- ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", "");
+
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Tree Type", "");
+ RNA_def_enum_funcs(prop, new_node_tree_type_itemf);
RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME - 2, "Name", "");
}
+
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 300328f5fd4..688377c7f3b 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -62,7 +62,7 @@ static int active_nodetree_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
- return (snode && snode->nodetree);
+ return (snode && ntreeIsValid(snode->nodetree));
}
/* poll callback for active node */
@@ -70,7 +70,7 @@ static int active_node_poll(const bContext *C, PanelType *UNUSED(pt))
{
SpaceNode *snode = CTX_wm_space_node(C);
- return (snode && snode->edittree && nodeGetActive(snode->edittree));
+ return (snode && ntreeIsValid(snode->edittree) && nodeGetActive(snode->edittree));
}
/* active node */
@@ -160,6 +160,86 @@ static void node_sockets_panel(const bContext *C, Panel *pa)
}
}
+static int 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 int node_tree_find_active_socket(bNodeTree *ntree, bNodeSocket **r_sock, int *r_in_out)
+{
+ bNodeSocket *sock;
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_IN;
+ return TRUE;
+ }
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ if (sock->flag & SELECT) {
+ *r_sock = sock;
+ *r_in_out = SOCK_OUT;
+ return TRUE;
+ }
+ }
+
+ *r_sock = NULL;
+ *r_in_out = 0;
+ return FALSE;
+}
+
+static void node_tree_interface_panel(const bContext *C, Panel *pa)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = (snode) ? snode->edittree : NULL;
+ bNodeSocket *sock;
+ int in_out;
+ uiLayout *layout = pa->layout, *row, *split, *col;
+ PointerRNA ptr, sockptr, opptr;
+
+ if (!ntree)
+ return;
+
+ RNA_id_pointer_create((ID *)ntree, &ptr);
+
+ node_tree_find_active_socket(ntree, &sock, &in_out);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocketInterface, sock, &sockptr);
+
+ row = uiLayoutRow(layout, FALSE);
+
+ split = uiLayoutRow(row, TRUE);
+ col = uiLayoutColumn(split, TRUE);
+ uiItemL(col, "Inputs:", ICON_NONE);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "inputs", &ptr, "active_input", 0, 0, 0);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "in_out", SOCK_IN);
+
+ col = uiLayoutColumn(split, TRUE);
+ uiItemL(col, "Outputs:", ICON_NONE);
+ uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "", &ptr, "outputs", &ptr, "active_output", 0, 0, 0);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "in_out", SOCK_OUT);
+
+ col = uiLayoutColumn(row, TRUE);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "direction", 1);
+ opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_enum_set(&opptr, "direction", 2);
+
+ if (sock) {
+ row = uiLayoutRow(layout, TRUE);
+ uiItemR(row, &sockptr, "name", 0, NULL, ICON_NONE);
+ uiItemO(row, "", ICON_X, "NODE_OT_tree_socket_remove");
+
+ if (sock->typeinfo->interface_draw) {
+ uiItemS(layout);
+ sock->typeinfo->interface_draw((bContext *)C, layout, &sockptr);
+ }
+ }
+}
+
/* ******************* node buttons registration ************** */
void node_buttons_register(ARegionType *art)
@@ -180,7 +260,14 @@ void node_buttons_register(ARegionType *art)
pt->poll = node_sockets_poll;
pt->flag |= PNL_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
-
+
+ pt = MEM_callocN(sizeof(PanelType), "spacetype node panel tree interface");
+ strcpy(pt->idname, "NODE_PT_node_tree_interface");
+ strcpy(pt->label, "Interface");
+ pt->draw = node_tree_interface_panel;
+ pt->poll = node_tree_interface_poll;
+ BLI_addtail(&art->paneltypes, pt);
+
pt = MEM_callocN(sizeof(PanelType), "spacetype node panel gpencil");
strcpy(pt->idname, "NODE_PT_gpencil");
strcpy(pt->label, "Grease Pencil");
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index d2cc42b0a56..0636dee9bc5 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -29,10 +29,14 @@
* \brief higher level node drawing for the node editor.
*/
+#include "DNA_lamp_types.h"
#include "DNA_node_types.h"
+#include "DNA_material_types.h"
#include "DNA_object_types.h"
-#include "DNA_space_types.h"
#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -44,6 +48,8 @@
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BLF_api.h"
+
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -52,6 +58,7 @@
#include "ED_node.h"
#include "ED_gpencil.h"
+#include "ED_screen.h"
#include "ED_space_api.h"
#include "UI_resources.h"
@@ -65,25 +72,49 @@
/* XXX interface.h */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
-/* XXX update functions for node editor are a mess, needs a clear concept */
-void ED_node_tree_update(SpaceNode *snode, Scene *scene)
+void ED_node_tree_update(const bContext *C)
{
- snode_set_context(snode, scene);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ snode_set_context(C);
if (snode->nodetree && snode->nodetree->id.us == 0)
snode->nodetree->id.us = 1;
}
-void ED_node_changed_update(ID *id, bNode *node)
+/* id is supposed to contain a node tree */
+static bNodeTree *node_tree_from_ID(ID *id)
{
- bNodeTree *nodetree, *edittree;
- int treetype;
-
- node_tree_from_ID(id, &nodetree, &edittree, &treetype);
+ if (id) {
+ short idtype = GS(id->name);
+
+ switch (idtype) {
+ case ID_NT:
+ return (bNodeTree *)id;
+ case ID_MA:
+ return ((Material *)id)->nodetree;
+ case ID_LA:
+ return ((Lamp *)id)->nodetree;
+ case ID_WO:
+ return ((World *)id)->nodetree;
+ case ID_SCE:
+ return ((Scene *)id)->nodetree;
+ case ID_TE:
+ return ((Tex *)id)->nodetree;
+ }
+ }
+
+ return NULL;
+}
- if (treetype == NTREE_SHADER) {
+void ED_node_tag_update_id(ID *id)
+{
+ bNodeTree *ntree = node_tree_from_ID(id);
+ if (id == NULL)
+ return;
+
+ if (ntree->type == NTREE_SHADER) {
DAG_id_tag_update(id, 0);
-
+
if (GS(id->name) == ID_MA)
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, id);
else if (GS(id->name) == ID_LA)
@@ -91,18 +122,10 @@ void ED_node_changed_update(ID *id, bNode *node)
else if (GS(id->name) == ID_WO)
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, id);
}
- else if (treetype == NTREE_COMPOSIT) {
- if (node)
- nodeUpdate(edittree, node);
- /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */
-
- node = node_tree_get_editgroup(nodetree);
- if (node)
- nodeUpdateID(nodetree, node->id);
-
+ else if (ntree->type == NTREE_COMPOSIT) {
WM_main_add_notifier(NC_SCENE | ND_NODES, id);
}
- else if (treetype == NTREE_TEXTURE) {
+ else if (ntree->type == NTREE_TEXTURE) {
DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_TEXTURE | ND_NODES, id);
}
@@ -123,25 +146,17 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
return 0;
}
-typedef struct NodeUpdateCalldata {
- bNodeTree *ntree;
- bNode *node;
-} NodeUpdateCalldata;
-static void node_generic_update_cb(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- NodeUpdateCalldata *cd = (NodeUpdateCalldata *)calldata;
- /* check if nodetree uses the group stored in calldata */
- if (has_nodetree(ntree, cd->ntree))
- ED_node_changed_update(owner_id, cd->node);
-}
-void ED_node_generic_update(Main *bmain, bNodeTree *ntree, bNode *node)
+void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree)
{
- bNodeTreeType *tti = ntreeGetType(ntree->type);
- NodeUpdateCalldata cd;
- cd.ntree = ntree;
- cd.node = node;
+ if (!ntreeIsValid(ntree))
+ return;
+
/* look through all datablocks, to support groups */
- tti->foreach_nodetree(bmain, &cd, node_generic_update_cb);
+ FOREACH_NODETREE(bmain, tntree, id) {
+ /* check if nodetree uses the group */
+ if (has_nodetree(tntree, ntree))
+ ED_node_tag_update_id(id);
+ } FOREACH_NODETREE_END
if (ntree->type == NTREE_TEXTURE)
ntreeTexCheckCyclics(ntree);
@@ -251,12 +266,12 @@ void ED_node_sort(bNodeTree *ntree)
}
-static void do_node_internal_buttons(bContext *C, void *node_v, int event)
+static void do_node_internal_buttons(bContext *C, void *UNUSED(node_v), int event)
{
if (event == B_NODE_EXEC) {
SpaceNode *snode = CTX_wm_space_node(C);
if (snode && snode->id)
- ED_node_changed_update(snode->id, node_v);
+ ED_node_tag_update_id(snode->id);
}
}
@@ -296,13 +311,15 @@ void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry)
/* based on settings in node, sets drawing rect info. each redraw! */
static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
{
- uiLayout *layout;
- PointerRNA ptr;
+ uiLayout *layout, *row;
+ PointerRNA nodeptr, sockptr;
bNodeSocket *nsock;
float locx, locy;
float dy;
int buty;
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
+
/* get "global" coords */
node_to_view(node, 0.0f, 0.0f, &locx, &locy);
dy = locy;
@@ -313,14 +330,36 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* little bit space in top */
if (node->outputs.first)
dy -= NODE_DYS / 2;
-
+
/* output sockets */
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = locx + NODE_WIDTH(node);
- nsock->locy = dy - NODE_DYS;
- dy -= NODE_DY;
- }
+ if (nodeSocketIsHidden(nsock))
+ continue;
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
+
+ layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
+ locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, UI_GetStyle());
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ /* align output buttons to the right */
+ row = uiLayoutRow(layout, 1);
+ uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
+
+ node->typeinfo->drawoutputfunc((bContext *)C, row, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
+
+ uiBlockEndAlign(node->block);
+ uiBlockLayoutResolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = MIN2(buty, dy - NODE_DY);
+
+ nsock->locx = locx + NODE_WIDTH(node);
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+ dy = buty;
}
node->prvr.xmin = locx + NODE_DYS;
@@ -328,43 +367,32 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* preview rect? */
if (node->flag & NODE_PREVIEW) {
- if (node->preview && node->preview->rect) {
- float aspect = 1.0f;
-
- if (node->preview && node->preview->xsize && node->preview->ysize)
- aspect = (float)node->preview->ysize / (float)node->preview->xsize;
+ float aspect = 1.0f;
+
+ if (node->preview_xsize && node->preview_ysize)
+ aspect = (float)node->preview_ysize / (float)node->preview_xsize;
+
+ dy -= NODE_DYS / 2;
+ node->prvr.ymax = dy;
+
+ if (aspect <= 1.0f)
+ node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
+ else {
+ /* width correction of image */
+ /* XXX huh? (ton) */
+ float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
+ node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
- if (aspect <= 1.0f)
- node->prvr.ymin = dy - aspect * (NODE_WIDTH(node) - NODE_DY);
- else {
- /* width correction of image */
- /* XXX huh? (ton) */
- float dx = (NODE_WIDTH(node) - NODE_DYS) - (NODE_WIDTH(node) - NODE_DYS) / aspect;
-
- node->prvr.ymin = dy - (NODE_WIDTH(node) - NODE_DY);
-
- node->prvr.xmin += 0.5f * dx;
- node->prvr.xmax -= 0.5f * dx;
- }
-
- dy = node->prvr.ymin - NODE_DYS / 2;
-
- /* make sure that maximums are bigger or equal to minimums */
- if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
- if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
- }
- else {
- float oldh = BLI_rctf_size_y(&node->prvr);
- if (oldh == 0.0f)
- oldh = 0.6f * NODE_WIDTH(node) - NODE_DY;
- dy -= NODE_DYS / 2;
- node->prvr.ymax = dy;
- node->prvr.ymin = dy - oldh;
- dy = node->prvr.ymin - NODE_DYS / 2;
+ node->prvr.xmin += 0.5f * dx;
+ node->prvr.xmax -= 0.5f * dx;
}
+
+ dy = node->prvr.ymin - NODE_DYS / 2;
+
+ /* make sure that maximums are bigger or equal to minimums */
+ if (node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
+ if (node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
}
/* buttons rect? */
@@ -378,14 +406,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
node->butr.ymin = 0;
node->butr.ymax = 0;
- RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
-
layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
locx + NODE_DYS, dy, node->butr.xmax, 0, UI_GetStyle());
- uiLayoutSetContextPointer(layout, "node", &ptr);
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
- node->typeinfo->uifunc(layout, (bContext *)C, &ptr);
+ node->typeinfo->uifunc(layout, (bContext *)C, &nodeptr);
uiBlockEndAlign(node->block);
uiBlockLayoutResolve(node->block, NULL, &buty);
@@ -395,11 +421,29 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
/* input sockets */
for (nsock = node->inputs.first; nsock; nsock = nsock->next) {
- if (!nodeSocketIsHidden(nsock)) {
- nsock->locx = locx;
- nsock->locy = dy - NODE_DYS;
- dy -= NODE_DY;
- }
+ if (nodeSocketIsHidden(nsock))
+ continue;
+
+ RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr);
+
+ layout = uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
+ locx + NODE_DYS, dy, NODE_WIDTH(node) - NODE_DY, NODE_DY, UI_GetStyle());
+ /* context pointers for current node and socket */
+ uiLayoutSetContextPointer(layout, "node", &nodeptr);
+ uiLayoutSetContextPointer(layout, "socket", &sockptr);
+
+ node->typeinfo->drawinputfunc((bContext *)C, layout, &sockptr, &nodeptr, (nsock->flag & SOCK_IN_USE));
+
+ uiBlockEndAlign(node->block);
+ uiBlockLayoutResolve(node->block, NULL, &buty);
+
+ /* ensure minimum socket height in case layout is empty */
+ buty = MIN2(buty, dy - NODE_DY);
+
+ nsock->locx = locx;
+ /* place the socket circle in the middle of the layout */
+ nsock->locy = 0.5f * (dy + buty);
+ dy = buty;
}
/* little bit space in end */
@@ -510,6 +554,7 @@ int node_get_colorid(bNode *node)
case NODE_CLASS_OP_VECTOR:
case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR;
case NODE_CLASS_GROUP: return TH_NODE_GROUP;
+ case NODE_CLASS_INTERFACE: return TH_NODE_INTERFACE;
case NODE_CLASS_MATTE: return TH_NODE_MATTE;
case NODE_CLASS_DISTORT: return TH_NODE_DISTORT;
default: return TH_NODE;
@@ -534,7 +579,7 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
}
/* this might have some more generic use */
-static void node_circle_draw(float x, float y, float size, char *col, int highlight)
+static void node_circle_draw(float x, float y, float size, float *col, int highlight)
{
/* 16 values of sin function */
static float si[16] = {
@@ -552,12 +597,14 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
};
int a;
- glColor3ub(col[0], col[1], col[2]);
+ glColor4fv(col);
+ glEnable(GL_BLEND);
glBegin(GL_POLYGON);
for (a = 0; a < 16; a++)
glVertex2f(x + size * si[a], y + size * co[a]);
glEnd();
+ glDisable(GL_BLEND);
if (highlight) {
UI_ThemeColor(TH_TEXT_HI);
@@ -577,66 +624,93 @@ static void node_circle_draw(float x, float y, float size, char *col, int highli
glLineWidth(1.0f);
}
-void node_socket_circle_draw(bNodeTree *UNUSED(ntree), bNodeSocket *sock, float size, int highlight)
+void node_socket_circle_draw(const bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock, float size, int highlight)
{
- bNodeSocketType *stype = ntreeGetSocketType(sock->type);
- node_circle_draw(sock->locx, sock->locy, size, stype->ui_color, highlight);
+ PointerRNA ptr, node_ptr;
+ float color[4];
+
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
+ RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
+ sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
+ node_circle_draw(sock->locx, sock->locy, size, color, highlight);
}
/* ************** Socket callbacks *********** */
-/* not a callback */
-static void node_draw_preview(bNodePreview *preview, rctf *prv)
+static void node_draw_preview_background(float tile, rctf *rect)
{
- float xscale = BLI_rctf_size_x(prv) / ((float)preview->xsize);
- float yscale = BLI_rctf_size_y(prv) / ((float)preview->ysize);
- float tile = BLI_rctf_size_x(prv) / 10.0f;
float x, y;
/* draw checkerboard backdrop to show alpha */
glColor3ub(120, 120, 120);
- glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
+ glRectf(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
glColor3ub(160, 160, 160);
- for (y = prv->ymin; y < prv->ymax; y += tile * 2) {
- for (x = prv->xmin; x < prv->xmax; x += tile * 2) {
+ for (y = rect->ymin; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
- if (x + tile > prv->xmax)
- tilex = prv->xmax - x;
- if (y + tile > prv->ymax)
- tiley = prv->ymax - y;
+ if (x + tile > rect->xmax)
+ tilex = rect->xmax - x;
+ if (y + tile > rect->ymax)
+ tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
- for (y = prv->ymin + tile; y < prv->ymax; y += tile * 2) {
- for (x = prv->xmin + tile; x < prv->xmax; x += tile * 2) {
+ for (y = rect->ymin + tile; y < rect->ymax; y += tile * 2) {
+ for (x = rect->xmin + tile; x < rect->xmax; x += tile * 2) {
float tilex = tile, tiley = tile;
- if (x + tile > prv->xmax)
- tilex = prv->xmax - x;
- if (y + tile > prv->ymax)
- tiley = prv->ymax - y;
+ if (x + tile > rect->xmax)
+ tilex = rect->xmax - x;
+ if (y + tile > rect->ymax)
+ tiley = rect->ymax - y;
glRectf(x, y, x + tilex, y + tiley);
}
}
-
- glPixelZoom(xscale, yscale);
+}
+/* not a callback */
+static void node_draw_preview(bNodePreview *preview, rctf *prv)
+{
+ float xrect = BLI_rctf_size_x(prv);
+ float yrect = BLI_rctf_size_y(prv);
+ float xscale = xrect / ((float)preview->xsize);
+ float yscale = yrect / ((float)preview->ysize);
+ float scale;
+ rctf draw_rect;
+
+ /* uniform scale and offset */
+ draw_rect = *prv;
+ if (xscale < yscale) {
+ float offset = 0.5f * (yrect - ((float)preview->ysize) * xscale);
+ draw_rect.ymin += offset;
+ draw_rect.ymax -= offset;
+ scale = xscale;
+ }
+ else {
+ float offset = 0.5f * (xrect - ((float)preview->xsize) * yscale);
+ draw_rect.xmin += offset;
+ draw_rect.xmax -= offset;
+ scale = yscale;
+ }
+
+ node_draw_preview_background(BLI_rctf_size_x(prv) / 10.0f, &draw_rect);
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
+ glPixelZoom(scale, scale);
+ glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
+ glPixelZoom(1.0f, 1.0f);
glDisable(GL_BLEND);
- glPixelZoom(1.0f, 1.0f);
UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
- fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
-
+ fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
}
/* common handle function for operator buttons that need to select the node first */
@@ -669,8 +743,9 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
}
}
-static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
+ bNodeInstanceHash *previews = CTX_data_pointer_get(C, "node_previews").data;
bNodeSocket *sock;
rctf *rct = &node->totr;
float iconofs;
@@ -680,9 +755,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
char showname[128]; /* 128 used below */
View2D *v2d = &ar->v2d;
- /* hurmf... another candidate for callback, have to see how this works first */
- if (node->id && node->block && snode->treetype == NTREE_SHADER)
- nodeShaderSynchronizeID(node, 0);
+ /* XXX hack: copy values from linked ID data where displayed as sockets */
+ if (node->block)
+ nodeSynchronizeID(node, false);
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == FALSE) {
@@ -823,11 +898,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
-
- node->typeinfo->drawinputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
- sock->locx + (NODE_DYS), sock->locy - NODE_DYS,
- NODE_WIDTH(node) - NODE_DY);
+ node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* socket outputs */
@@ -835,17 +906,14 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (nodeSocketIsHidden(sock))
continue;
- node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE, sock->flag & SELECT);
-
- node->typeinfo->drawoutputfunc(C, node->block, ntree, node, sock, IFACE_(sock->name),
- sock->locx - NODE_WIDTH(node) + (NODE_DYS), sock->locy - NODE_DYS,
- NODE_WIDTH(node) - NODE_DY);
+ node_socket_circle_draw(C, ntree, node, sock, NODE_SOCKSIZE, sock->flag & SELECT);
}
/* preview */
if (node->flag & NODE_PREVIEW) {
- if (node->preview && node->preview->rect && !BLI_rctf_is_empty(&node->prvr))
- node_draw_preview(node->preview, &node->prvr);
+ bNodePreview *preview = previews ? BKE_node_instance_hash_lookup(previews, key) : NULL;
+ if (preview && preview->rect && !BLI_rctf_is_empty(&node->prvr))
+ node_draw_preview(preview, &node->prvr);
}
UI_ThemeClearColor(color_id);
@@ -855,7 +923,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
node->block = NULL;
}
-static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key))
{
bNodeSocket *sock;
rctf *rct = &node->totr;
@@ -957,12 +1025,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
/* sockets */
for (sock = node->inputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
for (sock = node->outputs.first; sock; sock = sock->next) {
if (!nodeSocketIsHidden(sock))
- node_socket_circle_draw(snode->nodetree, sock, socket_size, sock->flag & SELECT);
+ node_socket_circle_draw(C, ntree, node, sock, socket_size, sock->flag & SELECT);
}
uiEndBlock(C, node->block);
@@ -989,7 +1057,7 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode)
bNodeSocket *sock;
int cursor = CURSOR_STD;
- if (ntree) {
+ if (ntreeIsValid(ntree)) {
if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN | SOCK_OUT)) {
/* pass */
}
@@ -1009,12 +1077,12 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode)
WM_cursor_set(win, cursor);
}
-void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->flag & NODE_HIDDEN)
- node_draw_hidden(C, ar, snode, ntree, node);
+ node_draw_hidden(C, ar, snode, ntree, node, key);
else
- node_draw_basis(C, ar, snode, ntree, node);
+ node_draw_basis(C, ar, snode, ntree, node, key);
}
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
@@ -1023,34 +1091,28 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
node->typeinfo->drawupdatefunc(C, ntree, node);
}
-void node_update_nodetree(const bContext *C, bNodeTree *ntree, float offsetx, float offsety)
+void node_update_nodetree(const bContext *C, bNodeTree *ntree)
{
bNode *node;
/* update nodes front to back, so children sizes get updated before parents */
for (node = ntree->nodes.last; node; node = node->prev) {
- /* XXX little hack (not used anyore?) */
- node->locx += offsetx;
- node->locy += offsety;
-
node_update(C, ntree, node);
-
- node->locx -= offsetx;
- node->locy -= offsety;
}
}
-static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
+static void node_draw(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
if (node->typeinfo->drawfunc)
- node->typeinfo->drawfunc(C, ar, snode, ntree, node);
+ node->typeinfo->drawfunc(C, ar, snode, ntree, node, key);
}
#define USE_DRAW_TOT_UPDATE
-void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree)
+void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNodeInstanceKey parent_key)
{
bNode *node;
+ bNodeInstanceKey key;
bNodeLink *link;
int a;
@@ -1073,122 +1135,200 @@ void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeT
if (!(node->flag & NODE_BACKGROUND))
continue;
+
+ key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node);
+ node_draw(C, ar, snode, ntree, node, key);
}
/* node lines */
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- for (link = ntree->links.first; link; link = link->next)
- node_draw_link(&ar->v2d, snode, link);
+ for (link = ntree->links.first; link; link = link->next) {
+ if (!nodeLinkIsHidden(link))
+ node_draw_link(&ar->v2d, snode, link);
+ }
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
/* draw foreground nodes, last nodes in front */
for (a = 0, node = ntree->nodes.first; node; node = node->next, a++) {
+ bNodeInstanceKey key = BKE_node_instance_key(parent_key, ntree, node);
if (node->flag & NODE_BACKGROUND)
continue;
+
+ key = BKE_node_instance_key(parent_key, ntree, node);
node->nr = a; /* index of node in list, used for exec event code */
- node_draw(C, ar, snode, ntree, node);
+ node_draw(C, ar, snode, ntree, node, key);
}
}
-void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
+/* draw tree path info in lower left corner */
+static void draw_tree_path(SpaceNode *snode)
+{
+ char info[256];
+
+ ED_node_tree_path_get_fixedbuf(snode, info, sizeof(info));
+
+ UI_ThemeColor(TH_TEXT_HI);
+ BLF_draw_default(30, 30, 0.0f, info, sizeof(info));
+}
+
+static void snode_setup_v2d(SpaceNode *snode, ARegion *ar, float centerx, float centery)
+{
+ View2D *v2d = &ar->v2d;
+
+ /* shift view to node tree center */
+ UI_view2d_setcenter(v2d, centerx, centery);
+ UI_view2d_view_ortho(v2d);
+
+ /* aspect+font, set each time */
+ snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
+ // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
+}
+
+static void draw_nodetree(const bContext *C, ARegion *ar, bNodeTree *ntree, bNodeInstanceKey parent_key)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+
+ node_uiblocks_init(C, ntree);
+
+#ifdef WITH_COMPOSITOR
+ if (ntree->type == NTREE_COMPOSIT) {
+ COM_startReadHighlights();
+ }
+#endif
+
+ node_update_nodetree(C, ntree);
+ node_draw_nodetree(C, ar, snode, ntree, parent_key);
+}
+
+/* shade the parent node group and add a uiBlock to clip mouse events */
+static void draw_group_overlay(const bContext *C, ARegion *ar)
+{
+ View2D *v2d = &ar->v2d;
+ rctf rect = v2d->cur;
+ uiBlock *block;
+
+ /* shade node groups to separate them visually */
+ UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
+ glEnable(GL_BLEND);
+ uiSetRoundBox(0);
+ uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0);
+ glDisable(GL_BLEND);
+
+ /* set the block bounds to clip mouse events from underlying nodes */
+ block = uiBeginBlock(C, ar, "node tree bounds block", UI_EMBOSS);
+ uiExplicitBoundsBlock(block, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ uiBlockSetFlag(block, UI_BLOCK_CLIP_EVENTS);
+ uiEndBlock(C, block);
+}
+
+void drawnodespace(const bContext *C, ARegion *ar)
{
View2DScrollers *scrollers;
SpaceNode *snode = CTX_wm_space_node(C);
- bNodeLinkDrag *nldrag;
- LinkData *linkdata;
+ View2D *v2d = &ar->v2d;
UI_ThemeClearColor(TH_BACK);
glClear(GL_COLOR_BUFFER_BIT);
UI_view2d_view_ortho(v2d);
-
- //uiFreeBlocksWin(&sa->uiblocks, sa->win);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
/* only set once */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MAP1_VERTEX_3);
-
- /* aspect+font, set each time */
- snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)ar->winx;
- // XXX snode->curfont = uiSetCurFont_ext(snode->aspect);
-
- /* grid */
- UI_view2d_multi_grid_draw(v2d, U.widget_unit, 5, 2);
-
- /* backdrop */
- draw_nodespace_back_pix(C, ar, snode);
/* nodes */
- snode_set_context(snode, CTX_data_scene(C));
-
- if (snode->nodetree) {
- bNode *node;
- /* void **highlights = 0; */ /* UNUSED */
+ snode_set_context(C);
+
+ /* draw parent node trees */
+ if (snode->treepath.last) {
+ static const int max_depth = 2;
+ bNodeTreePath *path;
+ int depth, curdepth;
+ float center[2];
+ bNodeTree *ntree;
+ bNodeLinkDrag *nldrag;
+ LinkData *linkdata;
- node_uiblocks_init(C, snode->nodetree);
+ /* current View2D center, will be set temporarily for parent node trees */
+ UI_view2d_getcenter(v2d, &center[0], &center[1]);
- /* uiBlocks must be initialized in drawing order for correct event clipping.
- * Node group internal blocks added after the main group block.
- */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_GROUP_EDIT)
- node_uiblocks_init(C, (bNodeTree *)node->id);
+ /* store new view center in current edittree */
+ if (snode->edittree)
+ copy_v2_v2(snode->edittree->view_center, center);
+
+ depth = 0;
+ path = snode->treepath.last;
+ while (path->prev && depth < max_depth) {
+ path = path->prev;
+ ++depth;
+ }
+ /* parent node trees in the background */
+ for (curdepth = depth; curdepth >= 0; path = path->next, --curdepth) {
+ ntree = path->nodetree;
+
+ if (ntreeIsValid(ntree)) {
+ snode_setup_v2d(snode, ar, ntree->view_center[0], ntree->view_center[1]);
+
+ if (curdepth == 0) {
+ /* grid, uses theme color based on node path depth */
+ UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), U.widget_unit, 5, 2);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode);
+ }
+
+ draw_nodetree(C, ar, ntree, path->parent_key);
+
+ if (curdepth > 0)
+ draw_group_overlay(C, ar);
+ }
}
- node_update_nodetree(C, snode->nodetree, 0.0f, 0.0f);
-
-#ifdef WITH_COMPOSITOR
- if (snode->nodetree->type == NTREE_COMPOSIT) {
- COM_startReadHighlights();
+ /* reset View2D */
+ UI_view2d_setcenter(v2d, center[0], center[1]);
+
+ /* temporary links */
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
+ for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next)
+ node_draw_link(v2d, snode, (bNodeLink *)linkdata->data);
}
-#endif
-
- node_draw_nodetree(C, ar, snode, snode->nodetree);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
- #if 0
- /* active group */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_GROUP_EDIT)
- node_draw_group(C, ar, snode, snode->nodetree, node);
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil ('canvas' strokes) */
+ draw_gpencil_view2d(C, TRUE);
}
- #endif
}
-
- /* temporary links */
- glEnable(GL_BLEND);
- glEnable(GL_LINE_SMOOTH);
- for (nldrag = snode->linkdrag.first; nldrag; nldrag = nldrag->next) {
- for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
- node_draw_link(&ar->v2d, snode, (bNodeLink *)linkdata->data);
- }
+ else {
+ /* default grid */
+ UI_view2d_multi_grid_draw(v2d, TH_BACK, U.widget_unit, 5, 2);
+
+ /* backdrop */
+ draw_nodespace_back_pix(C, ar, snode);
}
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* draw grease-pencil ('canvas' strokes) */
- if (snode->nodetree) {
- draw_gpencil_view2d(C, TRUE);
- }
- }
-
/* reset view matrix */
UI_view2d_view_restore(C);
- if (snode->flag & SNODE_SHOW_GPENCIL) {
- /* draw grease-pencil (screen strokes, and also paintbuffer) */
- if (snode->nodetree) {
+ if (snode->treepath.last) {
+ if (snode->flag & SNODE_SHOW_GPENCIL) {
+ /* draw grease-pencil (screen strokes, and also paintbuffer) */
draw_gpencil_view2d(C, FALSE);
}
}
+
+ /* tree path info */
+ draw_tree_path(snode);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 941bd783c39..256b02d3288 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -31,6 +31,8 @@
#include "MEM_guardedalloc.h"
+#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -65,6 +67,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -76,6 +79,12 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
+#include "NOD_socket.h"
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
+
#define USE_ESC_COMPO
@@ -241,27 +250,12 @@ int composite_node_active(bContext *C)
{
if (ED_operator_node_active(C)) {
SpaceNode *snode = CTX_wm_space_node(C);
- if (snode->treetype == NTREE_COMPOSIT)
+ if (ED_node_is_compositor(snode))
return 1;
}
return 0;
}
-/* also checks for edited groups */
-bNode *editnode_get_active(bNodeTree *ntree)
-{
- bNode *node;
-
- /* check for edited group */
- for (node = ntree->nodes.first; node; node = node->next)
- if (nodeGroupEditGet(node))
- break;
- if (node)
- return nodeGetActive((bNodeTree *)node->id);
- else
- return nodeGetActive(ntree);
-}
-
static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
{
bNode *node;
@@ -277,20 +271,16 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
return 0;
}
-static void snode_dag_update_group(void *calldata, ID *owner_id, bNodeTree *ntree)
-{
- if (has_nodetree(ntree, calldata))
- DAG_id_tag_update(owner_id, 0);
-}
-
void snode_dag_update(bContext *C, SpaceNode *snode)
{
Main *bmain = CTX_data_main(C);
/* for groups, update all ID's using this */
if (snode->edittree != snode->nodetree) {
- bNodeTreeType *tti = ntreeGetType(snode->edittree->type);
- tti->foreach_nodetree(bmain, snode->edittree, snode_dag_update_group);
+ FOREACH_NODETREE(bmain, tntree, id) {
+ if (has_nodetree(tntree, snode->edittree))
+ DAG_id_tag_update(id, 0);
+ } FOREACH_NODETREE_END
}
DAG_id_tag_update(snode->id, 0);
@@ -300,37 +290,53 @@ void snode_notify(bContext *C, SpaceNode *snode)
{
WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL);
- if (snode->treetype == NTREE_SHADER)
+ if (ED_node_is_shader(snode))
WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id);
- else if (snode->treetype == NTREE_COMPOSIT)
+ else if (ED_node_is_compositor(snode))
WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id);
- else if (snode->treetype == NTREE_TEXTURE)
+ else if (ED_node_is_texture(snode))
WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id);
}
-bNode *node_tree_get_editgroup(bNodeTree *nodetree)
+void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo)
{
- bNode *gnode;
-
- /* get the groupnode */
- for (gnode = nodetree->nodes.first; gnode; gnode = gnode->next)
- if (nodeGroupEditGet(gnode))
- break;
- return gnode;
+ if (typeinfo)
+ BLI_strncpy(snode->tree_idname, typeinfo->idname, sizeof(snode->tree_idname));
+ else
+ snode->tree_idname[0] = '\0';
+}
+
+int ED_node_is_compositor(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Composite->idname);
+}
+
+int ED_node_is_shader(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Shader->idname);
+}
+
+int ED_node_is_texture(struct SpaceNode *snode)
+{
+ return STREQ(snode->tree_idname, ntreeType_Texture->idname);
}
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_shader_default(Scene *scene, ID *id)
+void ED_node_shader_default(const bContext *C, ID *id)
{
+ Scene *scene = CTX_data_scene(C);
bNode *in, *out;
bNodeSocket *fromsock, *tosock, *sock;
bNodeTree *ntree;
- bNodeTemplate ntemp;
+ PointerRNA ptr;
int output_type, shader_type;
- float color[3], strength = 1.0f;
+ float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }, strength = 1.0f;
- ntree = ntreeAddTree(G.main, "Shader Nodetree", NTREE_SHADER, 0);
+ ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+
+ RNA_id_pointer_create((ID *)ntree, &ptr);
+ RNA_boolean_set(&ptr, "is_local_tree", TRUE);
switch (GS(id->name)) {
case ID_MA:
@@ -383,12 +389,10 @@ void ED_node_shader_default(Scene *scene, ID *id)
return;
}
- ntemp.type = output_type;
- out = nodeAddNode(ntree, &ntemp);
+ out = nodeAddStaticNode(C, ntree, output_type);
out->locx = 300.0f; out->locy = 300.0f;
- ntemp.type = shader_type;
- in = nodeAddNode(ntree, &ntemp);
+ in = nodeAddStaticNode(C, ntree, shader_type);
in->locx = 10.0f; in->locy = 300.0f;
nodeSetActive(ntree, in);
@@ -399,12 +403,16 @@ void ED_node_shader_default(Scene *scene, ID *id)
/* default values */
if (BKE_scene_use_new_shading_nodes(scene)) {
+ PointerRNA sockptr;
sock = in->inputs.first;
- copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, color);
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+
+ RNA_float_set_array(&sockptr, "default_value", color);
if (strength != 0.0f) {
sock = in->inputs.last;
- ((bNodeSocketValueFloat *)sock->default_value)->value = strength;
+ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &sockptr);
+ RNA_float_set(&sockptr, "default_value", strength);
}
}
@@ -413,11 +421,11 @@ void ED_node_shader_default(Scene *scene, ID *id)
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_composit_default(Scene *sce)
+void ED_node_composit_default(const bContext *C, struct Scene *sce)
{
bNode *in, *out;
bNodeSocket *fromsock, *tosock;
- bNodeTemplate ntemp;
+ PointerRNA ptr;
/* but lets check it anyway */
if (sce->nodetree) {
@@ -426,20 +434,21 @@ void ED_node_composit_default(Scene *sce)
return;
}
- sce->nodetree = ntreeAddTree(G.main, "Compositing Nodetree", NTREE_COMPOSIT, 0);
-
+ sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname);
+
+ RNA_id_pointer_create((ID *)sce->nodetree, &ptr);
+ RNA_boolean_set(&ptr, "is_local_tree", TRUE);
+
sce->nodetree->chunksize = 256;
sce->nodetree->edit_quality = NTREE_QUALITY_HIGH;
sce->nodetree->render_quality = NTREE_QUALITY_HIGH;
- ntemp.type = CMP_NODE_COMPOSITE;
- out = nodeAddNode(sce->nodetree, &ntemp);
+ out = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_COMPOSITE);
out->locx = 300.0f; out->locy = 400.0f;
out->id = &sce->id;
id_us_plus(out->id);
- ntemp.type = CMP_NODE_R_LAYERS;
- in = nodeAddNode(sce->nodetree, &ntemp);
+ in = nodeAddStaticNode(C, sce->nodetree, CMP_NODE_R_LAYERS);
in->locx = 10.0f; in->locy = 400.0f;
in->id = &sce->id;
id_us_plus(in->id);
@@ -457,11 +466,11 @@ void ED_node_composit_default(Scene *sce)
/* assumes nothing being done in ntree yet, sets the default in/out node */
/* called from shading buttons or header */
-void ED_node_texture_default(Tex *tx)
+void ED_node_texture_default(const bContext *C, Tex *tx)
{
bNode *in, *out;
bNodeSocket *fromsock, *tosock;
- bNodeTemplate ntemp;
+ PointerRNA ptr;
/* but lets check it anyway */
if (tx->nodetree) {
@@ -470,14 +479,15 @@ void ED_node_texture_default(Tex *tx)
return;
}
- tx->nodetree = ntreeAddTree(G.main, "Texture Nodetree", NTREE_TEXTURE, 0);
+ tx->nodetree = ntreeAddTree(NULL, "Texture Nodetree", ntreeType_Texture->idname);
- ntemp.type = TEX_NODE_OUTPUT;
- out = nodeAddNode(tx->nodetree, &ntemp);
+ RNA_id_pointer_create((ID *)tx->nodetree, &ptr);
+ RNA_boolean_set(&ptr, "is_local_tree", TRUE);
+
+ out = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_OUTPUT);
out->locx = 300.0f; out->locy = 300.0f;
- ntemp.type = TEX_NODE_CHECKER;
- in = nodeAddNode(tx->nodetree, &ntemp);
+ in = nodeAddStaticNode(C, tx->nodetree, TEX_NODE_CHECKER);
in->locx = 10.0f; in->locy = 300.0f;
nodeSetActive(tx->nodetree, in);
@@ -488,162 +498,68 @@ void ED_node_texture_default(Tex *tx)
ntreeUpdateTree(tx->nodetree);
}
-/* id is supposed to contain a node tree */
-void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype)
+/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
+void snode_set_context(const bContext *C)
{
- if (id) {
- bNode *node = NULL;
- short idtype = GS(id->name);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTreeType *treetype = ntreeTypeFind(snode->tree_idname);
+ bNodeTree *ntree = snode->nodetree;
+ ID *id = snode->id, *from = snode->from;
- if (idtype == ID_NT) {
- *ntree = (bNodeTree *)id;
- if (treetype) *treetype = (*ntree)->type;
- }
- else if (idtype == ID_MA) {
- *ntree = ((Material *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_LA) {
- *ntree = ((Lamp *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_WO) {
- *ntree = ((World *)id)->nodetree;
- if (treetype) *treetype = NTREE_SHADER;
- }
- else if (idtype == ID_SCE) {
- *ntree = ((Scene *)id)->nodetree;
- if (treetype) *treetype = NTREE_COMPOSIT;
- }
- else if (idtype == ID_TE) {
- *ntree = ((Tex *)id)->nodetree;
- if (treetype) *treetype = NTREE_TEXTURE;
- }
- else {
- if (treetype) *treetype = 0;
- return;
- }
+ /* we use this to signal warnings, when node shaders are drawn in wrong render engine */
+ if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C)))
+ snode->flag |= SNODE_NEW_SHADERS;
+ else
+ snode->flag &= ~SNODE_NEW_SHADERS;
+
+ /* check the tree type */
+ if (!treetype ||
+ (treetype->poll && !treetype->poll(C, treetype)))
+ {
+ /* invalid tree type, disable */
+ snode->tree_idname[0] = '\0';
+ ED_node_tree_start(snode, NULL, NULL, NULL);
+ return;
+ }
- /* find editable group */
- if (edittree) {
- if (*ntree)
- for (node = (*ntree)->nodes.first; node; node = node->next)
- if (nodeGroupEditGet(node))
- break;
-
- if (node && node->id)
- *edittree = (bNodeTree *)node->id;
- else
- *edittree = *ntree;
- }
+ if (snode->nodetree && strcmp(snode->nodetree->idname, snode->tree_idname) != 0) {
+ /* current tree does not match selected type, clear tree path */
+ ntree = NULL;
+ id = NULL;
+ from = NULL;
}
- else {
- *ntree = NULL;
- *edittree = NULL;
- if (treetype) *treetype = 0;
+
+ if (!(snode->flag & SNODE_PIN) || ntree == NULL) {
+ if (treetype->get_from_context)
+ treetype->get_from_context(C, treetype, &ntree, &id, &from);
+ }
+
+ if (snode->nodetree != ntree || snode->id != id || snode->from != snode->from) {
+ ED_node_tree_start(snode, ntree, id, from);
}
}
-/* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
-void snode_set_context(SpaceNode *snode, Scene *scene)
+void snode_update(SpaceNode *snode, bNode *node)
{
- Object *ob = OBACT;
+ bNodeTreePath *path;
- snode->id = snode->from = NULL;
+ /* XXX this only updates nodes in the current node space tree path.
+ * The function supposedly should update any potential group node linking to changed tree,
+ * this really requires a working depsgraph ...
+ */
- if (snode->treetype == NTREE_SHADER) {
- /* we use this to signal warnings, when node shaders are drawn in wrong render engine */
- if (BKE_scene_use_new_shading_nodes(scene))
- snode->flag |= SNODE_NEW_SHADERS;
- else
- snode->flag &= ~SNODE_NEW_SHADERS;
-
- /* need active object, or we allow pinning... */
- if (snode->shaderfrom == SNODE_SHADER_OBJECT) {
- if (ob) {
- if (ob->type == OB_LAMP) {
- snode->from = &ob->id;
- snode->id = ob->data;
- }
- else {
- Material *ma = give_current_material(ob, ob->actcol);
- if (ma) {
- snode->from = &ob->id;
- snode->id = &ma->id;
- }
- }
- }
- }
- else { /* SNODE_SHADER_WORLD */
- if (scene->world) {
- snode->from = NULL;
- snode->id = &scene->world->id;
- }
- }
- }
- else if (snode->treetype == NTREE_COMPOSIT) {
- snode->id = &scene->id;
-
- /* update output sockets based on available layers */
- ntreeCompositForceHidden(scene->nodetree, scene);
- }
- else if (snode->treetype == NTREE_TEXTURE) {
- Tex *tx = NULL;
-
- if (snode->texfrom == SNODE_TEX_OBJECT) {
- if (ob) {
- tx = give_current_object_texture(ob);
-
- if (ob->type == OB_LAMP)
- snode->from = (ID *)ob->data;
- else
- snode->from = (ID *)give_current_material(ob, ob->actcol);
-
- /* from is not set fully for material nodes, should be ID + Node then */
- snode->id = &tx->id;
- }
+ /* update all edited group nodes */
+ path = snode->treepath.last;
+ if (path) {
+ bNodeTree *ngroup = path->nodetree;
+ for (path = path->prev; path; path = path->prev) {
+ nodeUpdateID(path->nodetree, (ID *)ngroup);
+ ngroup = path->nodetree;
}
- else if (snode->texfrom == SNODE_TEX_WORLD) {
- tx = give_current_world_texture(scene->world);
- snode->from = (ID *)scene->world;
- snode->id = &tx->id;
- }
- else {
- struct Brush *brush = NULL;
-
- if (ob && (ob->mode & OB_MODE_SCULPT))
- brush = paint_brush(&scene->toolsettings->sculpt->paint);
- else
- brush = paint_brush(&scene->toolsettings->imapaint.paint);
-
- if (brush) {
- snode->from = (ID *)brush;
- tx = give_current_brush_texture(brush);
- snode->id = &tx->id;
- }
- }
- }
- else {
- if (snode->nodetree && snode->nodetree->type == snode->treetype)
- snode->id = &snode->nodetree->id;
- else
- snode->id = NULL;
}
- node_tree_from_ID(snode->id, &snode->nodetree, &snode->edittree, NULL);
-}
-
-void snode_update(SpaceNode *snode, bNode *node)
-{
- bNode *gnode;
-
if (node)
nodeUpdate(snode->edittree, node);
-
- /* if inside group, tag entire group */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode)
- nodeUpdateID(snode->nodetree, gnode->id);
}
void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
@@ -654,6 +570,19 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
if (node->type != NODE_GROUP) {
int was_output = (node->flag & NODE_DO_OUTPUT);
+ int do_update = 0;
+
+ /* generic node group output: set node as active output */
+ if (node->type == NODE_GROUP_OUTPUT) {
+ bNode *tnode;
+ for (tnode = ntree->nodes.first; tnode; tnode = tnode->next)
+ if (tnode->type == NODE_GROUP_OUTPUT)
+ tnode->flag &= ~NODE_DO_OUTPUT;
+
+ node->flag |= NODE_DO_OUTPUT;
+ if (!was_output)
+ do_update = 1;
+ }
/* tree specific activate calls */
if (ntree->type == NTREE_SHADER) {
@@ -670,8 +599,10 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0)
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
+ else if (do_update)
+ ED_node_tag_update_nodetree(bmain, ntree);
/* if active texture changed, free glsl materials */
if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
@@ -698,7 +629,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
node->flag |= NODE_DO_OUTPUT;
if (was_output == 0)
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
/* addnode() doesnt link this yet... */
node->id = (ID *)BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
@@ -723,9 +654,11 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
tnode->flag &= ~NODE_DO_OUTPUT;
node->flag |= NODE_DO_OUTPUT;
- ED_node_generic_update(bmain, ntree, node);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
}
+ else if (do_update)
+ ED_node_tag_update_nodetree(bmain, ntree);
}
else if (ntree->type == NTREE_TEXTURE) {
// XXX
@@ -762,7 +695,7 @@ static void edit_node_properties(wmOperatorType *ot)
/* XXX could node be a context pointer? */
RNA_def_string(ot->srna, "node", "", MAX_NAME, "Node", "");
RNA_def_int(ot->srna, "socket", 0, 0, MAX_SOCKET, "Socket", "", 0, MAX_SOCKET);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Side", "");
+ RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Side", "");
}
static int edit_node_invoke_properties(bContext *C, wmOperator *op)
@@ -874,7 +807,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
- bNode *node = editnode_get_active(snode->edittree);
+ bNode *node = nodeGetActive(snode->edittree);
NodeSizeWidget *nsw = op->customdata;
float mx, my, dx, dy;
@@ -977,7 +910,7 @@ static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
SpaceNode *snode = CTX_wm_space_node(C);
ARegion *ar = CTX_wm_region(C);
- bNode *node = editnode_get_active(snode->edittree);
+ bNode *node = nodeGetActive(snode->edittree);
int dir;
if (node) {
@@ -1056,33 +989,6 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
}
}
-/* return 0, nothing done */
-static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode *snode)
-{
- bNode *gnode;
- float mx = 0, my = 0;
-// XXX int mval[2];
-
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode == NULL) return 0;
-
-// XXX getmouseco_areawin(mval);
-// XXX areamouseco_to_ipoco(G.v2d, mval, &mx, &my);
-
- /* click in header or outside? */
- if (BLI_rctf_isect_pt(&gnode->totr, mx, my) == 0) {
- rctf rect = gnode->totr;
-
- rect.ymax += NODE_DY;
- if (BLI_rctf_isect_pt(&rect, mx, my) == 0)
- snode_make_group_editable(snode, NULL); /* toggles, so exits editmode */
-// else
-// XXX transform_nodes(snode->nodetree, 'g', "Move group");
-
- return 1;
- }
- return 0;
-}
/* checks snode->mouse position, and returns found node/socket */
/* type is SOCK_IN and/or SOCK_OUT */
@@ -1143,32 +1049,6 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
}
}
- /* check group sockets
- * NB: using ngroup->outputs as input sockets and vice versa here!
- */
- if (in_out & SOCK_IN) {
- for (sock = snode->edittree->outputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- *nodep = NULL; /* NULL node pointer indicates group socket */
- *sockp = sock;
- return 1;
- }
- }
- }
- }
- if (in_out & SOCK_OUT) {
- for (sock = snode->edittree->inputs.first; sock; sock = sock->next) {
- if (!nodeSocketIsHidden(sock)) {
- if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) {
- *nodep = NULL; /* NULL node pointer indicates group socket */
- *sockp = sock;
- return 1;
- }
- }
- }
- }
-
return 0;
}
@@ -1215,7 +1095,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
* but operators and readfile.c do. */
id_us_plus(newnode->id);
/* to ensure redraws or rerenders happen */
- ED_node_changed_update(snode->id, newnode);
+ ED_node_tag_update_id(snode->id);
}
}
@@ -1276,9 +1156,9 @@ static int node_duplicate_exec(bContext *C, wmOperator *op)
/* has been set during copy above */
newnode = node->new_node;
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
node->flag &= ~NODE_ACTIVE;
- node_select(newnode);
+ nodeSetSelected(newnode, TRUE);
}
/* make sure we don't copy new nodes again! */
@@ -1312,6 +1192,8 @@ void NODE_OT_duplicate(wmOperatorType *ot)
}
int ED_node_select_check(ListBase *lb)
+
+
{
bNode *node;
@@ -1456,6 +1338,7 @@ void NODE_OT_render_changed(wmOperatorType *ot)
ot->flag = 0;
}
+
/* ****************** Hide operator *********************** */
static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
@@ -1962,8 +1845,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- float gnode_x = 0.0f, gnode_y = 0.0f;
bNode *node;
bNodeLink *link, *newlink;
@@ -1973,10 +1854,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
BKE_node_clipboard_clear();
BKE_node_clipboard_init(ntree);
- /* get group node offset */
- if (gnode)
- node_to_view(gnode, 0.0f, 0.0f, &gnode_x, &gnode_y);
-
for (node = ntree->nodes.first; node; node = node->next) {
if (node->flag & SELECT) {
bNode *new_node;
@@ -1999,12 +1876,6 @@ static int node_clipboard_copy_exec(bContext *C, wmOperator *UNUSED(op))
nodeDetachNode(new_node);
}
}
-
- /* transform to basic view space. child node location is relative to parent */
- if (!new_node->parent) {
- new_node->locx += gnode_x;
- new_node->locy += gnode_y;
- }
}
}
@@ -2051,8 +1922,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ntree = snode->edittree;
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- float gnode_center[2];
const ListBase *clipboard_nodes_lb;
const ListBase *clipboard_links_lb;
bNode *node;
@@ -2086,14 +1955,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
/* deselect old nodes */
node_deselect_all(snode);
- /* get group node offset */
- if (gnode) {
- node_to_view(gnode, 0.0f, 0.0f, &gnode_center[0], &gnode_center[1]);
- }
- else {
- zero_v2(gnode_center);
- }
-
/* calculate "barycenter" for placing on mouse cursor */
zero_v2(center);
for (node = clipboard_nodes_lb->first, num_nodes = 0; node; node = node->next, num_nodes++) {
@@ -2110,7 +1971,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
id_us_plus(node->id);
/* pasted nodes are selected */
- node_select(new_node);
+ nodeSetSelected(new_node, TRUE);
}
/* reparent copied nodes */
@@ -2118,13 +1979,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
bNode *new_node = node->new_node;
if (new_node->parent)
new_node->parent = new_node->parent->new_node;
-
-
- /* place nodes around the mouse cursor. child nodes locations are relative to parent */
- if (!new_node->parent) {
- new_node->locx += snode->cursor[0] - center[0] - gnode_center[0];
- new_node->locy += snode->cursor[1] - center[1] - gnode_center[1];
- }
}
for (link = clipboard_links_lb->first; link; link = link->next) {
@@ -2167,15 +2021,195 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************** Shader Script Update ******************/
+/********************** Add interface socket operator *********************/
-typedef struct ScriptUpdateData {
- RenderEngine *engine;
- RenderEngineType *type;
+static bNodeSocket *ntree_get_active_interface_socket(ListBase *lb)
+{
+ bNodeSocket *sock;
+ for (sock = lb->first; sock; sock = sock->next)
+ if (sock->flag & SELECT)
+ return sock;
+ return NULL;
+}
- Text *text;
- int found;
-} ScriptUpdateData;
+static int ntree_socket_add_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int in_out = RNA_enum_get(op->ptr, "in_out");
+ PointerRNA ntree_ptr;
+ bNodeSocket *sock, *tsock, *active_sock;
+ const char *default_name;
+
+ RNA_id_pointer_create((ID *)ntree, &ntree_ptr);
+
+ if (in_out == SOCK_IN) {
+ active_sock = ntree_get_active_interface_socket(&ntree->inputs);
+ default_name = "Input";
+ }
+ else {
+ active_sock = ntree_get_active_interface_socket(&ntree->outputs);
+ default_name = "Output";
+ }
+
+ if (active_sock) {
+ /* insert a copy of the active socket right after it */
+ sock = ntreeInsertSocketInterface(ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
+ /* XXX this only works for actual sockets, not interface templates! */
+ /*nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);*/
+ }
+ else {
+ /* XXX TODO define default socket type for a tree! */
+ sock = ntreeAddSocketInterface(ntree, in_out, "NodeSocketFloat", default_name);
+ }
+
+ /* deactivate sockets (has to check both lists) */
+ for (tsock = ntree->inputs.first; tsock; tsock = tsock->next)
+ tsock->flag &= ~SELECT;
+ for (tsock = ntree->outputs.first; tsock; tsock = tsock->next)
+ tsock->flag &= ~SELECT;
+ /* make the new socket active */
+ sock->flag |= SELECT;
+
+ ntreeUpdateTree(ntree);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Node Tree Interface Socket";
+ ot->description = "Add an input or output socket to the current node tree";
+ ot->idname = "NODE_OT_tree_socket_add";
+
+ /* api callbacks */
+ ot->exec = ntree_socket_add_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "in_out", node_socket_in_out_items, SOCK_IN, "Socket Type", "");
+}
+
+/********************** Remove interface socket operator *********************/
+
+static int ntree_socket_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeSocket *iosock, *active_sock;
+
+ iosock = ntree_get_active_interface_socket(&ntree->inputs);
+ if (!iosock)
+ iosock = ntree_get_active_interface_socket(&ntree->outputs);
+ if (!iosock)
+ return OPERATOR_CANCELLED;
+
+ /* preferably next socket becomes active, otherwise try previous socket */
+ active_sock = (iosock->next ? iosock->next : iosock->prev);
+ ntreeRemoveSocketInterface(ntree, iosock);
+
+ /* set active socket */
+ if (active_sock)
+ active_sock->flag |= SELECT;
+
+ ntreeUpdateTree(ntree);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Node Tree Interface Socket";
+ ot->description = "Remove an input or output socket to the current node tree";
+ ot->idname = "NODE_OT_tree_socket_remove";
+
+ /* api callbacks */
+ ot->exec = ntree_socket_remove_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** Move interface socket operator *********************/
+
+static EnumPropertyItem move_direction_items[] = {
+ { 1, "UP", 0, "Up", "" },
+ { 2, "DOWN", 0, "Down", "" },
+ { 0, NULL, 0, NULL, NULL },
+};
+
+static int ntree_socket_move_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ int direction = RNA_enum_get(op->ptr, "direction");
+ bNodeSocket *iosock;
+ ListBase *lb;
+
+ lb = &ntree->inputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ if (!iosock) {
+ lb = &ntree->outputs;
+ iosock = ntree_get_active_interface_socket(lb);
+ }
+ if (!iosock)
+ return OPERATOR_CANCELLED;
+
+ switch (direction) {
+ case 1: { /* up */
+ bNodeSocket *before = iosock->prev;
+ BLI_remlink(lb, iosock);
+ if (before)
+ BLI_insertlinkbefore(lb, before, iosock);
+ else
+ BLI_addhead(lb, iosock);
+ break;
+ }
+ case 2: { /* down */
+ bNodeSocket *after = iosock->next;
+ BLI_remlink(lb, iosock);
+ if (after)
+ BLI_insertlinkafter(lb, after, iosock);
+ else
+ BLI_addtail(lb, iosock);
+ break;
+ }
+ }
+
+ ntreeUpdateTree(ntree);
+
+ WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_tree_socket_move(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Move Node Tree Socket";
+ ot->description = "Move a socket up or down in the current node tree's sockets stack";
+ ot->idname = "NODE_OT_tree_socket_move";
+
+ /* api callbacks */
+ ot->exec = ntree_socket_move_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna, "direction", move_direction_items, 1, "Direction", "");
+}
+
+/* ********************** Shader Script Update ******************/
static int node_shader_script_update_poll(bContext *C)
{
@@ -2208,64 +2242,79 @@ static int node_shader_script_update_poll(bContext *C)
return 0;
}
-static void node_shader_script_update_text(void *data_, ID *UNUSED(id), bNodeTree *ntree)
+/* recursively check for script nodes in groups using this text and update */
+static int node_shader_script_update_text_recursive(RenderEngine *engine, RenderEngineType *type, bNodeTree *ntree, Text *text)
{
- ScriptUpdateData *data = (ScriptUpdateData *)data_;
+ int found = FALSE;
bNode *node;
-
+
+ ntree->done = TRUE;
+
/* update each script that is using this text datablock */
for (node = ntree->nodes.first; node; node = node->next) {
if (node->type == NODE_GROUP) {
- node_shader_script_update_text(data_, NULL, (bNodeTree *)node->id);
+ bNodeTree *ngroup = (bNodeTree *)node->id;
+ if (ngroup && !ngroup->done)
+ found |= node_shader_script_update_text_recursive(engine, type, ngroup, text);
}
- else if (node->type == SH_NODE_SCRIPT && node->id == &data->text->id) {
- data->type->update_script_node(data->engine, ntree, node);
- data->found = TRUE;
+ else if (node->type == SH_NODE_SCRIPT && node->id == &text->id) {
+ type->update_script_node(engine, ntree, node);
+ found = TRUE;
}
}
+
+ return found;
}
static int node_shader_script_update_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ScriptUpdateData data;
PointerRNA nodeptr = CTX_data_pointer_get_type(C, "node", &RNA_ShaderNodeScript);
+ RenderEngine *engine;
+ RenderEngineType *type;
+ int found = FALSE;
/* setup render engine */
- data.type = RE_engines_find(scene->r.engine);
- data.engine = RE_engine_create(data.type);
- data.engine->reports = op->reports;
- data.text = NULL;
- data.found = FALSE;
+ type = RE_engines_find(scene->r.engine);
+ engine = RE_engine_create(type);
+ engine->reports = op->reports;
if (nodeptr.data) {
/* update single node */
bNodeTree *ntree = nodeptr.id.data;
bNode *node = nodeptr.data;
- data.type->update_script_node(data.engine, ntree, node);
+ type->update_script_node(engine, ntree, node);
- data.found = TRUE;
+ found = TRUE;
}
else {
/* update all nodes using text datablock */
- data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
-
- if (data.text) {
- bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-
- if (ntreetype && ntreetype->foreach_nodetree)
- ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text);
+ Text *text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data;
+
+ if (text) {
+ /* clear flags for recursion check */
+ FOREACH_NODETREE(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER)
+ ntree->done = FALSE;
+ } FOREACH_NODETREE_END
+
+ FOREACH_NODETREE(bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ if (!ntree->done)
+ found |= node_shader_script_update_text_recursive(engine, type, ntree, text);
+ }
+ } FOREACH_NODETREE_END
- if (!data.found)
+ if (!found)
BKE_report(op->reports, RPT_INFO, "Text not used by any node, no update done");
}
}
- RE_engine_free(data.engine);
+ RE_engine_free(engine);
- return (data.found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
+ return (found)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
}
void NODE_OT_shader_script_update(wmOperatorType *ot)
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 6696284b169..10f9718f1b6 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -66,85 +66,132 @@
#include "UI_resources.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
#include "NOD_socket.h"
-static EnumPropertyItem socket_in_out_items[] = {
- { SOCK_IN, "SOCK_IN", 0, "Input", "" },
- { SOCK_OUT, "SOCK_OUT", 0, "Output", "" },
- { 0, NULL, 0, NULL, NULL },
-};
-
-/* ***************** Edit Group operator ************* */
-
-void snode_make_group_editable(SpaceNode *snode, bNode *gnode)
+/* define common group node operator properties */
+static void node_group_operator_properties(wmOperatorType *ot)
{
- bNode *node;
-
- /* make sure nothing has group editing on */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- nodeGroupEditClear(node);
+ /* NB: not using an enum here, because that it would have to use an item callback and thus require
+ * copying of identifier strings anyway. node_type is not a user option, just a way of allowing
+ * node group operators to work on different types of group nodes.
+ */
+ RNA_def_string(ot->srna, "node_type", "", 0, "Node Type", "Group node type the operator works on");
+}
- /* while we're here, clear texture active */
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
- /* this is not 100% sure to be reliable, see comment on the flag */
- node->flag &= ~NODE_ACTIVE_TEXTURE;
- }
+/* Internal poll functions so group node operators can work with different group node types.
+ * This checks the operator node type property and looks up the respective types.
+ * If this function returns FALSE the operator should return PASS_THROUGH to allow other variants.
+ */
+static int node_group_operator_check_type(bContext *C, wmOperator *op, char **r_node_idname, char **r_ntree_idname)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ PropertyRNA *ntype_prop = RNA_struct_find_property(op->ptr, "node_type");
+ char *node_idname, *ntree_idname;
+ bNodeType *ntype;
+ bNodeTreeType *ntreetype;
+
+ if (!RNA_property_is_set(op->ptr, ntype_prop)) {
+ BKE_report(op->reports, RPT_ERROR, "Group node type not set");
+ return FALSE;
}
-
- if (gnode == NULL) {
- /* with NULL argument we do a toggle */
- if (snode->edittree == snode->nodetree)
- gnode = nodeGetActive(snode->nodetree);
+
+ node_idname = RNA_property_string_get_alloc(op->ptr, ntype_prop, NULL, 0, NULL);
+ ntype = nodeTypeFind(node_idname);
+ if (!ntype) {
+ BKE_reportf(op->reports, RPT_ERROR, "Group node type %s undefined", node_idname);
+ MEM_freeN(node_idname);
+ return FALSE;
}
-
- if (gnode) {
- snode->edittree = nodeGroupEditSet(gnode, 1);
-
- /* deselect all other nodes, so we can also do grabbing of entire subtree */
- for (node = snode->nodetree->nodes.first; node; node = node->next) {
- node_deselect(node);
-
- if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
- /* this is not 100% sure to be reliable, see comment on the flag */
- node->flag &= ~NODE_ACTIVE_TEXTURE;
- }
- }
- node_select(gnode);
+
+ if (!ntype->poll(ntype, ntree)) {
+ MEM_freeN(node_idname);
+ return FALSE;
}
+
+ ntree_idname = BLI_strdup(ntype->group_tree_idname);
+ ntreetype = ntreeTypeFind(ntree_idname);
+ if (!ntreetype) {
+ BKE_reportf(op->reports, RPT_ERROR, "Group node tree type %s undefined", ntree_idname);
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+ return FALSE;
+ }
+
+ if (r_node_idname)
+ *r_node_idname = node_idname;
+ else
+ MEM_freeN(node_idname);
+
+ if (r_ntree_idname)
+ *r_ntree_idname = ntree_idname;
else
- snode->edittree = snode->nodetree;
+ MEM_freeN(ntree_idname);
+
+ return TRUE;
}
-static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op))
+static bNode *node_group_get_active(bContext *C, const char *node_idname)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ bNode *node = nodeGetActive(snode->edittree);
+
+ if (node && STREQ(node->idname, node_idname))
+ return node;
+ else
+ return NULL;
+}
- ED_preview_kill_jobs(C);
+/* ***************** Edit Group operator ************* */
- if (snode->nodetree == snode->edittree) {
- bNode *gnode = nodeGetActive(snode->edittree);
- snode_make_group_editable(snode, gnode);
+static int node_group_edit_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
+ bNode *gnode;
+ int exit = RNA_boolean_get(op->ptr, "exit");
+
+ ED_preview_kill_jobs(C);
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (gnode && !exit) {
+ bNodeTree *ngroup = (bNodeTree *)gnode->id;
+
+ if (ngroup) {
+ if (ngroup->id.lib)
+ ntreeMakeLocal(ngroup);
+
+ ED_node_tree_push(snode, ngroup, gnode);
+ }
}
else
- snode_make_group_editable(snode, NULL);
-
+ ED_node_tree_pop(snode);
+
WM_event_add_notifier(C, NC_SCENE | ND_NODES, NULL);
-
+
return OPERATOR_FINISHED;
}
static int node_group_edit_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
bNode *gnode;
-
- /* XXX callback? */
- if (snode->nodetree == snode->edittree) {
- gnode = nodeGetActive(snode->edittree);
- if (gnode && gnode->id && GS(gnode->id->name) == ID_NT && gnode->id->lib) {
- uiPupMenuOkee(C, op->type->idname, "Make group local?");
- return OPERATOR_CANCELLED;
- }
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (gnode && gnode->id && gnode->id->lib) {
+ WM_operator_confirm_message(C, op, "Make group local?");
+ return OPERATOR_CANCELLED;
}
return node_group_edit_exec(C, op);
@@ -156,258 +203,17 @@ void NODE_OT_group_edit(wmOperatorType *ot)
ot->name = "Edit Group";
ot->description = "Edit node group";
ot->idname = "NODE_OT_group_edit";
-
+
/* api callbacks */
ot->invoke = node_group_edit_invoke;
ot->exec = node_group_edit_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ***************** Add Group Socket operator ************* */
-
-static int node_group_socket_add_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int in_out = -1;
- char name[MAX_NAME] = "";
- int type = SOCK_FLOAT;
- bNodeTree *ngroup = snode->edittree;
- /* bNodeSocket *sock; */ /* UNUSED */
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "name"))
- RNA_string_get(op->ptr, "name", name);
-
- if (RNA_struct_property_is_set(op->ptr, "type"))
- type = RNA_enum_get(op->ptr, "type");
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* using placeholder subtype first */
- /* sock = */ /* UNUSED */ node_group_add_socket(ngroup, name, type, in_out);
-
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Group Socket";
- ot->description = "Add node group socket";
- ot->idname = "NODE_OT_group_socket_add";
-
- /* api callbacks */
- ot->exec = node_group_socket_add_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
- RNA_def_string(ot->srna, "name", "", MAX_NAME, "Name", "Group socket name");
- RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_FLOAT, "Type", "Type of the group socket");
-}
-
-/* ***************** Remove Group Socket operator ************* */
-
-static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- sock = (bNodeSocket *)BLI_findlink(in_out == SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
- if (sock) {
- node_group_remove_socket(ngroup, sock, in_out);
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Group Socket";
- ot->description = "Remove a node group socket";
- ot->idname = "NODE_OT_group_socket_remove";
-
- /* api callbacks */
- ot->exec = node_group_socket_remove_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
-}
-
-/* ***************** Move Group Socket Up operator ************* */
-
-static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock, *prev;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* swap */
- if (in_out == SOCK_IN) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
- prev = sock->prev;
- /* can't move up the first socket */
- if (!prev)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->inputs, sock);
- BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- }
- else if (in_out == SOCK_OUT) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
- prev = sock->prev;
- /* can't move up the first socket */
- if (!prev)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->outputs, sock);
- BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- }
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_move_up(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move Group Socket Up";
- ot->description = "Move up node group socket";
- ot->idname = "NODE_OT_group_socket_move_up";
-
- /* api callbacks */
- ot->exec = node_group_socket_move_up_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
-}
-
-/* ***************** Move Group Socket Up operator ************* */
-
-static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- int index = -1;
- int in_out = -1;
- bNodeTree *ngroup = snode->edittree;
- bNodeSocket *sock, *next;
-
- ED_preview_kill_jobs(C);
-
- if (RNA_struct_property_is_set(op->ptr, "index"))
- index = RNA_int_get(op->ptr, "index");
- else
- return OPERATOR_CANCELLED;
-
- if (RNA_struct_property_is_set(op->ptr, "in_out"))
- in_out = RNA_enum_get(op->ptr, "in_out");
- else
- return OPERATOR_CANCELLED;
-
- /* swap */
- if (in_out == SOCK_IN) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->inputs, index);
- next = sock->next;
- /* can't move down the last socket */
- if (!next)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->inputs, sock);
- BLI_insertlinkafter(&ngroup->inputs, next, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_IN;
- }
- else if (in_out == SOCK_OUT) {
- sock = (bNodeSocket *)BLI_findlink(&ngroup->outputs, index);
- next = sock->next;
- /* can't move down the last socket */
- if (!next)
- return OPERATOR_CANCELLED;
- BLI_remlink(&ngroup->outputs, sock);
- BLI_insertlinkafter(&ngroup->outputs, next, sock);
-
- ngroup->update |= NTREE_UPDATE_GROUP_OUT;
- }
- ntreeUpdateTree(ngroup);
-
- snode_notify(C, snode);
-
- return OPERATOR_FINISHED;
-}
-
-void NODE_OT_group_socket_move_down(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move Group Socket Down";
- ot->description = "Move down node group socket";
- ot->idname = "NODE_OT_group_socket_move_down";
-
- /* api callbacks */
- ot->exec = node_group_socket_move_down_exec;
- ot->poll = ED_operator_node_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
- RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
+
+ node_group_operator_properties(ot);
+ RNA_def_boolean(ot->srna, "exit", FALSE, "Exit", "");
}
/* ******************** Ungroup operator ********************** */
@@ -415,180 +221,185 @@ void NODE_OT_group_socket_move_down(wmOperatorType *ot)
/* returns 1 if its OK */
static int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
{
- bNodeLink *link, *linkn;
- bNode *node, *nextn;
+ bNodeLink *link, *linkn, *tlink;
+ bNode *node, *nextnode;
bNodeTree *ngroup, *wgroup;
ListBase anim_basepaths = {NULL, NULL};
-
+
ngroup = (bNodeTree *)gnode->id;
- if (ngroup == NULL) return 0;
-
+
/* clear new pointers, set in copytree */
for (node = ntree->nodes.first; node; node = node->next)
node->new_node = NULL;
-
+
/* wgroup is a temporary copy of the NodeTree we're merging in
* - all of wgroup's nodes are transferred across to their new home
* - ngroup (i.e. the source NodeTree) is left unscathed
* - temp copy. don't change ID usercount
*/
wgroup = ntreeCopyTree_ex(ngroup, FALSE);
-
- /* add the nodes into the ntree */
- for (node = wgroup->nodes.first; node; node = nextn) {
- nextn = node->next;
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+
+ /* Add the nodes into the ntree */
+ for (node = wgroup->nodes.first; node; node = nextnode) {
+ nextnode = node->next;
+
+ /* Remove interface nodes.
+ * This also removes remaining links to and from interface nodes.
+ */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ nodeFreeNode(wgroup, node);
+ continue;
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
* if the old nodetree has animation data which potentially covers this node
*/
if (wgroup->adt) {
PointerRNA ptr;
char *path;
-
+
RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
path = RNA_path_from_ID_to_struct(&ptr);
-
+
if (path)
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
-
+
/* migrate node */
BLI_remlink(&wgroup->nodes, node);
BLI_addtail(&ntree->nodes, node);
-
- /* ensure unique node name in the nodee tree */
+
+ /* ensure unique node name in the node tree */
nodeUniqueName(ntree, node);
-
+
if (!node->parent) {
node->locx += gnode->locx;
node->locy += gnode->locy;
}
-
+
node->flag |= NODE_SELECT;
}
-
- /* restore external links to and from the gnode */
- for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode == gnode) {
- if (link->fromsock->groupsock) {
- bNodeSocket *gsock = link->fromsock->groupsock;
- if (gsock->link) {
- if (gsock->link->fromnode) {
- /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
- link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
- link->fromsock = gsock->link->fromsock->new_sock;
- }
- else {
- /* group output directly maps to group input */
- bNodeSocket *insock = node_group_find_input(gnode, gsock->link->fromsock);
- if (insock->link) {
- link->fromnode = insock->link->fromnode;
- link->fromsock = insock->link->fromsock;
- }
- }
- }
- else {
- /* copy the default input value from the group socket default to the external socket */
- node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, gsock->type, gsock->default_value);
- }
- }
- }
- }
- /* remove internal output links, these are not used anymore */
- for (link = wgroup->links.first; link; link = linkn) {
- linkn = link->next;
- if (!link->tonode)
- nodeRemLink(wgroup, link);
- }
- /* restore links from internal nodes */
- for (link = wgroup->links.first; link; link = linkn) {
- linkn = link->next;
- /* indicates link to group input */
- if (!link->fromnode) {
- /* NB: can't use find_group_node_input here,
- * because gnode sockets still point to the old tree!
- */
- bNodeSocket *insock;
- for (insock = gnode->inputs.first; insock; insock = insock->next)
- if (insock->groupsock->new_sock == link->fromsock)
- break;
- if (insock->link) {
- link->fromnode = insock->link->fromnode;
- link->fromsock = insock->link->fromsock;
- }
- else {
- /* copy the default input value from the group node socket default to the internal socket */
- node_socket_convert_default_value(link->tosock->type, link->tosock->default_value, insock->type, insock->default_value);
- nodeRemLink(wgroup, link);
- }
- }
- }
-
- /* add internal links to the ntree */
+
+ /* Add internal links to the ntree */
for (link = wgroup->links.first; link; link = linkn) {
linkn = link->next;
BLI_remlink(&wgroup->links, link);
BLI_addtail(&ntree->links, link);
}
-
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (wgroup->adt) {
LinkData *ld, *ldn = NULL;
bAction *waction;
-
+
/* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
waction = wgroup->adt->action = BKE_action_copy(wgroup->adt->action);
-
+
/* now perform the moving */
BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
-
+
/* free temp action too */
if (waction) {
BKE_libblock_free(&G.main->action, waction);
}
}
-
- /* delete the group instance. this also removes old input links! */
- nodeFreeNode(ntree, gnode);
-
+
/* free the group tree (takes care of user count) */
BKE_libblock_free(&G.main->nodetree, wgroup);
-
+
+ /* restore external links to and from the gnode */
+ /* note: the nodes have been copied to intermediate wgroup first (so need to use new_node),
+ * then transferred to ntree (new_node pointers remain valid).
+ */
+
+ /* input links */
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->fromnode->type == NODE_GROUP_INPUT) {
+ const char *identifier = link->fromsock->identifier;
+ int num_external_links = 0;
+
+ /* find external links to this input */
+ for (tlink = ntree->links.first; tlink; tlink = tlink->next) {
+ if (tlink->tonode == gnode && STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode, tlink->fromsock, link->tonode->new_node, link->tosock->new_sock);
+ ++num_external_links;
+ }
+ }
+
+ /* if group output is not externally linked,
+ * convert the constant input value to ensure somewhat consistent behavior */
+ if (num_external_links == 0) {
+ bNodeSocket *sock = node_group_find_input_socket(gnode, identifier);
+ BLI_assert(sock);
+
+ /* XXX TODO nodeSocketCopy(ntree, link->tosock->new_sock, link->tonode->new_node, ntree, sock, gnode);*/
+ }
+ }
+ }
+
+ /* output links */
+ for (link = ntree->links.first; link; link = link->next) {
+ if (link->fromnode == gnode) {
+ const char *identifier = link->fromsock->identifier;
+ int num_internal_links = 0;
+
+ /* find internal links to this output */
+ for (tlink = ngroup->links.first; tlink; tlink = tlink->next) {
+ /* only use active output node */
+ if (tlink->tonode->type == NODE_GROUP_OUTPUT && (tlink->tonode->flag & NODE_DO_OUTPUT)) {
+ if (STREQ(tlink->tosock->identifier, identifier)) {
+ nodeAddLink(ntree, tlink->fromnode->new_node, tlink->fromsock->new_sock, link->tonode, link->tosock);
+ ++num_internal_links;
+ }
+ }
+ }
+
+ /* if group output is not internally linked,
+ * convert the constant output value to ensure somewhat consistent behavior */
+ if (num_internal_links == 0) {
+ bNodeSocket *sock = node_group_find_output_socket(gnode, identifier);
+ BLI_assert(sock);
+
+ /* XXX TODO nodeSocketCopy(ntree, link->tosock, link->tonode, ntree, sock, gnode); */
+ }
+ }
+ }
+
+ /* delete the group instance */
+ nodeFreeNode(ntree, gnode);
+
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
+
return 1;
}
+
static int node_group_ungroup_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ char *node_idname;
bNode *gnode;
ED_preview_kill_jobs(C);
- /* are we inside of a group? */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode)
- snode_make_group_editable(snode, NULL);
-
- gnode = nodeGetActive(snode->edittree);
- if (gnode == NULL)
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+ if (!gnode)
return OPERATOR_CANCELLED;
-
- if (gnode->type != NODE_GROUP) {
- BKE_report(op->reports, RPT_WARNING, "Not a group");
- return OPERATOR_CANCELLED;
- }
- else if (node_group_ungroup(snode->nodetree, gnode)) {
+
+ if (gnode->id && node_group_ungroup(snode->edittree, gnode)) {
ntreeUpdateTree(snode->nodetree);
}
else {
@@ -608,93 +419,92 @@ void NODE_OT_group_ungroup(wmOperatorType *ot)
ot->name = "Ungroup";
ot->description = "Ungroup selected nodes";
ot->idname = "NODE_OT_group_ungroup";
-
+
/* api callbacks */
ot->exec = node_group_ungroup_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
}
/* ******************** Separate operator ********************** */
/* returns 1 if its OK */
-static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make_copy)
+static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
{
bNodeLink *link, *link_next;
bNode *node, *node_next, *newnode;
- bNodeTree *ngroup;
ListBase anim_basepaths = {NULL, NULL};
-
- ngroup = (bNodeTree *)gnode->id;
- if (ngroup == NULL) return 0;
-
+
/* deselect all nodes in the target tree */
for (node = ntree->nodes.first; node; node = node->next)
- node_deselect(node);
-
+ nodeSetSelected(node, FALSE);
+
/* clear new pointers, set in nodeCopyNode */
for (node = ngroup->nodes.first; node; node = node->next)
node->new_node = NULL;
-
+
/* add selected nodes into the ntree */
for (node = ngroup->nodes.first; node; node = node_next) {
node_next = node->next;
- if (node->flag & NODE_SELECT) {
-
- if (make_copy) {
- /* make a copy */
- newnode = nodeCopyNode(ngroup, node);
- }
- else {
- /* use the existing node */
- newnode = node;
- }
-
- /* keep track of this node's RNA "base" path (the part of the path identifying the node)
- * if the old nodetree has animation data which potentially covers this node
- */
- if (ngroup->adt) {
- PointerRNA ptr;
- char *path;
-
- RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
- path = RNA_path_from_ID_to_struct(&ptr);
-
- if (path)
- BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
- }
-
- /* ensure valid parent pointers, detach if parent stays inside the group */
- if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
- nodeDetachNode(newnode);
-
- /* migrate node */
- BLI_remlink(&ngroup->nodes, newnode);
- BLI_addtail(&ntree->nodes, newnode);
+ if (!(node->flag & NODE_SELECT))
+ continue;
+
+ /* ignore interface nodes */
+ if (ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT)) {
+ nodeSetSelected(node, FALSE);
+ continue;
+ }
+
+ if (make_copy) {
+ /* make a copy */
+ newnode = nodeCopyNode(ngroup, node);
+ }
+ else {
+ /* use the existing node */
+ newnode = node;
+ }
+
+ /* keep track of this node's RNA "base" path (the part of the path identifying the node)
+ * if the old nodetree has animation data which potentially covers this node
+ */
+ if (ngroup->adt) {
+ PointerRNA ptr;
+ char *path;
- /* ensure unique node name in the node tree */
- nodeUniqueName(ntree, newnode);
+ RNA_pointer_create(&ngroup->id, &RNA_Node, newnode, &ptr);
+ path = RNA_path_from_ID_to_struct(&ptr);
- if (!newnode->parent) {
- newnode->locx += gnode->locx;
- newnode->locy += gnode->locy;
- }
+ if (path)
+ BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
- else {
- /* ensure valid parent pointers, detach if child stays inside the group */
- if (node->parent && (node->parent->flag & NODE_SELECT))
- nodeDetachNode(node);
+
+ /* ensure valid parent pointers, detach if parent stays inside the group */
+ if (newnode->parent && !(newnode->parent->flag & NODE_SELECT))
+ nodeDetachNode(newnode);
+
+ /* migrate node */
+ BLI_remlink(&ngroup->nodes, newnode);
+ BLI_addtail(&ntree->nodes, newnode);
+
+ /* ensure unique node name in the node tree */
+ nodeUniqueName(ntree, newnode);
+
+ if (!newnode->parent) {
+ newnode->locx += offx;
+ newnode->locy += offy;
}
}
-
+
/* add internal links to the ntree */
for (link = ngroup->links.first; link; link = link_next) {
int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT));
int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT));
link_next = link->next;
-
+
if (make_copy) {
/* make a copy of internal links */
if (fromselect && toselect)
@@ -711,28 +521,28 @@ static int node_group_separate_selected(bNodeTree *ntree, bNode *gnode, int make
}
}
}
-
+
/* and copy across the animation,
* note that the animation data's action can be NULL here */
if (ngroup->adt) {
LinkData *ld, *ldn = NULL;
-
+
/* now perform the moving */
BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
}
-
+
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
if (!make_copy)
ngroup->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
+
return 1;
}
@@ -751,56 +561,64 @@ EnumPropertyItem node_group_separate_types[] = {
static int node_group_separate_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
- bNode *gnode;
+ bNodeTree *ngroup, *nparent;
int type = RNA_enum_get(op->ptr, "type");
+ float offx, offy;
ED_preview_kill_jobs(C);
/* are we inside of a group? */
- gnode = node_tree_get_editgroup(snode->nodetree);
- if (!gnode) {
+ ngroup = snode->edittree;
+ nparent = ED_node_tree_get(snode, 1);
+ if (!nparent) {
BKE_report(op->reports, RPT_WARNING, "Not inside node group");
return OPERATOR_CANCELLED;
}
-
+ /* get node tree offset */
+ snode_group_offset(snode, &offx, &offy);
+
switch (type) {
case NODE_GS_COPY:
- if (!node_group_separate_selected(snode->nodetree, gnode, 1)) {
+ if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
case NODE_GS_MOVE:
- if (!node_group_separate_selected(snode->nodetree, gnode, 0)) {
+ if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
}
-
+
/* switch to parent tree */
- snode_make_group_editable(snode, NULL);
-
+ ED_node_tree_pop(snode);
+
ntreeUpdateTree(snode->nodetree);
-
+
snode_notify(C, snode);
snode_dag_update(C, snode);
return OPERATOR_FINISHED;
}
-static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
+static int node_group_separate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
-
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
- uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
-
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
+ if (!node_group_operator_check_type(C, op, NULL, NULL))
+ return OPERATOR_PASS_THROUGH;
+ else {
+ uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE);
+ uiLayout *layout = uiPupMenuLayout(pup);
+
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
+ uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_COPY);
+ uiItemEnumO(layout, "NODE_OT_group_separate", NULL, 0, "type", NODE_GS_MOVE);
+
+ uiPupMenuEnd(C, pup);
+
+ return OPERATOR_CANCELLED;
+ }
}
void NODE_OT_group_separate(wmOperatorType *ot)
@@ -809,162 +627,183 @@ void NODE_OT_group_separate(wmOperatorType *ot)
ot->name = "Separate";
ot->description = "Separate selected nodes from the node group";
ot->idname = "NODE_OT_group_separate";
-
+
/* api callbacks */
ot->invoke = node_group_separate_invoke;
ot->exec = node_group_separate_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
+
+ node_group_operator_properties(ot);
RNA_def_enum(ot->srna, "type", node_group_separate_types, NODE_GS_COPY, "Type", "");
}
/* ****************** Make Group operator ******************* */
-static int node_group_make_test(bNodeTree *ntree, bNode *gnode)
+static bool node_group_make_use_node(bNode *node, bNode *gnode)
{
+ return (node != gnode &&
+ !ELEM(node->type, NODE_GROUP_INPUT, NODE_GROUP_OUTPUT) &&
+ (node->flag & NODE_SELECT));
+}
+
+static bool node_group_make_test_selected(bNodeTree *ntree, bNode *gnode, const char *ntree_idname, struct ReportList *reports)
+{
+ bNodeTree *ngroup;
bNode *node;
bNodeLink *link;
- int totnode = 0;
-
- /* is there something to group? also do some clearing */
+ int ok = true;
+
+ /* make a local pseudo node tree to pass to the node poll functions */
+ ngroup = ntreeAddTree(NULL, "Pseudo Node Group", ntree_idname);
+
+ /* check poll functions for selected nodes */
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
-
- if (node->flag & NODE_SELECT) {
- /* no groups in groups */
- if (node->type == NODE_GROUP)
- return 0;
- totnode++;
+ if (node_group_make_use_node(node, gnode)) {
+ if (node->typeinfo->poll_instance && !node->typeinfo->poll_instance(node, ngroup)) {
+ BKE_reportf(reports, RPT_WARNING, "Can not add node '%s' in a group", node->name);
+ ok = false;
+ break;
+ }
}
node->done = 0;
}
- if (totnode == 0) return 0;
-
+
+ /* free local pseudo node tree again */
+ ntreeFreeTree(ngroup);
+ MEM_freeN(ngroup);
+ if (!ok)
+ return false;
+
/* check if all connections are OK, no unselected node has both
* inputs and outputs to a selection */
for (link = ntree->links.first; link; link = link->next) {
- if (link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT && link->fromnode != gnode)
+ if (node_group_make_use_node(link->fromnode, gnode))
link->tonode->done |= 1;
- if (link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT && link->tonode != gnode)
+ if (node_group_make_use_node(link->tonode, gnode))
link->fromnode->done |= 2;
}
-
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
- if ((node->flag & NODE_SELECT) == 0)
- if (node->done == 3)
- break;
+ if (!(node->flag & NODE_SELECT) &&
+ node != gnode &&
+ node->done == 3)
+ {
+ return false;
+ }
}
- if (node)
- return 0;
-
- return 1;
+ return true;
}
-
-static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
+static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max)
{
bNode *node;
float loc[2];
+ int totselect = 0;
+
INIT_MINMAX2(min, max);
for (node = ntree->nodes.first; node; node = node->next) {
- if (node == gnode)
- continue;
- if (node->flag & NODE_SELECT) {
+ if (node_group_make_use_node(node, gnode)) {
nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]);
minmax_v2v2_v2(min, max, loc);
+ ++totselect;
}
}
+
+ /* sane min/max if no selected nodes */
+ if (totselect == 0) {
+ min[0] = min[1] = max[0] = max[1] = 0.0f;
+ }
+
+ return totselect;
}
-static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
+static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode)
{
bNodeTree *ngroup = (bNodeTree *)gnode->id;
bNodeLink *link, *linkn;
bNode *node, *nextn;
- bNodeSocket *gsock, *sock;
+ bNodeSocket *sock;
ListBase anim_basepaths = {NULL, NULL};
- float min[2], max[2];
-
+ float min[2], max[2], center[2];
+ int totselect;
+ int expose_all = FALSE;
+ bNode *input_node = NULL, *output_node = NULL; /* lazy initialized, in case there are no external links */
+
+ /* XXX rough guess, not nice but we don't have access to UI constants here ... */
+ static const float offsetx = 200;
+ static const float offsety = 0.0f;
+
/* deselect all nodes in the target tree */
for (node = ngroup->nodes.first; node; node = node->next)
- node_deselect(node);
-
- node_get_selected_minmax(ntree, gnode, min, max);
-
+ nodeSetSelected(node, FALSE);
+
+ totselect = node_get_selected_minmax(ntree, gnode, min, max);
+ add_v2_v2v2(center, min, max);
+ mul_v2_fl(center, 0.5f);
+
+ /* auto-add interface for "solo" nodes */
+ if (totselect == 1)
+ expose_all = TRUE;
+
/* move nodes over */
for (node = ntree->nodes.first; node; node = nextn) {
nextn = node->next;
- if (node == gnode)
- continue;
- if (node->flag & NODE_SELECT) {
- /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
+ if (node_group_make_use_node(node, gnode)) {
+ /* keep track of this node's RNA "base" path (the part of the pat identifying the node)
* if the old nodetree has animation data which potentially covers this node
*/
if (ntree->adt) {
PointerRNA ptr;
char *path;
-
+
RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
path = RNA_path_from_ID_to_struct(&ptr);
-
+
if (path)
BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
}
-
+
/* ensure valid parent pointers, detach if parent stays outside the group */
if (node->parent && !(node->parent->flag & NODE_SELECT))
nodeDetachNode(node);
-
+
/* change node-collection membership */
BLI_remlink(&ntree->nodes, node);
BLI_addtail(&ngroup->nodes, node);
-
+
/* ensure unique node name in the ngroup */
nodeUniqueName(ngroup, node);
-
- if (!node->parent) {
- node->locx -= 0.5f * (min[0] + max[0]);
- node->locy -= 0.5f * (min[1] + max[1]);
- }
- }
- else {
- /* if the parent is to be inserted but not the child, detach properly */
- if (node->parent && (node->parent->flag & NODE_SELECT))
- nodeDetachNode(node);
}
}
-
+
/* move animation data over */
if (ntree->adt) {
LinkData *ld, *ldn = NULL;
-
+
BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
-
+
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
ldn = ld->next;
-
+
MEM_freeN(ld->data);
BLI_freelinkN(&anim_basepaths, ld);
}
}
-
+
/* node groups don't use internal cached data */
ntreeFreeCache(ngroup);
-
+
/* relink external sockets */
for (link = ntree->links.first; link; link = linkn) {
- int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT) && link->fromnode != gnode);
- int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT) && link->tonode != gnode);
+ int fromselect = node_group_make_use_node(link->fromnode, gnode);
+ int toselect = node_group_make_use_node(link->tonode, gnode);
+
linkn = link->next;
-
+
if ((fromselect && link->tonode == gnode) || (toselect && link->fromnode == gnode)) {
/* remove all links to/from the gnode.
* this can remove link information, but there's no general way to preserve it.
@@ -976,58 +815,123 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
BLI_addtail(&ngroup->links, link);
}
else if (toselect) {
- gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN);
- link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
- link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->tonode, link->tosock);
+ bNodeSocket *input_sock;
+
+ /* lazy init */
+ if (!input_node) {
+ input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
+
+ input_node->locx = min[0] - center[0] - offsetx;
+ input_node->locy = -offsety;
+ }
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, link->tonode, link->tosock);
+
+ /* redirect external link */
link->tonode = gnode;
+ link->tosock = node_group_find_input_socket(gnode, iosock->identifier);
}
else if (fromselect) {
- /* search for existing group node socket */
- for (gsock = ngroup->outputs.first; gsock; gsock = gsock->next)
- if (gsock->link && gsock->link->fromsock == link->fromsock)
- break;
- if (!gsock) {
- gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT);
- gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
- link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
+ bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->fromnode, link->fromsock);
+ bNodeSocket *output_sock;
+
+ /* lazy init */
+ if (!output_node) {
+ output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
+
+ output_node->locx = max[0] - center[0] + offsetx;
+ output_node->locy = -offsety;
}
- else
- link->fromsock = node_group_find_output(gnode, gsock);
+ /* update the group node and interface node sockets,
+ * so the new interface socket can be linked.
+ */
+ node_group_verify(ntree, gnode, (ID *)ngroup);
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, link->fromnode, link->fromsock, output_node, output_sock);
+
+ /* redirect external link */
link->fromnode = gnode;
+ link->fromsock = node_group_find_output_socket(gnode, iosock->identifier);
}
}
- /* auto-add interface for "solo" nodes */
- node = ((bNodeTree *)gnode->id)->nodes.first;
- if (node && !node->next) {
- for (sock = node->inputs.first; sock; sock = sock->next) {
- int skip = FALSE;
-
- for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
- if (link->tosock == sock)
- skip = TRUE;
-
- if (skip == TRUE)
- continue;
-
- gsock = node_group_expose_socket(ngroup, sock, SOCK_IN);
- node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
- nodeAddLink(ngroup, NULL, gsock, node, sock);
+ /* move nodes in the group to the center */
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode) && !node->parent) {
+ node->locx -= center[0];
+ node->locy -= center[1];
}
-
- for (sock = node->outputs.first; sock; sock = sock->next) {
- int skip = FALSE;
-
- for (link = ((bNodeTree *)gnode->id)->links.first; link; link = link->next)
- if (link->fromsock == sock)
- skip = TRUE;
-
- if (skip == TRUE)
- continue;
-
- gsock = node_group_expose_socket(ngroup, sock, SOCK_OUT);
- node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
- nodeAddLink(ngroup, NULL, gsock, node, sock);
+ }
+
+ /* expose all unlinked sockets too */
+ if (expose_all) {
+ for (node = ngroup->nodes.first; node; node = node->next) {
+ if (node_group_make_use_node(node, gnode)) {
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *input_sock;
+ int skip = FALSE;
+ for (link = ngroup->links.first; link; link = link->next) {
+ if (link->tosock == sock) {
+ skip = TRUE;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ /* lazy init */
+ if (!input_node) {
+ input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT);
+
+ input_node->locx = min[0] - center[0] - offsetx;
+ input_node->locy = -offsety;
+ }
+ node_group_input_verify(ngroup, input_node, (ID *)ngroup);
+
+ /* create new internal link */
+ input_sock = node_group_input_find_socket(input_node, iosock->identifier);
+ nodeAddLink(ngroup, input_node, input_sock, node, sock);
+ }
+
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ bNodeSocket *iosock, *output_sock;
+ int skip = FALSE;
+ for (link = ngroup->links.first; link; link = link->next)
+ if (link->fromsock == sock)
+ skip = TRUE;
+ if (skip)
+ continue;
+
+ iosock = ntreeAddSocketInterfaceFromSocket(ngroup, node, sock);
+
+ /* lazy init */
+ if (!output_node) {
+ output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT);
+
+ output_node->locx = max[0] - center[0] + offsetx;
+ output_node->locy = -offsety;
+ }
+
+ node_group_output_verify(ngroup, output_node, (ID *)ngroup);
+
+ /* create new internal link */
+ output_sock = node_group_output_find_socket(output_node, iosock->identifier);
+ nodeAddLink(ngroup, node, sock, output_node, output_sock);
+ }
+ }
}
}
@@ -1035,30 +939,32 @@ static int node_group_make_insert_selected(bNodeTree *ntree, bNode *gnode)
ngroup->update |= NTREE_UPDATE | NTREE_UPDATE_LINKS;
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
-
- return 1;
}
-static bNode *node_group_make_from_selected(bNodeTree *ntree)
+static bNode *node_group_make_from_selected(const bContext *C, bNodeTree *ntree, const char *ntype, const char *ntreetype)
{
+ Main *bmain = CTX_data_main(C);
bNode *gnode;
bNodeTree *ngroup;
float min[2], max[2];
- bNodeTemplate ntemp;
-
- node_get_selected_minmax(ntree, NULL, min, max);
-
+ int totselect;
+
+ totselect = node_get_selected_minmax(ntree, NULL, min, max);
+ /* don't make empty group */
+ if (totselect == 0)
+ return NULL;
+
/* new nodetree */
- ngroup = ntreeAddTree(G.main, "NodeGroup", ntree->type, NODE_GROUP);
-
+ ngroup = ntreeAddTree(bmain, "NodeGroup", ntreetype);
+
/* make group node */
- ntemp.type = NODE_GROUP;
- ntemp.ngroup = ngroup;
- gnode = nodeAddNode(ntree, &ntemp);
+ gnode = nodeAddNode(C, ntree, ntype);
+ gnode->id = (ID *)ngroup;
+
gnode->locx = 0.5f * (min[0] + max[0]);
gnode->locy = 0.5f * (min[1] + max[1]);
-
- node_group_make_insert_selected(ntree, gnode);
+
+ node_group_make_insert_selected(C, ntree, gnode);
/* update of the tree containing the group instance node */
ntree->update |= NTREE_UPDATE_NODES;
@@ -1066,120 +972,116 @@ static bNode *node_group_make_from_selected(bNodeTree *ntree)
return gnode;
}
-typedef enum eNodeGroupMakeType {
- NODE_GM_NEW,
- NODE_GM_INSERT
-} eNodeGroupMakeType;
-
-/* Operator Property */
-EnumPropertyItem node_group_make_types[] = {
- {NODE_GM_NEW, "NEW", 0, "New", "Create a new node group from selected nodes"},
- {NODE_GM_INSERT, "INSERT", 0, "Insert", "Insert into active node group"},
- {0, NULL, 0, NULL, NULL}
-};
-
static int node_group_make_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ char *node_idname, *ntree_idname;
+ bNodeTree *ngroup;
bNode *gnode;
- int type = RNA_enum_get(op->ptr, "type");
-
- if (snode->edittree != snode->nodetree) {
- BKE_report(op->reports, RPT_WARNING, "Cannot add a new group in a group");
- return OPERATOR_CANCELLED;
- }
-
- /* for time being... is too complex to handle */
- if (snode->treetype == NTREE_COMPOSIT) {
- for (gnode = snode->nodetree->nodes.first; gnode; gnode = gnode->next) {
- if (gnode->flag & SELECT)
- if (gnode->type == CMP_NODE_R_LAYERS)
- break;
- }
-
- if (gnode) {
- BKE_report(op->reports, RPT_WARNING, "Cannot add a Render Layers node in a group");
- return OPERATOR_CANCELLED;
- }
- }
-
+
ED_preview_kill_jobs(C);
-
- switch (type) {
- case NODE_GM_NEW:
- if (node_group_make_test(snode->nodetree, NULL)) {
- gnode = node_group_make_from_selected(snode->nodetree);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Cannot make group");
- return OPERATOR_CANCELLED;
- }
- break;
- case NODE_GM_INSERT:
- gnode = nodeGetActive(snode->nodetree);
- if (!gnode || gnode->type != NODE_GROUP) {
- BKE_report(op->reports, RPT_WARNING, "No active group node");
- return OPERATOR_CANCELLED;
- }
- if (node_group_make_test(snode->nodetree, gnode)) {
- node_group_make_insert_selected(snode->nodetree, gnode);
- }
- else {
- BKE_report(op->reports, RPT_WARNING, "Cannot insert into group");
- return OPERATOR_CANCELLED;
- }
- break;
+
+ if (!node_group_operator_check_type(C, op, &node_idname, &ntree_idname))
+ return OPERATOR_PASS_THROUGH;
+
+ if (!node_group_make_test_selected(ntree, NULL, ntree_idname, op->reports)) {
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+ return OPERATOR_CANCELLED;
}
-
+
+ gnode = node_group_make_from_selected(C, ntree, node_idname, ntree_idname);
+ MEM_freeN(node_idname);
+ MEM_freeN(ntree_idname);
+
if (gnode) {
- nodeSetActive(snode->nodetree, gnode);
- snode_make_group_editable(snode, gnode);
+ ngroup = (bNodeTree *)gnode->id;
+
+ nodeSetActive(ntree, gnode);
+ if (ngroup) {
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(ngroup);
+ }
}
-
- if (gnode)
- ntreeUpdateTree((bNodeTree *)gnode->id);
- ntreeUpdateTree(snode->nodetree);
+
+ ntreeUpdateTree(ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
return OPERATOR_FINISHED;
}
-static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- bNode *act = nodeGetActive(snode->edittree);
- uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Group"), ICON_NONE);
- uiLayout *layout = uiPupMenuLayout(pup);
-
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
- uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_NEW);
-
- /* if active node is a group, add insert option */
- if (act && act->type == NODE_GROUP) {
- uiItemEnumO(layout, "NODE_OT_group_make", NULL, 0, "type", NODE_GM_INSERT);
- }
-
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
-}
-
void NODE_OT_group_make(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Group";
+ ot->name = "Make Group";
ot->description = "Make group from selected nodes";
ot->idname = "NODE_OT_group_make";
-
+
/* api callbacks */
- ot->invoke = node_group_make_invoke;
ot->exec = node_group_make_exec;
ot->poll = ED_operator_node_active;
-
+
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
+}
- RNA_def_enum(ot->srna, "type", node_group_make_types, NODE_GM_NEW, "Type", "");
+/* ****************** Group Insert operator ******************* */
+
+static int node_group_insert_exec(bContext *C, wmOperator *op)
+{
+ SpaceNode *snode = CTX_wm_space_node(C);
+ bNodeTree *ntree = snode->edittree;
+ bNodeTree *ngroup;
+ char *node_idname;
+ bNode *gnode;
+
+ ED_preview_kill_jobs(C);
+
+ if (!node_group_operator_check_type(C, op, &node_idname, NULL))
+ return OPERATOR_PASS_THROUGH;
+
+ gnode = node_group_get_active(C, node_idname);
+ MEM_freeN(node_idname);
+
+ if (!gnode || !gnode->id)
+ return OPERATOR_CANCELLED;
+
+ ngroup = (bNodeTree *)gnode->id;
+ if (!node_group_make_test_selected(ntree, gnode, ngroup->idname, op->reports))
+ return OPERATOR_CANCELLED;
+
+ node_group_make_insert_selected(C, ntree, gnode);
+
+ nodeSetActive(ntree, gnode);
+ ED_node_tree_push(snode, ngroup, gnode);
+ ntreeUpdateTree(ngroup);
+
+ ntreeUpdateTree(ntree);
+
+ snode_notify(C, snode);
+ snode_dag_update(C, snode);
+
+ return OPERATOR_FINISHED;
+}
+
+void NODE_OT_group_insert(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Group Insert";
+ ot->description = "Insert selected nodes into a node group";
+ ot->idname = "NODE_OT_group_insert";
+
+ /* api callbacks */
+ ot->exec = node_group_insert_exec;
+ ot->poll = ED_operator_node_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ node_group_operator_properties(ot);
}
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index f26b6ff0f54..175bbce756e 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -58,186 +58,21 @@
/* ************************ add menu *********************** */
-static void do_node_add(bContext *C, bNodeTemplate *ntemp)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
- bNode *node, *node_new;
-
- /* get location to add node at mouse */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- wmWindow *win = CTX_wm_window(C);
- int x = win->eventstate->x - ar->winrct.xmin;
- int y = win->eventstate->y - ar->winrct.ymin;
-
- if (y < 60) y += 60;
- UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]);
- }
- }
-
- /* store selection in temp test flag */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_SELECT) node->flag |= NODE_TEST;
- else node->flag &= ~NODE_TEST;
- }
-
- node_new = node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]);
-
- /* select previous selection before autoconnect */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) node->flag |= NODE_SELECT;
- }
-
- /* deselect after autoconnection */
- for (node = snode->edittree->nodes.first; node; node = node->next) {
- if (node->flag & NODE_TEST) node->flag &= ~NODE_SELECT;
- }
-
- /* once this is called from an operator, this should be removed */
- if (node_new) {
- char undostr[BKE_UNDO_STR_MAX];
- BLI_snprintf(undostr, sizeof(undostr), "Add Node %s", nodeLabel(node_new));
- BKE_write_undo(C, undostr);
- }
-
- snode_notify(C, snode);
- snode_dag_update(C, snode);
-}
-
-static void do_node_add_static(bContext *C, void *UNUSED(arg), int event)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- ntemp.type = event;
- ntemp.main = bmain;
- ntemp.scene = scene;
-
- do_node_add(C, &ntemp);
-}
-
-static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
-{
- SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- if (event >= 0) {
- ntemp.ngroup = BLI_findlink(&G.main->nodetree, event);
- ntemp.type = ntemp.ngroup->nodetype;
- }
- else {
- ntemp.type = -event;
- switch (ntemp.type) {
- case NODE_GROUP:
- ntemp.ngroup = ntreeAddTree(bmain, "Group", snode->treetype, ntemp.type);
- break;
- default:
- ntemp.ngroup = NULL;
- }
- }
- if (!ntemp.ngroup)
- return;
-
- ntemp.main = bmain;
- ntemp.scene = scene;
-
- do_node_add(C, &ntemp);
-}
-
-static int node_tree_has_type(int treetype, int nodetype)
-{
- bNodeTreeType *ttype = ntreeGetType(treetype);
- bNodeType *ntype;
- for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
- if (ntype->type == nodetype)
- return 1;
- }
- return 0;
-}
-
-static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- bNodeTree *ntree;
- int nodeclass = GET_INT_FROM_POINTER(arg_nodeclass);
- int event, compatibility = 0;
-
- ntree = snode->nodetree;
-
- if (!ntree) {
- uiItemS(layout);
- return;
- }
-
- if (ntree->type == NTREE_SHADER) {
- if (BKE_scene_use_new_shading_nodes(scene))
- compatibility = NODE_NEW_SHADING;
- else
- compatibility = NODE_OLD_SHADING;
- }
-
- if (nodeclass == NODE_CLASS_GROUP) {
- bNodeTree *ngroup;
-
- uiLayoutSetFunc(layout, do_node_add_group, NULL);
-
- /* XXX hack: negative numbers used for empty group types */
- if (node_tree_has_type(ntree->type, NODE_GROUP))
- uiItemV(layout, IFACE_("New Group"), 0, -NODE_GROUP);
- uiItemS(layout);
-
- for (ngroup = bmain->nodetree.first, event = 0; ngroup; ngroup = ngroup->id.next, ++event) {
- /* only use group trees */
- if (ngroup->type == ntree->type && ngroup->nodetype == NODE_GROUP) {
- uiItemV(layout, ngroup->id.name + 2, 0, event);
- }
- }
- }
- else {
- bNodeType *ntype;
-
- uiLayoutSetFunc(layout, do_node_add_static, NULL);
-
- for (ntype = ntreeGetType(ntree->type)->node_types.first; ntype; ntype = ntype->next) {
- if (ntype->nclass == nodeclass && ntype->name) {
- if (!compatibility || (ntype->compatibility & compatibility)) {
- uiItemV(layout, IFACE_(ntype->name), 0, ntype->type);
- }
- }
- }
- }
-}
-
-static void node_menu_add_foreach_cb(void *calldata, int nclass, const char *name)
-{
- uiLayout *layout = calldata;
- uiItemMenuF(layout, IFACE_(name), 0, node_add_menu, SET_INT_IN_POINTER(nclass));
-}
-
static void node_menu_add(const bContext *C, Menu *menu)
{
- Scene *scene = CTX_data_scene(C);
SpaceNode *snode = CTX_wm_space_node(C);
uiLayout *layout = menu->layout;
- bNodeTreeType *ntreetype = ntreeGetType(snode->treetype);
+ bNodeTree *ntree = snode->edittree;
- if (!snode->nodetree)
+ if (!ntree || !ntree->typeinfo || !ntree->typeinfo->draw_add_menu) {
uiLayoutSetActive(layout, FALSE);
-
+ return;
+ }
+
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Search ..."), 0, "NODE_OT_add_search");
- if (ntreetype && ntreetype->foreach_nodeclass)
- ntreetype->foreach_nodeclass(scene, layout, node_menu_add_foreach_cb);
+ ntree->typeinfo->draw_add_menu(C, layout, ntree);
}
void node_menus_register(void)
diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h
index cbf7101a101..a24da7143f9 100644
--- a/source/blender/editors/space_node/node_intern.h
+++ b/source/blender/editors/space_node/node_intern.h
@@ -32,6 +32,7 @@
#define __NODE_INTERN_H__
#include <stddef.h> /* for size_t */
+#include "BKE_node.h"
#include "UI_interface.h"
/* internal exports only */
@@ -43,7 +44,6 @@ struct bContext;
struct wmWindow;
struct wmWindowManager;
struct wmEvent;
-struct bNodeTemplate;
struct bNode;
struct bNodeSocket;
struct bNodeLink;
@@ -66,21 +66,26 @@ typedef struct bNodeLinkDrag {
ARegion *node_has_buttons_region(ScrArea *sa);
ARegion *node_has_tools_region(ScrArea *sa);
+void snode_group_offset(struct SpaceNode *snode, float *x, float *y); /* transform between View2Ds in the tree path */
+
/* node_header.c */
void node_menus_register(void);
/* node_draw.c */
int node_get_colorid(struct bNode *node);
-void node_socket_circle_draw(struct bNodeTree *ntree, struct bNodeSocket *sock, float size, int highlight);
+void node_socket_circle_draw(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node,
+ struct bNodeSocket *sock, float size, int highlight);
int node_get_resize_cursor(int directions);
void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha);
-void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
+void node_draw_default(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key);
void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node);
int node_select_area_default(struct bNode *node, int x, int y);
int node_tweak_area_default(struct bNode *node, int x, int y);
-void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree, float offsetx, float offsety);
-void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree);
-void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d);
+void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree);
+void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode,
+ struct bNodeTree *ntree, bNodeInstanceKey parent_key);
+void drawnodespace(const bContext *C, ARegion *ar);
void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode);
/* DPI scaled coords */
@@ -100,8 +105,6 @@ void node_operatortypes(void);
void node_keymap(struct wmKeyConfig *keyconf);
/* node_select.c */
-void node_select(struct bNode *node);
-void node_deselect(struct bNode *node);
void node_deselect_all(struct SpaceNode *snode);
void node_socket_select(struct bNode *node, struct bNodeSocket *sock);
void node_socket_deselect(struct bNode *node, struct bNodeSocket *sock, int deselect_node);
@@ -138,13 +141,15 @@ void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *ar, struc
/* node_add.c */
-bNode *node_add_node(struct SpaceNode *snode, struct Main *bmain, struct Scene *scene,
- struct bNodeTemplate *ntemp, float locx, float locy);
+bNode *node_add_node(const struct bContext *C, const char *idname, int type, float locx, float locy);
void NODE_OT_add_reroute(struct wmOperatorType *ot);
+void NODE_OT_add_file(struct wmOperatorType *ot);
+void NODE_OT_new_node_tree(struct wmOperatorType *ot);
/* node_group.c */
void NODE_OT_group_make(struct wmOperatorType *ot);
+void NODE_OT_group_insert(struct wmOperatorType *ot);
void NODE_OT_group_ungroup(struct wmOperatorType *ot);
void NODE_OT_group_separate(struct wmOperatorType *ot);
void NODE_OT_group_edit(struct wmOperatorType *ot);
@@ -154,11 +159,6 @@ void NODE_OT_group_socket_move_up(struct wmOperatorType *ot);
void NODE_OT_group_socket_move_down(struct wmOperatorType *ot);
-/* note_add.c */
-void NODE_OT_add_file(struct wmOperatorType *ot);
-void NODE_OT_new_node_tree(struct wmOperatorType *ot);
-
-
/* node_relationships.c */
void NODE_OT_link(struct wmOperatorType *ot);
void NODE_OT_link_make(struct wmOperatorType *ot);
@@ -175,11 +175,9 @@ void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot);
void NODE_OT_link_viewer(struct wmOperatorType *ot);
/* node_edit.c */
-void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *treetype);
void snode_notify(struct bContext *C, struct SpaceNode *snode);
void snode_dag_update(struct bContext *C, struct SpaceNode *snode);
-void snode_set_context(struct SpaceNode *snode, Scene *scene);
-void snode_make_group_editable(struct SpaceNode *snode, struct bNode *gnode);
+void snode_set_context(const struct bContext *C);
bNode *node_tree_get_editgroup(bNodeTree *ntree);
void snode_update(struct SpaceNode *snode, struct bNode *node);
@@ -215,6 +213,10 @@ void NODE_OT_output_file_move_active_socket(struct wmOperatorType *ot);
void NODE_OT_clipboard_copy(struct wmOperatorType *ot);
void NODE_OT_clipboard_paste(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_add(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_remove(struct wmOperatorType *ot);
+void NODE_OT_tree_socket_move(struct wmOperatorType *ot);
+
void NODE_OT_shader_script_update(struct wmOperatorType *ot);
void NODE_OT_viewer_border(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c
index d16c6627d3f..1e4e02b6ae1 100644
--- a/source/blender/editors/space_node/node_ops.c
+++ b/source/blender/editors/space_node/node_ops.c
@@ -84,13 +84,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_add_reroute);
WM_operatortype_append(NODE_OT_group_make);
+ WM_operatortype_append(NODE_OT_group_insert);
WM_operatortype_append(NODE_OT_group_ungroup);
WM_operatortype_append(NODE_OT_group_separate);
WM_operatortype_append(NODE_OT_group_edit);
- WM_operatortype_append(NODE_OT_group_socket_add);
- WM_operatortype_append(NODE_OT_group_socket_remove);
- WM_operatortype_append(NODE_OT_group_socket_move_up);
- WM_operatortype_append(NODE_OT_group_socket_move_down);
WM_operatortype_append(NODE_OT_link_viewer);
@@ -122,6 +119,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_shader_script_update);
WM_operatortype_append(NODE_OT_viewer_border);
+
+ WM_operatortype_append(NODE_OT_tree_socket_add);
+ WM_operatortype_append(NODE_OT_tree_socket_remove);
+ WM_operatortype_append(NODE_OT_tree_socket_move);
}
void ED_operatormacros_node(void)
@@ -198,6 +199,29 @@ static void node_select_keymap(wmKeyMap *keymap, int extend)
}
}
+/* register group operators for a specific group node type */
+static void node_group_operators(wmKeyMap *keymap, const char *node_type)
+{
+ wmKeyMapItem *kmi;
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+ RNA_boolean_set(kmi->ptr, "exit", FALSE);
+
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_string_set(kmi->ptr, "node_type", node_type);
+ RNA_boolean_set(kmi->ptr, "exit", TRUE);
+}
+
void node_keymap(struct wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
@@ -230,9 +254,18 @@ void node_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "deselect", TRUE);
/* each of these falls through if not handled... */
- WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "detach", FALSE);
+ RNA_boolean_set(kmi->ptr, "expose", FALSE);
kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
RNA_boolean_set(kmi->ptr, "detach", TRUE);
+ RNA_boolean_set(kmi->ptr, "expose", FALSE);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "detach", FALSE);
+ RNA_boolean_set(kmi->ptr, "expose", TRUE);
+ kmi = WM_keymap_add_item(keymap, "NODE_OT_link", LEFTMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0);
+ RNA_boolean_set(kmi->ptr, "detach", TRUE);
+ RNA_boolean_set(kmi->ptr, "expose", TRUE);
WM_keymap_add_item(keymap, "NODE_OT_resize", LEFTMOUSE, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "NODE_OT_add_reroute", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
@@ -288,11 +321,10 @@ void node_keymap(struct wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_next", RIGHTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_select_same_type_prev", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_make", GKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_ungroup", GKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_separate", PKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NODE_OT_group_edit", TABKEY, KM_PRESS, 0, 0);
-
+ node_group_operators(keymap, "ShaderNodeGroup");
+ node_group_operators(keymap, "CompositorNodeGroup");
+ node_group_operators(keymap, "TextureNodeGroup");
+
WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 097e4f418e0..8ff964aa932 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -54,6 +54,7 @@
#include "UI_view2d.h"
#include "node_intern.h" /* own include */
+#include "NOD_common.h"
/* ****************** Add *********************** */
@@ -107,7 +108,7 @@ static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocke
/* check for same types */
if (sock->type == sock_target->type) {
- if (strcmp(sock->name, sock_target->name) == 0)
+ if (STREQ(sock->name, sock_target->name))
return sock;
}
}
@@ -323,13 +324,8 @@ static int node_link_viewer(const bContext *C, bNode *tonode)
if (sock) {
/* add a new viewer if none exists yet */
if (!node) {
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bNodeTemplate ntemp;
-
- ntemp.type = CMP_NODE_VIEWER;
/* XXX location is a quick hack, just place it next to the linked socket */
- node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy);
+ node = node_add_node(C, NULL, CMP_NODE_VIEWER, sock->locx + 100, sock->locy);
if (!node)
return OPERATOR_CANCELLED;
@@ -364,7 +360,7 @@ static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op))
SpaceNode *snode = CTX_wm_space_node(C);
bNode *node;
- node = editnode_get_active(snode->edittree);
+ node = nodeGetActive(snode->edittree);
if (!node)
return OPERATOR_CANCELLED;
@@ -434,18 +430,6 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
}
}
-static int outside_group_rect(SpaceNode *snode)
-{
- bNode *gnode = node_tree_get_editgroup(snode->nodetree);
- if (gnode) {
- return (snode->cursor[0] < gnode->totr.xmin ||
- snode->cursor[0] >= gnode->totr.xmax ||
- snode->cursor[1] < gnode->totr.ymin ||
- snode->cursor[1] >= gnode->totr.ymax);
- }
- return 0;
-}
-
/* loop that adds a nodelink, called by function below */
/* in_out = starting socket */
static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
@@ -459,55 +443,41 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
bNodeLink *link;
LinkData *linkdata;
int in_out;
+ int expose;
in_out = nldrag->in_out;
-
+
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
&snode->cursor[0], &snode->cursor[1]);
+ expose = RNA_boolean_get(op->ptr, "expose");
+
switch (event->type) {
case MOUSEMOVE:
-
+
if (in_out == SOCK_OUT) {
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
/* skip if this is already the target socket */
if (link->tosock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->fromnode == tnode)
continue;
-
+
/* attach links to the socket */
link->tonode = tnode;
link->tosock = tsock;
- /* add it to the node tree temporarily */
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
- ntree->update |= NTREE_UPDATE_LINKS;
}
- ntreeUpdateTree(ntree);
}
else {
- int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
- if (link->tonode || link->tosock) {
- BLI_remlink(&ntree->links, link);
- link->prev = link->next = NULL;
- link->tonode = NULL;
- link->tosock = NULL;
-
- ntree->update |= NTREE_UPDATE_LINKS;
- do_update = TRUE;
- }
- }
- if (do_update) {
- ntreeUpdateTree(ntree);
+
+ link->tonode = NULL;
+ link->tosock = NULL;
}
}
}
@@ -515,108 +485,126 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
/* skip if this is already the target socket */
if (link->fromsock == tsock)
continue;
/* skip if socket is on the same node as the fromsock */
if (tnode && link->tonode == tnode)
continue;
-
+
/* attach links to the socket */
link->fromnode = tnode;
link->fromsock = tsock;
- /* add it to the node tree temporarily */
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
- ntree->update |= NTREE_UPDATE_LINKS;
}
- ntreeUpdateTree(ntree);
}
else {
- int do_update = FALSE;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
- if (link->fromnode || link->fromsock) {
- BLI_remlink(&ntree->links, link);
- link->prev = link->next = NULL;
- link->fromnode = NULL;
- link->fromsock = NULL;
-
- ntree->update |= NTREE_UPDATE_LINKS;
- do_update = TRUE;
- }
- }
- if (do_update) {
- ntreeUpdateTree(ntree);
+
+ link->fromnode = NULL;
+ link->fromsock = NULL;
}
}
}
-
+
ED_region_tag_redraw(ar);
break;
-
+
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
{
+ /* XXX expose + detach could have some ugly corner cases and is not great.
+ * The first link will define the exposed socket type, which is arbitrary.
+ * Some of the resulting links may turn out to be invalid.
+ */
+ bNode *ionode = NULL;
+ bNodeSocket *iosock = NULL, *gsock;
for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
link = linkdata->data;
-
+
if (link->tosock && link->fromsock) {
- /* send changed events for original tonode and new */
- if (link->tonode)
- snode_update(snode, link->tonode);
-
+ /* add link to the node tree */
+ BLI_addtail(&ntree->links, link);
+
+ ntree->update |= NTREE_UPDATE_LINKS;
+
+ /* tag tonode for update */
+ link->tonode->update |= NODE_UPDATE;
+
/* we might need to remove a link */
if (in_out == SOCK_OUT)
node_remove_extra_links(snode, link->tosock, link);
-
- /* when linking to group outputs, update the socket type */
- /* XXX this should all be part of a generic update system */
- if (!link->tonode) {
- if (link->tosock->type != link->fromsock->type)
- nodeSocketSetType(link->tosock, link->fromsock->type);
- }
}
- else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
- /* automatically add new group socket */
- if (link->tonode && link->tosock) {
- link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN);
- link->fromnode = NULL;
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
+ else if (expose) {
+ if (link->tosock) {
+ if (!ionode) {
+ ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_INPUT);
+ gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->tonode, link->tosock);
+ node_group_input_verify(snode->edittree, ionode, (ID *)snode->edittree);
+ iosock = node_group_input_find_socket(ionode, gsock->identifier);
+
+ {
+ /* place the node at the mouse pointer */
+ float sockx = 42.0f + 3 * HIDDEN_RAD; /* XXX totally arbitrary initial hidden node size ... */
+ float socky = -HIDDEN_RAD;
+
+ ionode->locx = snode->cursor[0] - sockx;
+ ionode->locy = snode->cursor[1] - socky;
+ }
+ }
+ link->fromnode = ionode;
+ link->fromsock = iosock;
+
+ BLI_addtail(&ntree->links, link);
+
ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS;
}
- else if (link->fromnode && link->fromsock) {
- link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT);
- link->tonode = NULL;
- if (BLI_findindex(&ntree->links, link) < 0)
- BLI_addtail(&ntree->links, link);
-
+ else if (link->fromsock) {
+ if (!ionode) {
+ ionode = nodeAddStaticNode(C, snode->edittree, NODE_GROUP_OUTPUT);
+ gsock = ntreeAddSocketInterfaceFromSocket(snode->edittree, link->fromnode, link->fromsock);
+ node_group_output_verify(snode->edittree, ionode, (ID *)snode->edittree);
+ iosock = node_group_output_find_socket(ionode, gsock->identifier);
+
+ {
+ /* place the node at the mouse pointer */
+ float sockx = 0;
+ float socky = -HIDDEN_RAD;
+
+ ionode->locx = snode->cursor[0] - sockx;
+ ionode->locy = snode->cursor[1] - socky;
+ }
+ }
+ link->tonode = ionode;
+ link->tosock = iosock;
+
+ BLI_addtail(&ntree->links, link);
+
ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS;
}
+ else {
+ nodeRemLink(snode->edittree, link);
+ }
}
else
nodeRemLink(ntree, link);
}
-
+
ntreeUpdateTree(ntree);
snode_notify(C, snode);
snode_dag_update(C, snode);
-
+
BLI_remlink(&snode->linkdrag, nldrag);
/* links->data pointers are either held by the tree or freed already */
BLI_freelistN(&nldrag->links);
MEM_freeN(nldrag);
-
+
return OPERATOR_FINISHED;
}
}
-
+
return OPERATOR_RUNNING_MODAL;
}
@@ -646,6 +634,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
}
@@ -659,6 +649,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->fromnode = node;
oplink->fromsock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -678,9 +670,11 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
*oplink = *link;
oplink->next = oplink->prev = NULL;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
nodeRemLink(snode->edittree, link);
-
+
/* send changed event to original link->tonode */
if (node)
snode_update(snode, node);
@@ -695,6 +689,8 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
oplink->tonode = node;
oplink->tosock = sock;
+ oplink->flag |= NODE_LINK_VALID;
+
BLI_addtail(&nldrag->links, linkdata);
}
}
@@ -760,6 +756,7 @@ void NODE_OT_link(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
RNA_def_boolean(ot->srna, "detach", FALSE, "Detach", "Detach and redirect existing links");
+ RNA_def_boolean(ot->srna, "expose", FALSE, "Expose", "Expose the socket as an interface node");
}
/* ********************** Make Link operator ***************** */
@@ -845,6 +842,8 @@ static int cut_links_exec(bContext *C, wmOperator *op)
for (link = snode->edittree->links.first; link; link = next) {
next = link->next;
+ if (nodeLinkIsHidden(link))
+ continue;
if (cut_links_intersect(link, mcoords, i)) {
@@ -1075,11 +1074,8 @@ static void node_join_attach_recursive(bNode *node, bNode *frame)
static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceNode *snode = CTX_wm_space_node(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
bNodeTree *ntree = snode->edittree;
bNode *node, *frame;
- bNodeTemplate ntemp;
/* XXX save selection: node_add_node call below sets the new frame as single active+selected node */
for (node = ntree->nodes.first; node; node = node->next) {
@@ -1089,10 +1085,7 @@ static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
}
- ntemp.main = bmain;
- ntemp.scene = scene;
- ntemp.type = NODE_FRAME;
- frame = node_add_node(snode, bmain, scene, &ntemp, 0.0f, 0.0f);
+ frame = node_add_node(C, NULL, NODE_FRAME, 0.0f, 0.0f);
/* reset tags */
for (node = ntree->nodes.first; node; node = node->next)
@@ -1310,6 +1303,9 @@ static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select)
/* test node for links */
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
+
if (link->tonode == *select || link->fromnode == *select)
return NULL;
}
@@ -1350,7 +1346,9 @@ void ED_node_link_intersect_test(ScrArea *sa, int test)
/* we only tag a single link for intersect now */
/* idea; use header dist when more? */
for (link = snode->edittree->links.first; link; link = link->next) {
-
+ if (nodeLinkIsHidden(link))
+ continue;
+
if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */
if (selink)
break;
@@ -1415,11 +1413,12 @@ void ED_node_link_insert(ScrArea *sa)
link->tonode = select;
link->tosock = socket_best_match(&select->inputs);
+ node_remove_extra_links(snode, link->tosock, link);
link->flag &= ~NODE_LINKFLAG_HILITE;
nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto);
ntreeUpdateTree(snode->edittree); /* needed for pointers */
snode_update(snode, select);
- ED_node_changed_update(snode->id, select);
+ ED_node_tag_update_id(snode->id);
}
}
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index c917b8ee756..faebeabdbba 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -82,30 +82,9 @@ static bNode *node_under_mouse_tweak(bNodeTree *ntree, int mx, int my)
return NULL;
}
-void node_select(bNode *node)
-{
- node->flag |= SELECT;
-}
-
-void node_deselect(bNode *node)
-{
- bNodeSocket *sock;
-
- node->flag &= ~SELECT;
-
- /* deselect sockets too */
- for (sock = node->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
- for (sock = node->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
-}
-
static void node_toggle(bNode *node)
{
- if (node->flag & SELECT)
- node_deselect(node);
- else
- node_select(node);
+ nodeSetSelected(node, !(node->flag & SELECT));
}
void node_socket_select(bNode *node, bNodeSocket *sock)
@@ -157,7 +136,7 @@ void node_deselect_all(SpaceNode *snode)
bNode *node;
for (node = snode->edittree->nodes.first; node; node = node->next)
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
}
void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
@@ -189,9 +168,6 @@ void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
-
- for (sock = snode->edittree->outputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
}
void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
@@ -223,9 +199,6 @@ void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
node->flag &= ~SELECT;
}
}
-
- for (sock = snode->edittree->inputs.first; sock; sock = sock->next)
- sock->flag &= ~SELECT;
}
/* return 1 if we need redraw otherwise zero. */
@@ -249,12 +222,12 @@ int node_select_same_type(SpaceNode *snode)
if (p->type != nac->type && p->flag & SELECT) {
/* if it's selected but different type, unselect */
redraw = 1;
- node_deselect(p);
+ nodeSetSelected(p, FALSE);
}
else if (p->type == nac->type && (!(p->flag & SELECT))) {
/* if it's the same type and is not selected, select! */
redraw = 1;
- node_select(p);
+ nodeSetSelected(p, TRUE);
}
}
return(redraw);
@@ -296,8 +269,8 @@ int node_select_same_type_np(SpaceNode *snode, int dir)
if (p) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != p)
- node_deselect(tnode);
- node_select(p);
+ nodeSetSelected(tnode, FALSE);
+ nodeSetSelected(p, TRUE);
return(1);
}
return(0);
@@ -311,8 +284,8 @@ void node_select_single(bContext *C, bNode *node)
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
if (tnode != node)
- node_deselect(tnode);
- node_select(node);
+ nodeSetSelected(tnode, FALSE);
+ nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
@@ -386,9 +359,10 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i
node = node_under_mouse_select(snode->edittree, mx, my);
if (node) {
- for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next)
- node_deselect(tnode);
- node_select(node);
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ nodeSetSelected(tnode, false);
+ }
+ nodeSetSelected(node, TRUE);
ED_node_set_active(bmain, snode->edittree, node);
selected = 1;
}
@@ -477,13 +451,10 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (BLI_rctf_isect(&rectf, &node->totr, NULL)) {
- if (gesture_mode == GESTURE_MODAL_SELECT)
- node_select(node);
- else
- node_deselect(node);
+ nodeSetSelected(node, (gesture_mode == GESTURE_MODAL_SELECT));
}
else if (!extend) {
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
}
}
@@ -566,11 +537,7 @@ static int do_lasso_select_node(bContext *C, const int mcords[][2], short moves,
if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) &&
BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX))
{
- if (select)
- node_select(node);
- else
- node_deselect(node);
-
+ nodeSetSelected(node, select);
change = TRUE;
}
}
@@ -642,13 +609,13 @@ static int node_select_all_exec(bContext *C, wmOperator *op)
for (node = node_lb->first; node; node = node->next) {
switch (action) {
case SEL_SELECT:
- node_select(node);
+ nodeSetSelected(node, TRUE);
break;
case SEL_DESELECT:
- node_deselect(node);
+ nodeSetSelected(node, FALSE);
break;
case SEL_INVERT:
- ((node->flag & SELECT) ? node_deselect : node_select)(node);
+ nodeSetSelected(node, !(node->flag & SELECT));
break;
}
}
@@ -688,13 +655,15 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT))
link->tonode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
- node_select(node);
+ nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
@@ -730,13 +699,15 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link = snode->edittree->links.first; link; link = link->next) {
+ if (nodeLinkIsHidden(link))
+ continue;
if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT))
link->fromnode->flag |= NODE_TEST;
}
for (node = snode->edittree->nodes.first; node; node = node->next) {
if (node->flag & NODE_TEST)
- node_select(node);
+ nodeSetSelected(node, TRUE);
}
ED_node_sort(snode->edittree);
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index ca85415cb5a..0bc2fba0d0b 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -130,7 +130,7 @@ static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
/* remove all nodes connected to this socket, if they aren't connected to other nodes */
@@ -145,11 +145,11 @@ static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bN
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(bmain, ntree);
}
/* add new node connected to this socket, or replace an existing one */
-static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num)
+static void node_socket_add_replace(const bContext *C, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, int type, bNodeTree *ngroup, int sock_num)
{
bNode *node_from;
bNodeSocket *sock_from_tmp;
@@ -163,24 +163,30 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
/* find existing node that we can use */
for (node_from = ntree->nodes.first; node_from; node_from = node_from->next)
- if (node_from->type == ntemp->type)
+ if (node_from->type == type)
break;
if (node_from)
if (!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
node_from = NULL;
- if (node_prev && node_prev->type == ntemp->type &&
- (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id))
+ /* XXX how can this be done nicely? bNodeTemplate is removed, it doesn't work for generic custom nodes */
+ if (node_prev && node_prev->type == type &&
+ (type != NODE_GROUP || node_prev->id == &ngroup->id))
{
/* keep the previous node if it's the same type */
node_from = node_prev;
}
else if (!node_from) {
- node_from = nodeAddNode(ntree, ntemp);
+ node_from = nodeAddStaticNode(C, ntree, type);
node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
node_from->locy = node_to->locy;
-
+
+ /* XXX bad, should be dispatched to generic operator or something ... */
+ if (type == NODE_GROUP) {
+ node_from->id = (ID *)ngroup;
+ }
+
if (node_from->id)
id_us_plus(node_from->id);
}
@@ -201,7 +207,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
if (nodeCountSocketLinks(ntree, sock_from) >= sock_from->limit)
continue;
- if (strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
+ if (STREQ(sock_prev->name, sock_from->name) && sock_prev->type == sock_from->type) {
bNodeLink *link = sock_prev->link;
if (link && link->fromnode) {
@@ -209,9 +215,11 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeRemLink(ntree, link);
}
- node_socket_free_default_value(sock_from->type, sock_from->default_value);
- sock_from->default_value = node_socket_make_default_value(sock_from->type);
- node_socket_copy_default_value(sock_from->type, sock_from->default_value, sock_prev->default_value);
+#if 0 /* XXX TODO */
+ node_socket_free_default_value(sock_from->typeinfo, sock_from->default_value);
+ sock_from->default_value = node_socket_make_default_value(sock_from->typeinfo);
+ node_socket_copy_default_value(sock_from->typeinfo, sock_from->default_value, sock_prev->default_value);
+#endif
}
}
}
@@ -231,7 +239,7 @@ static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_t
nodeUpdate(ntree, node_to);
ntreeUpdateTree(ntree);
- ED_node_generic_update(bmain, ntree, node_to);
+ ED_node_tag_update_nodetree(CTX_data_main(C), ntree);
}
/****************************** Node Link Menu *******************************/
@@ -262,19 +270,13 @@ static void ui_node_link(bContext *C, void *arg_p, void *event_p)
bNodeSocket *sock_to = arg->sock;
bNodeTree *ntree = arg->ntree;
int event = GET_INT_FROM_POINTER(event_p);
- bNodeTemplate ntemp;
-
- ntemp.type = arg->type;
- ntemp.ngroup = arg->ngroup;
- ntemp.scene = CTX_data_scene(C);
- ntemp.main = CTX_data_main(C);
if (event == UI_NODE_LINK_DISCONNECT)
node_socket_disconnect(bmain, ntree, node_to, sock_to);
else if (event == UI_NODE_LINK_REMOVE)
node_socket_remove(bmain, ntree, node_to, sock_to);
else
- node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output);
+ node_socket_add_replace(C, ntree, node_to, sock_to, arg->type, arg->ngroup, arg->output);
ED_undo_push(C, "Node input modify");
}
@@ -289,10 +291,10 @@ static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
if (node->id)
BLI_strncpy(node_name, node->id->name + 2, UI_MAX_NAME_STR);
else
- BLI_strncpy(node_name, N_("Group"), UI_MAX_NAME_STR);
+ BLI_strncpy(node_name, N_(node->typeinfo->ui_name), UI_MAX_NAME_STR);
}
else
- BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
+ BLI_strncpy(node_name, node->typeinfo->ui_name, UI_MAX_NAME_STR);
if (node->inputs.first == NULL &&
node->outputs.first != node->outputs.last)
@@ -316,19 +318,16 @@ static int ui_compatible_sockets(int typeA, int typeB)
static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
{
- Main *bmain = arg->bmain;
bNodeTree *ntree = arg->ntree;
bNodeSocket *sock = arg->sock;
uiLayout *layout = arg->layout;
uiLayout *column = NULL;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but;
- bNodeType *ntype;
- bNodeTree *ngroup;
NodeLinkArg *argN;
int first = 1;
int compatibility = 0;
-
+
if (ntree->type == NTREE_SHADER) {
if (BKE_scene_use_new_shading_nodes(arg->scene))
compatibility = NODE_NEW_SHADING;
@@ -336,114 +335,58 @@ static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
compatibility = NODE_OLD_SHADING;
}
- if (nclass == NODE_CLASS_GROUP) {
- for (ngroup = bmain->nodetree.first; ngroup; ngroup = ngroup->id.next) {
- bNodeSocket *gsock;
- char name[UI_MAX_NAME_STR];
- int i, j, num = 0;
-
- if (ngroup->type != ntree->type)
+ NODE_TYPES_BEGIN(ntype)
+ bNodeSocketTemplate *stemp;
+ char name[UI_MAX_NAME_STR];
+ int i, j, num = 0;
+
+ if (compatibility && !(ntype->compatibility & compatibility))
+ continue;
+
+ if (ntype->nclass != nclass)
+ continue;
+
+ for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
+ if (ui_compatible_sockets(stemp->type, sock->type))
+ num++;
+
+ for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
+ if (!ui_compatible_sockets(stemp->type, sock->type))
continue;
-
- for (gsock = ngroup->inputs.first; gsock; gsock = gsock->next)
- if (ui_compatible_sockets(gsock->type, sock->type))
- num++;
-
- for (i = 0, j = 0, gsock = ngroup->outputs.first; gsock; gsock = gsock->next, i++) {
- if (!ui_compatible_sockets(gsock->type, sock->type))
- continue;
-
- if (first) {
- column = uiLayoutColumn(layout, FALSE);
- uiBlockSetCurLayout(block, column);
-
- uiItemL(column, IFACE_(cname), ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
-
- first = 0;
- }
-
- if (num > 1) {
- if (j == 0) {
- uiItemL(column, ngroup->id.name + 2, ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
- }
-
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", gsock->name);
- j++;
- }
- else
- BLI_strncpy(name, ngroup->id.name + 2, UI_MAX_NAME_STR);
-
- but = uiDefBut(block, BUT, 0, ngroup->id.name + 2, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
-
- argN = MEM_dupallocN(arg);
- argN->type = NODE_GROUP;
- argN->ngroup = ngroup;
- argN->output = i;
- uiButSetNFunc(but, ui_node_link, argN, NULL);
+
+ if (first) {
+ column = uiLayoutColumn(layout, 0);
+ uiBlockSetCurLayout(block, column);
+
+ uiItemL(column, IFACE_(cname), ICON_NODE);
+ but = block->buttons.last;
+ but->flag = UI_TEXT_LEFT;
+
+ first = 0;
}
- }
- }
- else {
- bNodeTreeType *ttype = ntreeGetType(ntree->type);
-
- for (ntype = ttype->node_types.first; ntype; ntype = ntype->next) {
- bNodeSocketTemplate *stemp;
- char name[UI_MAX_NAME_STR];
- int i, j, num = 0;
-
- if (compatibility && !(ntype->compatibility & compatibility))
- continue;
-
- if (ntype->nclass != nclass)
- continue;
-
- for (i = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
- if (ui_compatible_sockets(stemp->type, sock->type))
- num++;
-
- for (i = 0, j = 0, stemp = ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
- if (!ui_compatible_sockets(stemp->type, sock->type))
- continue;
-
- if (first) {
- column = uiLayoutColumn(layout, FALSE);
- uiBlockSetCurLayout(block, column);
-
- uiItemL(column, IFACE_(cname), ICON_NODE);
+
+ if (num > 1) {
+ if (j == 0) {
+ uiItemL(column, IFACE_(ntype->ui_name), ICON_NODE);
but = block->buttons.last;
but->flag = UI_TEXT_LEFT;
-
- first = 0;
- }
-
- if (num > 1) {
- if (j == 0) {
- uiItemL(column, IFACE_(ntype->name), ICON_NODE);
- but = block->buttons.last;
- but->flag = UI_TEXT_LEFT;
- }
-
- BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
- j++;
}
- else
- BLI_strncpy(name, IFACE_(ntype->name), UI_MAX_NAME_STR);
-
- but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
- NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
-
- argN = MEM_dupallocN(arg);
- argN->type = ntype->type;
- argN->output = i;
- uiButSetNFunc(but, ui_node_link, argN, NULL);
+
+ BLI_snprintf(name, UI_MAX_NAME_STR, " %s", IFACE_(stemp->name));
+ j++;
}
+ else
+ BLI_strncpy(name, IFACE_(ntype->ui_name), UI_MAX_NAME_STR);
+
+ but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X * 4, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Add node to input"));
+
+ argN = MEM_dupallocN(arg);
+ argN->type = ntype->type;
+ argN->output = i;
+ uiButSetNFunc(but, ui_node_link, argN, NULL);
}
- }
+ NODE_TYPES_END
}
static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
@@ -463,7 +406,7 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_
uiLayout *split, *column;
NodeLinkArg *arg = (NodeLinkArg *)but->func_argN;
bNodeSocket *sock = arg->sock;
- bNodeTreeType *ntreetype = ntreeGetType(arg->ntree->type);
+ bNodeTreeType *ntreetype = arg->ntree->typeinfo;
uiBlockSetCurLayout(block, layout);
split = uiLayoutSplit(layout, 0.0f, FALSE);
@@ -557,7 +500,7 @@ static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, b
static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
{
- PointerRNA inputptr;
+ PointerRNA inputptr, nodeptr;
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *bt;
uiLayout *split, *row, *col;
@@ -579,6 +522,7 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
/* socket RNA pointer */
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
+ RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
/* indented label */
memset(label, ' ', indent);
@@ -627,16 +571,25 @@ static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree,
}
else {
/* input not linked, show value */
- if (input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) {
- if (input->type == SOCK_VECTOR) {
+ if (!(input->flag & SOCK_HIDE_VALUE)) {
+ switch (input->type) {
+ case SOCK_FLOAT:
+ case SOCK_INT:
+ case SOCK_BOOLEAN:
+ case SOCK_RGBA:
+ case SOCK_STRING:
+ row = uiLayoutRow(split, TRUE);
+ uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+ break;
+ case SOCK_VECTOR:
row = uiLayoutRow(split, FALSE);
col = uiLayoutColumn(row, FALSE);
-
uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE);
- }
- else {
- row = uiLayoutRow(split, TRUE);
- uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE);
+ break;
+
+ default:
+ row = uiLayoutRow(split, FALSE);
+ break;
}
}
else
@@ -653,7 +606,7 @@ void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *
{
bNode *tnode;
- if (!ntree)
+ if (!ntreeIsValid(ntree))
return;
/* clear for cycle check */
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index a2fa7d3caf6..293913dff11 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -61,6 +61,7 @@
#include "IMB_imbuf_types.h"
#include "node_intern.h" /* own include */
+#include "NOD_composite.h"
/* **************** View All Operator ************** */
@@ -370,7 +371,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float
float fx, fy, bufx, bufy;
int ret = FALSE;
- if (snode->treetype != NTREE_COMPOSIT || (snode->flag & SNODE_BACKDRAW) == 0) {
+ if (STREQ(snode->tree_idname, ntreeType_Composite->idname) || (snode->flag & SNODE_BACKDRAW) == 0) {
/* use viewer image for color sampling only if we're in compositor tree
* with backdrop enabled
*/
@@ -524,7 +525,7 @@ static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ARegion *ar = CTX_wm_region(C);
ImageSampleInfo *info;
- if (snode->treetype != NTREE_COMPOSIT || !(snode->flag & SNODE_BACKDRAW))
+ if (!ED_node_is_compositor(snode) || !(snode->flag & SNODE_BACKDRAW))
return OPERATOR_CANCELLED;
info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo");
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 75f28baf558..2d5207e69db 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -45,10 +45,10 @@
#include "BKE_node.h"
#include "ED_space_api.h"
+#include "ED_node.h"
#include "ED_render.h"
#include "ED_screen.h"
#include "ED_node.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -59,6 +59,168 @@
#include "node_intern.h" /* own include */
+
+/* ******************** tree path ********************* */
+
+void ED_node_tree_start(SpaceNode *snode, bNodeTree *ntree, ID *id, ID *from)
+{
+ bNodeTreePath *path, *path_next;
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
+ snode->treepath.first = snode->treepath.last = NULL;
+
+ if (ntree) {
+ path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ path->nodetree = ntree;
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+ if (id)
+ BLI_strncpy(path->node_name, id->name + 2, sizeof(path->node_name));
+ BLI_addtail(&snode->treepath, path);
+ }
+
+ /* update current tree */
+ snode->nodetree = snode->edittree = ntree;
+ snode->id = id;
+ snode->from = from;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+}
+
+void ED_node_tree_push(SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
+{
+ bNodeTreePath *path = MEM_callocN(sizeof(bNodeTreePath), "node tree path");
+ bNodeTreePath *prev_path = snode->treepath.last;
+ path->nodetree = ntree;
+ if (gnode) {
+ if (prev_path)
+ path->parent_key = BKE_node_instance_key(prev_path->parent_key, prev_path->nodetree, gnode);
+ else
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+
+ BLI_strncpy(path->node_name, gnode->name, sizeof(path->node_name));
+ }
+ else
+ path->parent_key = NODE_INSTANCE_KEY_BASE;
+
+ BLI_addtail(&snode->treepath, path);
+
+ /* update current tree */
+ snode->edittree = ntree;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+}
+
+void ED_node_tree_pop(SpaceNode *snode)
+{
+ bNodeTreePath *path = snode->treepath.last;
+
+ /* don't remove root */
+ if (path == snode->treepath.first)
+ return;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
+
+ /* update current tree */
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
+
+ /* listener updates the View2D center from edittree */
+ WM_main_add_notifier(NC_SCENE | ND_NODES, NULL);
+}
+
+int ED_node_tree_depth(SpaceNode *snode)
+{
+ return BLI_countlist(&snode->treepath);
+}
+
+bNodeTree *ED_node_tree_get(SpaceNode *snode, int level)
+{
+ bNodeTreePath *path;
+ int i;
+ for (path = snode->treepath.last, i = 0; path; path = path->prev, ++i) {
+ if (i == level)
+ return path->nodetree;
+ }
+ return NULL;
+}
+
+int ED_node_tree_path_length(SpaceNode *snode)
+{
+ bNodeTreePath *path;
+ int length = 0;
+ int i;
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ length += strlen(path->node_name);
+ if (i > 0)
+ length += 1; /* for separator char */
+ }
+ return length;
+}
+
+void ED_node_tree_path_get(SpaceNode *snode, char *value)
+{
+ bNodeTreePath *path;
+ int i;
+
+ value[0] = '\0';
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ if (i == 0) {
+ strcpy(value, path->node_name);
+ value += strlen(path->node_name);
+ }
+ else {
+ sprintf(value, "/%s", path->node_name);
+ value += strlen(path->node_name) + 1;
+ }
+ }
+}
+
+void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_length)
+{
+ bNodeTreePath *path;
+ int size, i;
+
+ value[0] = '\0';
+ for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) {
+ if (i == 0) {
+ BLI_strncpy(value, path->node_name, max_length);
+ size = strlen(path->node_name);
+ }
+ else {
+ BLI_snprintf(value, max_length, "/%s", path->node_name);
+ size = strlen(path->node_name) + 1;
+ }
+ max_length -= size;
+ if (max_length <= 0)
+ break;
+ value += size;
+ }
+}
+
+void snode_group_offset(SpaceNode *snode, float *x, float *y)
+{
+ bNodeTreePath *path = snode->treepath.last;
+ float cx, cy;
+
+ if (path) {
+ cx = path->nodetree->view_center[0];
+ cy = path->nodetree->view_center[1];
+
+ if (path->prev) {
+ *x = cx - path->prev->nodetree->view_center[0];
+ *y = cy - path->prev->nodetree->view_center[1];
+ return;
+ }
+ }
+
+ *x = *y = 0.0f;
+}
+
/* ******************** manage regions ********************* */
ARegion *node_has_buttons_region(ScrArea *sa)
@@ -124,6 +286,12 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
/* backdrop */
snode->zoom = 1.0f;
+ /* select the first tree type for valid type */
+ NODE_TREE_TYPES_BEGIN(treetype)
+ strcpy(snode->tree_idname, treetype->idname);
+ break;
+ NODE_TREE_TYPES_END
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for node");
@@ -167,10 +335,15 @@ static SpaceLink *node_new(const bContext *UNUSED(C))
return (SpaceLink *)snode;
}
-/* not spacelink itself */
-static void node_free(SpaceLink *UNUSED(sl))
+static void node_free(SpaceLink *sl)
{
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
+ for (path = snode->treepath.first; path; path = path_next) {
+ path_next = path->next;
+ MEM_freeN(path);
+ }
}
@@ -184,14 +357,21 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
{
/* note, ED_area_tag_refresh will re-execute compositor */
SpaceNode *snode = sa->spacedata.first;
- int type = snode->treetype;
short shader_type = snode->shaderfrom;
/* preview renders */
switch (wmn->category) {
case NC_SCENE:
switch (wmn->data) {
- case ND_NODES:
+ case ND_NODES: {
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ /* shift view to node tree center */
+ if (ar && snode->edittree)
+ UI_view2d_setcenter(&ar->v2d, snode->edittree->view_center[0], snode->edittree->view_center[1]);
+
+ ED_area_tag_refresh(sa);
+ break;
+ }
case ND_FRAME:
ED_area_tag_refresh(sa);
break;
@@ -199,7 +379,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
ED_area_tag_redraw(sa);
break;
case ND_TRANSFORM_DONE:
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
if (snode->flag & SNODE_AUTO_RENDER) {
snode->recalc = 1;
ED_area_tag_refresh(sa);
@@ -211,7 +391,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
/* future: add ID checks? */
case NC_MATERIAL:
- if (type == NTREE_SHADER) {
+ if (ED_node_is_shader(snode)) {
if (wmn->data == ND_SHADING)
ED_area_tag_refresh(sa);
else if (wmn->data == ND_SHADING_DRAW)
@@ -224,18 +404,18 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
}
break;
case NC_TEXTURE:
- if (type == NTREE_SHADER || type == NTREE_TEXTURE) {
+ if (ED_node_is_shader(snode) || ED_node_is_texture(snode)) {
if (wmn->data == ND_NODES)
ED_area_tag_refresh(sa);
}
break;
case NC_WORLD:
- if (type == NTREE_SHADER && shader_type == SNODE_SHADER_WORLD) {
+ if (ED_node_is_shader(snode) && shader_type == SNODE_SHADER_WORLD) {
ED_area_tag_refresh(sa);
}
break;
case NC_OBJECT:
- if (type == NTREE_SHADER) {
+ if (ED_node_is_shader(snode)) {
if (wmn->data == ND_OB_SHADING)
ED_area_tag_refresh(sa);
}
@@ -261,7 +441,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
break;
case NC_MASK:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (snode->nodetree && snode->nodetree->type == NTREE_COMPOSIT) {
ED_area_tag_refresh(sa);
}
}
@@ -269,7 +449,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_IMAGE:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
/* note that nodeUpdateID is already called by BKE_image_signal() on all
* scenes so really this is just to know if the images is used in the compo else
* painting on images could become very slow when the compositor is open. */
@@ -281,7 +461,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
case NC_MOVIECLIP:
if (wmn->action == NA_EDITED) {
- if (type == NTREE_COMPOSIT) {
+ if (ED_node_is_compositor(snode)) {
if (nodeUpdateID(snode->nodetree, wmn->reference))
ED_area_tag_refresh(sa);
}
@@ -294,11 +474,13 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
{
/* default now: refresh node is starting preview */
SpaceNode *snode = sa->spacedata.first;
+
+ ED_preview_kill_jobs(C);
+
+ snode_set_context(C);
- snode_set_context(snode, CTX_data_scene(C));
-
- if (snode->nodetree) {
- if (snode->treetype == NTREE_SHADER) {
+ if (ntreeIsValid(snode->nodetree)) {
+ if (snode->nodetree->type == NTREE_SHADER) {
if (GS(snode->id->name) == ID_MA) {
Material *ma = (Material *)snode->id;
if (ma->use_nodes)
@@ -315,7 +497,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
}
}
- else if (snode->treetype == NTREE_COMPOSIT) {
+ else if (snode->nodetree->type == NTREE_COMPOSIT) {
Scene *scene = (Scene *)snode->id;
if (scene->use_nodes) {
/* recalc is set on 3d view changes for auto compo */
@@ -328,7 +510,7 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
}
}
}
- else if (snode->treetype == NTREE_TEXTURE) {
+ else if (snode->nodetree->type == NTREE_TEXTURE) {
Tex *tex = (Tex *)snode->id;
if (tex->use_nodes) {
ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER);
@@ -339,11 +521,14 @@ static void node_area_refresh(const struct bContext *C, ScrArea *sa)
static SpaceLink *node_duplicate(SpaceLink *sl)
{
- SpaceNode *snoden = MEM_dupallocN(sl);
+ SpaceNode *snode = (SpaceNode *)sl;
+ SpaceNode *snoden = MEM_dupallocN(snode);
/* clear or remove stuff from old */
snoden->nodetree = NULL;
snoden->linkdrag.first = snoden->linkdrag.last = NULL;
+
+ BLI_duplicatelist(&snoden->treepath, &snode->treepath);
return (SpaceLink *)snoden;
}
@@ -415,9 +600,7 @@ static void node_main_area_init(wmWindowManager *wm, ARegion *ar)
static void node_main_area_draw(const bContext *C, ARegion *ar)
{
- View2D *v2d = &ar->v2d;
-
- drawnodespace(C, ar, v2d);
+ drawnodespace(C, ar);
}
@@ -469,11 +652,8 @@ static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
static void node_header_area_draw(const bContext *C, ARegion *ar)
{
- SpaceNode *snode = CTX_wm_space_node(C);
- Scene *scene = CTX_data_scene(C);
-
/* find and set the context */
- snode_set_context(snode, scene);
+ snode_set_context(C);
ED_region_header(C, ar);
}
@@ -549,6 +729,14 @@ static int node_context(const bContext *C, const char *member, bContextDataResul
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
return 1;
}
+ else if (CTX_data_equals(member, "node_previews")) {
+ if (snode->nodetree) {
+ CTX_data_pointer_set(result, &snode->nodetree->id, &RNA_NodeInstanceHash, snode->nodetree->previews);
+ }
+
+ CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
+ return 1;
+ }
return 0;
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 743b53ce16c..15c3385f67c 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -5992,6 +5992,15 @@ static void draw_bb_quadric(BoundBox *bb, char type)
glScalef(radius, radius, 2.0f * size[2]);
gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
}
+ else if (type == OB_BOUND_CAPSULE) {
+ float radius = size[0] > size[1] ? size[0] : size[1];
+ float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f;
+ glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f);
+ gluCylinder(qobj, radius, radius, length, 8, 1);
+ gluSphere(qobj, radius, 8, 4);
+ glTranslatef(0.0, 0.0, length);
+ gluSphere(qobj, radius, 8, 4);
+ }
glPopMatrix();
gluDeleteQuadric(qobj);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index d18ec225c5f..e27f00de748 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2041,11 +2041,11 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
(dob->type == OB_DUPLIGROUP && dob->animated) ||
!(bb_tmp = BKE_object_boundbox_get(dob->ob)))
{
- // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name+2);
+ // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
use_displist = FALSE;
}
else {
- // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name+2);
+ // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2);
bb = *bb_tmp; /* must make a copy */
/* disable boundbox check for list creation */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 85375bcaf83..6ea37644533 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -159,7 +159,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
if (node && is_image_texture_node(node)) {
node->id = &ima->id;
- ED_node_generic_update(bmain, ma->nodetree, node);
+ ED_node_tag_update_nodetree(bmain, ma->nodetree);
}
}