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