Cycles: svn merge -r40934:41157 ^/trunk/blender
[blender.git] / source / blender / editors / space_node / node_header.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/editors/space_node/node_header.c
30  *  \ingroup spnode
31  */
32
33
34 #include <string.h>
35 #include <stdio.h>
36
37 #include "DNA_space_types.h"
38 #include "DNA_node_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_screen_types.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_utildefines.h"
46
47 #include "BLF_translation.h"
48
49 #include "BKE_context.h"
50 #include "BKE_global.h"
51 #include "BKE_main.h"
52 #include "BKE_node.h"
53 #include "BKE_scene.h"
54 #include "BKE_screen.h"
55
56 #include "RNA_access.h"
57
58 #include "WM_api.h"
59 #include "WM_types.h"
60
61 #include "UI_interface.h"
62 #include "UI_interface_icons.h"
63 #include "UI_resources.h"
64 #include "UI_view2d.h"
65
66 #include "node_intern.h"
67
68 /* ************************ add menu *********************** */
69
70 static void do_node_add(bContext *C, bNodeTemplate *ntemp)
71 {
72         Main *bmain= CTX_data_main(C);
73         Scene *scene= CTX_data_scene(C);
74         SpaceNode *snode= CTX_wm_space_node(C);
75         ScrArea *sa= CTX_wm_area(C);
76         ARegion *ar;
77         bNode *node;
78         
79         /* get location to add node at mouse */
80         for(ar=sa->regionbase.first; ar; ar=ar->next) {
81                 if(ar->regiontype == RGN_TYPE_WINDOW) {
82                         wmWindow *win= CTX_wm_window(C);
83                         int x= win->eventstate->x - ar->winrct.xmin;
84                         int y= win->eventstate->y - ar->winrct.ymin;
85                         
86                         if(y < 60) y+= 60;
87                         UI_view2d_region_to_view(&ar->v2d, x, y, &snode->mx, &snode->my);
88                 }
89         }
90         
91         /* store selection in temp test flag */
92         for(node= snode->edittree->nodes.first; node; node= node->next) {
93                 if(node->flag & NODE_SELECT) node->flag |= NODE_TEST;
94                 else node->flag &= ~NODE_TEST;
95         }
96         
97         /* node= */ node_add_node(snode, bmain, scene, ntemp, snode->mx, snode->my);
98         
99         /* select previous selection before autoconnect */
100         for(node= snode->edittree->nodes.first; node; node= node->next) {
101                 if(node->flag & NODE_TEST) node->flag |= NODE_SELECT;
102         }
103         
104         /* deselect after autoconnection */
105         for(node= snode->edittree->nodes.first; node; node= node->next) {
106                 if(node->flag & NODE_TEST) node->flag &= ~NODE_SELECT;
107         }
108                 
109         snode_notify(C, snode);
110         snode_dag_update(C, snode);
111 }
112
113 static void do_node_add_static(bContext *C, void *UNUSED(arg), int event)
114 {
115         bNodeTemplate ntemp;
116         ntemp.type = event;
117         do_node_add(C, &ntemp);
118 }
119
120 static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
121 {
122         SpaceNode *snode= CTX_wm_space_node(C);
123         bNodeTemplate ntemp;
124         
125         if (event>=0) {
126                 ntemp.ngroup= BLI_findlink(&G.main->nodetree, event);
127                 ntemp.type = ntemp.ngroup->nodetype;
128         }
129         else {
130                 ntemp.type = -event;
131                 switch (ntemp.type) {
132                 case NODE_GROUP:
133                         ntemp.ngroup = ntreeAddTree("Group", snode->treetype, ntemp.type);
134                         break;
135                 case NODE_FORLOOP:
136                         ntemp.ngroup = ntreeAddTree("For Loop", snode->treetype, ntemp.type);
137                         break;
138                 case NODE_WHILELOOP:
139                         ntemp.ngroup = ntreeAddTree("While Loop", snode->treetype, ntemp.type);
140                         break;
141                 default:
142                         ntemp.ngroup = NULL;
143                 }
144         }
145         if (!ntemp.ngroup)
146                 return;
147         
148         do_node_add(C, &ntemp);
149 }
150
151 #if 0 /* disabled */
152 static void do_node_add_dynamic(bContext *C, void *UNUSED(arg), int event)
153 {
154         bNodeTemplate ntemp;
155         ntemp.type = NODE_DYNAMIC;
156         do_node_add(C, &ntemp);
157 }
158 #endif
159
160 static int node_tree_has_type(int treetype, int nodetype)
161 {
162         bNodeTreeType *ttype= ntreeGetType(treetype);
163         bNodeType *ntype;
164         for (ntype=ttype->node_types.first; ntype; ntype=ntype->next) {
165                 if (ntype->type==nodetype)
166                         return 1;
167         }
168         return 0;
169 }
170
171 static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass)
172 {
173         Main *bmain= CTX_data_main(C);
174         Scene *scene= CTX_data_scene(C);
175         SpaceNode *snode= CTX_wm_space_node(C);
176         bNodeTree *ntree;
177         int nodeclass= GET_INT_FROM_POINTER(arg_nodeclass);
178         int event, compatibility= 0;
179         
180         ntree = snode->nodetree;
181         
182         if(!ntree) {
183                 uiItemS(layout);
184                 return;
185         }
186
187         if(ntree->type == NTREE_SHADER) {
188                 if(scene_use_new_shading_nodes(scene))
189                         compatibility= NODE_NEW_SHADING;
190                 else
191                         compatibility= NODE_OLD_SHADING;
192         }
193         
194         if (nodeclass==NODE_CLASS_GROUP) {
195                 bNodeTree *ngroup;
196                 
197                 uiLayoutSetFunc(layout, do_node_add_group, NULL);
198                 
199                 /* XXX hack: negative numbers used for empty group types */
200                 if (node_tree_has_type(ntree->type, NODE_GROUP))
201                         uiItemV(layout, "New Group", 0, -NODE_GROUP);
202                 if (node_tree_has_type(ntree->type, NODE_FORLOOP))
203                         uiItemV(layout, "New For Loop", 0, -NODE_FORLOOP);
204                 if (node_tree_has_type(ntree->type, NODE_WHILELOOP))
205                         uiItemV(layout, "New While Loop", 0, -NODE_WHILELOOP);
206                 uiItemS(layout);
207                 
208                 for(ngroup=bmain->nodetree.first, event=0; ngroup; ngroup= ngroup->id.next, ++event) {
209                         /* only use group trees */
210                         if (ngroup->type==ntree->type && ELEM3(ngroup->nodetype, NODE_GROUP, NODE_FORLOOP, NODE_WHILELOOP)) {
211                                 uiItemV(layout, ngroup->id.name+2, 0, event);
212                         }
213                 }
214         }
215         else if (nodeclass==NODE_DYNAMIC) {
216                 /* disabled */
217         }
218         else {
219                 bNodeType *ntype;
220                 
221                 uiLayoutSetFunc(layout, do_node_add_static, NULL);
222                 
223                 for (ntype=ntreeGetType(ntree->type)->node_types.first; ntype; ntype=ntype->next) {
224                         if (ntype->nclass==nodeclass && ntype->name)
225                                 if (!compatibility || (ntype->compatibility & compatibility))
226                                         uiItemV(layout, ntype->name, 0, ntype->type);
227                 }
228         }
229 }
230
231 #define IFACE_(msgid) UI_translate_do_iface(msgid)
232 static void node_menu_add(const bContext *C, Menu *menu)
233 {
234         Scene *scene= CTX_data_scene(C);
235         SpaceNode *snode= CTX_wm_space_node(C);
236         uiLayout *layout= menu->layout;
237
238         if(!snode->nodetree)
239                 uiLayoutSetActive(layout, 0);
240
241         if(snode->treetype==NTREE_SHADER) {
242                 uiItemMenuF(layout, IFACE_(N_("Input")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
243                 uiItemMenuF(layout, IFACE_(N_("Output")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT));
244                 if(scene_use_new_shading_nodes(scene)) {
245                         uiItemMenuF(layout, IFACE_(N_("Shader")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_SHADER));
246                         uiItemMenuF(layout, IFACE_(N_("Texture")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_TEXTURE));
247                 }
248                 uiItemMenuF(layout, IFACE_(N_("Color")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR));
249                 uiItemMenuF(layout, IFACE_(N_("Vector")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_VECTOR));
250                 uiItemMenuF(layout, IFACE_(N_("Convertor")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
251                 uiItemMenuF(layout, IFACE_(N_("Group")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
252                 //uiItemMenuF(layout, IFACE_(N_("Dynamic")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_DYNAMIC));
253                 uiItemMenuF(layout, IFACE_(N_("Layout")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
254         }
255         else if(snode->treetype==NTREE_COMPOSIT) {
256                 uiItemMenuF(layout, IFACE_(N_("Input")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
257                 uiItemMenuF(layout, IFACE_(N_("Output")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT));
258                 uiItemMenuF(layout, IFACE_(N_("Color")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR));
259                 uiItemMenuF(layout, IFACE_(N_("Vector")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_VECTOR));
260                 uiItemMenuF(layout, IFACE_(N_("Filter")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_FILTER));
261                 uiItemMenuF(layout, IFACE_(N_("Convertor")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
262                 uiItemMenuF(layout, IFACE_(N_("Matte")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_MATTE));
263                 uiItemMenuF(layout, IFACE_(N_("Distort")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT));
264                 uiItemMenuF(layout, IFACE_(N_("Group")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
265                 uiItemMenuF(layout, IFACE_(N_("Layout")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
266         }
267         else if(snode->treetype==NTREE_TEXTURE) {
268                 uiItemMenuF(layout, IFACE_(N_("Input")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
269                 uiItemMenuF(layout, IFACE_(N_("Output")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT));
270                 uiItemMenuF(layout, IFACE_(N_("Color")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR));
271                 uiItemMenuF(layout, IFACE_(N_("Patterns")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_PATTERN));
272                 uiItemMenuF(layout, IFACE_(N_("Textures")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_TEXTURE));
273                 uiItemMenuF(layout, IFACE_(N_("Convertor")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
274                 uiItemMenuF(layout, IFACE_(N_("Distort")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT));
275                 uiItemMenuF(layout, IFACE_(N_("Group")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
276                 uiItemMenuF(layout, IFACE_(N_("Layout")), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
277         }
278 }
279 #undef IFACE_
280
281 void node_menus_register(void)
282 {
283         MenuType *mt;
284
285         mt= MEM_callocN(sizeof(MenuType), "spacetype node menu add");
286         strcpy(mt->idname, "NODE_MT_add");
287         strcpy(mt->label, "Add");
288         mt->draw= node_menu_add;
289         WM_menutype_add(mt);
290 }
291