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