Blender V2.61 - r43446

drawnode.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2005 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Bob Holcomb, Thomas Dinges
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <math.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 
00037 #include "BLI_blenlib.h"
00038 #include "BLI_math.h"
00039 #include "BLI_utildefines.h"
00040 
00041 #include "DNA_node_types.h"
00042 #include "DNA_material_types.h"
00043 #include "DNA_object_types.h"
00044 #include "DNA_scene_types.h"
00045 #include "DNA_space_types.h"
00046 #include "DNA_screen_types.h"
00047 
00048 #include "BKE_context.h"
00049 #include "BKE_curve.h"
00050 #include "BKE_global.h"
00051 #include "BKE_image.h"
00052 #include "BKE_library.h"
00053 #include "BKE_main.h"
00054 #include "BKE_node.h"
00055 
00056 #include "NOD_composite.h"
00057 #include "NOD_shader.h"
00058 
00059 #include "BIF_gl.h"
00060 #include "BIF_glutil.h"
00061 
00062 #include "BLF_api.h"
00063 
00064 #include "MEM_guardedalloc.h"
00065 
00066 
00067 #include "RNA_access.h"
00068 
00069 #include "ED_node.h"
00070 
00071 #include "WM_api.h"
00072 #include "WM_types.h"
00073 
00074 #include "UI_interface.h"
00075 #include "UI_resources.h"
00076 
00077 #include "IMB_imbuf.h"
00078 #include "IMB_imbuf_types.h"
00079 
00080 #include "node_intern.h"
00081 
00082 
00083 // XXX interface.h
00084 extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
00085 
00086 /* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
00087 
00088 static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
00089 {
00090     SpaceNode *snode= snode_v;
00091     
00092     if(snode->treetype==NTREE_SHADER) {
00093         nodeShaderSynchronizeID(node_v, 1);
00094         // allqueue(REDRAWBUTSSHADING, 0);
00095     }
00096 }
00097 
00098 static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
00099                               bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock,
00100                               const char *UNUSED(name), int x, int y, int width)
00101 {
00102     uiDefBut(block, LABEL, 0, sock->name, x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
00103 }
00104 
00105 
00106 static void node_socket_button_default(const bContext *C, uiBlock *block,
00107                                 bNodeTree *ntree, bNode *node, bNodeSocket *sock,
00108                                 const char *name, int x, int y, int width)
00109 {
00110     PointerRNA ptr;
00111     uiBut *bt;
00112     
00113     RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
00114     
00115     bt = uiDefButR(block, NUM, B_NODE_EXEC, name,
00116                    x, y+1, width, NODE_DY-2, 
00117                    &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
00118     if (node)
00119         uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
00120 }
00121 
00122 typedef struct SocketComponentMenuArgs {
00123     PointerRNA ptr;
00124     int x, y, width;
00125     uiButHandleFunc cb;
00126     void *arg1, *arg2;
00127 } SocketComponentMenuArgs;
00128 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
00129 static uiBlock *socket_component_menu(bContext *C, ARegion *ar, void *args_v)
00130 {
00131     SocketComponentMenuArgs *args= (SocketComponentMenuArgs*)args_v;
00132     uiBlock *block;
00133     uiLayout *layout;
00134     
00135     block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
00136     uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
00137     
00138     layout= uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, args->x, args->y+2, args->width, NODE_DY, UI_GetStyle()), 0);
00139     
00140     uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NONE);
00141     
00142     return block;
00143 }
00144 static void node_socket_button_components(const bContext *C, uiBlock *block,
00145                                    bNodeTree *ntree, bNode *node, bNodeSocket *sock,
00146                                    const char *name, int x, int y, int width)
00147 {
00148     PointerRNA ptr;
00149     SocketComponentMenuArgs *args;
00150     
00151     RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
00152     
00153     args= MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
00154     
00155     args->ptr = ptr;
00156     args->x = x;
00157     args->y = y;
00158     args->width = width;
00159     args->cb = node_sync_cb;
00160     args->arg1 = CTX_wm_space_node(C);
00161     args->arg2 = node;
00162     
00163     uiDefBlockButN(block, socket_component_menu, args, name, x, y+1, width, NODE_DY-2, "");
00164 }
00165 
00166 static void node_socket_button_color(const bContext *C, uiBlock *block,
00167                               bNodeTree *ntree, bNode *node, bNodeSocket *sock,
00168                               const char *name, int x, int y, int width)
00169 {
00170     PointerRNA ptr;
00171     uiBut *bt;
00172     int labelw= width - 40;
00173     
00174     RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
00175     
00176     bt=uiDefButR(block, COL, B_NODE_EXEC, "",
00177                  x, y+2, (labelw>0 ? 40 : width), NODE_DY-2, 
00178                  &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
00179     if (node)
00180         uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
00181     
00182     if (name[0]!='\0' && labelw>0)
00183         uiDefBut(block, LABEL, 0, name, x + 40, y+2, labelw, NODE_DY-2, NULL, 0, 0, 0, 0, "");
00184 }
00185 
00186 /* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
00187 
00188 #if 0 /* UNUSED */
00189 static void node_draw_socket_new(bNodeSocket *sock, float size)
00190 {
00191     float x=sock->locx, y=sock->locy;
00192     
00193     /* 16 values of sin function */
00194     static float si[16] = {
00195         0.00000000f, 0.39435585f,0.72479278f,0.93775213f,
00196         0.99871650f,0.89780453f,0.65137248f,0.29936312f,
00197         -0.10116832f,-0.48530196f,-0.79077573f,-0.96807711f,
00198         -0.98846832f,-0.84864425f,-0.57126821f,-0.20129852f
00199     };
00200     /* 16 values of cos function */
00201     static float co[16] ={
00202         1.00000000f,0.91895781f,0.68896691f,0.34730525f,
00203         -0.05064916f,-0.44039415f,-0.75875812f,-0.95413925f,
00204         -0.99486932f,-0.87434661f,-0.61210598f,-0.25065253f,
00205         0.15142777f,0.52896401f,0.82076344f,0.97952994f,
00206     };
00207     int a;
00208     
00209     glColor3ub(180, 180, 180);
00210     
00211     glBegin(GL_POLYGON);
00212     for(a=0; a<16; a++)
00213         glVertex2f(x+size*si[a], y+size*co[a]);
00214     glEnd();
00215     
00216     glColor4ub(0, 0, 0, 150);
00217     glEnable(GL_BLEND);
00218     glEnable( GL_LINE_SMOOTH );
00219     glBegin(GL_LINE_LOOP);
00220     for(a=0; a<16; a++)
00221         glVertex2f(x+size*si[a], y+size*co[a]);
00222     glEnd();
00223     glDisable( GL_LINE_SMOOTH );
00224     glDisable(GL_BLEND);
00225 }
00226 #endif
00227 
00228 /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
00229 
00230 static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00231 {
00232     PointerRNA sockptr;
00233     PropertyRNA *prop;
00234     
00235     /* first socket stores value */
00236     prop = RNA_struct_find_property(ptr, "outputs");
00237     RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
00238     
00239     uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
00240 }
00241 
00242 static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00243 {
00244     uiLayout *col;
00245     PointerRNA sockptr;
00246     PropertyRNA *prop;
00247     
00248     /* first socket stores value */
00249     prop = RNA_struct_find_property(ptr, "outputs");
00250     RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
00251     
00252     col = uiLayoutColumn(layout, 0);
00253     uiTemplateColorWheel(col, &sockptr, "default_value", 1, 0, 0, 0);
00254     uiItemR(col, &sockptr, "default_value", 0, "", ICON_NONE);
00255 }
00256 
00257 static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00258 {   
00259     uiLayout *row;
00260 
00261     bNodeTree *ntree= (bNodeTree*)ptr->id.data;
00262 
00263     row= uiLayoutRow(layout, 1);
00264     uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE);
00265     if(ntree->type == NTREE_COMPOSIT)
00266         uiItemR(row, ptr, "use_alpha", 0, "", ICON_IMAGE_RGB_ALPHA);
00267 }
00268 
00269 static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00270 {
00271     uiLayout *row;
00272 #if 0
00273     /* XXX no context access here .. */
00274     bNode *node= ptr->data;
00275     CurveMapping *cumap= node->storage;
00276     
00277     if(cumap) {
00278         cumap->flag |= CUMA_DRAW_CFRA;
00279         if(node->custom1<node->custom2)
00280             cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
00281     }
00282 #endif
00283 
00284     uiTemplateCurveMapping(layout, ptr, "curve", 's', 0, 0);
00285 
00286     row= uiLayoutRow(layout, 1);
00287     uiItemR(row, ptr, "frame_start", 0, "Sta", ICON_NONE);
00288     uiItemR(row, ptr, "frame_end", 0, "End", ICON_NONE);
00289 }
00290 
00291 static void node_buts_colorramp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00292 {
00293     uiTemplateColorRamp(layout, ptr, "color_ramp", 0);
00294 }
00295 
00296 static void node_buts_curvevec(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00297 {
00298     uiTemplateCurveMapping(layout, ptr, "mapping", 'v', 0, 0);
00299 }
00300 
00301 static float *_sample_col= NULL;    // bad bad, 2.5 will do better?
00302 #if 0
00303 static void node_curvemap_sample(float *col)
00304 {
00305     _sample_col= col;
00306 }
00307 #endif
00308 
00309 static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00310 {
00311     bNode *node= ptr->data;
00312     CurveMapping *cumap= node->storage;
00313 
00314     if(_sample_col) {
00315         cumap->flag |= CUMA_DRAW_SAMPLE;
00316         copy_v3_v3(cumap->sample, _sample_col);
00317     }
00318     else 
00319         cumap->flag &= ~CUMA_DRAW_SAMPLE;
00320 
00321     uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0, 0);
00322 }
00323 
00324 static void node_normal_cb(bContext *C, void *ntree_v, void *node_v)
00325 {
00326     Main *bmain = CTX_data_main(C);
00327 
00328     ED_node_generic_update(bmain, ntree_v, node_v);
00329     WM_event_add_notifier(C, NC_NODE|NA_EDITED, ntree_v);
00330 }
00331 
00332 static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00333 {
00334     uiBlock *block= uiLayoutAbsoluteBlock(layout);
00335     bNodeTree *ntree= ptr->id.data;
00336     bNode *node= ptr->data;
00337     rctf *butr= &node->butr;
00338     bNodeSocket *sock= node->outputs.first;     /* first socket stores normal */
00339     float *nor= ((bNodeSocketValueVector*)sock->default_value)->value;
00340     uiBut *bt;
00341     
00342     bt= uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", 
00343                   (short)butr->xmin, (short)butr->xmin,
00344                   butr->xmax-butr->xmin, butr->xmax-butr->xmin,
00345                   nor, 0.0f, 1.0f, 0, 0, "");
00346     uiButSetFunc(bt, node_normal_cb, ntree, node);
00347 }
00348 #if 0 // not used in 2.5x yet
00349 static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
00350 {
00351     Main *bmain= CTX_data_main(C);
00352     bNodeTree *ntree= ntree_v;
00353     bNode *node= node_v;
00354     Tex *tex;
00355     
00356     if(node->menunr<1) return;
00357     
00358     if(node->id) {
00359         node->id->us--;
00360         node->id= NULL;
00361     }
00362     tex= BLI_findlink(&bmain->tex, node->menunr-1);
00363 
00364     node->id= &tex->id;
00365     id_us_plus(node->id);
00366     BLI_strncpy(node->name, node->id->name+2, sizeof(node->name));
00367     
00368     nodeSetActive(ntree, node);
00369     
00370     if( ntree->type == NTREE_TEXTURE )
00371         ntreeTexCheckCyclics( ntree );
00372     
00373     // allqueue(REDRAWBUTSSHADING, 0);
00374     // allqueue(REDRAWNODE, 0);
00375     NodeTagChanged(ntree, node); 
00376     
00377     node->menunr= 0;
00378 }
00379 #endif
00380 static void node_dynamic_update_cb(bContext *C, void *UNUSED(ntree_v), void *node_v)
00381 {
00382     Main *bmain= CTX_data_main(C);
00383     Material *ma;
00384     bNode *node= (bNode *)node_v;
00385     ID *id= node->id;
00386     int error= 0;
00387 
00388     if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) error= 1;
00389 
00390     /* Users only have to press the "update" button in one pynode
00391      * and we also update all others sharing the same script */
00392     for (ma= bmain->mat.first; ma; ma= ma->id.next) {
00393         if (ma->nodetree) {
00394             bNode *nd;
00395             for (nd= ma->nodetree->nodes.first; nd; nd= nd->next) {
00396                 if ((nd->type == NODE_DYNAMIC) && (nd->id == id)) {
00397                     nd->custom1= 0;
00398                     nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_REPARSE);
00399                     nd->menunr= 0;
00400                     if (error)
00401                         nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_ERROR);
00402                 }
00403             }
00404         }
00405     }
00406 
00407     // allqueue(REDRAWBUTSSHADING, 0);
00408     // allqueue(REDRAWNODE, 0);
00409     // XXX BIF_preview_changed(ID_MA);
00410 }
00411 
00412 static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00413 {
00414     bNode *node= ptr->data;
00415 
00416     short multi = (
00417         node->id &&
00418         ((Tex*)node->id)->use_nodes &&
00419         (node->type != CMP_NODE_TEXTURE) &&
00420         (node->type != TEX_NODE_TEXTURE)
00421     );
00422     
00423     uiItemR(layout, ptr, "texture", 0, "", ICON_NONE);
00424     
00425     if(multi) {
00426         /* Number Drawing not optimal here, better have a list*/
00427         uiItemR(layout, ptr, "node_output", 0, "", ICON_NONE);
00428     }
00429 }
00430 
00431 static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00432 { 
00433     uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
00434 }
00435 
00436 static int node_resize_area_default(bNode *node, int x, int y)
00437 {
00438     if (node->flag & NODE_HIDDEN) {
00439         rctf totr= node->totr;
00440         /* right part of node */
00441         totr.xmin= node->totr.xmax-20.0f;
00442         return BLI_in_rctf(&totr, x, y);
00443     }
00444     else {
00445         /* rect we're interested in is just the bottom right corner */
00446         rctf totr= node->totr;
00447         /* bottom right corner */
00448         totr.xmin= totr.xmax-10.0f;
00449         totr.ymax= totr.ymin+10.0f;
00450         return BLI_in_rctf(&totr, x, y);
00451     }
00452 }
00453 
00454 /* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
00455 
00456 /* width of socket columns in group display */
00457 #define NODE_GROUP_FRAME        120
00458 
00459 /* based on settings in node, sets drawing rect info. each redraw! */
00460 /* note: this assumes only 1 group at a time is drawn (linked data) */
00461 /* in node->totr the entire boundbox for the group is stored */
00462 static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
00463 {
00464     if (!(gnode->flag & NODE_GROUP_EDIT)) {
00465         node_update_default(C, ntree, gnode);
00466     }
00467     else {
00468         bNodeTree *ngroup= (bNodeTree *)gnode->id;
00469         bNode *node;
00470         bNodeSocket *sock, *gsock;
00471         float locx, locy;
00472         rctf *rect= &gnode->totr;
00473         float node_group_frame= U.dpi*NODE_GROUP_FRAME/72;
00474         float group_header= 26*U.dpi/72;
00475         int counter;
00476         int dy;
00477         
00478         /* get "global" coords */
00479         nodeSpaceCoords(gnode, &locx, &locy);
00480         
00481         /* center them, is a bit of abuse of locx and locy though */
00482         node_update_nodetree(C, ngroup, locx, locy);
00483         
00484         rect->xmin = rect->xmax = locx;
00485         rect->ymin = rect->ymax = locy;
00486         
00487         counter= 1;
00488         for(node= ngroup->nodes.first; node; node= node->next) {
00489             if(counter) {
00490                 *rect= node->totr;
00491                 counter= 0;
00492             }
00493             else
00494                 BLI_union_rctf(rect, &node->totr);
00495         }
00496         
00497         /* add some room for links to group sockets */
00498         rect->xmin -= 4*NODE_DY;
00499         rect->xmax += 4*NODE_DY;
00500         rect->ymin-= NODE_DY;
00501         rect->ymax+= NODE_DY;
00502         
00503         /* input sockets */
00504         dy = 0.5f*(rect->ymin+rect->ymax) + NODE_DY*(BLI_countlist(&gnode->inputs)-1);
00505         gsock=ngroup->inputs.first;
00506         sock=gnode->inputs.first;
00507         while (gsock || sock) {
00508             while (sock && !sock->groupsock) {
00509                 sock->locx = rect->xmin - node_group_frame;
00510                 sock->locy = dy;
00511 
00512                 /* prevent long socket lists from growing out of the group box */
00513                 if (dy-3*NODE_DYS < rect->ymin)
00514                     rect->ymin = dy-3*NODE_DYS;
00515                 if (dy+3*NODE_DYS > rect->ymax)
00516                     rect->ymax = dy+3*NODE_DYS;
00517                 dy -= 2*NODE_DY;
00518                 
00519                 sock = sock->next;
00520             }
00521             while (gsock && (!sock || sock->groupsock!=gsock)) {
00522                 gsock->locx = rect->xmin;
00523                 gsock->locy = dy;
00524                 
00525                 /* prevent long socket lists from growing out of the group box */
00526                 if (dy-3*NODE_DYS < rect->ymin)
00527                     rect->ymin = dy-3*NODE_DYS;
00528                 if (dy+3*NODE_DYS > rect->ymax)
00529                     rect->ymax = dy+3*NODE_DYS;
00530                 dy -= 2*NODE_DY;
00531                 
00532                 gsock = gsock->next;
00533             }
00534             while (sock && gsock && sock->groupsock==gsock) {
00535                 gsock->locx = rect->xmin;
00536                 sock->locx = rect->xmin - node_group_frame;
00537                 sock->locy = gsock->locy = dy;
00538                 
00539                 /* prevent long socket lists from growing out of the group box */
00540                 if (dy-3*NODE_DYS < rect->ymin)
00541                     rect->ymin = dy-3*NODE_DYS;
00542                 if (dy+3*NODE_DYS > rect->ymax)
00543                     rect->ymax = dy+3*NODE_DYS;
00544                 dy -= 2*NODE_DY;
00545                 
00546                 sock = sock->next;
00547                 gsock = gsock->next;
00548             }
00549         }
00550         
00551         /* output sockets */
00552         dy = 0.5f*(rect->ymin+rect->ymax) + NODE_DY*(BLI_countlist(&gnode->outputs)-1);
00553         gsock=ngroup->outputs.first;
00554         sock=gnode->outputs.first;
00555         while (gsock || sock) {
00556             while (sock && !sock->groupsock) {
00557                 sock->locx = rect->xmax + node_group_frame;
00558                 sock->locy = dy - NODE_DYS;
00559                 
00560                 /* prevent long socket lists from growing out of the group box */
00561                 if (dy-3*NODE_DYS < rect->ymin)
00562                     rect->ymin = dy-3*NODE_DYS;
00563                 if (dy+3*NODE_DYS > rect->ymax)
00564                     rect->ymax = dy+3*NODE_DYS;
00565                 dy -= 2*NODE_DY;
00566                 
00567                 sock = sock->next;
00568             }
00569             while (gsock && (!sock || sock->groupsock!=gsock)) {
00570                 gsock->locx = rect->xmax;
00571                 gsock->locy = dy - NODE_DYS;
00572                 
00573                 /* prevent long socket lists from growing out of the group box */
00574                 if (dy-3*NODE_DYS < rect->ymin)
00575                     rect->ymin = dy-3*NODE_DYS;
00576                 if (dy+3*NODE_DYS > rect->ymax)
00577                     rect->ymax = dy+3*NODE_DYS;
00578                 dy -= 2*NODE_DY;
00579                 
00580                 gsock = gsock->next;
00581             }
00582             while (sock && gsock && sock->groupsock==gsock) {
00583                 gsock->locx = rect->xmax;
00584                 sock->locx = rect->xmax + node_group_frame;
00585                 sock->locy = gsock->locy = dy - NODE_DYS;
00586                 
00587                 /* prevent long socket lists from growing out of the group box */
00588                 if (dy-3*NODE_DYS < rect->ymin)
00589                     rect->ymin = dy-3*NODE_DYS;
00590                 if (dy+3*NODE_DYS > rect->ymax)
00591                     rect->ymax = dy+3*NODE_DYS;
00592                 dy -= 2*NODE_DY;
00593                 
00594                 sock = sock->next;
00595                 gsock = gsock->next;
00596             }
00597         }
00598         
00599         /* Set the block bounds to clip mouse events from underlying nodes.
00600          * Add margin for header and input/output columns.
00601          */
00602         uiExplicitBoundsBlock(gnode->block,
00603                               rect->xmin - node_group_frame,
00604                               rect->ymin,
00605                               rect->xmax + node_group_frame,
00606                               rect->ymax + group_header);
00607     }
00608 }
00609 
00610 static void update_group_input_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
00611 {
00612     bNodeTree *ngroup= (bNodeTree*)ngroup_v;
00613     
00614     ngroup->update |= NTREE_UPDATE_GROUP_IN;
00615     ntreeUpdateTree(ngroup);
00616 }
00617 
00618 static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
00619 {
00620     bNodeTree *ngroup= (bNodeTree*)ngroup_v;
00621     
00622     ngroup->update |= NTREE_UPDATE_GROUP_OUT;
00623     ntreeUpdateTree(ngroup);
00624 }
00625 
00626 static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock, int in_out, float xoffset, float yoffset)
00627 {
00628     bNodeTree *ngroup= (bNodeTree*)gnode->id;
00629     uiBut *bt;
00630     
00631     if (sock->flag & SOCK_DYNAMIC) {
00632         bt = uiDefBut(gnode->block, TEX, 0, "", 
00633                       sock->locx+xoffset, sock->locy+1+yoffset, 72, NODE_DY,
00634                       sock->name, 0, sizeof(sock->name), 0, 0, "");
00635         if (in_out==SOCK_IN)
00636             uiButSetFunc(bt, update_group_input_cb, snode, ngroup);
00637         else
00638             uiButSetFunc(bt, update_group_output_cb, snode, ngroup);
00639     }
00640     else {
00641         uiDefBut(gnode->block, LABEL, 0, sock->name,
00642                  sock->locx+xoffset, sock->locy+1+yoffset, 72, NODE_DY,
00643                  NULL, 0, sizeof(sock->name), 0, 0, "");
00644     }
00645 }
00646 
00647 static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode, bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out)
00648 {
00649     bNodeTree *ngroup= (bNodeTree*)gnode->id;
00650     bNodeSocketType *stype= ntreeGetSocketType(gsock ? gsock->type : sock->type);
00651     uiBut *bt;
00652     float offset;
00653     int draw_value;
00654     float node_group_frame= U.dpi*NODE_GROUP_FRAME/72;
00655     float socket_size= NODE_SOCKSIZE*U.dpi/72;
00656     float arrowbutw= 0.8f*UI_UNIT_X;
00657     /* layout stuff for buttons on group left frame */
00658     float colw= 0.6f*node_group_frame;
00659     float col1= 6 - node_group_frame;
00660     float col2= col1 + colw+6;
00661     float col3= - arrowbutw - 6;
00662     /* layout stuff for buttons on group right frame */
00663     float cor1= 6;
00664     float cor2= cor1 + arrowbutw + 6;
00665     float cor3= cor2 + arrowbutw + 6;
00666     
00667     /* node and group socket circles */
00668     if (sock)
00669         node_socket_circle_draw(ntree, sock, socket_size);
00670     if (gsock)
00671         node_socket_circle_draw(ngroup, gsock, socket_size);
00672     
00673     /* socket name */
00674     offset = (in_out==SOCK_IN ? col1 : cor3);
00675     if (!gsock)
00676         offset += (in_out==SOCK_IN ? node_group_frame : -node_group_frame);
00677     
00678     /* draw both name and value button if:
00679      * 1) input: not internal
00680      * 2) output: (node type uses const outputs) and (group output is unlinked)
00681      */
00682     draw_value = 0;
00683     switch (in_out) {
00684     case SOCK_IN:
00685         draw_value = !(gsock && (gsock->flag & SOCK_INTERNAL));
00686         break;
00687     case SOCK_OUT:
00688         if (gnode->typeinfo->flag & NODE_CONST_OUTPUT)
00689             draw_value = !(gsock && gsock->link);
00690         break;
00691     }
00692     if (draw_value) {
00693         /* both name and value buttons */
00694         if (gsock) {
00695             draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0);
00696             if (stype->buttonfunc)
00697                 stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "", gsock->locx+offset, gsock->locy-NODE_DY, colw);
00698         }
00699         else {
00700             draw_group_socket_name(snode, gnode, sock, in_out, offset, 0);
00701             if (stype->buttonfunc)
00702                 stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "", sock->locx+offset, sock->locy-NODE_DY, colw);
00703         }
00704     }
00705     else {
00706         /* only name, no value button */
00707         if (gsock)
00708             draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS);
00709         else
00710             draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS);
00711     }
00712     
00713     if (gsock && (gsock->flag & SOCK_DYNAMIC)) {
00714         /* up/down buttons */
00715         offset = (in_out==SOCK_IN ? col2 : cor2);
00716         uiBlockSetDirection(gnode->block, UI_TOP);
00717         uiBlockBeginAlign(gnode->block);
00718         bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP,
00719                            gsock->locx+offset, gsock->locy, arrowbutw, arrowbutw, "");
00720         if (!gsock->prev || !(gsock->prev->flag & SOCK_DYNAMIC))
00721             uiButSetFlag(bt, UI_BUT_DISABLED);
00722         RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
00723         RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
00724         bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN,
00725                            gsock->locx+offset, gsock->locy-arrowbutw, arrowbutw, arrowbutw, "");
00726         if (!gsock->next || !(gsock->next->flag & SOCK_DYNAMIC))
00727             uiButSetFlag(bt, UI_BUT_DISABLED);
00728         RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
00729         RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
00730         uiBlockEndAlign(gnode->block);
00731         uiBlockSetDirection(gnode->block, 0);
00732         
00733         /* remove button */
00734         offset = (in_out==SOCK_IN ? col3 : cor1);
00735         uiBlockSetEmboss(gnode->block, UI_EMBOSSN);
00736         bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X,
00737                            gsock->locx+offset, gsock->locy-0.5f*arrowbutw, arrowbutw, arrowbutw, "");
00738         RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
00739         RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
00740         uiBlockSetEmboss(gnode->block, UI_EMBOSS);
00741     }
00742 }
00743 
00744 /* groups are, on creation, centered around 0,0 */
00745 static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
00746 {
00747     if (!(gnode->flag & NODE_GROUP_EDIT)) {
00748         node_draw_default(C, ar, snode, ntree, gnode);
00749     }
00750     else {
00751         bNodeTree *ngroup= (bNodeTree *)gnode->id;
00752         bNodeSocket *sock, *gsock;
00753         uiLayout *layout;
00754         PointerRNA ptr;
00755         rctf rect= gnode->totr;
00756         float node_group_frame= U.dpi*NODE_GROUP_FRAME/72;
00757         float group_header= 26*U.dpi/72;
00758         
00759         int index;
00760         
00761         /* backdrop header */
00762         glEnable(GL_BLEND);
00763         uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
00764         UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
00765         uiDrawBox(GL_POLYGON, rect.xmin-node_group_frame, rect.ymax, rect.xmax+node_group_frame, rect.ymax+group_header, BASIS_RAD);
00766         
00767         /* backdrop body */
00768         UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
00769         uiSetRoundBox(UI_CNR_NONE);
00770         uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
00771     
00772         /* input column */
00773         UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
00774         uiSetRoundBox(UI_CNR_BOTTOM_LEFT);
00775         uiDrawBox(GL_POLYGON, rect.xmin-node_group_frame, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD);
00776     
00777         /* output column */
00778         UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
00779         uiSetRoundBox(UI_CNR_BOTTOM_RIGHT);
00780         uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax+node_group_frame, rect.ymax, BASIS_RAD);
00781     
00782         /* input column separator */
00783         glColor4ub(200, 200, 200, 140);
00784         glBegin(GL_LINES);
00785         glVertex2f(rect.xmin, rect.ymin);
00786         glVertex2f(rect.xmin, rect.ymax);
00787         glEnd();
00788     
00789         /* output column separator */
00790         glColor4ub(200, 200, 200, 140);
00791         glBegin(GL_LINES);
00792         glVertex2f(rect.xmax, rect.ymin);
00793         glVertex2f(rect.xmax, rect.ymax);
00794         glEnd();
00795     
00796         /* group node outline */
00797         uiSetRoundBox(UI_CNR_ALL);
00798         glColor4ub(200, 200, 200, 140);
00799         glEnable( GL_LINE_SMOOTH );
00800         uiDrawBox(GL_LINE_LOOP, rect.xmin-node_group_frame, rect.ymin, rect.xmax+node_group_frame, rect.ymax+group_header, BASIS_RAD);
00801         glDisable( GL_LINE_SMOOTH );
00802         glDisable(GL_BLEND);
00803         
00804         /* backdrop title */
00805         UI_ThemeColor(TH_TEXT_HI);
00806     
00807         layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, (short)(rect.xmin+15), (short)(rect.ymax+group_header),
00808                                MIN2((int)(rect.xmax - rect.xmin-18.0f), node_group_frame+20), group_header, UI_GetStyle());
00809         RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr);
00810         uiTemplateIDBrowse(layout, (bContext*)C, &ptr, "node_tree", NULL, NULL, NULL);
00811         uiBlockLayoutResolve(gnode->block, NULL, NULL);
00812     
00813         /* draw the internal tree nodes and links */
00814         node_draw_nodetree(C, ar, snode, ngroup);
00815     
00816         /* group sockets */
00817         gsock=ngroup->inputs.first;
00818         sock=gnode->inputs.first;
00819         index = 0;
00820         while (gsock || sock) {
00821             while (sock && !sock->groupsock) {
00822                 draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_IN);
00823                 sock = sock->next;
00824             }
00825             while (gsock && (!sock || sock->groupsock!=gsock)) {
00826                 draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_IN);
00827                 gsock = gsock->next;
00828                 ++index;
00829             }
00830             while (sock && gsock && sock->groupsock==gsock) {
00831                 draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_IN);
00832                 sock = sock->next;
00833                 gsock = gsock->next;
00834                 ++index;
00835             }
00836         }
00837         gsock=ngroup->outputs.first;
00838         sock=gnode->outputs.first;
00839         index = 0;
00840         while (gsock || sock) {
00841             while (sock && !sock->groupsock) {
00842                 draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_OUT);
00843                 sock = sock->next;
00844             }
00845             while (gsock && (!sock || sock->groupsock!=gsock)) {
00846                 draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_OUT);
00847                 gsock = gsock->next;
00848                 ++index;
00849             }
00850             while (sock && gsock && sock->groupsock==gsock) {
00851                 draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_OUT);
00852                 sock = sock->next;
00853                 gsock = gsock->next;
00854                 ++index;
00855             }
00856         }
00857         
00858         uiEndBlock(C, gnode->block);
00859         uiDrawBlock(C, gnode->block);
00860         gnode->block= NULL;
00861     }
00862 }
00863 
00864 void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
00865 {
00866     uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL);
00867 }
00868 
00869 static void node_common_buts_whileloop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00870 {
00871     uiItemR(layout, ptr, "max_iterations", 0, NULL, 0);
00872 }
00873 
00874 static void node_update_frame(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node)
00875 {
00876     float locx, locy;
00877 
00878     /* get "global" coords */
00879     nodeSpaceCoords(node, &locx, &locy);
00880 
00881     node->prvr.xmin= locx + NODE_DYS;
00882     node->prvr.xmax= locx + node->width- NODE_DYS;
00883 
00884     node->totr.xmin= locx;
00885     node->totr.xmax= locx + node->width;
00886     node->totr.ymax= locy;
00887     node->totr.ymin= locy - node->height;
00888 }
00889 
00890 static void node_common_set_butfunc(bNodeType *ntype)
00891 {
00892     switch(ntype->type) {
00893         case NODE_GROUP:
00894             ntype->uifunc= node_uifunc_group;
00895             ntype->drawfunc= node_draw_group;
00896             ntype->drawupdatefunc= node_update_group;
00897             break;
00898         case NODE_FORLOOP:
00899 //          ntype->uifunc= node_common_buts_group;
00900             ntype->drawfunc= node_draw_group;
00901             ntype->drawupdatefunc= node_update_group;
00902             break;
00903         case NODE_WHILELOOP:
00904             ntype->uifunc= node_common_buts_whileloop;
00905             ntype->drawfunc= node_draw_group;
00906             ntype->drawupdatefunc= node_update_group;
00907             break;
00908         case NODE_FRAME:
00909             ntype->drawupdatefunc= node_update_frame;
00910             break;
00911     }
00912 }
00913 
00914 /* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
00915 
00916 static void node_browse_text_cb(bContext *C, void *ntree_v, void *node_v)
00917 {
00918     Main *bmain= CTX_data_main(C);
00919     bNodeTree *ntree= ntree_v;
00920     bNode *node= node_v;
00921     /* ID *oldid; */ /* UNUSED */
00922     
00923     if(node->menunr<1) return;
00924     
00925     if(node->id) {
00926         node->id->us--;
00927     }
00928     /* oldid= node->id; */ /* UNUSED */
00929     node->id= BLI_findlink(&bmain->text, node->menunr-1);
00930     id_us_plus(node->id);
00931     BLI_strncpy(node->name, node->id->name+2, sizeof(node->name));
00932 
00933     node->custom1= BSET(node->custom1, NODE_DYNAMIC_NEW);
00934     
00935     nodeSetActive(ntree, node);
00936 
00937     // allqueue(REDRAWBUTSSHADING, 0);
00938     // allqueue(REDRAWNODE, 0);
00939 
00940     node->menunr= 0;
00941 }
00942 
00943 static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr)
00944 {
00945     bNode *node= ptr->data;
00946     uiLayout *col;
00947     
00948     uiTemplateID(layout, C, ptr, "material", "MATERIAL_OT_new", NULL, NULL);
00949     
00950     if(!node->id) return;
00951     
00952     col= uiLayoutColumn(layout, 0);
00953     uiItemR(col, ptr, "use_diffuse", 0, NULL, ICON_NONE);
00954     uiItemR(col, ptr, "use_specular", 0, NULL, ICON_NONE);
00955     uiItemR(col, ptr, "invert_normal", 0, NULL, ICON_NONE);
00956 }
00957 
00958 static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00959 {
00960     uiLayout *row;
00961     
00962     uiItemL(layout, "Location:", ICON_NONE);
00963     row= uiLayoutRow(layout, 1);
00964     uiItemR(row, ptr, "location", 0, "", ICON_NONE);
00965     
00966     uiItemL(layout, "Rotation:", ICON_NONE);
00967     row= uiLayoutRow(layout, 1);
00968     uiItemR(row, ptr, "rotation", 0, "", ICON_NONE);
00969     
00970     uiItemL(layout, "Scale:", ICON_NONE);
00971     row= uiLayoutRow(layout, 1);
00972     uiItemR(row, ptr, "scale", 0, "", ICON_NONE);
00973     
00974     row= uiLayoutRow(layout, 1);
00975     uiItemR(row, ptr, "use_min", 0, "Min", ICON_NONE);
00976     uiItemR(row, ptr, "min", 0, "", ICON_NONE);
00977     
00978     row= uiLayoutRow(layout, 1);
00979     uiItemR(row, ptr, "use_max", 0, "Max", ICON_NONE);
00980     uiItemR(row, ptr, "max", 0, "", ICON_NONE);
00981 }
00982 
00983 static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
00984 { 
00985     uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
00986 }
00987 
00988 static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA *ptr)
00989 {
00990     PointerRNA obptr= CTX_data_pointer_get(C, "active_object");
00991     uiLayout *col;
00992 
00993     col= uiLayoutColumn(layout, 0);
00994 
00995     if(obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
00996         PointerRNA dataptr= RNA_pointer_get(&obptr, "data");
00997 
00998         uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_textures", "", ICON_NONE);
00999         uiItemPointerR(col, ptr, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE);
01000     }
01001     else {
01002         uiItemR(col, ptr, "uv_layer", 0, "UV", ICON_NONE);
01003         uiItemR(col, ptr, "color_layer", 0, "VCol", ICON_NONE);
01004     }
01005 }
01006 
01007 static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01008 {
01009     uiItemR(layout, ptr, "attribute_name", 0, "Name", ICON_NONE);
01010 }
01011 
01012 static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
01013 {
01014     uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
01015     uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
01016 }
01017 
01018 static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01019 {
01020     uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE);
01021     uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE);
01022 }
01023 
01024 static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01025 {
01026     uiItemR(layout, ptr, "gradient_type", 0, "", ICON_NONE);
01027 }
01028 
01029 static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01030 {
01031     uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE);
01032 }
01033 
01034 static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01035 {
01036     uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE);
01037 }
01038 
01039 static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01040 {
01041     uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
01042 }
01043 
01044 static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01045 {
01046     uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
01047 }
01048 
01049 static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01050 {
01051     uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
01052 }
01053 
01054 static void node_shader_buts_dynamic(uiLayout *layout, bContext *C, PointerRNA *ptr)
01055 { 
01056     Main *bmain= CTX_data_main(C);
01057     uiBlock *block= uiLayoutAbsoluteBlock(layout);
01058     bNode *node= ptr->data;
01059     bNodeTree *ntree= ptr->id.data;
01060     rctf *butr= &node->butr;
01061     uiBut *bt;
01062     // XXX SpaceNode *snode= curarea->spacedata.first;
01063     short dy= (short)butr->ymin;
01064     int xoff=0;
01065 
01066     /* B_NODE_EXEC is handled in butspace.c do_node_buts */
01067     if(!node->id) {
01068             const char *strp;
01069             IDnames_to_pupstring(&strp, NULL, "", &(bmain->text), NULL, NULL);
01070             node->menunr= 0;
01071             bt= uiDefButS(block, MENU, B_NODE_EXEC/*+node->nr*/, strp, 
01072                             butr->xmin, dy, 19, 19, 
01073                             &node->menunr, 0, 0, 0, 0, "Browses existing choices");
01074             uiButSetFunc(bt, node_browse_text_cb, ntree, node);
01075             xoff=19;
01076             if(strp) MEM_freeN((void *)strp);
01077     }
01078     else {
01079         bt = uiDefBut(block, BUT, B_NOP, "Update",
01080                 butr->xmin+xoff, butr->ymin+20, 50, 19,
01081                 &node->menunr, 0.0, 19.0, 0, 0, "Refresh this node (and all others that use the same script)");
01082         uiButSetFunc(bt, node_dynamic_update_cb, ntree, node);
01083 
01084         if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
01085             // UI_ThemeColor(TH_REDALERT);
01086             // XXX ui_rasterpos_safe(butr->xmin + xoff, butr->ymin + 5, snode->aspect);
01087             // XXX snode_drawstring(snode, "Error! Check console...", butr->xmax - butr->xmin);
01088             ;
01089         }
01090     }
01091 }
01092 
01093 /* only once called */
01094 static void node_shader_set_butfunc(bNodeType *ntype)
01095 {
01096     ntype->uifuncbut = NULL;
01097     switch(ntype->type) {
01098         /* case NODE_GROUP:  note, typeinfo for group is generated... see "XXX ugly hack" */
01099 
01100         case SH_NODE_MATERIAL:
01101         case SH_NODE_MATERIAL_EXT:
01102             ntype->uifunc= node_shader_buts_material;
01103             break;
01104         case SH_NODE_TEXTURE:
01105             ntype->uifunc= node_buts_texture;
01106             break;
01107         case SH_NODE_NORMAL:
01108             ntype->uifunc= node_buts_normal;
01109             break;
01110         case SH_NODE_CURVE_VEC:
01111             ntype->uifunc= node_buts_curvevec;
01112             break;
01113         case SH_NODE_CURVE_RGB:
01114             ntype->uifunc= node_buts_curvecol;
01115             break;
01116         case SH_NODE_MAPPING:
01117             ntype->uifunc= node_shader_buts_mapping;
01118             break;
01119         case SH_NODE_VALUE:
01120             ntype->uifunc= node_buts_value;
01121             break;
01122         case SH_NODE_RGB:
01123             ntype->uifunc= node_buts_rgb;
01124             break;
01125         case SH_NODE_MIX_RGB:
01126             ntype->uifunc= node_buts_mix_rgb;
01127             break;
01128         case SH_NODE_VALTORGB:
01129             ntype->uifunc= node_buts_colorramp;
01130             break;
01131         case SH_NODE_MATH: 
01132             ntype->uifunc= node_buts_math;
01133             break; 
01134         case SH_NODE_VECT_MATH: 
01135             ntype->uifunc= node_shader_buts_vect_math;
01136             break; 
01137         case SH_NODE_GEOMETRY:
01138             ntype->uifunc= node_shader_buts_geometry;
01139             break;
01140         case SH_NODE_ATTRIBUTE:
01141             ntype->uifunc= node_shader_buts_attribute;
01142             break;
01143         case SH_NODE_TEX_SKY:
01144             ntype->uifunc= node_shader_buts_tex_sky;
01145             break;
01146         case SH_NODE_TEX_IMAGE:
01147             ntype->uifunc= node_shader_buts_tex_image;
01148             break;
01149         case SH_NODE_TEX_ENVIRONMENT:
01150             ntype->uifunc= node_shader_buts_tex_image;
01151             break;
01152         case SH_NODE_TEX_GRADIENT:
01153             ntype->uifunc= node_shader_buts_tex_gradient;
01154             break;
01155         case SH_NODE_TEX_MAGIC:
01156             ntype->uifunc= node_shader_buts_tex_magic;
01157             break;
01158         case SH_NODE_TEX_WAVE:
01159             ntype->uifunc= node_shader_buts_tex_wave;
01160             break;
01161         case SH_NODE_TEX_MUSGRAVE:
01162             ntype->uifunc= node_shader_buts_tex_musgrave;
01163             break;
01164         case SH_NODE_TEX_VORONOI:
01165             ntype->uifunc= node_shader_buts_tex_voronoi;
01166             break;
01167         case SH_NODE_BSDF_GLOSSY:
01168         case SH_NODE_BSDF_GLASS:
01169             ntype->uifunc= node_shader_buts_glossy;
01170             break;
01171         case NODE_DYNAMIC:
01172             ntype->uifunc= node_shader_buts_dynamic;
01173             break;
01174     }
01175         if (ntype->uifuncbut == NULL) ntype->uifuncbut = ntype->uifunc;
01176 }
01177 
01178 /* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
01179 
01180 static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
01181 {
01182     uiLayout *col;
01183     bNode *node= ptr->data;
01184     PointerRNA imaptr;
01185     PropertyRNA *prop;
01186     int source;
01187     
01188     uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
01189     
01190     if(!node->id) return;
01191     
01192     prop = RNA_struct_find_property(ptr, "image");
01193     if (!prop || RNA_property_type(prop) != PROP_POINTER) return;
01194     imaptr= RNA_property_pointer_get(ptr, prop);
01195     
01196     col= uiLayoutColumn(layout, 0);
01197     
01198     uiItemR(col, &imaptr, "source", 0, NULL, ICON_NONE);
01199     
01200     source= RNA_enum_get(&imaptr, "source");
01201 
01202     if(source == IMA_SRC_SEQUENCE) {
01203         /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
01204         Scene *scene= CTX_data_scene(C);
01205         ImageUser *iuser= node->storage;
01206         char numstr[32];
01207         const int framenr= BKE_image_user_get_frame(iuser, CFRA, 0);
01208         BLI_snprintf(numstr, sizeof(numstr), "Frame: %d", framenr);
01209         uiItemL(layout, numstr, ICON_NONE);
01210     }
01211 
01212     if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
01213         col= uiLayoutColumn(layout, 1);
01214         uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE);
01215         uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE);
01216         uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE);
01217         uiItemR(col, ptr, "use_cyclic", 0, NULL, ICON_NONE);
01218         uiItemR(col, ptr, "use_auto_refresh", UI_ITEM_R_ICON_ONLY, NULL, ICON_NONE);
01219     }
01220 
01221     col= uiLayoutColumn(layout, 0);
01222     
01223     if (RNA_enum_get(&imaptr, "type")== IMA_TYPE_MULTILAYER)
01224         uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
01225 }
01226 
01227 static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
01228 {
01229     bNode *node= ptr->data;
01230     uiLayout *col, *row;
01231     PointerRNA op_ptr;
01232     PointerRNA scn_ptr;
01233     PropertyRNA *prop;
01234     const char *layer_name;
01235     char scene_name[MAX_ID_NAME-2];
01236     
01237     uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL);
01238     
01239     if(!node->id) return;
01240 
01241     col= uiLayoutColumn(layout, 0);
01242     row = uiLayoutRow(col, 0);
01243     uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
01244     
01245     prop = RNA_struct_find_property(ptr, "layer");
01246     if (!(RNA_property_enum_identifier(C, ptr, prop, RNA_property_enum_get(ptr, prop), &layer_name)))
01247         return;
01248     
01249     scn_ptr = RNA_pointer_get(ptr, "scene");
01250     RNA_string_get(&scn_ptr, "name", scene_name);
01251     
01252     WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
01253     RNA_string_set(&op_ptr, "layer", layer_name);
01254     RNA_string_set(&op_ptr, "scene", scene_name);
01255     uiItemFullO(row, "RENDER_OT_render", "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
01256 
01257 }
01258 
01259 
01260 static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01261 {
01262     uiLayout *col, *row;
01263     
01264     col= uiLayoutColumn(layout, 0);
01265     
01266     uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE);
01267     if (RNA_enum_get(ptr, "filter_type")!= R_FILTER_FAST_GAUSS) {
01268         uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE);
01269         uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
01270     }
01271     
01272     uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE);
01273     
01274     if (RNA_boolean_get(ptr, "use_relative")) {
01275         uiItemL(col, "Aspect Correction", 0);
01276         row= uiLayoutRow(layout, 1);
01277         uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, 0);
01278         
01279         col= uiLayoutColumn(layout, 1);
01280         uiItemR(col, ptr, "factor_x", 0, "X", ICON_NONE);
01281         uiItemR(col, ptr, "factor_y", 0, "Y", ICON_NONE);
01282     }
01283     else {
01284         col= uiLayoutColumn(layout, 1);
01285         uiItemR(col, ptr, "size_x", 0, "X", ICON_NONE);
01286         uiItemR(col, ptr, "size_y", 0, "Y", ICON_NONE);
01287     }
01288 }
01289 
01290 static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01291 {
01292     uiLayout *col;
01293     
01294     uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
01295     uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE);
01296     
01297     col= uiLayoutColumn(layout, 1);
01298     uiItemL(col, "Center:", ICON_NONE);
01299     uiItemR(col, ptr, "center_x", 0, "X", ICON_NONE);
01300     uiItemR(col, ptr, "center_y", 0, "Y", ICON_NONE);
01301     
01302     uiItemS(layout);
01303     
01304     col= uiLayoutColumn(layout, 1);
01305     uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
01306     uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
01307     
01308     uiItemS(layout);
01309     
01310     uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE);
01311     uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE);
01312 }
01313 
01314 static void node_composit_buts_bilateralblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01315 {   
01316     uiLayout *col;
01317     
01318     col= uiLayoutColumn(layout, 1);
01319     uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
01320     uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE);
01321     uiItemR(col, ptr, "sigma_space", 0, NULL, ICON_NONE);
01322 }
01323 
01324 static void node_composit_buts_defocus(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01325 {
01326     uiLayout *sub, *col;
01327     
01328     col= uiLayoutColumn(layout, 0);
01329     uiItemL(col, "Bokeh Type:", ICON_NONE);
01330     uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE);
01331     uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
01332 
01333     uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
01334 
01335     col = uiLayoutColumn(layout, 0);
01336     uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer")==1);
01337     uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE);
01338 
01339     uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
01340     uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
01341 
01342     col = uiLayoutColumn(layout, 0);
01343     uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
01344     sub = uiLayoutColumn(col, 0);
01345     uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_preview"));
01346     uiItemR(sub, ptr, "samples", 0, NULL, ICON_NONE);
01347     
01348     col = uiLayoutColumn(layout, 0);
01349     uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
01350     sub = uiLayoutColumn(col, 0);
01351     uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer")==0);
01352     uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE);
01353 }
01354 
01355 /* qdn: glare node */
01356 static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01357 {   
01358     uiItemR(layout, ptr, "glare_type", 0, "", ICON_NONE);
01359     uiItemR(layout, ptr, "quality", 0, "", ICON_NONE);
01360 
01361     if (RNA_enum_get(ptr, "glare_type")!= 1) {
01362         uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
01363     
01364         if (RNA_enum_get(ptr, "glare_type")!= 0) 
01365             uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01366     }
01367     
01368     uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE);
01369     uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
01370 
01371     if (RNA_enum_get(ptr, "glare_type")== 2) {
01372         uiItemR(layout, ptr, "streaks", 0, NULL, ICON_NONE);
01373         uiItemR(layout, ptr, "angle_offset", 0, NULL, ICON_NONE);
01374     }
01375     if (RNA_enum_get(ptr, "glare_type")== 0 || RNA_enum_get(ptr, "glare_type")== 2) {
01376         uiItemR(layout, ptr, "fade", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01377         
01378         if (RNA_enum_get(ptr, "glare_type")== 0) 
01379             uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE);
01380     }
01381     if (RNA_enum_get(ptr, "glare_type")== 1) {
01382         uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE);
01383     }
01384 }
01385 
01386 static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01387 {   
01388     uiLayout *col;
01389 
01390     col = uiLayoutColumn(layout, 0);
01391     uiItemR(col, ptr, "tonemap_type", 0, "", ICON_NONE);
01392     if (RNA_enum_get(ptr, "tonemap_type")== 0) {
01393         uiItemR(col, ptr, "key", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01394         uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
01395         uiItemR(col, ptr, "gamma", 0, NULL, ICON_NONE);
01396     }
01397     else {
01398         uiItemR(col, ptr, "intensity", 0, NULL, ICON_NONE);
01399         uiItemR(col, ptr, "contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01400         uiItemR(col, ptr, "adaptation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01401         uiItemR(col, ptr, "correction", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01402     }
01403 }
01404 
01405 static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01406 {
01407     uiLayout *col;
01408 
01409     col= uiLayoutColumn(layout, 0);
01410     uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE);
01411 
01412     col = uiLayoutColumn(col, 0);
01413     uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector")==0);
01414     uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE);
01415     uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE);
01416 }
01417 
01418 static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01419 {
01420     uiLayout *col;
01421     
01422     col= uiLayoutColumn(layout, 0);
01423     uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE);
01424     uiItemR(col, ptr, "factor", 0, "Blur", ICON_NONE);
01425     
01426     col= uiLayoutColumn(layout, 1);
01427     uiItemL(col, "Speed:", ICON_NONE);
01428     uiItemR(col, ptr, "speed_min", 0, "Min", ICON_NONE);
01429     uiItemR(col, ptr, "speed_max", 0, "Max", ICON_NONE);
01430 
01431     uiItemR(layout, ptr, "use_curved", 0, NULL, ICON_NONE);
01432 }
01433 
01434 static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01435 {
01436     uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
01437 }
01438 
01439 static void node_composit_buts_flip(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01440 {
01441     uiItemR(layout, ptr, "axis", 0, "", ICON_NONE);
01442 }
01443 
01444 static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01445 {
01446     uiLayout *col;
01447 
01448     uiItemR(layout, ptr, "use_crop_size", 0, NULL, ICON_NONE);
01449     uiItemR(layout, ptr, "relative", 0, NULL, ICON_NONE);
01450 
01451     col= uiLayoutColumn(layout, 1);
01452     if (RNA_boolean_get(ptr, "relative")){
01453         uiItemR(col, ptr, "rel_min_x", 0, "Left", ICON_NONE);
01454         uiItemR(col, ptr, "rel_max_x", 0, "Right", ICON_NONE);
01455         uiItemR(col, ptr, "rel_min_y", 0, "Up", ICON_NONE);
01456         uiItemR(col, ptr, "rel_max_y", 0, "Down", ICON_NONE);
01457     } else {
01458         uiItemR(col, ptr, "min_x", 0, "Left", ICON_NONE);
01459         uiItemR(col, ptr, "max_x", 0, "Right", ICON_NONE);
01460         uiItemR(col, ptr, "min_y", 0, "Up", ICON_NONE);
01461         uiItemR(col, ptr, "max_y", 0, "Down", ICON_NONE);
01462     }
01463 }
01464 
01465 static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01466 {
01467     uiLayout *row, *col;
01468     
01469     col= uiLayoutColumn(layout, 0);
01470     row= uiLayoutRow(col, 0);
01471     uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01472     uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE);
01473 }
01474 
01475 static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01476 {
01477     uiLayout *col;
01478 
01479     col= uiLayoutColumn(layout, 0);
01480 
01481     uiItemL(col, "Inner Edge:", ICON_NONE);
01482     uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE);
01483     uiItemL(col, "Buffer Edge:", ICON_NONE);
01484     uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE);
01485 }
01486 
01487 static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01488 {
01489     uiLayout *sub, *col;
01490     
01491     col =uiLayoutColumn(layout, 1);
01492     uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
01493     uiItemR(col, ptr, "size", 0, NULL, ICON_NONE);
01494     
01495     col =uiLayoutColumn(layout, 1);
01496     uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE);
01497     sub =uiLayoutColumn(col, 0);
01498     uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
01499     uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
01500     
01501     col =uiLayoutColumn(layout, 1);
01502     uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE);
01503     sub =uiLayoutColumn(col, 0);
01504     uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
01505     uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
01506 }
01507 
01508 static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01509 {   
01510     uiLayout *col;
01511     
01512     col =uiLayoutColumn(layout, 1);
01513     uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE);
01514     uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE);
01515 }
01516 
01517 static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01518 {   
01519     uiLayout *col;
01520     
01521     col =uiLayoutColumn(layout, 1);
01522     uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE);
01523 }
01524 
01525 
01526 static void node_composit_buts_hue_sat(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01527 {
01528     uiLayout *col;
01529     
01530     col =uiLayoutColumn(layout, 0);
01531     uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01532     uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01533     uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01534 }
01535 
01536 static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01537 {
01538     uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
01539 }
01540 
01541 static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01542 {
01543     uiLayout *col;
01544     
01545     col =uiLayoutColumn(layout, 1);
01546     uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01547     uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01548 }
01549 
01550 static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01551 {
01552     uiLayout *col;
01553     
01554     col =uiLayoutColumn(layout, 1);
01555     uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01556     uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01557 }
01558 
01559 static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01560 {
01561     uiLayout *row, *col;
01562     
01563     uiItemL(layout, "Despill Channel:", ICON_NONE);
01564     row =uiLayoutRow(layout,0);
01565     uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01566 
01567     col= uiLayoutColumn(layout, 0);
01568     uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
01569 
01570     if(RNA_enum_get(ptr, "limit_method")==0) {
01571         uiItemL(col, "Limiting Channel:", ICON_NONE);
01572         row=uiLayoutRow(col,0);
01573         uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01574     }
01575 
01576     uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01577     uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE);
01578     if (RNA_boolean_get(ptr, "use_unspill")== 1) {
01579         uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01580         uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01581         uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01582     }
01583 }
01584 
01585 static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01586 {
01587     uiLayout *col;
01588     
01589     col= uiLayoutColumn(layout, 0);
01590     uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE);
01591     uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
01592     
01593     col= uiLayoutColumn(layout, 1);
01594     /*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now */
01595     uiItemR(col, ptr, "gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01596     /*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now*/
01597 }
01598 
01599 static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01600 {
01601     uiLayout *col;
01602     
01603     col= uiLayoutColumn(layout, 1);
01604     uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01605     uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01606     uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01607 }
01608 
01609 static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01610 {   
01611     uiLayout *col, *row;
01612 
01613     uiItemL(layout, "Color Space:", ICON_NONE);
01614     row= uiLayoutRow(layout, 0);
01615     uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01616 
01617     col=uiLayoutColumn(layout, 0);
01618     uiItemL(col, "Key Channel:", ICON_NONE);
01619     row= uiLayoutRow(col, 0);
01620     uiItemR(row, ptr, "matte_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01621 
01622     col =uiLayoutColumn(layout, 0);
01623 
01624     uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
01625     if(RNA_enum_get(ptr, "limit_method")==0) {
01626         uiItemL(col, "Limiting Channel:", ICON_NONE);
01627         row=uiLayoutRow(col,0);
01628         uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01629     }
01630 
01631     uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01632     uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01633 }
01634 
01635 static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01636 {
01637     uiLayout *col;
01638     
01639     col= uiLayoutColumn(layout, 1);
01640     uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01641     uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
01642 }
01643 
01644 static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01645 {
01646     uiItemR(layout, ptr, "alpha", 0, NULL, ICON_NONE);
01647 }
01648 
01649 static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01650 {
01651     uiItemR(layout, ptr, "index", 0, NULL, ICON_NONE);
01652     uiItemR(layout, ptr, "use_smooth_mask", 0, NULL, ICON_NONE);
01653 }
01654 
01655 static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01656 {
01657     bNode *node= ptr->data;
01658     NodeImageFile *nif= node->storage;
01659     PointerRNA imfptr;
01660 
01661     uiLayout *row;
01662 
01663     uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
01664 
01665     RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &nif->im_format, &imfptr);
01666     uiTemplateImageSettings(layout, &imfptr);
01667 
01668     row= uiLayoutRow(layout, 1);
01669     uiItemR(row, ptr, "frame_start", 0, "Start", ICON_NONE);
01670     uiItemR(row, ptr, "frame_end", 0, "End", ICON_NONE);
01671 }
01672 
01673 static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01674 {
01675     uiItemR(layout, ptr, "space", 0, "", ICON_NONE);
01676 }
01677 
01678 static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01679 {
01680     uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
01681 }
01682 
01683 static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01684 {
01685     uiLayout *col;
01686     
01687     col= uiLayoutColumn(layout, 0);
01688     uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
01689     uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE);
01690 }
01691 
01692 static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01693 {
01694     uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE);
01695 }
01696 
01697 static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01698 {
01699     uiItemR(layout, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01700 }
01701 
01702 static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01703 {
01704     uiLayout *split, *col, *row;
01705     
01706     uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
01707     
01708     if (RNA_enum_get(ptr, "correction_method")== 0) {
01709     
01710         split = uiLayoutSplit(layout, 0, 0);
01711         col = uiLayoutColumn(split, 0);
01712         uiTemplateColorWheel(col, ptr, "lift", 1, 1, 0, 1);
01713         row = uiLayoutRow(col, 0);
01714         uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE);
01715         
01716         col = uiLayoutColumn(split, 0);
01717         uiTemplateColorWheel(col, ptr, "gamma", 1, 1, 1, 1);
01718         row = uiLayoutRow(col, 0);
01719         uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE);
01720         
01721         col = uiLayoutColumn(split, 0);
01722         uiTemplateColorWheel(col, ptr, "gain", 1, 1, 1, 1);
01723         row = uiLayoutRow(col, 0);
01724         uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE);
01725 
01726     } else {
01727         
01728         split = uiLayoutSplit(layout, 0, 0);
01729         col = uiLayoutColumn(split, 0);
01730         uiTemplateColorWheel(col, ptr, "offset", 1, 1, 0, 1);
01731         row = uiLayoutRow(col, 0);
01732         uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE);
01733         
01734         col = uiLayoutColumn(split, 0);
01735         uiTemplateColorWheel(col, ptr, "power", 1, 1, 0, 1);
01736         row = uiLayoutRow(col, 0);
01737         uiItemR(row, ptr, "power", 0, NULL, ICON_NONE);
01738         
01739         col = uiLayoutColumn(split, 0);
01740         uiTemplateColorWheel(col, ptr, "slope", 1, 1, 0, 1);
01741         row = uiLayoutRow(col, 0);
01742         uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE);
01743     }
01744 
01745 }
01746 static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01747 {
01748     uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
01749 
01750     if (RNA_enum_get(ptr, "correction_method")== 0) {
01751 
01752     uiTemplateColorWheel(layout, ptr, "lift", 1, 1, 0, 1);
01753         uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
01754 
01755         uiTemplateColorWheel(layout, ptr, "gamma", 1, 1, 1, 1);
01756         uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
01757 
01758         uiTemplateColorWheel(layout, ptr, "gain", 1, 1, 1, 1);
01759         uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
01760     } else {
01761         uiTemplateColorWheel(layout, ptr, "offset", 1, 1, 0, 1);
01762         uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
01763 
01764         uiTemplateColorWheel(layout, ptr, "power", 1, 1, 0, 1);
01765         uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
01766 
01767         uiTemplateColorWheel(layout, ptr, "slope", 1, 1, 0, 1);
01768         uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
01769     }
01770 }
01771 
01772 
01773 static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01774 {
01775     uiTemplateCurveMapping(layout, ptr, "mapping", 'h', 0, 0);
01776 }
01777 
01778 static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01779 { 
01780     uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
01781 }
01782 
01783 static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
01784 {
01785     uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
01786 }
01787 
01788 static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr)
01789 {
01790     bNode *node= ptr->data;
01791 
01792     uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
01793 
01794     if(!node->id)
01795         return;
01796 
01797     uiItemR(layout, ptr, "filter_type", 0, "", 0);
01798 }
01799 
01800 static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01801 {
01802     uiItemR(layout, ptr, "filter_type", 0, "", 0);
01803 }
01804 
01805 static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr)
01806 {
01807     bNode *node= ptr->data;
01808 
01809     uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
01810 
01811     if(!node->id)
01812         return;
01813 
01814     uiItemR(layout, ptr, "distortion_type", 0, "", 0);
01815 }
01816 
01817 /* only once called */
01818 static void node_composit_set_butfunc(bNodeType *ntype)
01819 {
01820     ntype->uifuncbut = NULL;
01821     switch(ntype->type) {
01822         /* case NODE_GROUP:  note, typeinfo for group is generated... see "XXX ugly hack" */
01823 
01824         case CMP_NODE_IMAGE:
01825             ntype->uifunc= node_composit_buts_image;
01826             break;
01827         case CMP_NODE_R_LAYERS:
01828             ntype->uifunc= node_composit_buts_renderlayers;
01829             break;
01830         case CMP_NODE_NORMAL:
01831             ntype->uifunc= node_buts_normal;
01832             break;
01833         case CMP_NODE_CURVE_VEC:
01834             ntype->uifunc= node_buts_curvevec;
01835             break;
01836         case CMP_NODE_CURVE_RGB:
01837             ntype->uifunc= node_buts_curvecol;
01838             break;
01839         case CMP_NODE_VALUE:
01840             ntype->uifunc= node_buts_value;
01841             break;
01842         case CMP_NODE_RGB:
01843             ntype->uifunc= node_buts_rgb;
01844             break;
01845         case CMP_NODE_FLIP:
01846             ntype->uifunc= node_composit_buts_flip;
01847             break;
01848         case CMP_NODE_SPLITVIEWER:
01849             ntype->uifunc= node_composit_buts_splitviewer;
01850             break;
01851         case CMP_NODE_MIX_RGB:
01852             ntype->uifunc= node_buts_mix_rgb;
01853             break;
01854         case CMP_NODE_VALTORGB:
01855             ntype->uifunc= node_buts_colorramp;
01856             break;
01857         case CMP_NODE_CROP:
01858             ntype->uifunc= node_composit_buts_crop;
01859             break;
01860         case CMP_NODE_BLUR:
01861             ntype->uifunc= node_composit_buts_blur;
01862             break;
01863         case CMP_NODE_DBLUR:
01864             ntype->uifunc= node_composit_buts_dblur;
01865             break;
01866         case CMP_NODE_BILATERALBLUR:
01867             ntype->uifunc= node_composit_buts_bilateralblur;
01868             break;
01869         case CMP_NODE_DEFOCUS:
01870             ntype->uifunc = node_composit_buts_defocus;
01871             break;
01872         case CMP_NODE_GLARE:
01873             ntype->uifunc = node_composit_buts_glare;
01874             break;
01875         case CMP_NODE_TONEMAP:
01876             ntype->uifunc = node_composit_buts_tonemap;
01877             break;
01878         case CMP_NODE_LENSDIST:
01879             ntype->uifunc = node_composit_buts_lensdist;
01880             break;
01881         case CMP_NODE_VECBLUR:
01882             ntype->uifunc= node_composit_buts_vecblur;
01883             break;
01884         case CMP_NODE_FILTER:
01885             ntype->uifunc= node_composit_buts_filter;
01886             break;
01887         case CMP_NODE_MAP_VALUE:
01888             ntype->uifunc= node_composit_buts_map_value;
01889             break;
01890         case CMP_NODE_TIME:
01891             ntype->uifunc= node_buts_time;
01892             break;
01893         case CMP_NODE_ALPHAOVER:
01894             ntype->uifunc= node_composit_buts_alphaover;
01895             break;
01896         case CMP_NODE_HUE_SAT:
01897             ntype->uifunc= node_composit_buts_hue_sat;
01898             break;
01899         case CMP_NODE_TEXTURE:
01900             ntype->uifunc= node_buts_texture;
01901             break;
01902         case CMP_NODE_DILATEERODE:
01903             ntype->uifunc= node_composit_buts_dilateerode;
01904             break;
01905         case CMP_NODE_OUTPUT_FILE:
01906             ntype->uifunc= node_composit_buts_file_output;
01907             break;
01908         case CMP_NODE_DIFF_MATTE:
01909             ntype->uifunc=node_composit_buts_diff_matte;
01910             break;
01911         case CMP_NODE_DIST_MATTE:
01912             ntype->uifunc=node_composit_buts_distance_matte;
01913             break;
01914         case CMP_NODE_COLOR_SPILL:
01915             ntype->uifunc=node_composit_buts_color_spill;
01916             break;
01917         case CMP_NODE_CHROMA_MATTE:
01918             ntype->uifunc=node_composit_buts_chroma_matte;
01919             break;
01920         case CMP_NODE_COLOR_MATTE:
01921             ntype->uifunc=node_composit_buts_color_matte;
01922             break;
01923         case CMP_NODE_SCALE:
01924             ntype->uifunc= node_composit_buts_scale;
01925             break;
01926         case CMP_NODE_ROTATE:
01927             ntype->uifunc=node_composit_buts_rotate;
01928             break;
01929         case CMP_NODE_CHANNEL_MATTE:
01930             ntype->uifunc= node_composit_buts_channel_matte;
01931             break;
01932         case CMP_NODE_LUMA_MATTE:
01933             ntype->uifunc= node_composit_buts_luma_matte;
01934             break;
01935         case CMP_NODE_MAP_UV:
01936             ntype->uifunc= node_composit_buts_map_uv;
01937             break;
01938         case CMP_NODE_ID_MASK:
01939             ntype->uifunc= node_composit_buts_id_mask;
01940             break;
01941         case CMP_NODE_DOUBLEEDGEMASK:
01942             ntype->uifunc= node_composit_buts_double_edge_mask;
01943             break;
01944         case CMP_NODE_MATH:
01945             ntype->uifunc= node_buts_math;
01946             break;
01947         case CMP_NODE_INVERT:
01948             ntype->uifunc= node_composit_buts_invert;
01949             break;
01950         case CMP_NODE_PREMULKEY:
01951             ntype->uifunc= node_composit_buts_premulkey;
01952             break;
01953         case CMP_NODE_VIEW_LEVELS:
01954             ntype->uifunc=node_composit_buts_view_levels;
01955             break;
01956         case CMP_NODE_COLORBALANCE:
01957             ntype->uifunc=node_composit_buts_colorbalance;
01958             ntype->uifuncbut=node_composit_buts_colorbalance_but;
01959             break;
01960         case CMP_NODE_HUECORRECT:
01961             ntype->uifunc=node_composit_buts_huecorrect;
01962             break;
01963         case CMP_NODE_ZCOMBINE:
01964             ntype->uifunc=node_composit_buts_zcombine;
01965             break;
01966         case CMP_NODE_COMBYCCA:
01967         case CMP_NODE_SEPYCCA:
01968             ntype->uifunc=node_composit_buts_ycc;
01969             break;
01970         case CMP_NODE_MOVIECLIP:
01971             ntype->uifunc= node_composit_buts_movieclip;
01972             break;
01973         case CMP_NODE_STABILIZE2D:
01974             ntype->uifunc= node_composit_buts_stabilize2d;
01975             break;
01976         case CMP_NODE_TRANSFORM:
01977             ntype->uifunc= node_composit_buts_transform;
01978             break;
01979         case CMP_NODE_MOVIEDISTORTION:
01980             ntype->uifunc= node_composit_buts_moviedistortion;
01981             break;
01982         default:
01983             ntype->uifunc= NULL;
01984     }
01985     if (ntype->uifuncbut == NULL) ntype->uifuncbut = ntype->uifunc;
01986 
01987 }
01988 
01989 /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
01990 
01991 static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
01992 {
01993     uiLayout *col;
01994     
01995     col= uiLayoutColumn(layout, 1);
01996     uiItemR(col, ptr, "offset", 0, "Offset", ICON_NONE);
01997     uiItemR(col, ptr, "offset_frequency", 0, "Frequency", ICON_NONE);
01998     
01999     col= uiLayoutColumn(layout, 1);
02000     uiItemR(col, ptr, "squash", 0, "Squash", ICON_NONE);
02001     uiItemR(col, ptr, "squash_frequency", 0, "Frequency", ICON_NONE);
02002 }
02003 
02004 static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
02005 {
02006     PointerRNA tex_ptr;
02007     bNode *node= ptr->data;
02008     ID *id= ptr->id.data;
02009     Tex *tex = (Tex *)node->storage;
02010     uiLayout *col, *row;
02011     
02012     RNA_pointer_create(id, &RNA_Texture, tex, &tex_ptr);
02013 
02014     col= uiLayoutColumn(layout, 0);
02015 
02016     switch( tex->type ) {
02017         case TEX_BLEND:
02018             uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
02019             row= uiLayoutRow(col, 0);
02020             uiItemR(row, &tex_ptr, "use_flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02021             break;
02022 
02023         case TEX_MARBLE:
02024             row= uiLayoutRow(col, 0);
02025             uiItemR(row, &tex_ptr, "marble_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02026             row= uiLayoutRow(col, 0);
02027             uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02028             row= uiLayoutRow(col, 0);
02029             uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
02030             row= uiLayoutRow(col, 0);
02031             uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02032             break;
02033 
02034         case TEX_MAGIC:
02035             uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE);
02036             break;
02037 
02038         case TEX_STUCCI:
02039             row= uiLayoutRow(col, 0);
02040             uiItemR(row, &tex_ptr, "stucci_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02041             row= uiLayoutRow(col, 0);
02042             uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02043             uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
02044             break;
02045 
02046         case TEX_WOOD:
02047             uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
02048             uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE);
02049             row= uiLayoutRow(col, 0);
02050             uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02051             row= uiLayoutRow(col, 0);
02052             uiLayoutSetActive(row, !(RNA_enum_get(&tex_ptr, "wood_type")==TEX_BAND || RNA_enum_get(&tex_ptr, "wood_type")==TEX_RING)); 
02053             uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02054             break;
02055             
02056         case TEX_CLOUDS:
02057             uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
02058             row= uiLayoutRow(col, 0);
02059             uiItemR(row, &tex_ptr, "cloud_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02060             row= uiLayoutRow(col, 0);
02061             uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
02062             uiItemR(col, &tex_ptr, "noise_depth", UI_ITEM_R_EXPAND, "Depth", ICON_NONE);
02063             break;
02064             
02065         case TEX_DISTNOISE:
02066             uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
02067             uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE);
02068             break;
02069 
02070         case TEX_MUSGRAVE:
02071             uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE);
02072             uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
02073             break;
02074         case TEX_VORONOI:
02075             uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE);
02076             if(tex->vn_distm == TEX_MINKOVSKY) {
02077                 uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE);
02078             }
02079             uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE);
02080             break;
02081     }
02082 }
02083 
02084 static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
02085 {
02086     uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
02087 }
02088 
02089 static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
02090 {
02091     uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
02092 }
02093 
02094 /* only once called */
02095 static void node_texture_set_butfunc(bNodeType *ntype)
02096 {
02097     ntype->uifuncbut = NULL;
02098     if( ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX ) {
02099         ntype->uifunc = node_texture_buts_proc;
02100     }
02101     else switch(ntype->type) {
02102         
02103         case TEX_NODE_MATH:
02104             ntype->uifunc = node_buts_math;
02105             break;
02106         
02107         case TEX_NODE_MIX_RGB:
02108             ntype->uifunc = node_buts_mix_rgb;
02109             break;
02110             
02111         case TEX_NODE_VALTORGB:
02112             ntype->uifunc = node_buts_colorramp;
02113             break;
02114             
02115         case TEX_NODE_CURVE_RGB:
02116             ntype->uifunc= node_buts_curvecol;
02117             break;
02118             
02119         case TEX_NODE_CURVE_TIME:
02120             ntype->uifunc = node_buts_time;
02121             break;
02122             
02123         case TEX_NODE_TEXTURE:
02124             ntype->uifunc = node_buts_texture;
02125             break;
02126             
02127         case TEX_NODE_BRICKS:
02128             ntype->uifunc = node_texture_buts_bricks;
02129             break;
02130             
02131         case TEX_NODE_IMAGE:
02132             ntype->uifunc = node_texture_buts_image;
02133             break;
02134             
02135         case TEX_NODE_OUTPUT:
02136             ntype->uifunc = node_texture_buts_output;
02137             break;
02138     }
02139     if (ntype->uifuncbut == NULL) ntype->uifuncbut = ntype->uifunc;
02140 }
02141 
02142 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
02143 
02144 void ED_init_node_butfuncs(void)
02145 {
02146     bNodeTreeType *treetype;
02147     bNodeType *ntype;
02148     bNodeSocketType *stype;
02149     int i;
02150     
02151     /* node type ui functions */
02152     for (i=0; i < NUM_NTREE_TYPES; ++i) {
02153         treetype = ntreeGetType(i);
02154         if (treetype) {
02155             for (ntype= treetype->node_types.first; ntype; ntype= ntype->next) {
02156                 /* default ui functions */
02157                 ntype->drawfunc = node_draw_default;
02158                 ntype->drawupdatefunc = node_update_default;
02159                 ntype->uifunc = NULL;
02160                 ntype->uifuncbut = NULL;
02161                 ntype->resize_area_func = node_resize_area_default;
02162                 
02163                 node_common_set_butfunc(ntype);
02164                 
02165                 switch (i) {
02166                 case NTREE_COMPOSIT:
02167                     node_composit_set_butfunc(ntype);
02168                     break;
02169                 case NTREE_SHADER:
02170                     node_shader_set_butfunc(ntype);
02171                     break;
02172                 case NTREE_TEXTURE:
02173                     node_texture_set_butfunc(ntype);
02174                     break;
02175                 }
02176             }
02177         }
02178     }
02179     
02180     /* socket type ui functions */
02181     for (i=0; i < NUM_SOCKET_TYPES; ++i) {
02182         stype = ntreeGetSocketType(i);
02183         if (stype) {
02184             switch(stype->type) {
02185             case SOCK_FLOAT:
02186             case SOCK_INT:
02187             case SOCK_BOOLEAN:
02188                 stype->buttonfunc = node_socket_button_default;
02189                 break;
02190             case SOCK_VECTOR:
02191                 stype->buttonfunc = node_socket_button_components;
02192                 break;
02193             case SOCK_RGBA:
02194                 stype->buttonfunc = node_socket_button_color;
02195                 break;
02196             case SOCK_SHADER:
02197                 stype->buttonfunc = node_socket_button_label;
02198                 break;
02199             default:
02200                 stype->buttonfunc = NULL;
02201             }
02202         }
02203     }
02204 }
02205 
02206 /* ************** Generic drawing ************** */
02207 
02208 void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
02209 {
02210     
02211     if((snode->flag & SNODE_BACKDRAW) && snode->treetype==NTREE_COMPOSIT) {
02212         Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
02213         void *lock;
02214         ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock);
02215         if(ibuf) {
02216             float x, y; 
02217             
02218             glMatrixMode(GL_PROJECTION);
02219             glPushMatrix();
02220             glMatrixMode(GL_MODELVIEW);
02221             glPushMatrix();
02222 
02223             /* keep this, saves us from a version patch */
02224             if(snode->zoom==0.0f) snode->zoom= 1.0f;
02225             
02226             /* somehow the offset has to be calculated inverse */
02227             
02228             glaDefine2DArea(&ar->winrct);
02229             /* ortho at pixel level curarea */
02230             wmOrtho2(-0.375, ar->winx-0.375, -0.375, ar->winy-0.375);
02231             
02232             x = (ar->winx-snode->zoom*ibuf->x)/2 + snode->xof;
02233             y = (ar->winy-snode->zoom*ibuf->y)/2 + snode->yof;
02234             
02235             if(!ibuf->rect) {
02236                 if(color_manage)
02237                     ibuf->profile = IB_PROFILE_LINEAR_RGB;
02238                 else
02239                     ibuf->profile = IB_PROFILE_NONE;
02240                 IMB_rect_from_float(ibuf);
02241             }
02242 
02243             if(ibuf->rect) {
02244                 if (snode->flag & SNODE_SHOW_ALPHA) {
02245                     glPixelZoom(snode->zoom, snode->zoom);
02246                     /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
02247                     if(ENDIAN_ORDER == B_ENDIAN)
02248                         glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
02249                     
02250                     glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, ibuf->rect);
02251                     
02252                     glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
02253                     glPixelZoom(1.0f, 1.0f);
02254                 } else if (snode->flag & SNODE_USE_ALPHA) {
02255                     glEnable(GL_BLEND);
02256                     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
02257                     glPixelZoom(snode->zoom, snode->zoom);
02258                     
02259                     glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
02260                     
02261                     glPixelZoom(1.0f, 1.0f);
02262                     glDisable(GL_BLEND);
02263                 } else {
02264                     glPixelZoom(snode->zoom, snode->zoom);
02265                     
02266                     glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
02267                     
02268                     glPixelZoom(1.0f, 1.0f);
02269                 }
02270             }
02271             
02272             glMatrixMode(GL_PROJECTION);
02273             glPopMatrix();
02274             glMatrixMode(GL_MODELVIEW);
02275             glPopMatrix();
02276         }
02277 
02278         BKE_image_release_ibuf(ima, lock);
02279     }
02280 }
02281 
02282 #if 0
02283 /* note: needs to be userpref or opengl profile option */
02284 static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
02285 {
02286 
02287     draw_nodespace_grid(snode);
02288     
02289     if(snode->flag & SNODE_BACKDRAW) {
02290         Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
02291         ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
02292         if(ibuf) {
02293             int x, y;
02294             float zoom = 1.0;
02295 
02296             glMatrixMode(GL_PROJECTION);
02297             glPushMatrix();
02298             glMatrixMode(GL_MODELVIEW);
02299             glPushMatrix();
02300             
02301             glaDefine2DArea(&sa->winrct);
02302 
02303             if(ibuf->x > sa->winx || ibuf->y > sa->winy) {
02304                 float zoomx, zoomy;
02305                 zoomx= (float)sa->winx/ibuf->x;
02306                 zoomy= (float)sa->winy/ibuf->y;
02307                 zoom = MIN2(zoomx, zoomy);
02308             }
02309             
02310             x = (sa->winx-zoom*ibuf->x)/2 + snode->xof;
02311             y = (sa->winy-zoom*ibuf->y)/2 + snode->yof;
02312 
02313             glPixelZoom(zoom, zoom);
02314 
02315             glColor4f(1.0, 1.0, 1.0, 1.0);
02316             if(ibuf->rect)
02317                 glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
02318             else if(ibuf->channels==4)
02319                 glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float);
02320 
02321             glPixelZoom(1.0, 1.0);
02322 
02323             glMatrixMode(GL_PROJECTION);
02324             glPopMatrix();
02325             glMatrixMode(GL_MODELVIEW);
02326             glPopMatrix();
02327         }
02328     }
02329 }
02330 #endif
02331 
02332 /* if v2d not NULL, it clips and returns 0 if not visible */
02333 int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
02334 {
02335     float dist, vec[4][2];
02336     
02337     /* in v0 and v3 we put begin/end points */
02338     if(link->fromsock) {
02339         vec[0][0]= link->fromsock->locx;
02340         vec[0][1]= link->fromsock->locy;
02341     }
02342     else {
02343         if(snode==NULL) return 0;
02344         vec[0][0]= snode->mx;
02345         vec[0][1]= snode->my;
02346     }
02347     if(link->tosock) {
02348         vec[3][0]= link->tosock->locx;
02349         vec[3][1]= link->tosock->locy;
02350     }
02351     else {
02352         if(snode==NULL) return 0;
02353         vec[3][0]= snode->mx;
02354         vec[3][1]= snode->my;
02355     }
02356 
02357     dist= UI_GetThemeValue(TH_NODE_CURVING)*0.10f*ABS(vec[0][0] - vec[3][0]);
02358     
02359     /* check direction later, for top sockets */
02360     vec[1][0]= vec[0][0]+dist;
02361     vec[1][1]= vec[0][1];
02362     
02363     vec[2][0]= vec[3][0]-dist;
02364     vec[2][1]= vec[3][1];
02365     
02366     if(v2d && MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax); /* clipped */  
02367     else if (v2d && MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin); /* clipped */
02368     else {
02369         
02370         /* always do all three, to prevent data hanging around */
02371         forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2);
02372         forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2);
02373         
02374         return 1;
02375     }
02376     return 0;
02377 }
02378 
02379 #define LINK_RESOL  24
02380 void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 )
02381 {
02382     float coord_array[LINK_RESOL+1][2];
02383     
02384     if(node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) {
02385         float dist, spline_step = 0.0f;
02386         int i;
02387         
02388         /* store current linewidth */
02389         float linew;
02390         glGetFloatv(GL_LINE_WIDTH, &linew);
02391         
02392         /* we can reuse the dist variable here to increment the GL curve eval amount*/
02393         dist = 1.0f/(float)LINK_RESOL;
02394         
02395         glEnable(GL_LINE_SMOOTH);
02396         
02397         if(do_triple) {
02398             UI_ThemeColorShadeAlpha(th_col3, -80, -120);
02399             glLineWidth(4.0f);
02400             
02401             glBegin(GL_LINE_STRIP);
02402             for(i=0; i<=LINK_RESOL; i++) {
02403                 glVertex2fv(coord_array[i]);
02404             }
02405             glEnd();
02406         }
02407         
02408         /* XXX using GL_LINES for shaded node lines is a workaround
02409          * for Intel hardware, this breaks with GL_LINE_STRIP and
02410          * changing color in begin/end blocks.
02411          */
02412         glLineWidth(1.5f);
02413         if(do_shaded) {
02414             glBegin(GL_LINES);
02415             for(i=0; i<LINK_RESOL; i++) {
02416                 UI_ThemeColorBlend(th_col1, th_col2, spline_step);
02417                 glVertex2fv(coord_array[i]);
02418                 
02419                 UI_ThemeColorBlend(th_col1, th_col2, spline_step+dist);
02420                 glVertex2fv(coord_array[i+1]);
02421                 
02422                 spline_step += dist;
02423             }
02424             glEnd();
02425         }
02426         else {
02427             UI_ThemeColor(th_col1);
02428             glBegin(GL_LINE_STRIP);
02429             for(i=0; i<=LINK_RESOL; i++) {
02430                 glVertex2fv(coord_array[i]);
02431             }
02432             glEnd();
02433         }
02434         
02435         glDisable(GL_LINE_SMOOTH);
02436         
02437         /* restore previuos linewidth */
02438         glLineWidth(linew);
02439     }
02440 }
02441 
02442 static void node_link_straight_points(View2D *UNUSED(v2d), SpaceNode *snode, bNodeLink *link, float coord_array[][2])
02443 {
02444     if(link->fromsock) {
02445         coord_array[0][0]= link->fromsock->locx;
02446         coord_array[0][1]= link->fromsock->locy;
02447     }
02448     else {
02449         if(snode==NULL) return;
02450         coord_array[0][0]= snode->mx;
02451         coord_array[0][1]= snode->my;
02452     }
02453     if(link->tosock) {
02454         coord_array[1][0]= link->tosock->locx;
02455         coord_array[1][1]= link->tosock->locy;
02456     }
02457     else {
02458         if(snode==NULL) return;
02459         coord_array[1][0]= snode->mx;
02460         coord_array[1][1]= snode->my;
02461     }
02462 }
02463 
02464 void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3 )
02465 {
02466     float coord_array[2][2];
02467     float linew;
02468     int i;
02469     
02470     node_link_straight_points(v2d, snode, link, coord_array);
02471     
02472     /* store current linewidth */
02473     glGetFloatv(GL_LINE_WIDTH, &linew);
02474     
02475     glEnable(GL_LINE_SMOOTH);
02476     
02477     if(do_triple) {
02478         UI_ThemeColorShadeAlpha(th_col3, -80, -120);
02479         glLineWidth(4.0f);
02480         
02481         glBegin(GL_LINES);
02482         glVertex2fv(coord_array[0]);
02483         glVertex2fv(coord_array[1]);
02484         glEnd();
02485     }
02486     
02487     UI_ThemeColor(th_col1);
02488     glLineWidth(1.5f);
02489     
02490     /* XXX using GL_LINES for shaded node lines is a workaround
02491      * for Intel hardware, this breaks with GL_LINE_STRIP and
02492      * changing color in begin/end blocks.
02493      */
02494     if(do_shaded) {
02495         glBegin(GL_LINES);
02496         for (i=0; i < LINK_RESOL-1; ++i) {
02497             float t= (float)i/(float)(LINK_RESOL-1);
02498             UI_ThemeColorBlend(th_col1, th_col2, t);
02499             glVertex2f((1.0f-t)*coord_array[0][0]+t*coord_array[1][0], (1.0f-t)*coord_array[0][1]+t*coord_array[1][1]);
02500             
02501             t= (float)(i+1)/(float)(LINK_RESOL-1);
02502             UI_ThemeColorBlend(th_col1, th_col2, t);
02503             glVertex2f((1.0f-t)*coord_array[0][0]+t*coord_array[1][0], (1.0f-t)*coord_array[0][1]+t*coord_array[1][1]);
02504         }
02505         glEnd();
02506     }
02507     else {
02508         glBegin(GL_LINE_STRIP);
02509         for (i=0; i < LINK_RESOL; ++i) {
02510             float t= (float)i/(float)(LINK_RESOL-1);
02511             glVertex2f((1.0f-t)*coord_array[0][0]+t*coord_array[1][0], (1.0f-t)*coord_array[0][1]+t*coord_array[1][1]);
02512         }
02513         glEnd();
02514     }
02515     
02516     glDisable(GL_LINE_SMOOTH);
02517     
02518     /* restore previuos linewidth */
02519     glLineWidth(linew);
02520 }
02521 
02522 /* note; this is used for fake links in groups too */
02523 void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
02524 {
02525     int do_shaded= 0, th_col1= TH_HEADER, th_col2= TH_HEADER;
02526     int do_triple= 0, th_col3= TH_WIRE;
02527     
02528     if(link->fromsock==NULL && link->tosock==NULL)
02529         return;
02530     
02531     /* new connection */
02532     if(!link->fromsock || !link->tosock) {
02533         th_col1 = TH_ACTIVE;
02534         do_triple = 1;
02535     }
02536     else {
02537         /* going to give issues once... */
02538         if(link->tosock->flag & SOCK_UNAVAIL)
02539             return;
02540         if(link->fromsock->flag & SOCK_UNAVAIL)
02541             return;
02542         
02543         /* a bit ugly... but thats how we detect the internal group links */
02544         if(!link->fromnode || !link->tonode) {
02545             UI_ThemeColorBlend(TH_BACK, TH_WIRE, 0.5f);
02546             do_shaded= 0;
02547         }
02548         else {
02549             /* check cyclic */
02550             if((link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) && (link->flag & NODE_LINK_VALID)) {
02551                 /* special indicated link, on drop-node */
02552                 if(link->flag & NODE_LINKFLAG_HILITE) {
02553                     th_col1= th_col2= TH_ACTIVE;
02554                 }
02555                 else {
02556                     /* regular link */
02557                     if(link->fromnode->flag & SELECT)
02558                         th_col1= TH_EDGE_SELECT;
02559                     if(link->tonode->flag & SELECT)
02560                         th_col2= TH_EDGE_SELECT;
02561                 }
02562                 do_shaded= 1;
02563                 do_triple= 1;
02564             }               
02565             else {
02566                 th_col1 = TH_REDALERT;
02567             }
02568         }
02569     }
02570     
02571     node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
02572 //  node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
02573 }