commit before doing some hefty shapekey change, will break compilation
[blender-staging.git] / source / blender / nodes / intern / CMP_nodes / CMP_image.c
index 563643a66f8c06655a13b03aa61808baf7c990d0..89a3072ac8dfd5628c35cec0689b55c395e863c9 100644 (file)
@@ -48,6 +48,7 @@ static bNodeSocketType cmp_node_rlayers_out[]= {
        {       SOCK_RGBA, 0, "Refract",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_RGBA, 0, "Radio",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       SOCK_VALUE, 0, "IndexOB",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 0, "Mist",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
 };
 
@@ -64,9 +65,32 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
        if(ibuf==NULL)
                return NULL;
        
-       if(ibuf->rect_float==NULL)
-               IMB_float_from_rect(ibuf);
+       if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
+               if (ibuf->profile == IB_PROFILE_NONE) {
+                       /* if float buffer already exists = already linear */
+                       /* else ... */
+                       if (ibuf->rect_float == NULL) {
+                               imb_freerectfloatImBuf(ibuf);
+                               ibuf->profile = IB_PROFILE_SRGB;
+                               IMB_float_from_rect(ibuf);
+                       } else {
+                               ibuf->profile = IB_PROFILE_LINEAR_RGB;
+                       }
+               }
+       } else {
+               if (ibuf->profile == IB_PROFILE_SRGB) {
+                       if (ibuf->rect_float != NULL) {
+                               imb_freerectfloatImBuf(ibuf);
+                       }
+                       ibuf->profile = IB_PROFILE_NONE;
+                       IMB_float_from_rect(ibuf);
+               }
+       }
        
+       if (ibuf->rect_float == NULL) {
+               IMB_float_from_rect(ibuf);
+       }
+
        type= ibuf->channels;
        
        if(rd->scemode & R_COMP_CROP) {
@@ -78,6 +102,21 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i
                stackbuf->rect= ibuf->rect_float;
        }
        
+       /*code to respect the premul flag of images; I'm
+         not sure if this is a good idea for multilayer images,
+         since it never worked before for them.
+       if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
+               //premul the image
+               int i;
+               float *pixel = stackbuf->rect;
+               
+               for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
+                       pixel[0] *= pixel[3];
+                       pixel[1] *= pixel[3];
+                       pixel[2] *= pixel[3];
+               }
+       }
+       */
        return stackbuf;
 };
 
@@ -149,6 +188,8 @@ void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, I
                out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO);
        if(out[RRES_OUT_INDEXOB]->hasoutput)
                out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
+       if(out[RRES_OUT_MIST]->hasoutput)
+               out[RRES_OUT_MIST]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_MIST);
        
 };
 
@@ -184,11 +225,32 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, b
                else {
                        stackbuf= node_composit_get_image(rd, ima, iuser);
 
-                       /* put image on stack */        
-                       out[0]->data= stackbuf;
+                       if (stackbuf) {
+                               /*respect image premul option*/
+                               if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) {
+                                       int i;
+                                       float *pixel;
+                       
+                                       /*first duplicate stackbuf->rect, since it's just a pointer
+                                         to the source imbuf, and we don't want to change that.*/
+                                       stackbuf->rect = MEM_dupallocN(stackbuf->rect);
+                               
+                                       /*premul the image*/
+                               
+                                       pixel = stackbuf->rect;
+                                       for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) {
+                                               pixel[0] *= pixel[3];
+                                               pixel[1] *= pixel[3];
+                                               pixel[2] *= pixel[3];
+                                       }
+                               }
+                       
+                               /* put image on stack */        
+                               out[0]->data= stackbuf;
                        
-                       if(out[2]->hasoutput)
-                               out[2]->data= node_composit_get_zimage(node, rd);
+                               if(out[2]->hasoutput)
+                                       out[2]->data= node_composit_get_zimage(node, rd);
+                       }
                }
                
                /* alpha and preview for both types */
@@ -196,218 +258,36 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, b
                        if(out[1]->hasoutput)
                                out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
 
-                       generate_preview(node, stackbuf);
+                       generate_preview(data, node, stackbuf);
                }
        }       
 };
 
-static void node_browse_image_cb(void *ntree_v, void *node_v)
-{
-   bNodeTree *ntree= ntree_v;
-   bNode *node= node_v;
-
-   nodeSetActive(ntree, node);
-
-   if(node->menunr<1) return;
-   if(node->menunr==32767) {   /* code for Load New */
-      addqueue(curarea->win, UI_BUT_EVENT, B_NODE_LOADIMAGE);
-   }
-   else {
-      if(node->id) node->id->us--;
-      node->id= BLI_findlink(&G.main->image, node->menunr-1);
-      id_us_plus(node->id);
-
-      BLI_strncpy(node->name, node->id->name+2, 21);
-
-      NodeTagChanged(ntree, node); 
-      BKE_image_signal((Image *)node->id, node->storage, IMA_SIGNAL_USER_NEW_IMAGE);
-      addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr);
-   }
-   node->menunr= 0;
-};
-
-static void node_active_cb(void *ntree_v, void *node_v)
-{
-   nodeSetActive(ntree_v, node_v);
-};
-
-static void node_image_type_cb(void *node_v, void *unused)
-{
-
-   allqueue(REDRAWNODE, 1);
-};
-
-static char *node_image_type_pup(void)
-{
-   char *str= MEM_mallocN(256, "image type pup");
-   int a;
-
-   str[0]= 0;
-
-   a= sprintf(str, "Image Type %%t|");
-   a+= sprintf(str+a, "  Image %%x%d %%i%d|", IMA_SRC_FILE, ICON_IMAGE_DEHLT);
-   a+= sprintf(str+a, "  Movie %%x%d %%i%d|", IMA_SRC_MOVIE, ICON_SEQUENCE);
-   a+= sprintf(str+a, "  Sequence %%x%d %%i%d|", IMA_SRC_SEQUENCE, ICON_IMAGE_COL);
-   a+= sprintf(str+a, "  Generated %%x%d %%i%d", IMA_SRC_GENERATED, ICON_BLANK1);
-
-   return str;
-};
-
-/* copy from buttons_shading.c */
-static char *layer_menu(RenderResult *rr)
-{
-   RenderLayer *rl;
-   int len= 40 + 40*BLI_countlist(&rr->layers);
-   short a, nr;
-   char *str= MEM_callocN(len, "menu layers");
-
-   strcpy(str, "Layer %t");
-   a= strlen(str);
-   for(nr=0, rl= rr->layers.first; rl; rl= rl->next, nr++) {
-      a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
-   }
-
-   return str;
-};
-
-static void image_layer_cb(void *ima_v, void *iuser_v)
-{
-
-   ntreeCompositForceHidden(G.scene->nodetree);
-   BKE_image_multilayer_index(ima_v, iuser_v);
-   allqueue(REDRAWNODE, 0);
-};
-
-static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
-{
-   ImageUser *iuser= node->storage;
-
-   if(block) {
-      uiBut *bt;
-      short dy= (short)butr->ymax-19;
-      char *strp;
-
-      uiBlockBeginAlign(block);
-      uiBlockSetCol(block, TH_BUT_SETTING2);
-
-      /* browse button */
-      IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
-      node->menunr= 0;
-      bt= uiDefButS(block, MENU, B_NOP, strp, 
-         butr->xmin, dy, 19, 19, 
-         &node->menunr, 0, 0, 0, 0, "Browses existing choices");
-      uiButSetFunc(bt, node_browse_image_cb, ntree, node);
-      if(strp) MEM_freeN(strp);
-
-      /* Add New button */
-      if(node->id==NULL) {
-         bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
-            butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, 
-            NULL, 0.0, 0.0, 0, 0, "Add new Image");
-         uiButSetFunc(bt, node_active_cb, ntree, node);
-         uiBlockSetCol(block, TH_AUTO);
-      }
-      else {
-         /* name button + type */
-         Image *ima= (Image *)node->id;
-         short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
-         short width= xmax - xmin - 45;
-         short icon= ICON_IMAGE_DEHLT;
-
-         if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE;
-         else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL;
-         else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1;
-
-         bt= uiDefBut(block, TEX, B_NOP, "IM:",
-            xmin+19, dy, width, 19, 
-            node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
-         uiButSetFunc(bt, node_ID_title_cb, node, NULL);
-
-         /* buffer type option */
-         strp= node_image_type_pup();
-         bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp,
-            xmax-26, dy, 26, 19, 
-            &ima->source, 0.0, 19.0, 0, 0, "Image type");
-         uiButSetFunc(bt, node_image_type_cb, node, ima);
-         MEM_freeN(strp);
-
-         if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) {
-            width= (xmax-xmin)/2;
-
-            dy-= 19;
-            uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Frs:",
-               xmin, dy, width, 19, 
-               &iuser->frames, 0.0, 10000.0, 0, 0, "Amount of images used in animation");
-            uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra:",
-               xmin+width, dy, width, 19, 
-               &iuser->sfra, 1.0, 10000.0, 0, 0, "Start frame of animation");
-            dy-= 19;
-            uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Offs:",
-               xmin, dy, width, 19, 
-               &iuser->offset, 0.0, 10000.0, 0, 0, "Offsets the number of the frame to use in the animation");
-            uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Cycl",
-               xmin+width, dy, width-20, 19, 
-               &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic");
-            uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC+node->nr, ICON_AUTO,
-               xmax-20, dy, 20, 19, 
-               &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes");
-         }
-         if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
-            RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
-            if(rl) {
-               width= (xmax-xmin);
-               dy-= 19;
-               strp= layer_menu(ima->rr);
-               bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp,
-                  xmin, dy, width, 19, 
-                  &iuser->layer, 0.0, 10000.0, 0, 0, "Layer");
-               uiButSetFunc(bt, image_layer_cb, ima, node->storage);
-               MEM_freeN(strp);
-            }
-         }
-      }
-
-   }   
-   if(node->id) {
-      Image *ima= (Image *)node->id;
-      int retval= 19;
-
-      /* for each draw we test for anim refresh event */
-      if(iuser->flag & IMA_ANIM_REFRESHED) {
-         iuser->flag &= ~IMA_ANIM_REFRESHED;
-         addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr);
-      }
-
-      if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) )
-         retval+= 38;
-      if( ima->type==IMA_TYPE_MULTILAYER)
-         retval+= 19;
-      return retval;
-   }
-   else
-      return 19;
-};
-
 static void node_composit_init_image(bNode* node)
 {
    ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
    node->storage= iuser;
+   iuser->frames= 1;
    iuser->sfra= 1;
    iuser->fie_ima= 2;
    iuser->ok= 1;
 }
 
 bNodeType cmp_node_image= {
-   /* type code   */   CMP_NODE_IMAGE,
-   /* name        */   "Image",
-   /* width+range */   120, 80, 300,
-   /* class+opts  */   NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
-   /* input sock  */   NULL,
-   /* output sock */   cmp_node_rlayers_out,
-   /* storage     */   "ImageUser",
-   /* execfunc    */   node_composit_exec_image,
-   /* butfunc     */ node_composit_buts_image,
-                     node_composit_init_image
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       CMP_NODE_IMAGE,
+       /* name        */       "Image",
+       /* width+range */       120, 80, 300,
+       /* class+opts  */       NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
+       /* input sock  */       NULL,
+       /* output sock */       cmp_node_rlayers_out,
+       /* storage     */       "ImageUser",
+       /* execfunc    */       node_composit_exec_image,
+       /* butfunc     */       NULL,
+       /* initfunc    */       node_composit_init_image,
+       /* freestoragefunc    */        node_free_standard_storage,
+       /* copystoragefunc    */        node_copy_standard_storage,
+       /* id          */       NULL
 };
 
 /* **************** RENDER RESULT ******************** */
@@ -419,7 +299,7 @@ static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, in
       CompBuf *buf;
       int buftype= CB_VEC3;
 
-      if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB))
+      if(ELEM3(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST))
          buftype= CB_VAL;
       else if(passcode==SCE_PASS_VECTOR)
          buftype= CB_VEC4;
@@ -465,17 +345,21 @@ void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out
    if(out[RRES_OUT_RADIO]->hasoutput)
       out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO);
    if(out[RRES_OUT_INDEXOB]->hasoutput)
-      out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
+          out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
+   if(out[RRES_OUT_MIST]->hasoutput)
+          out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST);
 
 };
 
 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
 {
-   Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */
+   Scene *sce= (Scene *)node->id;
+   Render *re= (sce)? RE_GetRender(sce->id.name): NULL;
    RenderData *rd= data;
-   RenderResult *rr;
+   RenderResult *rr= NULL;
 
-   rr= RE_GetResult(RE_GetRender(sce->id.name));
+   if(re)
+          rr= RE_AcquireResultRead(re);
 
    if(rr) {
       SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
@@ -506,134 +390,33 @@ static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in,
 
                node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
 
-               generate_preview(node, stackbuf);
+               generate_preview(data, node, stackbuf);
             }
          }
       }
-   }   
-};
-
-/* if we use render layers from other scene, we make a nice title */
-static void set_render_layers_title(void *node_v, void *unused)
-{
-   bNode *node= node_v;
-   Scene *sce;
-   SceneRenderLayer *srl;
-   char str[64];
-
-   if(node->id) {
-      BLI_strncpy(str, node->id->name+2, 21);
-      strcat(str, "|");
-      sce= (Scene *)node->id;
-   }
-   else {
-      str[0]= 0;
-      sce= G.scene;
-   }
-   srl= BLI_findlink(&sce->r.layers, node->custom1);
-   if(srl==NULL) {
-      node->custom1= 0;
-      srl= sce->r.layers.first;
    }
 
-   strcat(str, srl->name);
-   BLI_strncpy(node->name, str, 32);
+   if(re)
+          RE_ReleaseResult(re);
 };
 
-static char *scene_layer_menu(Scene *sce)
-{
-   SceneRenderLayer *srl;
-   int len= 40 + 40*BLI_countlist(&sce->r.layers);
-   short a, nr;
-   char *str= MEM_callocN(len, "menu layers");
-
-   strcpy(str, "Active Layer %t");
-   a= strlen(str);
-   for(nr=0, srl= sce->r.layers.first; srl; srl= srl->next, nr++) {
-      a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
-   }
 
-   return str;
-};
-
-static void node_browse_scene_cb(void *ntree_v, void *node_v)
-{
-   bNodeTree *ntree= ntree_v;
-   bNode *node= node_v;
-   Scene *sce;
-
-   if(node->menunr<1) return;
-
-   if(node->id) {
-      node->id->us--;
-      node->id= NULL;
-   }
-   sce= BLI_findlink(&G.main->scene, node->menunr-1);
-   if(sce!=G.scene) {
-      node->id= &sce->id;
-      id_us_plus(node->id);
-   }
-
-   set_render_layers_title(node, NULL);
-   nodeSetActive(ntree, node);
-
-   allqueue(REDRAWBUTSSHADING, 0);
-   allqueue(REDRAWNODE, 0);
-   NodeTagChanged(ntree, node); 
-
-   node->menunr= 0;
-};
-
-static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
-{
-   if(block) {
-      uiBut *bt;
-      char *strp;
-
-      /* browse button scene */
-      uiBlockBeginAlign(block);
-      IDnames_to_pupstring(&strp, NULL, "", &(G.main->scene), NULL, NULL);
-      node->menunr= 0;
-      bt= uiDefButS(block, MENU, B_NOP, strp, 
-         butr->xmin, butr->ymin, 20, 19, 
-         &node->menunr, 0, 0, 0, 0, "Browse Scene to use RenderLayer from");
-      uiButSetFunc(bt, node_browse_scene_cb, ntree, node);
-      if(strp) MEM_freeN(strp);
-
-      /* browse button layer */
-      strp= scene_layer_menu(node->id?(Scene *)node->id:G.scene);
-      if(node->id)
-         bt= uiDefIconTextButS(block, MENU, B_NODE_EXEC+node->nr, ICON_SCENE_DEHLT, strp, 
-         butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
-         &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
-      else
-         bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp, 
-         butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
-         &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
-      uiButSetFunc(bt, set_render_layers_title, node, NULL);
-      MEM_freeN(strp);
-
-      /* re-render */
-      /* uses custom2, not the best implementation of the world... but we need it to work now :) */
-      bt= uiDefIconButS(block, TOG, B_NODE_EXEC+node->nr, ICON_SCENE, 
-         butr->xmax-20, butr->ymin, 20, 19, 
-         &node->custom2, 0, 0, 0, 0, "Re-render this Layer");
+bNodeType cmp_node_rlayers= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       CMP_NODE_R_LAYERS,
+       /* name        */       "Render Layers",
+       /* width+range */       150, 100, 300,
+       /* class+opts  */       NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
+       /* input sock  */       NULL,
+       /* output sock */       cmp_node_rlayers_out,
+       /* storage     */       "",
+       /* execfunc    */       node_composit_exec_rlayers,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
 
-   }
-   return 19;
 };
 
 
-bNodeType cmp_node_rlayers= {
-   /* type code   */   CMP_NODE_R_LAYERS,
-   /* name        */   "Render Layers",
-   /* width+range */   150, 100, 300,
-   /* class+opts  */   NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
-   /* input sock  */   NULL,
-   /* output sock */   cmp_node_rlayers_out,
-   /* storage     */   "",
-   /* execfunc    */   node_composit_exec_rlayers,
-   /* butfunc     */ node_composit_buts_renderlayers,
-                     NULL
-
-};
\ No newline at end of file