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