Merging r46725 through r46963 from trunk into soc-2011-tomato
[blender.git] / source / blender / editors / space_node / drawnode.c
index 42aea32..fcc92ff 100644 (file)
@@ -53,6 +53,8 @@
 #include "BKE_main.h"
 #include "BKE_node.h"
 
+#include "BLF_api.h"
+
 #include "NOD_composite.h"
 #include "NOD_shader.h"
 
@@ -79,6 +81,9 @@
 
 #include "node_intern.h"
 
+// XXX interface.h
+extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
+
 /* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
 
 static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
@@ -98,71 +103,23 @@ static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
        uiDefBut(block, LABEL, 0, sock->name, x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
 }
 
-/* draw function for file output node sockets.
- * XXX a bit ugly use atm, called from datatype button functions,
- * since all node types and callbacks only use data type without struct_type.
- */
-static void node_socket_button_output_file(const bContext *C, uiBlock *block,
-                                           bNodeTree *ntree, bNode *node, bNodeSocket *sock,
-                                           const char *UNUSED(name), int x, int y, int width)
-{
-       uiLayout *layout, *row;
-       PointerRNA nodeptr, sockptr, imfptr;
-       int imtype;
-       int rx, ry;
-       RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
-       RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr);
-       
-       layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y+NODE_DY, width, 20, UI_GetStyle());
-       row = uiLayoutRow(layout, 0);           
-       
-       uiItemL(row, sock->name, 0);
-       
-       imfptr = RNA_pointer_get(&nodeptr, "format");
-       imtype = RNA_enum_get(&imfptr, "file_format");
-       /* in multilayer format all socket format details are ignored */
-       if (imtype != R_IMF_IMTYPE_MULTILAYER) {
-               PropertyRNA *imtype_prop;
-               const char *imtype_name;
-               
-               if (!RNA_boolean_get(&sockptr, "use_node_format"))
-                       imfptr = RNA_pointer_get(&sockptr, "format");
-               
-               imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
-               RNA_property_enum_name((bContext*)C, &imfptr, imtype_prop, RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
-               uiBlockSetEmboss(block, UI_EMBOSSP);
-               uiItemL(row, imtype_name, 0);
-               uiBlockSetEmboss(block, UI_EMBOSSN);
-       }
-       
-       uiBlockLayoutResolve(block, &rx, &ry);
-}
-
 static void node_socket_button_default(const bContext *C, uiBlock *block,
                                                                bNodeTree *ntree, bNode *node, bNodeSocket *sock,
                                                                const char *name, int x, int y, int width)
 {
-       switch (sock->struct_type) {
-       case SOCK_STRUCT_NONE: {
-               if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
-                       node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
-               else {
-                       PointerRNA ptr;
-                       uiBut *bt;
-                       
-                       RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-                       
-                       bt = uiDefButR(block, NUM, B_NODE_EXEC, name,
-                                                  x, y+1, width, NODE_DY-2, 
-                                                  &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
-                       if (node)
-                               uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
-               }
-               break;
-       }
-       case SOCK_STRUCT_OUTPUT_FILE:
-               node_socket_button_output_file(C, block, ntree, node, sock, name, x, y, width);
-               break;
+       if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
+               node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
+       else {
+               PointerRNA ptr;
+               uiBut *bt;
+               
+               RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
+               
+               bt = uiDefButR(block, NUM, B_NODE_EXEC, name,
+                                          x, y+1, width, NODE_DY-2, 
+                                          &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
+               if (node)
+                       uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
        }
 }
 
@@ -192,33 +149,25 @@ static void node_socket_button_components(const bContext *C, uiBlock *block,
                                                                   bNodeTree *ntree, bNode *node, bNodeSocket *sock,
                                                                   const char *name, int x, int y, int width)
 {
-       switch (sock->struct_type) {
-       case SOCK_STRUCT_NONE: {
-               if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
-                       node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
-               else {
-                       PointerRNA ptr;
-                       SocketComponentMenuArgs *args;
-                       
-                       RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-                       
-                       args= MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
-                       
-                       args->ptr = ptr;
-                       args->x = x;
-                       args->y = y;
-                       args->width = width;
-                       args->cb = node_sync_cb;
-                       args->arg1 = CTX_wm_space_node(C);
-                       args->arg2 = node;
-                       
-                       uiDefBlockButN(block, socket_component_menu, args, name, x, y+1, width, NODE_DY-2, "");
-               }
-               break;
-       }
-       case SOCK_STRUCT_OUTPUT_FILE:
-               node_socket_button_output_file(C, block, ntree, node, sock, name, x, y, width);
-               break;
+       if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
+               node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
+       else {
+               PointerRNA ptr;
+               SocketComponentMenuArgs *args;
+               
+               RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
+               
+               args= MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
+               
+               args->ptr = ptr;
+               args->x = x;
+               args->y = y;
+               args->width = width;
+               args->cb = node_sync_cb;
+               args->arg1 = CTX_wm_space_node(C);
+               args->arg2 = node;
+               
+               uiDefBlockButN(block, socket_component_menu, args, name, x, y+1, width, NODE_DY-2, "");
        }
 }
 
@@ -226,35 +175,52 @@ static void node_socket_button_color(const bContext *C, uiBlock *block,
                                                          bNodeTree *ntree, bNode *node, bNodeSocket *sock,
                                                          const char *name, int x, int y, int width)
 {
-       /* XXX would be nicer to have draw function based on sock->struct_type as well,
-        * but currently socket types are completely identified by data type only.
-        */
-       
-       switch (sock->struct_type) {
-       case SOCK_STRUCT_NONE: {
-               if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
-                       node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
-               else {
-                       PointerRNA ptr;
-                       uiBut *bt;
-                       int labelw= width - 40;
-                       RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
-                       
-                       bt=uiDefButR(block, COL, B_NODE_EXEC, "",
-                                                x, y+2, (labelw>0 ? 40 : width), NODE_DY-2, 
-                                                &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
-                       if (node)
-                               uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
-                       
-                       if (name[0]!='\0' && labelw>0)
-                               uiDefBut(block, LABEL, 0, name, x + 40, y+2, labelw, NODE_DY-2, NULL, 0, 0, 0, 0, "");
-               }
-               break;
+       if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
+               node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
+       else {
+               PointerRNA ptr;
+               uiBut *bt;
+               int labelw= width - 40;
+               RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
+               
+               bt=uiDefButR(block, COL, B_NODE_EXEC, "",
+                                        x, y+2, (labelw>0 ? 40 : width), NODE_DY-2, 
+                                        &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
+               if (node)
+                       uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
+               
+               if (name[0]!='\0' && labelw>0)
+                       uiDefBut(block, LABEL, 0, name, x + 40, y+2, labelw, NODE_DY-2, NULL, 0, 0, 0, 0, "");
        }
-       case SOCK_STRUCT_OUTPUT_FILE:
-               node_socket_button_output_file(C, block, ntree, node, sock, name, x, y, width);
-               break;
+}
+
+/* standard draw function, display the default input value */
+static void node_draw_input_default(const bContext *C, uiBlock *block,
+                                     bNodeTree *ntree, bNode *node, bNodeSocket *sock,
+                                     const char *name, int x, int y, int width)
+{
+       bNodeSocketType *stype = ntreeGetSocketType(sock->type);
+       if (stype->buttonfunc)
+               stype->buttonfunc(C, block, ntree, node, sock, name, x, y, width);
+       else
+               node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
+}
+
+static void node_draw_output_default(const bContext *C, uiBlock *block,
+                                     bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock,
+                                     const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width))
+{
+       SpaceNode *snode = CTX_wm_space_node(C);
+       float slen;
+       int ofs = 0;
+       UI_ThemeColor(TH_TEXT);
+       slen= snode->aspect*UI_GetStringWidth(name);
+       while (slen > node->width) {
+               ofs++;
+               slen= snode->aspect*UI_GetStringWidth(name+ofs);
        }
+       uiDefBut(block, LABEL, 0, name+ofs, (short)(sock->locx-15.0f-slen), (short)(sock->locy-9.0f), 
+             (short)(node->width-NODE_DY), NODE_DY,  NULL, 0, 0, 0, 0, "");
 }
 
 /* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
@@ -266,7 +232,7 @@ static void node_draw_socket_new(bNodeSocket *sock, float size)
        
        /* 16 values of sin function */
        static float si[16] = {
-               0.00000000f, 0.39435585f,0.72479278f,0.93775213f,
+               0.00000000f, 0.39435585f, 0.72479278f,0.93775213f,
                0.99871650f,0.89780453f,0.65137248f,0.29936312f,
                -0.10116832f,-0.48530196f,-0.79077573f,-0.96807711f,
                -0.98846832f,-0.84864425f,-0.57126821f,-0.20129852f
@@ -289,12 +255,12 @@ static void node_draw_socket_new(bNodeSocket *sock, float size)
        
        glColor4ub(0, 0, 0, 150);
        glEnable(GL_BLEND);
-       glEnable( GL_LINE_SMOOTH );
+       glEnable(GL_LINE_SMOOTH);
        glBegin(GL_LINE_LOOP);
        for (a=0; a<16; a++)
                glVertex2f(x+size*si[a], y+size*co[a]);
        glEnd();
-       glDisable( GL_LINE_SMOOTH );
+       glDisable(GL_LINE_SMOOTH);
        glDisable(GL_BLEND);
 }
 #endif
@@ -442,7 +408,7 @@ static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
        nodeSetActive(ntree, node);
        
        if ( ntree->type == NTREE_TEXTURE )
-               ntreeTexCheckCyclics( ntree );
+               ntreeTexCheckCyclics(ntree);
        
        // allqueue(REDRAWBUTSSHADING, 0);
        // allqueue(REDRAWNODE, 0);
@@ -513,15 +479,21 @@ static int node_resize_area_default(bNode *node, int x, int y)
                rctf totr= node->totr;
                /* right part of node */
                totr.xmin = node->totr.xmax-20.0f;
-               return BLI_in_rctf(&totr, x, y);
+               if (BLI_in_rctf(&totr, x, y))
+                       return NODE_RESIZE_RIGHT;
+               else
+                       return 0;
        }
        else {
-               /* rect we're interested in is just the bottom right corner */
+               const float size = 10.0f;
                rctf totr= node->totr;
-               /* bottom right corner */
-               totr.xmin = totr.xmax-10.0f;
-               totr.ymax = totr.ymin+10.0f;
-               return BLI_in_rctf(&totr, x, y);
+               int dir = 0;
+               
+               if (x >= totr.xmax-size && x < totr.xmax && y >= totr.ymin && y < totr.ymax)
+                       dir |= NODE_RESIZE_RIGHT;
+               if (x >= totr.xmin && x < totr.xmin+size && y >= totr.ymin && y < totr.ymax)
+                       dir |= NODE_RESIZE_LEFT;
+               return dir;
        }
 }
 
@@ -550,7 +522,7 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
                int dy;
                
                /* get "global" coords */
-               nodeSpaceCoords(gnode, &locx, &locy);
+               nodeToView(gnode, 0.0f, 0.0f, &locx, &locy);
                
                /* center them, is a bit of abuse of locx and locy though */
                node_update_nodetree(C, ngroup, locx, locy);
@@ -870,16 +842,16 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN
                /* group node outline */
                uiSetRoundBox(UI_CNR_ALL);
                glColor4ub(200, 200, 200, 140);
-               glEnable( GL_LINE_SMOOTH );
+               glEnable(GL_LINE_SMOOTH);
                uiDrawBox(GL_LINE_LOOP, rect.xmin-node_group_frame, rect.ymin, rect.xmax+node_group_frame, rect.ymax+group_header, BASIS_RAD);
-               glDisable( GL_LINE_SMOOTH );
+               glDisable(GL_LINE_SMOOTH);
                glDisable(GL_BLEND);
                
                /* backdrop title */
                UI_ThemeColor(TH_TEXT_HI);
        
                layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, (short)(rect.xmin+15), (short)(rect.ymax+group_header),
-                                                          MIN2((int)(rect.xmax - rect.xmin-18.0f), node_group_frame+20), group_header, UI_GetStyle());
+                                      MIN2((int)(rect.xmax - rect.xmin-18.0f), node_group_frame+20), group_header, UI_GetStyle());
                RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr);
                uiTemplateIDBrowse(layout, (bContext*)C, &ptr, "node_tree", NULL, NULL, NULL);
                uiBlockLayoutResolve(gnode->block, NULL, NULL);
@@ -945,25 +917,171 @@ static void node_common_buts_whileloop(uiLayout *layout, bContext *UNUSED(C), Po
        uiItemR(layout, ptr, "max_iterations", 0, NULL, 0);
 }
 
-static void node_update_frame(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node)
+/* XXX Does a bounding box update by iterating over all children.
+ * Not ideal to do this in every draw call, but doing as transform callback doesn't work,
+ * since the child node totr rects are not updated properly at that point.
+ */
+static void node_update_frame(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node)
+{
+       const float margin = 30.0f;
+       NodeFrame *data = (NodeFrame *)node->storage;
+       int bbinit;
+       bNode *tnode;
+       rctf rect, noderect;
+       float xmax, ymax;
+       
+       /* init rect from current frame size */
+       nodeToView(node, node->offsetx, node->offsety, &rect.xmin, &rect.ymax);
+       nodeToView(node, node->offsetx+node->width, node->offsety-node->height, &rect.xmax, &rect.ymin);
+       
+       /* frame can be resized manually only if shrinking is disabled or no children are attached */
+       data->flag |= NODE_FRAME_RESIZEABLE;
+       /* for shrinking bbox, initialize the rect from first child node */
+       bbinit = (data->flag & NODE_FRAME_SHRINK);
+       /* fit bounding box to all children */
+       for (tnode=ntree->nodes.first; tnode; tnode=tnode->next) {
+               if (tnode->parent!=node)
+                       continue;
+               
+               /* add margin to node rect */
+               noderect = tnode->totr;
+               noderect.xmin -= margin;
+               noderect.xmax += margin;
+               noderect.ymin -= margin;
+               noderect.ymax += margin;
+               
+               /* first child initializes frame */
+               if (bbinit) {
+                       bbinit = 0;
+                       rect = noderect;
+                       data->flag &= ~NODE_FRAME_RESIZEABLE;
+               }
+               else
+                       BLI_union_rctf(&rect, &noderect);
+       }
+       
+       /* now adjust the frame size from view-space bounding box */
+       nodeFromView(node, rect.xmin, rect.ymax, &node->offsetx, &node->offsety);
+       nodeFromView(node, rect.xmax, rect.ymin, &xmax, &ymax);
+       node->width = xmax - node->offsetx;
+       node->height = -ymax + node->offsety;
+       
+       node->totr = rect;
+}
+
+static void node_draw_frame_label(bNode *node)
+{
+       /* XXX font id is crap design */
+       const int fontid = blf_mono_font;
+       NodeFrame *data = (NodeFrame *)node->storage;
+       rctf *rct= &node->totr;
+       int color_id= node_get_colorid(node);
+       char label[128];
+       /* XXX a bit hacky, should use separate align values for x and y */
+       float width, ascender;
+       float x, y;
+       
+       BLI_strncpy(label, nodeLabel(node), sizeof(label));
+       BLF_size(fontid, data->label_size, U.dpi);
+       
+       /* title color */
+       UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.8f, 10);
+
+       width = BLF_width(fontid, label);
+       ascender = BLF_ascender(fontid);
+       
+       x = 0.5f*(rct->xmin + rct->xmax) - 0.5f*width;
+       y = rct->ymax - NODE_DYS - ascender;
+       
+       BLF_position(fontid, x, y, 0);
+       BLF_draw(fontid, label, BLF_DRAW_STR_DUMMY_MAX);
+}
+
+static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *UNUSED(ntree), bNode *node)
 {
-       float locx, locy;
+       rctf *rct= &node->totr;
+       int color_id= node_get_colorid(node);
+       
+       /* skip if out of view */
+       if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
+                       node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) {
+               
+               uiEndBlock(C, node->block);
+               node->block= NULL;
+               return;
+       }
+       
+       /* shadow */
+       node_draw_shadow(snode, node, BASIS_RAD);
+       
+       /* body */
+       if (node->flag & NODE_CUSTOM_COLOR)
+               glColor3fv(node->color);
+       else
+               UI_ThemeColor4(TH_NODE);
+       glEnable(GL_BLEND);
+       uiSetRoundBox(UI_CNR_ALL);
+       uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
+       glDisable(GL_BLEND);
 
-       /* get "global" coords */
-       nodeSpaceCoords(node, &locx, &locy);
+       /* outline active and selected emphasis */
+       if ( node->flag & (NODE_ACTIVE|SELECT) ) {
+               glEnable(GL_BLEND);
+               glEnable( GL_LINE_SMOOTH );
+               
+               if (node->flag & NODE_ACTIVE)
+                       UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
+               else
+                       UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
+               uiSetRoundBox(UI_CNR_ALL);
+               uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
+               
+               glDisable( GL_LINE_SMOOTH );
+               glDisable(GL_BLEND);
+       }
+       
+       /* label */
+       node_draw_frame_label(node);
+       
+       UI_ThemeClearColor(color_id);
+               
+       uiEndBlock(C, node->block);
+       uiDrawBlock(C, node->block);
+       node->block= NULL;
+}
 
-       node->prvr.xmin = locx + NODE_DYS;
-       node->prvr.xmax = locx + node->width- NODE_DYS;
+static int node_resize_area_frame(bNode *node, int x, int y)
+{
+       const float size = 10.0f;
+       NodeFrame *data = (NodeFrame *)node->storage;
+       rctf totr= node->totr;
+       int dir = 0;
+       
+       /* shrinking frame size is determined by child nodes */
+       if (!(data->flag & NODE_FRAME_RESIZEABLE))
+               return 0;
+       
+       if (x >= totr.xmax-size && x < totr.xmax && y >= totr.ymin && y < totr.ymax)
+               dir |= NODE_RESIZE_RIGHT;
+       if (x >= totr.xmin && x < totr.xmin+size && y >= totr.ymin && y < totr.ymax)
+               dir |= NODE_RESIZE_LEFT;
+       if (x >= totr.xmin && x < totr.xmax && y >= totr.ymax-size && y < totr.ymax)
+               dir |= NODE_RESIZE_TOP;
+       if (x >= totr.xmin && x < totr.xmax && y >= totr.ymin && y < totr.ymin+size)
+               dir |= NODE_RESIZE_BOTTOM;
+       
+       return dir;
+}
 
-       node->totr.xmin = locx;
-       node->totr.xmax = locx + node->width;
-       node->totr.ymax = locy;
-       node->totr.ymin = locy - node->height;
+static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiItemR(layout, ptr, "label_size", 0, "Label Size", ICON_NONE);
+       uiItemR(layout, ptr, "shrink", 0, "Shrink", ICON_NONE);
 }
 
 static void node_common_set_butfunc(bNodeType *ntype)
 {
-       switch(ntype->type) {
+       switch (ntype->type) {
                case NODE_GROUP:
                        ntype->uifunc= node_uifunc_group;
                        ntype->drawfunc= node_draw_group;
@@ -980,7 +1098,10 @@ static void node_common_set_butfunc(bNodeType *ntype)
                        ntype->drawupdatefunc= node_update_group;
                        break;
                case NODE_FRAME:
+                       ntype->drawfunc= node_draw_frame;
                        ntype->drawupdatefunc= node_update_frame;
+                       ntype->uifuncbut= node_buts_frame_details;
+                       ntype->resize_area_func= node_resize_area_frame;
                        break;
        }
 }
@@ -1175,8 +1296,7 @@ static void node_shader_buts_dynamic(uiLayout *layout, bContext *C, PointerRNA *
 /* only once called */
 static void node_shader_set_butfunc(bNodeType *ntype)
 {
-       ntype->uifuncbut = NULL;
-       switch(ntype->type) {
+       switch (ntype->type) {
                /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
 
                case SH_NODE_MATERIAL:
@@ -1254,7 +1374,6 @@ static void node_shader_set_butfunc(bNodeType *ntype)
                        ntype->uifunc= node_shader_buts_dynamic;
                        break;
        }
-               if (ntype->uifuncbut == NULL) ntype->uifuncbut = ntype->uifunc;
 }
 
 /* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
@@ -1286,7 +1405,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
                Scene *scene= CTX_data_scene(C);
                ImageUser *iuser= node->storage;
                char numstr[32];
-               const int framenr= BKE_image_user_get_frame(iuser, CFRA, 0);
+               const int framenr= BKE_image_user_frame_get(iuser, CFRA, 0);
                BLI_snprintf(numstr, sizeof(numstr), "Frame: %d", framenr);
                uiItemL(layout, numstr, ICON_NONE);
        }
@@ -1301,7 +1420,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
        }
 
        col= uiLayoutColumn(layout, 0);
-       
+
        if (RNA_enum_get(&imaptr, "type")== IMA_TYPE_MULTILAYER)
                uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
 }
@@ -1418,7 +1537,7 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *UNUSED(C), Po
        uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
 
        col = uiLayoutColumn(layout, 0);
-       uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer")==1);
+       uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == TRUE);
        uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE);
 
        uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
@@ -1433,7 +1552,7 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *UNUSED(C), Po
        col = uiLayoutColumn(layout, 0);
        uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
        sub = uiLayoutColumn(col, 0);
-       uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer")==0);
+       uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == FALSE);
        uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE);
 }
 
@@ -1495,7 +1614,7 @@ static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), P
        uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE);
 
        col = uiLayoutColumn(col, 0);
-       uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector")==0);
+       uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == FALSE);
        uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE);
        uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE);
 }
@@ -1621,7 +1740,11 @@ static void node_composit_buts_hue_sat(uiLayout *layout, bContext *UNUSED(C), Po
 
 static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
+       uiItemR(layout, ptr, "type", 0, NULL, ICON_NONE);
        uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
+       if (RNA_enum_get(ptr, "type") == CMP_NODE_DILATEERODE_DISTANCE) {
+               uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
+       }
 }
 
 static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -1635,9 +1758,14 @@ static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C),
 
 static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
-       uiLayout *col;
+       uiLayout *col, *row;
        
        col = uiLayoutColumn(layout, 1);
+   
+       uiItemL(layout, "Color Space:", ICON_NONE);
+       row= uiLayoutRow(layout, 0);
+       uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
        uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
        uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
 }
@@ -1647,7 +1775,7 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C)
        uiLayout *row, *col;
        
        uiItemL(layout, "Despill Channel:", ICON_NONE);
-       row = uiLayoutRow(layout,0);
+       row = uiLayoutRow(layout, 0);
        uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
 
        col= uiLayoutColumn(layout, 0);
@@ -1655,13 +1783,13 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C)
 
        if (RNA_enum_get(ptr, "limit_method")==0) {
                uiItemL(col, "Limiting Channel:", ICON_NONE);
-               row=uiLayoutRow(col,0);
+               row=uiLayoutRow(col, 0);
                uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
        }
 
        uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
        uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE);
-       if (RNA_boolean_get(ptr, "use_unspill")== 1) {
+       if (RNA_boolean_get(ptr, "use_unspill") == TRUE) {
                uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
                uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
                uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
@@ -1710,7 +1838,7 @@ static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(
        uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
        if (RNA_enum_get(ptr, "limit_method")==0) {
                uiItemL(col, "Limiting Channel:", ICON_NONE);
-               row=uiLayoutRow(col,0);
+               row=uiLayoutRow(col, 0);
                uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
        }
 
@@ -1738,6 +1866,48 @@ static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), Po
        uiItemR(layout, ptr, "use_smooth_mask", 0, NULL, ICON_NONE);
 }
 
+/* draw function for file output node sockets, displays only sub-path and format, no value button */
+static void node_draw_input_file_output(const bContext *C, uiBlock *block,
+                                         bNodeTree *ntree, bNode *node, bNodeSocket *sock,
+                                         const char *UNUSED(name), int x, int y, int width)
+{
+       uiLayout *layout, *row;
+       PointerRNA nodeptr, inputptr, imfptr;
+       int imtype;
+       int rx, ry;
+       RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
+       
+       layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y+NODE_DY, width, 20, UI_GetStyle());
+       row = uiLayoutRow(layout, 0);
+       
+       imfptr = RNA_pointer_get(&nodeptr, "format");
+       imtype = RNA_enum_get(&imfptr, "file_format");
+       if (imtype == R_IMF_IMTYPE_MULTILAYER) {
+               NodeImageMultiFileSocket *input = sock->storage;
+               RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
+               
+               uiItemL(row, input->layer, 0);
+       }
+       else {
+               NodeImageMultiFileSocket *input = sock->storage;
+               PropertyRNA *imtype_prop;
+               const char *imtype_name;
+               RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
+               
+               uiItemL(row, input->path, 0);
+               
+               if (!RNA_boolean_get(&inputptr, "use_node_format"))
+                       imfptr = RNA_pointer_get(&inputptr, "format");
+               
+               imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
+               RNA_property_enum_name((bContext*)C, &imfptr, imtype_prop, RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
+               uiBlockSetEmboss(block, UI_EMBOSSP);
+               uiItemL(row, imtype_name, 0);
+               uiBlockSetEmboss(block, UI_EMBOSSN);
+       }
+       
+       uiBlockLayoutResolve(block, &rx, &ry);
+}
 static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
 {
        PointerRNA imfptr = RNA_pointer_get(ptr, "format");
@@ -1752,7 +1922,9 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C)
 static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
 {
        PointerRNA imfptr = RNA_pointer_get(ptr, "format");
-       PointerRNA active_input_ptr = RNA_pointer_get(ptr, "active_input");
+       PointerRNA active_input_ptr, op_ptr;
+       uiLayout *row;
+       int active_index;
        int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
        
        node_composit_buts_file_output(layout, C, ptr);
@@ -1762,22 +1934,45 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
        
        uiItemO(layout, "Add Input", ICON_ZOOMIN, "NODE_OT_output_file_add_socket");
        
-       uiTemplateList(layout, C, ptr, "inputs", ptr, "active_input_index", NULL, 0, 0, 0);
+       active_index = RNA_int_get(ptr, "active_input_index");
+       /* using different collection properties if multilayer format is enabled */
+       if (multilayer) {
+               uiTemplateList(layout, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+               RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"), active_index, &active_input_ptr);
+       }
+       else {
+               uiTemplateList(layout, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+               RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"), active_index, &active_input_ptr);
+       }
+       /* XXX collection lookup does not return the ID part of the pointer, setting this manually here */
+       active_input_ptr.id.data = ptr->id.data;
+       
+       row = uiLayoutRow(layout, 1);
+       op_ptr = uiItemFullO(row, "NODE_OT_output_file_move_active_socket", "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+       RNA_enum_set(&op_ptr, "direction", 1);
+       op_ptr = uiItemFullO(row, "NODE_OT_output_file_move_active_socket", "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+       RNA_enum_set(&op_ptr, "direction", 2);
        
        if (active_input_ptr.data) {
-               uiLayout *row, *col;
-               
-               col = uiLayoutColumn(layout, 1);
-               if (multilayer)
-                       uiItemL(col, "Layer Name:", 0);
-               else
+               if (multilayer) {
+                       uiLayout *row, *col;
+                       col = uiLayoutColumn(layout, 1);
+                       
+                       uiItemL(col, "Layer:", 0);
+                       row = uiLayoutRow(col, 0);
+                       uiItemR(row, &active_input_ptr, "name", 0, "", 0);
+                       uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
+               }
+               else {
+                       uiLayout *row, *col;
+                       col = uiLayoutColumn(layout, 1);
+                       
                        uiItemL(col, "File Path:", 0);
-               row = uiLayoutRow(col, 0);
-               uiItemR(row, &active_input_ptr, "name", 0, "", 0);
-               uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
-               
-               /* in multilayer format all socket format details are ignored */
-               if (!multilayer) {
+                       row = uiLayoutRow(col, 0);
+                       uiItemR(row, &active_input_ptr, "path", 0, "", 0);
+                       uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
+                       
+                       /* format details for individual files */
                        imfptr = RNA_pointer_get(&active_input_ptr, "format");
                        
                        col = uiLayoutColumn(layout, 1);
@@ -1785,7 +1980,7 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
                        uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, 0);
                        
                        col= uiLayoutColumn(layout, 0);
-                       uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format")==0);
+                       uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE);
                        uiTemplateImageSettings(col, &imfptr);
                }
        }
@@ -1937,11 +2132,271 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po
        uiItemR(layout, ptr, "distortion_type", 0, "", 0);
 }
 
+static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiLayout *row;
+       
+       row = uiLayoutRow(layout, 0);
+       uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
+
+       row = uiLayoutRow(layout, 0);
+       uiItemL(row, "", 0);
+       uiItemL(row, "Saturation", 0);
+       uiItemL(row, "Contrast", 0);
+       uiItemL(row, "Gamma", 0);
+       uiItemL(row, "Gain", 0);
+       uiItemL(row, "Lift", 0);
+
+       row = uiLayoutRow(layout, 0);
+       uiItemL(row, "Master", 0);
+       uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+
+       row = uiLayoutRow(layout, 0);
+       uiItemL(row, "Highlights", 0);
+       uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+
+       row = uiLayoutRow(layout, 0);
+       uiItemL(row, "Midtones", 0);
+       uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+
+       row = uiLayoutRow(layout, 0);
+       uiItemL(row, "Shadows", 0);
+       uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
+       uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
+
+       row = uiLayoutRow(layout, 0);
+       uiItemR(row, ptr, "midtones_start", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+}
+
+static void node_composit_buts_colorcorrection_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) {
+       uiLayout *row;
+       
+       row = uiLayoutRow(layout, 0);
+       uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
+       row = layout;
+       uiItemL(row, "Saturation", 0);
+       uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+
+       uiItemL(row, "Contrast", 0);
+       uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+
+       uiItemL(row, "Gamma", 0);
+       uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+
+       uiItemL(row, "Gain", 0);
+       uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       
+       uiItemL(row, "Lift", 0);
+       uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+
+       row = uiLayoutRow(layout, 0);
+       uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE);
+}
+
+static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE);
+}
+
+static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiLayout *row;
+       
+       row= uiLayoutRow(layout, 1);
+       uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
+       
+       row= uiLayoutRow(layout, 1);
+       uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+
+       uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
+}
+
+static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiItemR(layout, ptr, "flaps", 0, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "rounding", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "catadioptric", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "shift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+}
+
+void node_composit_backdrop_viewer(SpaceNode* snode, ImBuf* backdrop, bNode* node, int x, int y)
+{
+//     node_composit_backdrop_canvas(snode, backdrop, node, x, y);
+       if (node->custom1 == 0) { /// @todo: why did we need this one?
+               const float backdropWidth = backdrop->x;
+               const float backdropHeight = backdrop->y;
+               const float cx  = x+snode->zoom*backdropWidth*node->custom3;
+               const float cy = y+snode->zoom*backdropHeight*node->custom4;
+
+               glColor3f(1.0, 1.0, 1.0);
+
+               glBegin(GL_LINES);
+               glVertex2f(cx-25, cy-25);
+               glVertex2f(cx+25, cy+25);
+               glVertex2f(cx+25, cy-25);
+               glVertex2f(cx-25, cy+25);
+               glEnd();
+       }
+}
+
+void node_composit_backdrop_boxmask(SpaceNode* snode, ImBuf* backdrop, bNode* node, int x, int y)
+{
+       NodeBoxMask *boxmask = node->storage;
+       const float backdropWidth = backdrop->x;
+       const float backdropHeight = backdrop->y;
+       const float aspect = backdropWidth/backdropHeight;
+       const float rad = DEG2RADF(-boxmask->rotation);
+       const float cosine = cosf(rad);
+       const float sine = sinf(rad);
+       const float halveBoxWidth = backdropWidth * (boxmask->width / 2.0f);
+       const float halveBoxHeight = backdropHeight * (boxmask->height / 2.0f) * aspect;
+
+       float cx, cy, x1, x2, x3, x4;
+       float y1, y2, y3, y4;
+
+
+       /* keep this, saves us from a version patch */
+       if (snode->zoom == 0.0f) snode->zoom = 1.0f;
+
+       glColor3f(1.0, 1.0, 1.0);
+
+       cx  = x+snode->zoom*backdropWidth*boxmask->x;
+       cy = y+snode->zoom*backdropHeight*boxmask->y;
+
+       x1 = cx - (cosine*halveBoxWidth+sine*halveBoxHeight)*snode->zoom;
+       x2 = cx - (cosine*-halveBoxWidth+sine*halveBoxHeight)*snode->zoom;
+       x3 = cx - (cosine*-halveBoxWidth+sine*-halveBoxHeight)*snode->zoom;
+       x4 = cx - (cosine*halveBoxWidth+sine*-halveBoxHeight)*snode->zoom;
+       y1 = cy - (-sine*halveBoxWidth + cosine*halveBoxHeight)*snode->zoom;
+       y2 = cy - (-sine*-halveBoxWidth + cosine*halveBoxHeight)*snode->zoom;
+       y3 = cy - (-sine*-halveBoxWidth + cosine*-halveBoxHeight)*snode->zoom;
+       y4 = cy - (-sine*halveBoxWidth + cosine*-halveBoxHeight)*snode->zoom;
+
+       glBegin(GL_LINE_LOOP);
+       glVertex2f(x1, y1);
+       glVertex2f(x2, y2);
+       glVertex2f(x3, y3);
+       glVertex2f(x4, y4);
+       glEnd();
+}
+
+void node_composit_backdrop_ellipsemask(SpaceNode* snode, ImBuf* backdrop, bNode* node, int x, int y)
+{
+       NodeEllipseMask * ellipsemask = node->storage;
+       const float backdropWidth = backdrop->x;
+       const float backdropHeight = backdrop->y;
+       const float aspect = backdropWidth / backdropHeight;
+       const float rad = DEG2RADF(-ellipsemask->rotation);
+       const float cosine = cosf(rad);
+       const float sine = sinf(rad);
+       const float halveBoxWidth = backdropWidth * (ellipsemask->width / 2.0f);
+       const float halveBoxHeight = backdropHeight * (ellipsemask->height / 2.0f) * aspect;
+
+       float cx, cy, x1, x2, x3, x4;
+       float y1, y2, y3, y4;
+
+
+       /* keep this, saves us from a version patch */
+       if (snode->zoom == 0.0f) snode->zoom = 1.0f;
+
+       glColor3f(1.0, 1.0, 1.0);
+
+       cx  = x+snode->zoom*backdropWidth*ellipsemask->x;
+       cy = y+snode->zoom*backdropHeight*ellipsemask->y;
+
+       x1 = cx - (cosine*halveBoxWidth+sine*halveBoxHeight)*snode->zoom;
+       x2 = cx - (cosine*-halveBoxWidth+sine*halveBoxHeight)*snode->zoom;
+       x3 = cx - (cosine*-halveBoxWidth+sine*-halveBoxHeight)*snode->zoom;
+       x4 = cx - (cosine*halveBoxWidth+sine*-halveBoxHeight)*snode->zoom;
+       y1 = cy - (-sine*halveBoxWidth + cosine*halveBoxHeight)*snode->zoom;
+       y2 = cy - (-sine*-halveBoxWidth + cosine*halveBoxHeight)*snode->zoom;
+       y3 = cy - (-sine*-halveBoxWidth + cosine*-halveBoxHeight)*snode->zoom;
+       y4 = cy - (-sine*halveBoxWidth + cosine*-halveBoxHeight)*snode->zoom;
+
+       glBegin(GL_LINE_LOOP);
+
+       glVertex2f(x1, y1);
+       glVertex2f(x2, y2);
+       glVertex2f(x3, y3);
+       glVertex2f(x4, y4);
+       glEnd();
+}
+
+static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiLayout *row;
+       row= uiLayoutRow(layout, 1);
+       uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
+       row= uiLayoutRow(layout, 1);
+       uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+       uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
+
+       uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
+}
+
+static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiLayout *col;
+       
+       uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE);
+       if (RNA_enum_get(ptr, "tile_order")==0) {
+               col= uiLayoutColumn(layout, 1);
+               uiItemR(col, ptr, "center_x", 0, NULL, ICON_NONE);
+               uiItemR(col, ptr, "center_y", 0, NULL, ICON_NONE);
+       }
+}
+
+static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr)
+{
+       uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL);
+}
+
 /* only once called */
 static void node_composit_set_butfunc(bNodeType *ntype)
 {
-       ntype->uifuncbut = NULL;
-       switch(ntype->type) {
+       switch (ntype->type) {
                /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
 
                case CMP_NODE_IMAGE:
@@ -2028,6 +2483,7 @@ static void node_composit_set_butfunc(bNodeType *ntype)
                case CMP_NODE_OUTPUT_FILE:
                        ntype->uifunc= node_composit_buts_file_output;
                        ntype->uifuncbut= node_composit_buts_file_output_details;
+                       ntype->drawinputfunc = node_draw_input_file_output;
                        break;
                case CMP_NODE_DIFF_MATTE:
                        ntype->uifunc=node_composit_buts_diff_matte;
@@ -2103,11 +2559,36 @@ static void node_composit_set_butfunc(bNodeType *ntype)
                case CMP_NODE_MOVIEDISTORTION:
                        ntype->uifunc= node_composit_buts_moviedistortion;
                        break;
+               case CMP_NODE_COLORCORRECTION:
+                       ntype->uifunc=node_composit_buts_colorcorrection;
+                       ntype->uifuncbut=node_composit_buts_colorcorrection_but;
+                       break;
+               case CMP_NODE_SWITCH:
+                       ntype->uifunc= node_composit_buts_switch;
+                       break;
+               case CMP_NODE_MASK_BOX:
+                       ntype->uifunc= node_composit_buts_boxmask;
+                       ntype->uibackdropfunc = node_composit_backdrop_boxmask;
+                       break;
+               case CMP_NODE_MASK_ELLIPSE:
+                       ntype->uifunc= node_composit_buts_ellipsemask;
+                       ntype->uibackdropfunc = node_composit_backdrop_ellipsemask;
+                       break;
+               case CMP_NODE_BOKEHIMAGE:
+                       ntype->uifunc= node_composit_buts_bokehimage;
+                       break;
+               case CMP_NODE_VIEWER:
+                       ntype->uifunc = NULL;
+                       ntype->uifuncbut= node_composit_buts_viewer_but;
+                       ntype->uibackdropfunc = node_composit_backdrop_viewer;
+                       break;
+               case CMP_NODE_MASK:
+                       ntype->uifunc= node_composit_buts_mask;
+                       break;
+
                default:
                        ntype->uifunc= NULL;
        }
-       if (ntype->uifuncbut == NULL) ntype->uifuncbut = ntype->uifunc;
-
 }
 
 /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
@@ -2137,7 +2618,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe
 
        col= uiLayoutColumn(layout, 0);
 
-       switch( tex->type ) {
+       switch ( tex->type ) {
                case TEX_BLEND:
                        uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
                        row= uiLayoutRow(col, 0);
@@ -2218,49 +2699,49 @@ static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), Poin
 /* only once called */
 static void node_texture_set_butfunc(bNodeType *ntype)
 {
-       ntype->uifuncbut = NULL;
        if ( ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX ) {
                ntype->uifunc = node_texture_buts_proc;
        }
-       else switch(ntype->type) {
-               
+       else {
+               switch (ntype->type) {
+
                case TEX_NODE_MATH:
                        ntype->uifunc = node_buts_math;
                        break;
-               
+
                case TEX_NODE_MIX_RGB:
                        ntype->uifunc = node_buts_mix_rgb;
                        break;
-                       
+
                case TEX_NODE_VALTORGB:
                        ntype->uifunc = node_buts_colorramp;
                        break;
-                       
+
                case TEX_NODE_CURVE_RGB:
                        ntype->uifunc= node_buts_curvecol;
                        break;
-                       
+
                case TEX_NODE_CURVE_TIME:
                        ntype->uifunc = node_buts_time;
                        break;
-                       
+
                case TEX_NODE_TEXTURE:
                        ntype->uifunc = node_buts_texture;
                        break;
-                       
+
                case TEX_NODE_BRICKS:
                        ntype->uifunc = node_texture_buts_bricks;
                        break;
-                       
+
                case TEX_NODE_IMAGE:
                        ntype->uifunc = node_texture_buts_image;
                        break;
-                       
+
                case TEX_NODE_OUTPUT:
                        ntype->uifunc = node_texture_buts_output;
                        break;
+               }
        }
-       if (ntype->uifuncbut == NULL) ntype->uifuncbut = ntype->uifunc;
 }
 
 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
@@ -2282,6 +2763,8 @@ void ED_init_node_butfuncs(void)
                                ntype->drawupdatefunc = node_update_default;
                                ntype->uifunc = NULL;
                                ntype->uifuncbut = NULL;
+                               ntype->drawinputfunc = node_draw_input_default;
+                               ntype->drawoutputfunc = node_draw_output_default;
                                ntype->resize_area_func = node_resize_area_default;
                                
                                node_common_set_butfunc(ntype);
@@ -2305,7 +2788,7 @@ void ED_init_node_butfuncs(void)
        for (i=0; i < NUM_SOCKET_TYPES; ++i) {
                stype = ntreeGetSocketType(i);
                if (stype) {
-                       switch(stype->type) {
+                       switch (stype->type) {
                        case SOCK_FLOAT:
                        case SOCK_INT:
                        case SOCK_BOOLEAN:
@@ -2394,6 +2877,19 @@ void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
                                        glPixelZoom(1.0f, 1.0f);
                                }
                        }
+
+                       /// @note draw selected info on backdrop
+                       if (snode->edittree) {
+                               bNode *node = snode->edittree->nodes.first;
+                               while (node) {
+                                       if (node->flag & NODE_SELECT) {
+                                               if (node->typeinfo->uibackdropfunc) {
+                                                       node->typeinfo->uibackdropfunc(snode, ibuf, node, x, y);
+                                               }
+                                       }
+                                       node = node->next;
+                               }
+                       }
                        
                        glMatrixMode(GL_PROJECTION);
                        glPopMatrix();
@@ -2494,8 +2990,8 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa
        else {
                
                /* always do all three, to prevent data hanging around */
-               forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2);
-               forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2);
+               BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2);
+               BKE_curve_forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2);
                
                return 1;
        }
@@ -2648,8 +3144,8 @@ void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link, int
 /* note; this is used for fake links in groups too */
 void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
 {
-       int do_shaded= 0, th_col1= TH_HEADER, th_col2= TH_HEADER;
-       int do_triple= 0, th_col3= TH_WIRE;
+       int do_shaded= FALSE, th_col1= TH_HEADER, th_col2= TH_HEADER;
+       int do_triple= FALSE, th_col3= TH_WIRE;
        
        if (link->fromsock==NULL && link->tosock==NULL)
                return;
@@ -2657,7 +3153,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
        /* new connection */
        if (!link->fromsock || !link->tosock) {
                th_col1 = TH_ACTIVE;
-               do_triple = 1;
+               do_triple = TRUE;
        }
        else {
                /* going to give issues once... */
@@ -2669,7 +3165,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
                /* a bit ugly... but thats how we detect the internal group links */
                if (!link->fromnode || !link->tonode) {
                        UI_ThemeColorBlend(TH_BACK, TH_WIRE, 0.5f);
-                       do_shaded= 0;
+                       do_shaded = FALSE;
                }
                else {
                        /* check cyclic */
@@ -2685,8 +3181,8 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
                                        if (link->tonode->flag & SELECT)
                                                th_col2= TH_EDGE_SELECT;
                                }
-                               do_shaded= 1;
-                               do_triple= 1;
+                               do_shaded = TRUE;
+                               do_triple = TRUE;
                        }                               
                        else {
                                th_col1 = TH_REDALERT;