converted more mixed tab/space indentations to tabs. only whitespace changes.
[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                         uiDefButF(block, NUM, B_TRANS_IMAGE, "X:",      10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
260                         uiDefButF(block, NUM, B_TRANS_IMAGE, "Y:",      165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
261                         uiBlockEndAlign(block);
262                 }
263         }
264         else {  // apply event
265                 float delta[2];
266                 
267                 cent[0]= cent[0]/nactive;
268                 cent[1]= cent[1]/nactive;
269                         
270                 if (sima->flag & SI_COORDFLOATS) {
271                         delta[0]= ocent[0]-cent[0];
272                         delta[1]= ocent[1]-cent[1];
273                 }
274                 else {
275                         delta[0]= ocent[0]/imx - cent[0];
276                         delta[1]= ocent[1]/imy - cent[1];
277                 }
278
279                 for (efa= em->faces.first; efa; efa= efa->next) {
280                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
281                         if (uvedit_face_visible(scene, ima, efa, tf)) {
282                                 if (uvedit_uv_selected(scene, efa, tf, 0)) {
283                                         tf->uv[0][0]+= delta[0];
284                                         tf->uv[0][1]+= delta[1];
285                                 }
286                                 if (uvedit_uv_selected(scene, efa, tf, 1)) {
287                                         tf->uv[1][0]+= delta[0];
288                                         tf->uv[1][1]+= delta[1];
289                                 }
290                                 if (uvedit_uv_selected(scene, efa, tf, 2)) {
291                                         tf->uv[2][0]+= delta[0];
292                                         tf->uv[2][1]+= delta[1];
293                                 }
294                                 if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) {
295                                         tf->uv[3][0]+= delta[0];
296                                         tf->uv[3][1]+= delta[1];
297                                 }
298                         }
299                 }
300                 
301                 WM_event_add_notifier(C, NC_IMAGE, sima->image);
302         }
303
304         BKE_mesh_end_editmesh(obedit->data, em);
305 }
306
307
308 /* is used for both read and write... */
309
310 static int image_panel_poll(const bContext *C, PanelType *UNUSED(pt))
311 {
312         SpaceImage *sima= CTX_wm_space_image(C);
313         ImBuf *ibuf;
314         void *lock;
315         int result;
316
317         ibuf= ED_space_image_acquire_buffer(sima, &lock);
318         result= ibuf && ibuf->rect_float;
319         ED_space_image_release_buffer(sima, lock);
320         
321         return result;
322 }
323
324 static void image_panel_curves(const bContext *C, Panel *pa)
325 {
326         bScreen *sc= CTX_wm_screen(C);
327         SpaceImage *sima= CTX_wm_space_image(C);
328         ImBuf *ibuf;
329         PointerRNA simaptr;
330         int levels;
331         void *lock;
332         
333         ibuf= ED_space_image_acquire_buffer(sima, &lock);
334         
335         if(ibuf) {
336                 if(sima->cumap==NULL)
337                         sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
338
339                 /* curvemap black/white levels only works for RGBA */
340                 levels= (ibuf->channels==4);
341
342                 RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr);
343                 uiTemplateCurveMapping(pa->layout, &simaptr, "curve", 'c', levels, 0);
344         }
345
346         ED_space_image_release_buffer(sima, lock);
347 }
348
349 #if 0
350 /* 0: disable preview 
351    otherwise refresh preview
352  
353    XXX if you put this back, also check XXX in image_main_area_draw() */
354 */
355 void image_preview_event(int event)
356 {
357         int exec= 0;
358         
359         if(event==0) {
360                 G.scene->r.scemode &= ~R_COMP_CROP;
361                 exec= 1;
362         }
363         else {
364                 if(image_preview_active(curarea, NULL, NULL)) {
365                         G.scene->r.scemode |= R_COMP_CROP;
366                         exec= 1;
367                 }
368                 else
369                         G.scene->r.scemode &= ~R_COMP_CROP;
370         }
371         
372         if(exec && G.scene->nodetree) {
373                 /* should work when no node editor in screen..., so we execute right away */
374                 
375                 ntreeCompositTagGenerators(G.scene->nodetree);
376
377                 G.afbreek= 0;
378                 G.scene->nodetree->timecursor= set_timecursor;
379                 G.scene->nodetree->test_break= blender_test_break;
380                 
381                 BIF_store_spare();
382                 
383                 ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1);       /* 1 is do_previews */
384                 
385                 G.scene->nodetree->timecursor= NULL;
386                 G.scene->nodetree->test_break= NULL;
387                 
388                 scrarea_do_windraw(curarea);
389                 waitcursor(0);
390                 
391                 WM_event_add_notifier(C, NC_IMAGE, ima_v);
392         }       
393 }
394
395
396 /* nothing drawn here, we use it to store values */
397 static void preview_cb(struct ScrArea *sa, struct uiBlock *block)
398 {
399         SpaceImage *sima= sa->spacedata.first;
400         rctf dispf;
401         rcti *disprect= &G.scene->r.disprect;
402         int winx= (G.scene->r.size*G.scene->r.xsch)/100;
403         int winy= (G.scene->r.size*G.scene->r.ysch)/100;
404         short mval[2];
405         
406         if(G.scene->r.mode & R_BORDER) {
407                 winx*= (G.scene->r.border.xmax - G.scene->r.border.xmin);
408                 winy*= (G.scene->r.border.ymax - G.scene->r.border.ymin);
409         }
410         
411         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
412
413         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
414         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
415         
416         /* correction for gla draw */
417         BLI_translate_rcti(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
418         
419         calc_image_view(sima, 'p');
420 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
421         /* map to image space coordinates */
422         mval[0]= disprect->xmin; mval[1]= disprect->ymin;
423         areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
424         mval[0]= disprect->xmax; mval[1]= disprect->ymax;
425         areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
426         
427         /* map to render coordinates */
428         disprect->xmin= dispf.xmin;
429         disprect->xmax= dispf.xmax;
430         disprect->ymin= dispf.ymin;
431         disprect->ymax= dispf.ymax;
432         
433         CLAMP(disprect->xmin, 0, winx);
434         CLAMP(disprect->xmax, 0, winx);
435         CLAMP(disprect->ymin, 0, winy);
436         CLAMP(disprect->ymax, 0, winy);
437 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
438
439 }
440
441 static int is_preview_allowed(ScrArea *cur)
442 {
443         SpaceImage *sima= cur->spacedata.first;
444         ScrArea *sa;
445
446         /* check if another areawindow has preview set */
447         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
448                 if(sa!=cur && sa->spacetype==SPACE_IMAGE) {
449                         if(image_preview_active(sa, NULL, NULL))
450                                 return 0;
451                 }
452         }
453         /* check image type */
454         if(sima->image==NULL || sima->image->type!=IMA_TYPE_COMPOSITE)
455                 return 0;
456         
457         return 1;
458 }
459
460
461 static void image_panel_preview(ScrArea *sa, short cntrl)       // IMAGE_HANDLER_PREVIEW
462 {
463         uiBlock *block;
464         SpaceImage *sima= sa->spacedata.first;
465         int ofsx, ofsy;
466         
467         if(is_preview_allowed(sa)==0) {
468                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
469                 G.scene->r.scemode &= ~R_COMP_CROP;     /* quite weak */
470                 return;
471         }
472         
473         block= uiBeginBlock(C, ar, "image_panel_preview", UI_EMBOSS);
474         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
475         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
476         
477         ofsx= -150+(sa->winx/2)/sima->blockscale;
478         ofsy= -100+(sa->winy/2)/sima->blockscale;
479         if(uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200)==0) return;
480         
481         uiBlockSetDrawExtraFunc(block, preview_cb);
482         
483 }
484 #endif
485
486
487 /* ********************* callbacks for standard image buttons *************** */
488
489 static char *slot_menu(void)
490 {
491         char *str;
492         int a, slot;
493         
494         str= MEM_callocN(IMA_MAX_RENDER_SLOT*32, "menu slots");
495         
496         strcpy(str, "Slot %t");
497         a= strlen(str);
498
499         for(slot=0; slot<IMA_MAX_RENDER_SLOT; slot++)
500                 a += sprintf(str+a, "|Slot %d %%x%d", slot+1, slot);
501         
502         return str;
503 }
504
505 /* TODO, curlay should be removed? */
506 static char *layer_menu(RenderResult *rr, short *UNUSED(curlay))
507 {
508         RenderLayer *rl;
509         int len= 64 + 32*BLI_countlist(&rr->layers);
510         short a, nr= 0;
511         char *str= MEM_callocN(len, "menu layers");
512         
513         strcpy(str, "Layer %t");
514         a= strlen(str);
515         
516         /* compo result */
517         if(rr->rectf) {
518                 a+= sprintf(str+a, "|Composite %%x0");
519                 nr= 1;
520         }
521         for(rl= rr->layers.first; rl; rl= rl->next, nr++) {
522                 a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
523         }
524         
525         /* no curlay clip here, on render (redraws) the amount of layers can be 1 fir single-layer render */
526         
527         return str;
528 }
529
530 /* rl==NULL means composite result */
531 static char *pass_menu(RenderLayer *rl, short *curpass)
532 {
533         RenderPass *rpass;
534         int len= 64 + 32*(rl?BLI_countlist(&rl->passes):1);
535         short a, nr= 0;
536         char *str= MEM_callocN(len, "menu layers");
537         
538         strcpy(str, "Pass %t");
539         a= strlen(str);
540         
541         /* rendered results don't have a Combined pass */
542         if(rl==NULL || rl->rectf) {
543                 a+= sprintf(str+a, "|Combined %%x0");
544                 nr= 1;
545         }
546         
547         if(rl)
548                 for(rpass= rl->passes.first; rpass; rpass= rpass->next, nr++)
549                         a+= sprintf(str+a, "|%s %%x%d", rpass->name, nr);
550         
551         if(*curpass >= nr)
552                 *curpass= 0;
553         
554         return str;
555 }
556
557 static void set_frames_cb(bContext *C, void *ima_v, void *iuser_v)
558 {
559         Scene *scene= CTX_data_scene(C);
560         Image *ima= ima_v;
561         ImageUser *iuser= iuser_v;
562         
563         if(ima->anim) {
564                 iuser->frames = IMB_anim_get_duration(ima->anim);
565                 BKE_image_user_calc_frame(iuser, scene->r.cfra, 0);
566         }
567 }
568
569 /* 5 layer button callbacks... */
570 static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) 
571 {
572         ImageUser *iuser= iuser_v;
573
574         BKE_image_multilayer_index(rr_v, iuser); 
575         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
576 }
577 static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) 
578 {
579         RenderResult *rr= rr_v;
580         ImageUser *iuser= iuser_v;
581         int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0);  /* fake compo result layer */
582
583         if(iuser->layer<tot-1) {
584                 iuser->layer++;
585                 BKE_image_multilayer_index(rr, iuser); 
586                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
587         }
588 }
589 static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) 
590 {
591         ImageUser *iuser= iuser_v;
592
593         if(iuser->layer>0) {
594                 iuser->layer--;
595                 BKE_image_multilayer_index(rr_v, iuser); 
596                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
597         }
598 }
599 static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) 
600 {
601         RenderResult *rr= rr_v;
602         ImageUser *iuser= iuser_v;
603         RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
604
605         if(rl) {
606                 int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0);  /* builtin render result has no combined pass in list */
607                 if(iuser->pass<tot-1) {
608                         iuser->pass++;
609                         BKE_image_multilayer_index(rr, iuser); 
610                         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
611                 }
612         }
613 }
614 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
615 {
616         ImageUser *iuser= iuser_v;
617
618         if(iuser->pass>0) {
619                 iuser->pass--;
620                 BKE_image_multilayer_index(rr_v, iuser); 
621                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
622         }
623 }
624
625 #if 0
626 static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) 
627 {
628         if(ima_v) {
629                 Image *ima= ima_v;
630                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
631                         if (ima->packedfile) {
632                                 if (G.fileflags & G_AUTOPACK) {
633                                         if (okee("Disable AutoPack ?")) {
634                                                 G.fileflags &= ~G_AUTOPACK;
635                                         }
636                                 }
637                                 
638                                 if ((G.fileflags & G_AUTOPACK) == 0) {
639                                         unpackImage(NULL, ima, PF_ASK); /* XXX report errors */
640                                         ED_undo_push(C, "Unpack image");
641                                 }
642                         } 
643                         else {
644                                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
645                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
646                                         // XXX error("Can't pack painted image. Save image or use Repack as PNG.");
647                                 } else {
648                                         ima->packedfile = newPackedFile(NULL, ima->name); /* XXX report errors */
649                                         ED_undo_push(C, "Pack image");
650                                 }
651                         }
652                 }
653         }
654 }
655 #endif
656
657 #if 0
658 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) 
659 {
660         Scene *scene= CTX_data_scene(C);
661         BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
662         WM_event_add_notifier(C, NC_IMAGE, ima_v);
663 }
664 #endif
665
666 #if 0
667 static void image_user_change(bContext *C, void *iuser_v, void *unused)
668 {
669         Scene *scene= CTX_data_scene(C);
670         BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
671 }
672 #endif
673
674 static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
675 {
676         uiBlock *block= uiLayoutGetBlock(layout);
677         uiBut *but;
678         RenderLayer *rl= NULL;
679         int wmenu1, wmenu2, wmenu3;
680         char *strp;
681
682         uiLayoutRow(layout, 1);
683
684         /* layer menu is 1/3 larger than pass */
685         wmenu1= (2*w)/5;
686         wmenu2= (3*w)/5;
687         wmenu3= (3*w)/6;
688         
689         /* menu buts */
690         if(render_slot) {
691                 strp= slot_menu();
692                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu1, 20, render_slot, 0,0,0,0, "Select Slot");
693                 uiButSetFunc(but, image_multi_cb, rr, iuser);
694                 MEM_freeN(strp);
695         }
696
697         if(rr) {
698                 strp= layer_menu(rr, &iuser->layer);
699                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu2, 20, &iuser->layer, 0,0,0,0, "Select Layer");
700                 uiButSetFunc(but, image_multi_cb, rr, iuser);
701                 MEM_freeN(strp);
702                 
703                 rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */
704                 strp= pass_menu(rl, &iuser->pass);
705                 but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu3, 20, &iuser->pass, 0,0,0,0, "Select Pass");
706                 uiButSetFunc(but, image_multi_cb, rr, iuser);
707                 MEM_freeN(strp);        
708         }
709 }
710
711 static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, short *render_slot)
712 {
713         uiBlock *block= uiLayoutGetBlock(layout);
714         uiLayout *row;
715         uiBut *but;
716         
717         row= uiLayoutRow(layout, 1);
718
719         if(rr==NULL || iuser==NULL)
720                 return;
721         if(rr->layers.first==NULL) {
722                 uiItemL(row, "No Layers in Render Result.", ICON_NONE);
723                 return;
724         }
725
726         /* decrease, increase arrows */
727         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Layer");
728         uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
729         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Layer");
730         uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
731
732         uiblock_layer_pass_buttons(row, rr, iuser, 230, render_slot);
733
734         /* decrease, increase arrows */
735         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Pass");
736         uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
737         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Pass");
738         uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
739
740         uiBlockEndAlign(block);
741 }
742
743 // XXX HACK!
744 // static int packdummy=0;
745
746 typedef struct RNAUpdateCb {
747         PointerRNA ptr;
748         PropertyRNA *prop;
749         ImageUser *iuser;
750 } RNAUpdateCb;
751
752 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
753 {
754         RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
755
756         /* ideally this would be done by RNA itself, but there we have
757            no image user available, so we just update this flag here */
758         cb->iuser->ok= 1;
759
760         /* we call update here on the pointer property, this way the
761            owner of the image pointer can still define it's own update
762            and notifier */
763         RNA_property_update(C, &cb->ptr, cb->prop);
764 }
765
766 void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
767 {
768         PropertyRNA *prop;
769         PointerRNA imaptr;
770         RNAUpdateCb *cb;
771         Image *ima;
772         ImageUser *iuser;
773         ImBuf *ibuf;
774         Scene *scene= CTX_data_scene(C);
775         uiLayout *row, *split, *col;
776         uiBlock *block;
777         uiBut *but;
778         char str[128];
779         void *lock;
780
781         if(!ptr->data)
782                 return;
783
784         prop= RNA_struct_find_property(ptr, propname);
785         if(!prop) {
786                 printf("uiTemplateImage: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
787                 return;
788         }
789
790         if(RNA_property_type(prop) != PROP_POINTER) {
791                 printf("uiTemplateImage: expected pointer property for %s.%s\n", RNA_struct_identifier(ptr->type), propname);
792                 return;
793         }
794
795         block= uiLayoutGetBlock(layout);
796
797
798         imaptr= RNA_property_pointer_get(ptr, prop);
799         ima= imaptr.data;
800         iuser= userptr->data;
801
802         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
803         cb->ptr= *ptr;
804         cb->prop= prop;
805         cb->iuser= iuser;
806
807         uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
808
809         if(!compact)
810                 uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
811
812         // XXX missing: reload, pack
813
814         if(ima) {
815                 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
816
817                 if(ima->source == IMA_SRC_VIEWER) {
818                         ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
819                         image_info(ima, ibuf, str);
820                         BKE_image_release_ibuf(ima, lock);
821
822                         uiItemL(layout, ima->id.name+2, ICON_NONE);
823                         uiItemL(layout, str, ICON_NONE);
824
825                         if(ima->type==IMA_TYPE_COMPOSITE) {
826                                 // XXX not working yet
827 #if 0
828                                 iuser= ntree_get_active_iuser(scene->nodetree);
829                                 if(iuser) {
830                                         uiBlockBeginAlign(block);
831                                         uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, "");
832                                         uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110,120,100,20, 0, 0, 0, 0, 0, "");
833                                         but= uiDefBut(block, BUT, B_NOP, "Free Cache",  210,120,100,20, 0, 0, 0, 0, 0, "");
834                                         uiButSetFunc(but, image_freecache_cb, ima, NULL);
835                                         
836                                         if(iuser->frames)
837                                                 sprintf(str, "(%d) Frames:", iuser->framenr);
838                                         else strcpy(str, "Frames:");
839                                         uiBlockBeginAlign(block);
840                                         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");
841                                         uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
842                                 }
843 #endif
844                         }
845                         else if(ima->type==IMA_TYPE_R_RESULT) {
846                                 /* browse layer/passes */
847                                 Render *re= RE_GetRender(scene->id.name);
848                                 RenderResult *rr= RE_AcquireResultRead(re);
849                                 uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot);
850                                 RE_ReleaseResult(re);
851                         }
852                 }
853                 else {
854                         row= uiLayoutRow(layout, 0);
855                         uiItemR(row, &imaptr, "source", 0, NULL, ICON_NONE);
856
857                         if(ima->source != IMA_SRC_GENERATED) {
858                                 row= uiLayoutRow(layout, 1);
859                                 split = uiLayoutSplit(row, 0.0, 0);
860                                 if (ima->packedfile)
861                                         uiItemO(split, "", ICON_PACKAGE, "image.unpack");
862                                 else
863                                         uiItemO(split, "", ICON_UGLYPACKAGE, "image.pack");
864                                 
865                                 split = uiLayoutSplit(row, 0.0, 0);
866                                 row= uiLayoutRow(split, 1);
867                                 uiLayoutSetEnabled(row, ima->packedfile==NULL);
868                                 
869                                 uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
870                                 uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
871                         }
872
873                         // XXX what was this for?
874 #if 0
875                          /* check for re-render, only buttons */
876                         if(imagechanged==B_IMAGECHANGED) {
877                                 if(iuser->flag & IMA_ANIM_REFRESHED) {
878                                         iuser->flag &= ~IMA_ANIM_REFRESHED;
879                                         WM_event_add_notifier(C, NC_IMAGE, ima);
880                                 }
881                         }
882 #endif
883
884                         /* multilayer? */
885                         if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
886                                 uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL);
887                         }
888                         else if(ima->source != IMA_SRC_GENERATED) {
889                                 if(compact == 0) {
890                                         ibuf= BKE_image_acquire_ibuf(ima, iuser, &lock);
891                                         image_info(ima, ibuf, str);
892                                         BKE_image_release_ibuf(ima, lock);
893                                         uiItemL(layout, str, ICON_NONE);
894                                 }
895                         }
896                         
897                         if(ima->source != IMA_SRC_GENERATED) {
898                                 if(compact == 0) { /* background image view doesnt need these */
899                                         uiItemS(layout);
900
901                                         split= uiLayoutSplit(layout, 0, 0);
902
903                                         col= uiLayoutColumn(split, 0);
904                                         uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE);
905                                         row= uiLayoutRow(col, 0);
906                                         uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
907                                         uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
908
909                                         col= uiLayoutColumn(split, 0);
910                                         uiItemR(col, &imaptr, "use_premultiply", 0, NULL, ICON_NONE);
911                                 }
912                         }
913
914                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
915                                 uiItemS(layout);
916                                 
917                                 split= uiLayoutSplit(layout, 0, 0);
918
919                                 col= uiLayoutColumn(split, 0);
920                                  
921                                 sprintf(str, "(%d) Frames", iuser->framenr);
922                                 row= uiLayoutRow(col, 1);
923                                 uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
924                                 if(ima->anim) {
925                                         block= uiLayoutGetBlock(row);
926                                         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.");
927                                         uiButSetFunc(but, set_frames_cb, ima, iuser);
928                                 }
929
930                                 uiItemR(col, userptr, "frame_start", 0, "Start", ICON_NONE);
931                                 uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
932
933                                 col= uiLayoutColumn(split, 0);
934                                 uiItemR(col, userptr, "fields_per_frame", 0, "Fields", ICON_NONE);
935                                 uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
936                                 uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
937                         }
938                         else if(ima->source==IMA_SRC_GENERATED) {
939                                 split= uiLayoutSplit(layout, 0, 0);
940
941                                 col= uiLayoutColumn(split, 1);
942                                 uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
943                                 uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
944
945                                 col= uiLayoutColumn(split, 0);
946                                 uiItemR(col, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
947                         }
948
949                                         }
950
951                 uiBlockSetNFunc(block, NULL, NULL, NULL);
952         }
953
954         MEM_freeN(cb);
955 }
956
957 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
958 {
959         Scene *scene= CTX_data_scene(C);
960         RenderResult *rr;
961
962         /* render layers and passes */
963         if(ima && iuser) {
964                 rr= BKE_image_acquire_renderresult(scene, ima);
965                 uiblock_layer_pass_buttons(layout, rr, iuser, 160, (ima->type==IMA_TYPE_R_RESULT)? &ima->render_slot: NULL);
966                 BKE_image_release_renderresult(scene, ima);
967         }
968 }
969
970 static int image_panel_uv_poll(const bContext *C, PanelType *UNUSED(pt))
971 {
972         Object *obedit= CTX_data_edit_object(C);
973         return ED_uvedit_test(obedit);
974 }
975
976 static void image_panel_uv(const bContext *C, Panel *pa)
977 {
978         uiBlock *block;
979         
980         block= uiLayoutAbsoluteBlock(pa->layout);
981         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
982
983         image_editvertex_buts(C, block);
984 }       
985
986 void image_buttons_register(ARegionType *art)
987 {
988         PanelType *pt;
989
990         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel curves");
991         strcpy(pt->idname, "IMAGE_PT_curves");
992         strcpy(pt->label, "Curves");
993         pt->draw= image_panel_curves;
994         pt->poll= image_panel_poll;
995         pt->flag |= PNL_DEFAULT_CLOSED;
996         BLI_addtail(&art->paneltypes, pt);
997         
998         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
999         strcpy(pt->idname, "IMAGE_PT_gpencil");
1000         strcpy(pt->label, "Grease Pencil");
1001         pt->draw= gpencil_panel_standard;
1002         BLI_addtail(&art->paneltypes, pt);
1003
1004         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel uv");
1005         strcpy(pt->idname, "IMAGE_PT_uv");
1006         strcpy(pt->label, "UV Vertex");
1007         pt->draw= image_panel_uv;
1008         pt->poll= image_panel_uv_poll;
1009         BLI_addtail(&art->paneltypes, pt);
1010 }
1011
1012 static int image_properties(bContext *C, wmOperator *UNUSED(op))
1013 {
1014         ScrArea *sa= CTX_wm_area(C);
1015         ARegion *ar= image_has_buttons_region(sa);
1016         
1017         if(ar)
1018                 ED_region_toggle_hidden(C, ar);
1019
1020         return OPERATOR_FINISHED;
1021 }
1022
1023 void IMAGE_OT_properties(wmOperatorType *ot)
1024 {
1025         ot->name= "Properties";
1026         ot->idname= "IMAGE_OT_properties";
1027         ot->description= "Toggle display properties panel";
1028         
1029         ot->exec= image_properties;
1030         ot->poll= ED_operator_image_active;
1031         
1032         /* flags */
1033         ot->flag= 0;
1034 }
1035
1036 static int image_scopes(bContext *C, wmOperator *UNUSED(op))
1037 {
1038         ScrArea *sa= CTX_wm_area(C);
1039         ARegion *ar= image_has_scope_region(sa);
1040         
1041         if(ar)
1042                 ED_region_toggle_hidden(C, ar);
1043         
1044         return OPERATOR_FINISHED;
1045 }
1046
1047 void IMAGE_OT_scopes(wmOperatorType *ot)
1048 {
1049         ot->name= "Scopes";
1050         ot->idname= "IMAGE_OT_scopes";
1051         ot->description= "Toggle display scopes panel";
1052         
1053         ot->exec= image_scopes;
1054         ot->poll= ED_operator_image_active;
1055         
1056         /* flags */
1057         ot->flag= 0;
1058 }
1059