4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2008 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation
26 * ***** END GPL LICENSE BLOCK *****
29 /** \file blender/editors/space_node/node_header.c
37 #include "DNA_space_types.h"
38 #include "DNA_node_types.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_screen_types.h"
42 #include "MEM_guardedalloc.h"
44 #include "BLI_blenlib.h"
45 #include "BLI_utildefines.h"
47 #include "BLF_translation.h"
49 #include "BKE_context.h"
50 #include "BKE_global.h"
53 #include "BKE_scene.h"
54 #include "BKE_screen.h"
56 #include "RNA_access.h"
61 #include "UI_interface.h"
62 #include "UI_interface_icons.h"
63 #include "UI_resources.h"
64 #include "UI_view2d.h"
66 #include "node_intern.h"
68 /* ************************ add menu *********************** */
70 static void do_node_add(bContext *C, bNodeTemplate *ntemp)
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);
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;
87 UI_view2d_region_to_view(&ar->v2d, x, y, &snode->mx, &snode->my);
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;
97 /* node= */ node_add_node(snode, bmain, scene, ntemp, snode->mx, snode->my);
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;
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;
109 snode_notify(C, snode);
110 snode_dag_update(C, snode);
113 static void do_node_add_static(bContext *C, void *UNUSED(arg), int event)
117 do_node_add(C, &ntemp);
120 static void do_node_add_group(bContext *C, void *UNUSED(arg), int event)
122 SpaceNode *snode= CTX_wm_space_node(C);
126 ntemp.ngroup= BLI_findlink(&G.main->nodetree, event);
127 ntemp.type = ntemp.ngroup->nodetype;
131 switch (ntemp.type) {
133 ntemp.ngroup = ntreeAddTree("Group", snode->treetype, ntemp.type);
136 ntemp.ngroup = ntreeAddTree("For Loop", snode->treetype, ntemp.type);
139 ntemp.ngroup = ntreeAddTree("While Loop", snode->treetype, ntemp.type);
148 do_node_add(C, &ntemp);
152 static void do_node_add_dynamic(bContext *C, void *UNUSED(arg), int event)
155 ntemp.type = NODE_DYNAMIC;
156 do_node_add(C, &ntemp);
160 static int node_tree_has_type(int treetype, int nodetype)
162 bNodeTreeType *ttype= ntreeGetType(treetype);
164 for (ntype=ttype->node_types.first; ntype; ntype=ntype->next) {
165 if (ntype->type==nodetype)
171 static void node_add_menu(bContext *C, uiLayout *layout, void *arg_nodeclass)
173 Main *bmain= CTX_data_main(C);
174 Scene *scene= CTX_data_scene(C);
175 SpaceNode *snode= CTX_wm_space_node(C);
177 int nodeclass= GET_INT_FROM_POINTER(arg_nodeclass);
178 int event, compatibility= 0;
180 ntree = snode->nodetree;
187 if(ntree->type == NTREE_SHADER) {
188 if(scene_use_new_shading_nodes(scene))
189 compatibility= NODE_NEW_SHADING;
191 compatibility= NODE_OLD_SHADING;
194 if (nodeclass==NODE_CLASS_GROUP) {
197 uiLayoutSetFunc(layout, do_node_add_group, NULL);
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);
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);
215 else if (nodeclass==NODE_DYNAMIC) {
221 uiLayoutSetFunc(layout, do_node_add_static, NULL);
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);
231 static void node_menu_add(const bContext *C, Menu *menu)
233 Scene *scene= CTX_data_scene(C);
234 SpaceNode *snode= CTX_wm_space_node(C);
235 uiLayout *layout= menu->layout;
238 uiLayoutSetActive(layout, 0);
240 if(snode->treetype==NTREE_SHADER) {
241 uiItemMenuF(layout, IFACE_("Input"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
242 uiItemMenuF(layout, IFACE_("Output"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT));
243 if(scene_use_new_shading_nodes(scene)) {
244 uiItemMenuF(layout, IFACE_("Shader"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_SHADER));
245 uiItemMenuF(layout, IFACE_("Texture"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_TEXTURE));
247 uiItemMenuF(layout, IFACE_("Color"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR));
248 uiItemMenuF(layout, IFACE_("Vector"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_VECTOR));
249 uiItemMenuF(layout, IFACE_("Convertor"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
250 uiItemMenuF(layout, IFACE_("Group"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
251 //uiItemMenuF(layout, IFACE_("Dynamic"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_DYNAMIC));
252 uiItemMenuF(layout, IFACE_("Layout"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
254 else if(snode->treetype==NTREE_COMPOSIT) {
255 uiItemMenuF(layout, IFACE_("Input"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
256 uiItemMenuF(layout, IFACE_("Output"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT));
257 uiItemMenuF(layout, IFACE_("Color"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR));
258 uiItemMenuF(layout, IFACE_("Vector"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_VECTOR));
259 uiItemMenuF(layout, IFACE_("Filter"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_FILTER));
260 uiItemMenuF(layout, IFACE_("Convertor"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
261 uiItemMenuF(layout, IFACE_("Matte"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_MATTE));
262 uiItemMenuF(layout, IFACE_("Distort"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT));
263 uiItemMenuF(layout, IFACE_("Group"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
264 uiItemMenuF(layout, IFACE_("Layout"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
266 else if(snode->treetype==NTREE_TEXTURE) {
267 uiItemMenuF(layout, IFACE_("Input"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_INPUT));
268 uiItemMenuF(layout, IFACE_("Output"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OUTPUT));
269 uiItemMenuF(layout, IFACE_("Color"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_OP_COLOR));
270 uiItemMenuF(layout, IFACE_("Patterns"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_PATTERN));
271 uiItemMenuF(layout, IFACE_("Textures"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_TEXTURE));
272 uiItemMenuF(layout, IFACE_("Convertor"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_CONVERTOR));
273 uiItemMenuF(layout, IFACE_("Distort"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_DISTORT));
274 uiItemMenuF(layout, IFACE_("Group"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_GROUP));
275 uiItemMenuF(layout, IFACE_("Layout"), 0, node_add_menu, SET_INT_IN_POINTER(NODE_CLASS_LAYOUT));
279 void node_menus_register(void)
283 mt= MEM_callocN(sizeof(MenuType), "spacetype node menu add");
284 strcpy(mt->idname, "NODE_MT_add");
285 strcpy(mt->label, "Add");
286 mt->draw= node_menu_add;