Blender  V2.59
image_buttons.c
Go to the documentation of this file.
00001 /*
00002  * $Id: image_buttons.c 38551 2011-07-21 00:41:00Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * Contributor(s): Blender Foundation, 2002-2009
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00034 #include <string.h>
00035 #include <stdio.h>
00036 
00037 #include "DNA_meshdata_types.h"
00038 #include "DNA_object_types.h"
00039 #include "DNA_node_types.h"
00040 #include "DNA_scene_types.h"
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "BLI_blenlib.h"
00045 #include "BLI_math.h"
00046 #include "BLI_editVert.h"
00047 #include "BLI_rand.h"
00048 #include "BLI_utildefines.h"
00049 
00050 #include "BKE_colortools.h"
00051 #include "BKE_context.h"
00052 #include "BKE_customdata.h"
00053 #include "BKE_image.h"
00054 #include "BKE_mesh.h"
00055 #include "BKE_node.h"
00056 #include "BKE_screen.h"
00057 
00058 #include "RE_pipeline.h"
00059 
00060 #include "IMB_imbuf.h"
00061 #include "IMB_imbuf_types.h"
00062 
00063 #include "ED_gpencil.h"
00064 #include "ED_image.h"
00065 #include "ED_screen.h"
00066 
00067 #include "RNA_access.h"
00068 
00069 #include "WM_api.h"
00070 #include "WM_types.h"
00071 
00072 #include "UI_interface.h"
00073 #include "UI_resources.h"
00074 
00075 #include "image_intern.h"
00076 
00077 #define B_REDR                          1
00078 #define B_IMAGECHANGED          2
00079 #define B_NOP                           0
00080 #define B_TWINANIM                      5
00081 #define B_SIMAGETILE            6
00082 #define B_IDNAME                        10
00083 #define B_FACESEL_PAINT_TEST    11
00084 #define B_SIMA_RECORD           12
00085 #define B_SIMA_PLAY                     13
00086 
00087 #define B_SIMANOTHING           16
00088 #define B_SIMABRUSHCHANGE       17      
00089 #define B_SIMABRUSHBROWSE       18
00090 #define B_SIMABRUSHLOCAL        19
00091 #define B_SIMABRUSHDELETE       20
00092 #define B_KEEPDATA                      21
00093 #define B_SIMABTEXBROWSE        22
00094 #define B_SIMABTEXDELETE        23
00095 #define B_VPCOLSLI                      24
00096 #define B_SIMACLONEBROWSE       25
00097 #define B_SIMACLONEDELETE       26
00098 
00099 /* proto */
00100 
00101 static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str)
00102 {
00103         int ofs= 0;
00104 
00105         str[0]= 0;
00106         
00107         if(ima==NULL) return;
00108 
00109         if(ibuf==NULL) {
00110                 ofs+= sprintf(str, "Can't Load Image");
00111         }
00112         else {
00113                 if(ima->source==IMA_SRC_MOVIE) {
00114                         ofs+= sprintf(str, "Movie");
00115                         if(ima->anim)
00116                                 ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
00117                 }
00118                 else
00119                         ofs+= sprintf(str, "Image");
00120 
00121                 ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
00122 
00123                 if(ibuf->rect_float) {
00124                         if(ibuf->channels!=4) {
00125                                 ofs+= sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
00126                         }
00127                         else if(ibuf->depth==32)
00128                                 ofs+= sprintf(str+ofs, " RGBA float");
00129                         else
00130                                 ofs+= sprintf(str+ofs, " RGB float");
00131                 }
00132                 else {
00133                         if(ibuf->depth==32)
00134                                 ofs+= sprintf(str+ofs, " RGBA byte");
00135                         else
00136                                 ofs+= sprintf(str+ofs, " RGB byte");
00137                 }
00138                 if(ibuf->zbuf || ibuf->zbuf_float)
00139                         ofs+= sprintf(str+ofs, " + Z");
00140 
00141                 if(ima->source==IMA_SRC_SEQUENCE) {
00142                         char *file= BLI_last_slash(ibuf->name);
00143                         if(file==NULL)  file= ibuf->name;
00144                         else                    file++;
00145                         ofs+= sprintf(str+ofs, ", %s", file);
00146                 }
00147         }
00148 
00149         /* the frame number, even if we cant */
00150         if(ima->source==IMA_SRC_SEQUENCE) {
00151                 /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
00152                 const int framenr= BKE_image_user_get_frame(iuser, CFRA, 0);
00153                 ofs+= sprintf(str+ofs, ", Frame: %d", framenr);
00154         }
00155 
00156         (void)ofs;
00157 }
00158 
00159 /* gets active viewer user */
00160 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
00161 {
00162         bNode *node;
00163         
00164         if(ntree)
00165                 for(node= ntree->nodes.first; node; node= node->next)
00166                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
00167                                 if(node->flag & NODE_DO_OUTPUT)
00168                                         return node->storage;
00169         return NULL;
00170 }
00171 
00172 
00173 /* ************ panel stuff ************* */
00174 
00175 /* is used for both read and write... */
00176 
00177 static int image_panel_poll(const bContext *C, PanelType *UNUSED(pt))
00178 {
00179         SpaceImage *sima= CTX_wm_space_image(C);
00180         ImBuf *ibuf;
00181         void *lock;
00182         int result;
00183 
00184         ibuf= ED_space_image_acquire_buffer(sima, &lock);
00185         result= ibuf && ibuf->rect_float;
00186         ED_space_image_release_buffer(sima, lock);
00187         
00188         return result;
00189 }
00190 
00191 static void image_panel_curves(const bContext *C, Panel *pa)
00192 {
00193         bScreen *sc= CTX_wm_screen(C);
00194         SpaceImage *sima= CTX_wm_space_image(C);
00195         ImBuf *ibuf;
00196         PointerRNA simaptr;
00197         int levels;
00198         void *lock;
00199         
00200         ibuf= ED_space_image_acquire_buffer(sima, &lock);
00201         
00202         if(ibuf) {
00203                 if(sima->cumap==NULL)
00204                         sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
00205 
00206                 /* curvemap black/white levels only works for RGBA */
00207                 levels= (ibuf->channels==4);
00208 
00209                 RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr);
00210                 uiTemplateCurveMapping(pa->layout, &simaptr, "curve", 'c', levels, 0);
00211         }
00212 
00213         ED_space_image_release_buffer(sima, lock);
00214 }
00215 
00216 #if 0
00217 /* 0: disable preview 
00218    otherwise refresh preview
00219  
00220    XXX if you put this back, also check XXX in image_main_area_draw() */
00221 */
00222 void image_preview_event(int event)
00223 {
00224         int exec= 0;
00225         
00226         if(event==0) {
00227                 G.scene->r.scemode &= ~R_COMP_CROP;
00228                 exec= 1;
00229         }
00230         else {
00231                 if(image_preview_active(curarea, NULL, NULL)) {
00232                         G.scene->r.scemode |= R_COMP_CROP;
00233                         exec= 1;
00234                 }
00235                 else
00236                         G.scene->r.scemode &= ~R_COMP_CROP;
00237         }
00238         
00239         if(exec && G.scene->nodetree) {
00240                 /* should work when no node editor in screen..., so we execute right away */
00241                 
00242                 ntreeCompositTagGenerators(G.scene->nodetree);
00243 
00244                 G.afbreek= 0;
00245                 G.scene->nodetree->timecursor= set_timecursor;
00246                 G.scene->nodetree->test_break= blender_test_break;
00247                 
00248                 BIF_store_spare();
00249                 
00250                 ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1);       /* 1 is do_previews */
00251                 
00252                 G.scene->nodetree->timecursor= NULL;
00253                 G.scene->nodetree->test_break= NULL;
00254                 
00255                 scrarea_do_windraw(curarea);
00256                 waitcursor(0);
00257                 
00258                 WM_event_add_notifier(C, NC_IMAGE, ima_v);
00259         }       
00260 }
00261 
00262 
00263 /* nothing drawn here, we use it to store values */
00264 static void preview_cb(struct ScrArea *sa, struct uiBlock *block)
00265 {
00266         SpaceImage *sima= sa->spacedata.first;
00267         rctf dispf;
00268         rcti *disprect= &G.scene->r.disprect;
00269         int winx= (G.scene->r.size*G.scene->r.xsch)/100;
00270         int winy= (G.scene->r.size*G.scene->r.ysch)/100;
00271         int mval[2];
00272         
00273         if(G.scene->r.mode & R_BORDER) {
00274                 winx*= (G.scene->r.border.xmax - G.scene->r.border.xmin);
00275                 winy*= (G.scene->r.border.ymax - G.scene->r.border.ymin);
00276         }
00277         
00278         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
00279 
00280         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
00281         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
00282         
00283         /* correction for gla draw */
00284         BLI_translate_rcti(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
00285         
00286         calc_image_view(sima, 'p');
00287 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
00288         /* map to image space coordinates */
00289         mval[0]= disprect->xmin; mval[1]= disprect->ymin;
00290         areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
00291         mval[0]= disprect->xmax; mval[1]= disprect->ymax;
00292         areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
00293         
00294         /* map to render coordinates */
00295         disprect->xmin= dispf.xmin;
00296         disprect->xmax= dispf.xmax;
00297         disprect->ymin= dispf.ymin;
00298         disprect->ymax= dispf.ymax;
00299         
00300         CLAMP(disprect->xmin, 0, winx);
00301         CLAMP(disprect->xmax, 0, winx);
00302         CLAMP(disprect->ymin, 0, winy);
00303         CLAMP(disprect->ymax, 0, winy);
00304 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
00305 
00306 }
00307 
00308 static int is_preview_allowed(ScrArea *cur)
00309 {
00310         SpaceImage *sima= cur->spacedata.first;
00311         ScrArea *sa;
00312 
00313         /* check if another areawindow has preview set */
00314         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
00315                 if(sa!=cur && sa->spacetype==SPACE_IMAGE) {
00316                         if(image_preview_active(sa, NULL, NULL))
00317                                 return 0;
00318                 }
00319         }
00320         /* check image type */
00321         if(sima->image==NULL || sima->image->type!=IMA_TYPE_COMPOSITE)
00322                 return 0;
00323         
00324         return 1;
00325 }
00326 
00327 
00328 static void image_panel_preview(ScrArea *sa, short cntrl)       // IMAGE_HANDLER_PREVIEW
00329 {
00330         uiBlock *block;
00331         SpaceImage *sima= sa->spacedata.first;
00332         int ofsx, ofsy;
00333         
00334         if(is_preview_allowed(sa)==0) {
00335                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
00336                 G.scene->r.scemode &= ~R_COMP_CROP;     /* quite weak */
00337                 return;
00338         }
00339         
00340         block= uiBeginBlock(C, ar, "image_panel_preview", UI_EMBOSS);
00341         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
00342         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
00343         
00344         ofsx= -150+(sa->winx/2)/sima->blockscale;
00345         ofsy= -100+(sa->winy/2)/sima->blockscale;
00346         if(uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200)==0) return;
00347         
00348         uiBlockSetDrawExtraFunc(block, preview_cb);
00349         
00350 }
00351 #endif
00352 
00353 
00354 /* ********************* callbacks for standard image buttons *************** */
00355 
00356 static char *slot_menu(void)
00357 {
00358         char *str;
00359         int a, slot;
00360         
00361         str= MEM_callocN(IMA_MAX_RENDER_SLOT*32, "menu slots");
00362         
00363         strcpy(str, "Slot %t");
00364         a= strlen(str);
00365 
00366         for(slot=0; slot<IMA_MAX_RENDER_SLOT; slot++)
00367                 a += sprintf(str+a, "|Slot %d %%x%d", slot+1, slot);
00368         
00369         return str;
00370 }
00371 
00372 /* TODO, curlay should be removed? */
00373 static char *layer_menu(RenderResult *rr, short *UNUSED(curlay))
00374 {
00375         RenderLayer *rl;
00376         int len= 64 + 32*BLI_countlist(&rr->layers);
00377         short a, nr= 0;
00378         char *str= MEM_callocN(len, "menu layers");
00379         
00380         strcpy(str, "Layer %t");
00381         a= strlen(str);
00382         
00383         /* compo result */
00384         if(rr->rectf) {
00385                 a+= sprintf(str+a, "|Composite %%x0");
00386                 nr= 1;
00387         }
00388         for(rl= rr->layers.first; rl; rl= rl->next, nr++) {
00389                 a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
00390         }
00391         
00392         /* no curlay clip here, on render (redraws) the amount of layers can be 1 fir single-layer render */
00393         
00394         return str;
00395 }
00396 
00397 /* rl==NULL means composite result */
00398 static char *pass_menu(RenderLayer *rl, short *curpass)
00399 {
00400         RenderPass *rpass;
00401         int len= 64 + 32*(rl?BLI_countlist(&rl->passes):1);
00402         short a, nr= 0;
00403         char *str= MEM_callocN(len, "menu layers");
00404         
00405         strcpy(str, "Pass %t");
00406         a= strlen(str);
00407         
00408         /* rendered results don't have a Combined pass */
00409         if(rl==NULL || rl->rectf) {
00410                 a+= sprintf(str+a, "|Combined %%x0");
00411                 nr= 1;
00412         }
00413         
00414         if(rl)
00415                 for(rpass= rl->passes.first; rpass; rpass= rpass->next, nr++)
00416                         a+= sprintf(str+a, "|%s %%x%d", rpass->name, nr);
00417         
00418         if(*curpass >= nr)
00419                 *curpass= 0;
00420         
00421         return str;
00422 }
00423 
00424 static void set_frames_cb(bContext *C, void *ima_v, void *iuser_v)
00425 {
00426         Scene *scene= CTX_data_scene(C);
00427         Image *ima= ima_v;
00428         ImageUser *iuser= iuser_v;
00429         
00430         if(ima->anim) {
00431                 iuser->frames = IMB_anim_get_duration(ima->anim);
00432                 BKE_image_user_calc_frame(iuser, scene->r.cfra, 0);
00433         }
00434 }
00435 
00436 /* 5 layer button callbacks... */
00437 static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) 
00438 {
00439         ImageUser *iuser= iuser_v;
00440 
00441         BKE_image_multilayer_index(rr_v, iuser); 
00442         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
00443 }
00444 static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) 
00445 {
00446         RenderResult *rr= rr_v;
00447         ImageUser *iuser= iuser_v;
00448         int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0);  /* fake compo result layer */
00449 
00450         if(iuser->layer<tot-1) {
00451                 iuser->layer++;
00452                 BKE_image_multilayer_index(rr, iuser); 
00453                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
00454         }
00455 }
00456 static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) 
00457 {
00458         ImageUser *iuser= iuser_v;
00459 
00460         if(iuser->layer>0) {
00461                 iuser->layer--;
00462                 BKE_image_multilayer_index(rr_v, iuser); 
00463                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
00464         }
00465 }
00466 static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) 
00467 {
00468         RenderResult *rr= rr_v;
00469         ImageUser *iuser= iuser_v;
00470         RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
00471 
00472         if(rl) {
00473                 int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0);  /* builtin render result has no combined pass in list */
00474                 if(iuser->pass<tot-1) {
00475                         iuser->pass++;
00476                         BKE_image_multilayer_index(rr, iuser); 
00477                         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
00478                 }
00479         }
00480 }
00481 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
00482 {
00483         ImageUser *iuser= iuser_v;
00484 
00485         if(iuser->pass>0) {
00486                 iuser->pass--;
00487                 BKE_image_multilayer_index(rr_v, iuser); 
00488                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
00489         }
00490 }
00491 
00492 #if 0
00493 static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) 
00494 {
00495         if(ima_v) {
00496                 Image *ima= ima_v;
00497                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
00498                         if (ima->packedfile) {
00499                                 if (G.fileflags & G_AUTOPACK) {
00500                                         if (okee("Disable AutoPack ?")) {
00501                                                 G.fileflags &= ~G_AUTOPACK;
00502                                         }
00503                                 }
00504                                 
00505                                 if ((G.fileflags & G_AUTOPACK) == 0) {
00506                                         unpackImage(NULL, ima, PF_ASK); /* XXX report errors */
00507                                         ED_undo_push(C, "Unpack image");
00508                                 }
00509                         } 
00510                         else {
00511                                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
00512                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
00513                                         // XXX error("Can't pack painted image. Save image or use Repack as PNG.");
00514                                 } else {
00515                                         ima->packedfile = newPackedFile(NULL, ima->name); /* XXX report errors */
00516                                         ED_undo_push(C, "Pack image");
00517                                 }
00518                         }
00519                 }
00520         }
00521 }
00522 #endif
00523 
00524 #if 0
00525 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) 
00526 {
00527         Scene *scene= CTX_data_scene(C);
00528         BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
00529         WM_event_add_notifier(C, NC_IMAGE, ima_v);
00530 }
00531 #endif
00532 
00533 #if 0
00534 static void image_user_change(bContext *C, void *iuser_v, void *unused)
00535 {
00536         Scene *scene= CTX_data_scene(C);
00537         BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
00538 }
00539 #endif
00540 
00541 static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
00542 {
00543         uiBlock *block= uiLayoutGetBlock(layout);
00544         uiBut *but;
00545         RenderLayer *rl= NULL;
00546         int wmenu1, wmenu2, wmenu3;
00547         char *strp;
00548 
00549         uiLayoutRow(layout, 1);
00550 
00551         /* layer menu is 1/3 larger than pass */
00552         wmenu1= (2*w)/5;
00553         wmenu2= (3*w)/5;
00554         wmenu3= (3*w)/6;
00555         
00556         /* menu buts */
00557         if(render_slot) {
00558                 strp= slot_menu();
00559                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu1, UI_UNIT_Y, render_slot, 0,0,0,0, "Select Slot");
00560                 uiButSetFunc(but, image_multi_cb, rr, iuser);
00561                 MEM_freeN(strp);
00562         }
00563 
00564         if(rr) {
00565                 strp= layer_menu(rr, &iuser->layer);
00566                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu2, UI_UNIT_Y, &iuser->layer, 0,0,0,0, "Select Layer");
00567                 uiButSetFunc(but, image_multi_cb, rr, iuser);
00568                 MEM_freeN(strp);
00569                 
00570                 rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */
00571                 strp= pass_menu(rl, &iuser->pass);
00572                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu3, UI_UNIT_Y, &iuser->pass, 0,0,0,0, "Select Pass");
00573                 uiButSetFunc(but, image_multi_cb, rr, iuser);
00574                 MEM_freeN(strp);        
00575         }
00576 }
00577 
00578 static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, short *render_slot)
00579 {
00580         uiBlock *block= uiLayoutGetBlock(layout);
00581         uiLayout *row;
00582         uiBut *but;
00583         const float dpi_fac= UI_DPI_FAC;
00584         
00585         row= uiLayoutRow(layout, 1);
00586 
00587         if(rr==NULL || iuser==NULL)
00588                 return;
00589         if(rr->layers.first==NULL) {
00590                 uiItemL(row, "No Layers in Render Result.", ICON_NONE);
00591                 return;
00592         }
00593 
00594         /* decrease, increase arrows */
00595         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Layer");
00596         uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
00597         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Layer");
00598         uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
00599 
00600         uiblock_layer_pass_buttons(row, rr, iuser, 230 * dpi_fac, render_slot);
00601 
00602         /* decrease, increase arrows */
00603         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Pass");
00604         uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
00605         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Pass");
00606         uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
00607 
00608         uiBlockEndAlign(block);
00609 }
00610 
00611 // XXX HACK!
00612 // static int packdummy=0;
00613 
00614 typedef struct RNAUpdateCb {
00615         PointerRNA ptr;
00616         PropertyRNA *prop;
00617         ImageUser *iuser;
00618 } RNAUpdateCb;
00619 
00620 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
00621 {
00622         RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
00623 
00624         /* ideally this would be done by RNA itself, but there we have
00625            no image user available, so we just update this flag here */
00626         cb->iuser->ok= 1;
00627 
00628         /* we call update here on the pointer property, this way the
00629            owner of the image pointer can still define it's own update
00630            and notifier */
00631         RNA_property_update(C, &cb->ptr, cb->prop);
00632 }
00633 
00634 void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
00635 {
00636         PropertyRNA *prop;
00637         PointerRNA imaptr;
00638         RNAUpdateCb *cb;
00639         Image *ima;
00640         ImageUser *iuser;
00641         ImBuf *ibuf;
00642         Scene *scene= CTX_data_scene(C);
00643         uiLayout *row, *split, *col;
00644         uiBlock *block;
00645         uiBut *but;
00646         char str[128];
00647         void *lock;
00648 
00649         if(!ptr->data)
00650                 return;
00651 
00652         prop= RNA_struct_find_property(ptr, propname);
00653         if(!prop) {
00654                 printf("uiTemplateImage: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
00655                 return;
00656         }
00657 
00658         if(RNA_property_type(prop) != PROP_POINTER) {
00659                 printf("uiTemplateImage: expected pointer property for %s.%s\n", RNA_struct_identifier(ptr->type), propname);
00660                 return;
00661         }
00662 
00663         block= uiLayoutGetBlock(layout);
00664 
00665         imaptr= RNA_property_pointer_get(ptr, prop);
00666         ima= imaptr.data;
00667         iuser= userptr->data;
00668 
00669         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
00670         cb->ptr= *ptr;
00671         cb->prop= prop;
00672         cb->iuser= iuser;
00673 
00674         uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
00675 
00676         if(!compact)
00677                 uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
00678 
00679         // XXX missing: reload, pack
00680 
00681         if(ima) {
00682                 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
00683 
00684                 if(ima->source == IMA_SRC_VIEWER) {
00685                         ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
00686                         image_info(scene, iuser, ima, ibuf, str);
00687                         BKE_image_release_ibuf(ima, lock);
00688 
00689                         uiItemL(layout, ima->id.name+2, ICON_NONE);
00690                         uiItemL(layout, str, ICON_NONE);
00691 
00692                         if(ima->type==IMA_TYPE_COMPOSITE) {
00693                                 // XXX not working yet
00694 #if 0
00695                                 iuser= ntree_get_active_iuser(scene->nodetree);
00696                                 if(iuser) {
00697                                         uiBlockBeginAlign(block);
00698                                         uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, "");
00699                                         uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110,120,100,20, 0, 0, 0, 0, 0, "");
00700                                         but= uiDefBut(block, BUT, B_NOP, "Free Cache",  210,120,100,20, 0, 0, 0, 0, 0, "");
00701                                         uiButSetFunc(but, image_freecache_cb, ima, NULL);
00702                                         
00703                                         if(iuser->frames)
00704                                                 sprintf(str, "(%d) Frames:", iuser->framenr);
00705                                         else strcpy(str, "Frames:");
00706                                         uiBlockBeginAlign(block);
00707                                         uiDefButI(block, NUM, imagechanged, str,                10, 90,150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
00708                                         uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
00709                                 }
00710 #endif
00711                         }
00712                         else if(ima->type==IMA_TYPE_R_RESULT) {
00713                                 /* browse layer/passes */
00714                                 Render *re= RE_GetRender(scene->id.name);
00715                                 RenderResult *rr= RE_AcquireResultRead(re);
00716                                 uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot);
00717                                 RE_ReleaseResult(re);
00718                         }
00719                 }
00720                 else {
00721                         uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
00722 
00723                         if(ima->source != IMA_SRC_GENERATED) {
00724                                 row= uiLayoutRow(layout, 1);
00725                                 if (ima->packedfile)
00726                                         uiItemO(row, "", ICON_PACKAGE, "image.unpack");
00727                                 else
00728                                         uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
00729                                 
00730                                 row= uiLayoutRow(row, 0);
00731                                 uiLayoutSetEnabled(row, ima->packedfile==NULL);
00732                                 uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
00733                                 uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
00734                         }
00735 
00736                         // XXX what was this for?
00737 #if 0
00738                          /* check for re-render, only buttons */
00739                         if(imagechanged==B_IMAGECHANGED) {
00740                                 if(iuser->flag & IMA_ANIM_REFRESHED) {
00741                                         iuser->flag &= ~IMA_ANIM_REFRESHED;
00742                                         WM_event_add_notifier(C, NC_IMAGE, ima);
00743                                 }
00744                         }
00745 #endif
00746 
00747                         /* multilayer? */
00748                         if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
00749                                 uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL);
00750                         }
00751                         else if(ima->source != IMA_SRC_GENERATED) {
00752                                 if(compact == 0) {
00753                                         ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
00754                                         image_info(scene, iuser, ima, ibuf, str);
00755                                         BKE_image_release_ibuf(ima, lock);
00756                                         uiItemL(layout, str, ICON_NONE);
00757                                 }
00758                         }
00759                         
00760                         if(ima->source != IMA_SRC_GENERATED) {
00761                                 if(compact == 0) { /* background image view doesnt need these */
00762                                         uiItemS(layout);
00763 
00764                                         split= uiLayoutSplit(layout, 0, 0);
00765 
00766                                         col= uiLayoutColumn(split, 0);
00767                                         uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE);
00768                                         row= uiLayoutRow(col, 0);
00769                                         uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
00770                                         uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
00771                                         
00772                                         uiItemR(split, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
00773                                 }
00774                         }
00775 
00776                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
00777                                 uiItemS(layout);
00778                                 
00779                                 split= uiLayoutSplit(layout, 0, 0);
00780 
00781                                 col= uiLayoutColumn(split, 0);
00782                                  
00783                                 sprintf(str, "(%d) Frames", iuser->framenr);
00784                                 uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
00785                                 if(ima->anim) {
00786                                         block= uiLayoutGetBlock(col);
00787                                         but= uiDefBut(block, BUT, 0, "Match Movie Length", 0, 0, UI_UNIT_X*2, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Set the number of frames to match the movie or sequence.");
00788                                         uiButSetFunc(but, set_frames_cb, ima, iuser);
00789                                 }
00790 
00791                                 uiItemR(col, userptr, "frame_start", 0, "Start", ICON_NONE);
00792                                 uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
00793 
00794                                 col= uiLayoutColumn(split, 0);
00795                                 row= uiLayoutRow(col, 0);
00796                                 uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
00797                                 uiItemR(row, userptr, "fields_per_frame", 0, "Fields", ICON_NONE);
00798                                 uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
00799                                 uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
00800                         }
00801                         else if(ima->source==IMA_SRC_GENERATED) {
00802                                 split= uiLayoutSplit(layout, 0, 0);
00803 
00804                                 col= uiLayoutColumn(split, 1);
00805                                 uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
00806                                 uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
00807                                 uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
00808 
00809                                 uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
00810                         }
00811 
00812                                         }
00813 
00814                 uiBlockSetNFunc(block, NULL, NULL, NULL);
00815         }
00816 
00817         MEM_freeN(cb);
00818 }
00819 
00820 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
00821 {
00822         Scene *scene= CTX_data_scene(C);
00823         RenderResult *rr;
00824 
00825         /* render layers and passes */
00826         if(ima && iuser) {
00827                 const float dpi_fac= UI_DPI_FAC;
00828                 rr= BKE_image_acquire_renderresult(scene, ima);
00829                 uiblock_layer_pass_buttons(layout, rr, iuser, 160 * dpi_fac, (ima->type==IMA_TYPE_R_RESULT)? &ima->render_slot: NULL);
00830                 BKE_image_release_renderresult(scene, ima);
00831         }
00832 }
00833 
00834 void image_buttons_register(ARegionType *art)
00835 {
00836         PanelType *pt;
00837 
00838         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel curves");
00839         strcpy(pt->idname, "IMAGE_PT_curves");
00840         strcpy(pt->label, "Curves");
00841         pt->draw= image_panel_curves;
00842         pt->poll= image_panel_poll;
00843         pt->flag |= PNL_DEFAULT_CLOSED;
00844         BLI_addtail(&art->paneltypes, pt);
00845         
00846         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
00847         strcpy(pt->idname, "IMAGE_PT_gpencil");
00848         strcpy(pt->label, "Grease Pencil");
00849         pt->draw= gpencil_panel_standard;
00850         BLI_addtail(&art->paneltypes, pt);
00851 }
00852 
00853 static int image_properties(bContext *C, wmOperator *UNUSED(op))
00854 {
00855         ScrArea *sa= CTX_wm_area(C);
00856         ARegion *ar= image_has_buttons_region(sa);
00857         
00858         if(ar)
00859                 ED_region_toggle_hidden(C, ar);
00860 
00861         return OPERATOR_FINISHED;
00862 }
00863 
00864 void IMAGE_OT_properties(wmOperatorType *ot)
00865 {
00866         ot->name= "Properties";
00867         ot->idname= "IMAGE_OT_properties";
00868         ot->description= "Toggle display properties panel";
00869         
00870         ot->exec= image_properties;
00871         ot->poll= ED_operator_image_active;
00872         
00873         /* flags */
00874         ot->flag= 0;
00875 }
00876 
00877 static int image_scopes(bContext *C, wmOperator *UNUSED(op))
00878 {
00879         ScrArea *sa= CTX_wm_area(C);
00880         ARegion *ar= image_has_scope_region(sa);
00881         
00882         if(ar)
00883                 ED_region_toggle_hidden(C, ar);
00884         
00885         return OPERATOR_FINISHED;
00886 }
00887 
00888 void IMAGE_OT_scopes(wmOperatorType *ot)
00889 {
00890         ot->name= "Scopes";
00891         ot->idname= "IMAGE_OT_scopes";
00892         ot->description= "Toggle display scopes panel";
00893         
00894         ot->exec= image_scopes;
00895         ot->poll= ED_operator_image_active;
00896         
00897         /* flags */
00898         ot->flag= 0;
00899 }
00900