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:
Diffstat (limited to 'source/blender/editors/space_node/node_edit.c')
-rw-r--r--source/blender/editors/space_node/node_edit.c688
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)