doxygen: blender/editors tagged.
[blender.git] / source / blender / editors / space_image / image_buttons.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2002-2009
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_image/image_buttons.c
29  *  \ingroup spimage
30  */
31
32
33
34 #include <string.h>
35 #include <stdio.h>
36
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_node_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_math.h"
46 #include "BLI_editVert.h"
47 #include "BLI_rand.h"
48 #include "BLI_utildefines.h"
49
50 #include "BKE_colortools.h"
51 #include "BKE_context.h"
52 #include "BKE_customdata.h"
53 #include "BKE_image.h"
54 #include "BKE_mesh.h"
55 #include "BKE_node.h"
56 #include "BKE_screen.h"
57
58 #include "RE_pipeline.h"
59
60 #include "IMB_imbuf.h"
61 #include "IMB_imbuf_types.h"
62
63 #include "ED_gpencil.h"
64 #include "ED_image.h"
65 #include "ED_screen.h"
66 #include "ED_uvedit.h"
67
68
69 #include "RNA_access.h"
70
71 #include "WM_api.h"
72 #include "WM_types.h"
73
74 #include "UI_interface.h"
75 #include "UI_resources.h"
76
77 #include "image_intern.h"
78
79 #define B_REDR                          1
80 #define B_IMAGECHANGED          2
81 #define B_TRANS_IMAGE           3
82 #define B_NOP                           0
83 #define B_TWINANIM                      5
84 #define B_SIMAGETILE            6
85 #define B_IDNAME                        10
86 #define B_FACESEL_PAINT_TEST    11
87 #define B_SIMA_RECORD           12
88 #define B_SIMA_PLAY                     13
89
90 #define B_SIMANOTHING           16
91 #define B_SIMABRUSHCHANGE       17      
92 #define B_SIMABRUSHBROWSE       18
93 #define B_SIMABRUSHLOCAL        19
94 #define B_SIMABRUSHDELETE       20
95 #define B_KEEPDATA                      21
96 #define B_SIMABTEXBROWSE        22
97 #define B_SIMABTEXDELETE        23
98 #define B_VPCOLSLI                      24
99 #define B_SIMACLONEBROWSE       25
100 #define B_SIMACLONEDELETE       26
101
102 /* proto */
103 static void image_editvertex_buts(const bContext *C, uiBlock *block);
104
105
106 static void do_image_panel_events(bContext *C, void *UNUSED(arg), int event)
107 {
108         SpaceImage *sima= CTX_wm_space_image(C);
109         
110         switch(event) {
111                 case B_REDR:
112                         break;
113                 case B_TRANS_IMAGE:
114                         image_editvertex_buts(C, NULL);
115                         break;
116         }
117
118         /* all events now */
119         WM_event_add_notifier(C, NC_IMAGE, sima->image);
120 }
121
122 static void image_info(Image *ima, ImBuf *ibuf, char *str)
123 {
124         int ofs= 0;
125         
126         str[0]= 0;
127         
128         if(ima==NULL) return;
129         if(ibuf==NULL) {
130                 sprintf(str, "Can not get an image");
131                 return;
132         }
133         
134         if(ima->source==IMA_SRC_MOVIE) {
135                 ofs= sprintf(str, "Movie");
136                 if(ima->anim) 
137                         ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
138         }
139         else
140                  ofs= sprintf(str, "Image");
141         
142         ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
143         
144         if(ibuf->rect_float) {
145                 if(ibuf->channels!=4) {
146                         ofs+= sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
147                 }
148                 else if(ibuf->depth==32)
149                         ofs+= sprintf(str+ofs, " RGBA float");
150                 else
151                         ofs+= sprintf(str+ofs, " RGB float");
152         }
153         else {
154                 if(ibuf->depth==32)
155                         ofs+= sprintf(str+ofs, " RGBA byte");
156                 else
157                         ofs+= sprintf(str+ofs, " RGB byte");
158         }
159         if(ibuf->zbuf || ibuf->zbuf_float)
160                 ofs+= sprintf(str+ofs, " + Z");
161
162         if(ima->source==IMA_SRC_SEQUENCE) {
163                 char *file= BLI_last_slash(ibuf->name);
164                 if(file==NULL)  file= ibuf->name;
165                 else                    file++;
166                 sprintf(str+ofs, ", %s", file);
167         }
168         
169 }
170
171 /* gets active viewer user */
172 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
173 {
174         bNode *node;
175         
176         if(ntree)
177                 for(node= ntree->nodes.first; node; node= node->next)
178                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
179                                 if(node->flag & NODE_DO_OUTPUT)
180                                         return node->storage;
181         return NULL;
182 }
183
184
185 /* ************ panel stuff ************* */
186
187 /* this function gets the values for cursor and vertex number buttons */
188 static void image_transform_but_attr(SpaceImage *sima, int *imx, int *imy, int *step, int *digits) /*, float *xcoord, float *ycoord)*/
189 {
190         ED_space_image_size(sima, imx, imy);
191         
192         if (sima->flag & SI_COORDFLOATS) {
193                 *step= 1;
194                 *digits= 3;
195         }
196         else {
197                 *step= 100;
198                 *digits= 2;
199         }
200 }
201
202
203 /* is used for both read and write... */
204 static void image_editvertex_buts(const bContext *C, uiBlock *block)
205 {
206         Scene *scene= CTX_data_scene(C);
207         SpaceImage *sima= CTX_wm_space_image(C);
208         Image *ima= sima->image;
209         Object *obedit= CTX_data_edit_object(C);
210         static float ocent[2];
211         float cent[2]= {0.0, 0.0};
212         int imx= 256, imy= 256;
213         int nactive= 0, step, digits;
214         EditMesh *em;
215         EditFace *efa;
216         MTFace *tf;
217         
218         image_transform_but_attr(sima, &imx, &imy, &step, &digits);
219         
220         em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
221         for (efa= em->faces.first; efa; efa= efa->next) {
222                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
223                 if (uvedit_face_visible(scene, ima, efa, tf)) {
224                         
225                         if (uvedit_uv_selected(scene, efa, tf, 0)) {
226                                 cent[0]+= tf->uv[0][0];
227                                 cent[1]+= tf->uv[0][1];
228                                 nactive++;
229                         }
230                         if (uvedit_uv_selected(scene, efa, tf, 1)) {
231                                 cent[0]+= tf->uv[1][0];
232                                 cent[1]+= tf->uv[1][1];
233                                 nactive++;
234                         }
235                         if (uvedit_uv_selected(scene, efa, tf, 2)) {
236                                 cent[0]+= tf->uv[2][0];
237                                 cent[1]+= tf->uv[2][1];
238                                 nactive++;
239                         }
240                         if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
241                                 cent[0]+= tf->uv[3][0];
242                                 cent[1]+= tf->uv[3][1];
243                                 nactive++;
244                         }
245                 }
246         }
247                 
248         if(block) {     // do the buttons
249                 if (nactive) {
250                         ocent[0]= cent[0]/nactive;
251                         ocent[1]= cent[1]/nactive;
252                         if (sima->flag & SI_COORDFLOATS) {
253                         } else {
254                                 ocent[0] *= imx;
255                                 ocent[1] *= imy;
256                         }
257                         
258                         //uiBlockBeginAlign(block);
259                         if(nactive==1) {
260                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
261                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
262                         }
263                         else {
264                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
265                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
266                         }
267                         //uiBlockEndAlign(block);
268                 }
269         }
270         else {  // apply event
271                 float delta[2];
272                 
273                 cent[0]= cent[0]/nactive;
274                 cent[1]= cent[1]/nactive;
275                         
276                 if (sima->flag & SI_COORDFLOATS) {
277                         delta[0]= ocent[0]-cent[0];
278                         delta[1]= ocent[1]-cent[1];
279                 }
280                 else {
281                         delta[0]= ocent[0]/imx - cent[0];
282                         delta[1]= ocent[1]/imy - cent[1];
283                 }
284
285                 for (efa= em->faces.first; efa; efa= efa->next) {
286                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
287                         if (uvedit_face_visible(scene, ima, efa, tf)) {
288                                 if (uvedit_uv_selected(scene, efa, tf, 0)) {
289                                         tf->uv[0][0]+= delta[0];
290                                         tf->uv[0][1]+= delta[1];
291                                 }
292                                 if (uvedit_uv_selected(scene, efa, tf, 1)) {
293                                         tf->uv[1][0]+= delta[0];
294                                         tf->uv[1][1]+= delta[1];
295                                 }
296                                 if (uvedit_uv_selected(scene, efa, tf, 2)) {
297                                         tf->uv[2][0]+= delta[0];
298                                         tf->uv[2][1]+= delta[1];
299                                 }
300                                 if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
301                                         tf->uv[3][0]+= delta[0];
302                                         tf->uv[3][1]+= delta[1];
303                                 }
304                         }
305                 }
306                 
307                 WM_event_add_notifier(C, NC_IMAGE, sima->image);
308         }
309
310         BKE_mesh_end_editmesh(obedit->data, em);
311 }
312
313
314 /* is used for both read and write... */
315
316 static int image_panel_poll(const bContext *C, PanelType *UNUSED(pt))
317 {
318         SpaceImage *sima= CTX_wm_space_image(C);
319         ImBuf *ibuf;
320         void *lock;
321         int result;
322
323         ibuf= ED_space_image_acquire_buffer(sima, &lock);
324         result= ibuf && ibuf->rect_float;
325         ED_space_image_release_buffer(sima, lock);
326         
327         return result;
328 }
329
330 static void image_panel_curves(const bContext *C, Panel *pa)
331 {
332         bScreen *sc= CTX_wm_screen(C);
333         SpaceImage *sima= CTX_wm_space_image(C);
334         ImBuf *ibuf;
335         PointerRNA simaptr;
336         int levels;
337         void *lock;
338         
339         ibuf= ED_space_image_acquire_buffer(sima, &lock);
340         
341         if(ibuf) {
342                 if(sima->cumap==NULL)
343                         sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
344
345                 /* curvemap black/white levels only works for RGBA */
346                 levels= (ibuf->channels==4);
347
348                 RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr);
349                 uiTemplateCurveMapping(pa->layout, &simaptr, "curves", 'c', levels, 0);
350         }
351
352         ED_space_image_release_buffer(sima, lock);
353 }
354
355 #if 0
356 /* 0: disable preview 
357    otherwise refresh preview
358  
359    XXX if you put this back, also check XXX in image_main_area_draw() */
360 */
361 void image_preview_event(int event)
362 {
363         int exec= 0;
364         
365         if(event==0) {
366                 G.scene->r.scemode &= ~R_COMP_CROP;
367                 exec= 1;
368         }
369         else {
370                 if(image_preview_active(curarea, NULL, NULL)) {
371                         G.scene->r.scemode |= R_COMP_CROP;
372                         exec= 1;
373                 }
374                 else
375                         G.scene->r.scemode &= ~R_COMP_CROP;
376         }
377         
378         if(exec && G.scene->nodetree) {
379                 /* should work when no node editor in screen..., so we execute right away */
380                 
381                 ntreeCompositTagGenerators(G.scene->nodetree);
382
383                 G.afbreek= 0;
384                 G.scene->nodetree->timecursor= set_timecursor;
385                 G.scene->nodetree->test_break= blender_test_break;
386                 
387                 BIF_store_spare();
388                 
389                 ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1);       /* 1 is do_previews */
390                 
391                 G.scene->nodetree->timecursor= NULL;
392                 G.scene->nodetree->test_break= NULL;
393                 
394                 scrarea_do_windraw(curarea);
395                 waitcursor(0);
396                 
397                 WM_event_add_notifier(C, NC_IMAGE, ima_v);
398         }       
399 }
400
401
402 /* nothing drawn here, we use it to store values */
403 static void preview_cb(struct ScrArea *sa, struct uiBlock *block)
404 {
405         SpaceImage *sima= sa->spacedata.first;
406         rctf dispf;
407         rcti *disprect= &G.scene->r.disprect;
408         int winx= (G.scene->r.size*G.scene->r.xsch)/100;
409         int winy= (G.scene->r.size*G.scene->r.ysch)/100;
410         short mval[2];
411         
412         if(G.scene->r.mode & R_BORDER) {
413                 winx*= (G.scene->r.border.xmax - G.scene->r.border.xmin);
414                 winy*= (G.scene->r.border.ymax - G.scene->r.border.ymin);
415         }
416         
417         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
418
419         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
420         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
421         
422         /* correction for gla draw */
423         BLI_translate_rcti(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
424         
425         calc_image_view(sima, 'p');
426 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
427         /* map to image space coordinates */
428         mval[0]= disprect->xmin; mval[1]= disprect->ymin;
429         areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
430         mval[0]= disprect->xmax; mval[1]= disprect->ymax;
431         areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
432         
433         /* map to render coordinates */
434         disprect->xmin= dispf.xmin;
435         disprect->xmax= dispf.xmax;
436         disprect->ymin= dispf.ymin;
437         disprect->ymax= dispf.ymax;
438         
439         CLAMP(disprect->xmin, 0, winx);
440         CLAMP(disprect->xmax, 0, winx);
441         CLAMP(disprect->ymin, 0, winy);
442         CLAMP(disprect->ymax, 0, winy);
443 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
444
445 }
446
447 static int is_preview_allowed(ScrArea *cur)
448 {
449         SpaceImage *sima= cur->spacedata.first;
450         ScrArea *sa;
451
452         /* check if another areawindow has preview set */
453         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
454                 if(sa!=cur && sa->spacetype==SPACE_IMAGE) {
455                         if(image_preview_active(sa, NULL, NULL))
456                            return 0;
457                 }
458         }
459         /* check image type */
460         if(sima->image==NULL || sima->image->type!=IMA_TYPE_COMPOSITE)
461                 return 0;
462         
463         return 1;
464 }
465
466
467 static void image_panel_preview(ScrArea *sa, short cntrl)       // IMAGE_HANDLER_PREVIEW
468 {
469         uiBlock *block;
470         SpaceImage *sima= sa->spacedata.first;
471         int ofsx, ofsy;
472         
473         if(is_preview_allowed(sa)==0) {
474                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
475                 G.scene->r.scemode &= ~R_COMP_CROP;     /* quite weak */
476                 return;
477         }
478         
479         block= uiBeginBlock(C, ar, "image_panel_preview", UI_EMBOSS);
480         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
481         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
482         
483         ofsx= -150+(sa->winx/2)/sima->blockscale;
484         ofsy= -100+(sa->winy/2)/sima->blockscale;
485         if(uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200)==0) return;
486         
487         uiBlockSetDrawExtraFunc(block, preview_cb);
488         
489 }
490 #endif
491
492
493 /* ********************* callbacks for standard image buttons *************** */
494
495 static char *slot_menu(void)
496 {
497         char *str;
498         int a, slot;
499         
500         str= MEM_callocN(IMA_MAX_RENDER_SLOT*32, "menu slots");
501         
502         strcpy(str, "Slot %t");
503         a= strlen(str);
504
505         for(slot=0; slot<IMA_MAX_RENDER_SLOT; slot++)
506                 a += sprintf(str+a, "|Slot %d %%x%d", slot+1, slot);
507         
508         return str;
509 }
510
511 /* TODO, curlay should be removed? */
512 static char *layer_menu(RenderResult *rr, short *UNUSED(curlay))
513 {
514         RenderLayer *rl;
515         int len= 64 + 32*BLI_countlist(&rr->layers);
516         short a, nr= 0;
517         char *str= MEM_callocN(len, "menu layers");
518         
519         strcpy(str, "Layer %t");
520         a= strlen(str);
521         
522         /* compo result */
523         if(rr->rectf) {
524                 a+= sprintf(str+a, "|Composite %%x0");
525                 nr= 1;
526         }
527         for(rl= rr->layers.first; rl; rl= rl->next, nr++) {
528                 a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
529         }
530         
531         /* no curlay clip here, on render (redraws) the amount of layers can be 1 fir single-layer render */
532         
533         return str;
534 }
535
536 /* rl==NULL means composite result */
537 static char *pass_menu(RenderLayer *rl, short *curpass)
538 {
539         RenderPass *rpass;
540         int len= 64 + 32*(rl?BLI_countlist(&rl->passes):1);
541         short a, nr= 0;
542         char *str= MEM_callocN(len, "menu layers");
543         
544         strcpy(str, "Pass %t");
545         a= strlen(str);
546         
547         /* rendered results don't have a Combined pass */
548         if(rl==NULL || rl->rectf) {
549                 a+= sprintf(str+a, "|Combined %%x0");
550                 nr= 1;
551         }
552         
553         if(rl)
554                 for(rpass= rl->passes.first; rpass; rpass= rpass->next, nr++)
555                         a+= sprintf(str+a, "|%s %%x%d", rpass->name, nr);
556         
557         if(*curpass >= nr)
558                 *curpass= 0;
559         
560         return str;
561 }
562
563 static void set_frames_cb(bContext *C, void *ima_v, void *iuser_v)
564 {
565         Scene *scene= CTX_data_scene(C);
566         Image *ima= ima_v;
567         ImageUser *iuser= iuser_v;
568         
569         if(ima->anim) {
570                 iuser->frames = IMB_anim_get_duration(ima->anim);
571                 BKE_image_user_calc_frame(iuser, scene->r.cfra, 0);
572         }
573 }
574
575 /* 5 layer button callbacks... */
576 static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) 
577 {
578         ImageUser *iuser= iuser_v;
579
580         BKE_image_multilayer_index(rr_v, iuser); 
581         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
582 }
583 static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) 
584 {
585         RenderResult *rr= rr_v;
586         ImageUser *iuser= iuser_v;
587         int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0);  /* fake compo result layer */
588
589         if(iuser->layer<tot-1) {
590                 iuser->layer++;
591                 BKE_image_multilayer_index(rr, iuser); 
592                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
593         }
594 }
595 static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) 
596 {
597         ImageUser *iuser= iuser_v;
598
599         if(iuser->layer>0) {
600                 iuser->layer--;
601                 BKE_image_multilayer_index(rr_v, iuser); 
602                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
603         }
604 }
605 static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) 
606 {
607         RenderResult *rr= rr_v;
608         ImageUser *iuser= iuser_v;
609         RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
610
611         if(rl) {
612                 int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0);  /* builtin render result has no combined pass in list */
613                 if(iuser->pass<tot-1) {
614                         iuser->pass++;
615                         BKE_image_multilayer_index(rr, iuser); 
616                         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
617                 }
618         }
619 }
620 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
621 {
622         ImageUser *iuser= iuser_v;
623
624         if(iuser->pass>0) {
625                 iuser->pass--;
626                 BKE_image_multilayer_index(rr_v, iuser); 
627                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
628         }
629 }
630
631 #if 0
632 static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) 
633 {
634         if(ima_v) {
635                 Image *ima= ima_v;
636                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
637                         if (ima->packedfile) {
638                                 if (G.fileflags & G_AUTOPACK) {
639                                         if (okee("Disable AutoPack ?")) {
640                                                 G.fileflags &= ~G_AUTOPACK;
641                                         }
642                                 }
643                                 
644                                 if ((G.fileflags & G_AUTOPACK) == 0) {
645                                         unpackImage(NULL, ima, PF_ASK); /* XXX report errors */
646                                         ED_undo_push(C, "Unpack image");
647                                 }
648                         } 
649                         else {
650                                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
651                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
652                                         // XXX error("Can't pack painted image. Save image or use Repack as PNG.");
653                                 } else {
654                                         ima->packedfile = newPackedFile(NULL, ima->name); /* XXX report errors */
655                                         ED_undo_push(C, "Pack image");
656                                 }
657                         }
658                 }
659         }
660 }
661 #endif
662
663 #if 0
664 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) 
665 {
666         Scene *scene= CTX_data_scene(C);
667         BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
668         WM_event_add_notifier(C, NC_IMAGE, ima_v);
669 }
670 #endif
671
672 #if 0
673 static void image_user_change(bContext *C, void *iuser_v, void *unused)
674 {
675         Scene *scene= CTX_data_scene(C);
676         BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
677 }
678 #endif
679
680 static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
681 {
682         uiBlock *block= uiLayoutGetBlock(layout);
683         uiBut *but;
684         RenderLayer *rl= NULL;
685         int wmenu1, wmenu2, wmenu3;
686         char *strp;
687
688         uiLayoutRow(layout, 1);
689
690         /* layer menu is 1/3 larger than pass */
691         wmenu1= (2*w)/5;
692         wmenu2= (3*w)/5;
693         wmenu3= (3*w)/6;
694         
695         /* menu buts */
696         if(render_slot) {
697                 strp= slot_menu();
698                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu1, 20, render_slot, 0,0,0,0, "Select Slot");
699                 uiButSetFunc(but, image_multi_cb, rr, iuser);
700                 MEM_freeN(strp);
701         }
702
703         if(rr) {
704                 strp= layer_menu(rr, &iuser->layer);
705                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu2, 20, &iuser->layer, 0,0,0,0, "Select Layer");
706                 uiButSetFunc(but, image_multi_cb, rr, iuser);
707                 MEM_freeN(strp);
708                 
709                 rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */
710                 strp= pass_menu(rl, &iuser->pass);
711                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu3, 20, &iuser->pass, 0,0,0,0, "Select Pass");
712                 uiButSetFunc(but, image_multi_cb, rr, iuser);
713                 MEM_freeN(strp);        
714         }
715 }
716
717 static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, short *render_slot)
718 {
719         uiBlock *block= uiLayoutGetBlock(layout);
720         uiLayout *row;
721         uiBut *but;
722         
723         row= uiLayoutRow(layout, 1);
724
725         if(rr==NULL || iuser==NULL)
726                 return;
727         if(rr->layers.first==NULL) {
728                 uiItemL(row, "No Layers in Render Result.", ICON_NONE);
729                 return;
730         }
731
732         /* decrease, increase arrows */
733         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Layer");
734         uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
735         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Layer");
736         uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
737
738         uiblock_layer_pass_buttons(row, rr, iuser, 230, render_slot);
739
740         /* decrease, increase arrows */
741         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Pass");
742         uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
743         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Pass");
744         uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
745
746         uiBlockEndAlign(block);
747 }
748
749 // XXX HACK!
750 // static int packdummy=0;
751
752 typedef struct RNAUpdateCb {
753         PointerRNA ptr;
754         PropertyRNA *prop;
755         ImageUser *iuser;
756 } RNAUpdateCb;
757
758 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
759 {
760         RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
761
762         /* ideally this would be done by RNA itself, but there we have
763            no image user available, so we just update this flag here */
764         cb->iuser->ok= 1;
765
766         /* we call update here on the pointer property, this way the
767            owner of the image pointer can still define it's own update
768            and notifier */
769         RNA_property_update(C, &cb->ptr, cb->prop);
770 }
771
772 void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
773 {
774         PropertyRNA *prop;
775         PointerRNA imaptr;
776         RNAUpdateCb *cb;
777         Image *ima;
778         ImageUser *iuser;
779         ImBuf *ibuf;
780         Scene *scene= CTX_data_scene(C);
781         uiLayout *row, *split, *col;
782         uiBlock *block;
783         uiBut *but;
784         char str[128];
785         void *lock;
786
787         if(!ptr->data)
788                 return;
789
790         prop= RNA_struct_find_property(ptr, propname);
791         if(!prop) {
792                 printf("uiTemplateImage: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
793                 return;
794         }
795
796         if(RNA_property_type(prop) != PROP_POINTER) {
797                 printf("uiTemplateImage: expected pointer property for %s.%s\n", RNA_struct_identifier(ptr->type), propname);
798                 return;
799         }
800
801         block= uiLayoutGetBlock(layout);
802
803
804         imaptr= RNA_property_pointer_get(ptr, prop);
805         ima= imaptr.data;
806         iuser= userptr->data;
807
808         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
809         cb->ptr= *ptr;
810         cb->prop= prop;
811         cb->iuser= iuser;
812
813         uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
814
815         if(!compact)
816                 uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
817
818         // XXX missing: reload, pack
819
820         if(ima) {
821                 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
822
823                 if(ima->source == IMA_SRC_VIEWER) {
824                         ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
825                         image_info(ima, ibuf, str);
826                         BKE_image_release_ibuf(ima, lock);
827
828                         uiItemL(layout, ima->id.name+2, ICON_NONE);
829                         uiItemL(layout, str, ICON_NONE);
830
831                         if(ima->type==IMA_TYPE_COMPOSITE) {
832                                 // XXX not working yet
833 #if 0
834                                 iuser= ntree_get_active_iuser(scene->nodetree);
835                                 if(iuser) {
836                                         uiBlockBeginAlign(block);
837                                         uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, "");
838                                         uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110,120,100,20, 0, 0, 0, 0, 0, "");
839                                         but= uiDefBut(block, BUT, B_NOP, "Free Cache",  210,120,100,20, 0, 0, 0, 0, 0, "");
840                                         uiButSetFunc(but, image_freecache_cb, ima, NULL);
841                                         
842                                         if(iuser->frames)
843                                                 sprintf(str, "(%d) Frames:", iuser->framenr);
844                                         else strcpy(str, "Frames:");
845                                         uiBlockBeginAlign(block);
846                                         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");
847                                         uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
848                                 }
849 #endif
850                         }
851                         else if(ima->type==IMA_TYPE_R_RESULT) {
852                                 /* browse layer/passes */
853                                 Render *re= RE_GetRender(scene->id.name);
854                                 RenderResult *rr= RE_AcquireResultRead(re);
855                                 uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot);
856                                 RE_ReleaseResult(re);
857                         }
858                 }
859                 else {
860                         row= uiLayoutRow(layout, 0);
861                         uiItemR(row, &imaptr, "source", 0, NULL, ICON_NONE);
862
863                         if(ima->source != IMA_SRC_GENERATED) {
864                                 row= uiLayoutRow(layout, 1);
865                                 split = uiLayoutSplit(row, 0.0, 0);
866                                 if (ima->packedfile)
867                                         uiItemO(split, "", ICON_PACKAGE, "image.unpack");
868                                 else
869                                         uiItemO(split, "", ICON_UGLYPACKAGE, "image.pack");
870                                 
871                                 split = uiLayoutSplit(row, 0.0, 0);
872                                 row= uiLayoutRow(split, 1);
873                                 uiLayoutSetEnabled(row, ima->packedfile==NULL);
874                                 
875                                 uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
876                                 uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
877                         }
878
879                         // XXX what was this for?
880 #if 0
881                          /* check for re-render, only buttons */
882                         if(imagechanged==B_IMAGECHANGED) {
883                                 if(iuser->flag & IMA_ANIM_REFRESHED) {
884                                         iuser->flag &= ~IMA_ANIM_REFRESHED;
885                                         WM_event_add_notifier(C, NC_IMAGE, ima);
886                                 }
887                         }
888 #endif
889
890                         /* multilayer? */
891                         if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
892                                 uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL);
893                         }
894                         else if(ima->source != IMA_SRC_GENERATED) {
895                                 if(compact == 0) {
896                                         ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
897                                         image_info(ima, ibuf, str);
898                                         BKE_image_release_ibuf(ima, lock);
899                                         uiItemL(layout, str, ICON_NONE);
900                                 }
901                         }
902                         
903                         if(ima->source != IMA_SRC_GENERATED) {
904                                 if(compact == 0) { /* background image view doesnt need these */
905                                         uiItemS(layout);
906
907                                         split= uiLayoutSplit(layout, 0, 0);
908
909                                         col= uiLayoutColumn(split, 0);
910                                         uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE);
911                                         row= uiLayoutRow(col, 0);
912                                         uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
913                                         uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
914
915                                         col= uiLayoutColumn(split, 0);
916                                         uiItemR(col, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
917                                 }
918                         }
919
920                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
921                                 uiItemS(layout);
922                                 
923                                 split= uiLayoutSplit(layout, 0, 0);
924
925                                 col= uiLayoutColumn(split, 0);
926                                  
927                                 sprintf(str, "(%d) Frames", iuser->framenr);
928                                 row= uiLayoutRow(col, 1);
929                                 uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
930                                 if(ima->anim) {
931                                         block= uiLayoutGetBlock(row);
932                                         but= uiDefBut(block, BUT, 0, "Match Movie Length", 0, 0, UI_UNIT_X*2, UI_UNIT_Y, 0, 0, 0, 0, 0, "Set the number of frames to match the movie or sequence.");
933                                         uiButSetFunc(but, set_frames_cb, ima, iuser);
934                                 }
935
936                                 uiItemR(col, userptr, "frame_start", 0, "Start", ICON_NONE);
937                                 uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
938
939                                 col= uiLayoutColumn(split, 0);
940                                 uiItemR(col, userptr, "fields_per_frame", 0, "Fields", ICON_NONE);
941                                 uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
942                                 uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
943                         }
944                         else if(ima->source==IMA_SRC_GENERATED) {
945                                 split= uiLayoutSplit(layout, 0, 0);
946
947                                 col= uiLayoutColumn(split, 1);
948                                 uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
949                                 uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
950
951                                 col= uiLayoutColumn(split, 0);
952                                 uiItemR(col, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
953                         }
954
955                                         }
956
957                 uiBlockSetNFunc(block, NULL, NULL, NULL);
958         }
959
960         MEM_freeN(cb);
961 }
962
963 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
964 {
965         Scene *scene= CTX_data_scene(C);
966         RenderResult *rr;
967
968         /* render layers and passes */
969         if(ima && iuser) {
970                 rr= BKE_image_acquire_renderresult(scene, ima);
971                 uiblock_layer_pass_buttons(layout, rr, iuser, 160, (ima->type==IMA_TYPE_R_RESULT)? &ima->render_slot: NULL);
972                 BKE_image_release_renderresult(scene, ima);
973         }
974 }
975
976 static int image_panel_uv_poll(const bContext *C, PanelType *UNUSED(pt))
977 {
978         Object *obedit= CTX_data_edit_object(C);
979         return ED_uvedit_test(obedit);
980 }
981
982 static void image_panel_uv(const bContext *C, Panel *pa)
983 {
984         uiBlock *block;
985         
986         block= uiLayoutAbsoluteBlock(pa->layout);
987         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
988
989         image_editvertex_buts(C, block);
990 }       
991
992 void image_buttons_register(ARegionType *art)
993 {
994         PanelType *pt;
995
996         /* editvertex_buts not working atm */
997         if(0) {
998                 pt= MEM_callocN(sizeof(PanelType), "spacetype image panel uv");
999                 strcpy(pt->idname, "IMAGE_PT_uv");
1000                 strcpy(pt->label, "UV");
1001                 pt->draw= image_panel_uv;
1002                 pt->poll= image_panel_uv_poll;
1003                 BLI_addtail(&art->paneltypes, pt);
1004         }
1005
1006         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel curves");
1007         strcpy(pt->idname, "IMAGE_PT_curves");
1008         strcpy(pt->label, "Curves");
1009         pt->draw= image_panel_curves;
1010         pt->poll= image_panel_poll;
1011         pt->flag |= PNL_DEFAULT_CLOSED;
1012         BLI_addtail(&art->paneltypes, pt);
1013         
1014         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
1015         strcpy(pt->idname, "IMAGE_PT_gpencil");
1016         strcpy(pt->label, "Grease Pencil");
1017         pt->draw= gpencil_panel_standard;
1018         BLI_addtail(&art->paneltypes, pt);
1019 }
1020
1021 static int image_properties(bContext *C, wmOperator *UNUSED(op))
1022 {
1023         ScrArea *sa= CTX_wm_area(C);
1024         ARegion *ar= image_has_buttons_region(sa);
1025         
1026         if(ar)
1027                 ED_region_toggle_hidden(C, ar);
1028
1029         return OPERATOR_FINISHED;
1030 }
1031
1032 void IMAGE_OT_properties(wmOperatorType *ot)
1033 {
1034         ot->name= "Properties";
1035         ot->idname= "IMAGE_OT_properties";
1036         ot->description= "Toggle display properties panel";
1037         
1038         ot->exec= image_properties;
1039         ot->poll= ED_operator_image_active;
1040         
1041         /* flags */
1042         ot->flag= 0;
1043 }
1044
1045 static int image_scopes(bContext *C, wmOperator *UNUSED(op))
1046 {
1047         ScrArea *sa= CTX_wm_area(C);
1048         ARegion *ar= image_has_scope_region(sa);
1049         
1050         if(ar)
1051                 ED_region_toggle_hidden(C, ar);
1052         
1053         return OPERATOR_FINISHED;
1054 }
1055
1056 void IMAGE_OT_scopes(wmOperatorType *ot)
1057 {
1058         ot->name= "Scopes";
1059         ot->idname= "IMAGE_OT_scopes";
1060         ot->description= "Toggle display scopes panel";
1061         
1062         ot->exec= image_scopes;
1063         ot->poll= ED_operator_image_active;
1064         
1065         /* flags */
1066         ot->flag= 0;
1067 }
1068