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