diff options
Diffstat (limited to 'source/blender/editors/space_node/node_edit.c')
-rw-r--r-- | source/blender/editors/space_node/node_edit.c | 688 |
1 files changed, 363 insertions, 325 deletions
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 941bd783c39..2012284f39b 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 (strcmp(snode->tree_idname, ntreeType_Composite->idname)==0); +} + +int ED_node_is_shader(struct SpaceNode *snode) +{ + return (strcmp(snode->tree_idname, ntreeType_Shader->idname)==0); +} + +int ED_node_is_texture(struct SpaceNode *snode) +{ + return (strcmp(snode->tree_idname, ntreeType_Texture->idname)==0); } /* 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); + + RNA_id_pointer_create((ID *)tx->nodetree, &ptr); + RNA_boolean_set(&ptr, "is_local_tree", TRUE); - ntemp.type = TEX_NODE_OUTPUT; - out = nodeAddNode(tx->nodetree, &ntemp); + 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,66 @@ 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; - } - } - 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; - } + /* 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->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 +568,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 +597,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 +627,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 +652,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 +693,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 +805,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 +908,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 +987,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 +1047,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 +1093,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 +1154,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 +1190,8 @@ void NODE_OT_duplicate(wmOperatorType *ot) } int ED_node_select_check(ListBase *lb) + + { bNode *node; @@ -1456,6 +1336,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 +1843,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 +1852,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 +1874,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 +1920,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 +1953,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 +1969,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 +1977,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 +2019,186 @@ 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); + + return OPERATOR_FINISHED; +} + +void NODE_OT_tree_socket_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Add Node Tree Interface Socket"; + 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); + + return OPERATOR_FINISHED; +} + +void NODE_OT_tree_socket_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Remove Node Tree Interface Socket"; + 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); + + return OPERATOR_FINISHED; +} + +void NODE_OT_tree_socket_move(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Move Node Tree Socket"; + 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 +2231,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) |