Cleanup: comments
[blender.git] / source / blender / editors / space_image / image_buttons.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file \ingroup spimage
21  */
22
23 #include <string.h>
24 #include <stdio.h>
25
26 #include "DNA_node_types.h"
27 #include "DNA_scene_types.h"
28
29 #include "MEM_guardedalloc.h"
30
31 #include "BLI_blenlib.h"
32 #include "BLI_utildefines.h"
33
34 #include "BLT_translation.h"
35
36 #include "BKE_context.h"
37 #include "BKE_image.h"
38 #include "BKE_node.h"
39 #include "BKE_screen.h"
40 #include "BKE_scene.h"
41
42 #include "RE_pipeline.h"
43
44 #include "IMB_imbuf.h"
45 #include "IMB_imbuf_types.h"
46
47 #include "ED_gpencil.h"
48 #include "ED_screen.h"
49 #include "ED_image.h"
50
51 #include "RNA_access.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "UI_interface.h"
57 #include "UI_resources.h"
58
59 #include "image_intern.h"
60
61 #define B_NOP -1
62 #define MAX_IMAGE_INFO_LEN  128
63
64 /* proto */
65
66 static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len)
67 {
68         size_t ofs = 0;
69
70         str[0] = 0;
71         if (ima == NULL)
72                 return;
73
74         if (ibuf == NULL) {
75                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs);
76         }
77         else {
78                 if (ima->source == IMA_SRC_MOVIE) {
79                         ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
80                         if (BKE_image_has_anim(ima))
81                                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"),
82                                                     IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN));
83                 }
84                 else {
85                         ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
86                 }
87
88                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y);
89
90                 if (ibuf->rect_float) {
91                         if (ibuf->channels != 4) {
92                                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
93                         }
94                         else if (ibuf->planes == R_IMF_PLANES_RGBA)
95                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
96                         else
97                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
98                 }
99                 else {
100                         if (ibuf->planes == R_IMF_PLANES_RGBA)
101                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
102                         else
103                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
104                 }
105                 if (ibuf->zbuf || ibuf->zbuf_float)
106                         ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
107
108                 if (ima->source == IMA_SRC_SEQUENCE) {
109                         const char *file = BLI_last_slash(ibuf->name);
110                         if (file == NULL)
111                                 file = ibuf->name;
112                         else
113                                 file++;
114                         ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file);
115                 }
116         }
117
118         /* the frame number, even if we cant */
119         if (ima->source == IMA_SRC_SEQUENCE) {
120                 /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
121                 const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
122                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr);
123         }
124 }
125
126 /* gets active viewer user */
127 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
128 {
129         bNode *node;
130
131         if (ntree)
132                 for (node = ntree->nodes.first; node; node = node->next)
133                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
134                                 if (node->flag & NODE_DO_OUTPUT)
135                                         return node->storage;
136         return NULL;
137 }
138
139
140 /* ************ panel stuff ************* */
141
142 #if 0
143 /* 0: disable preview
144  * otherwise refresh preview
145  *
146  * XXX if you put this back, also check XXX in image_main_region_draw() */
147 void image_preview_event(int event)
148 {
149         int exec = 0;
150
151         if (event == 0) {
152                 G.scene->r.scemode &= ~R_COMP_CROP;
153                 exec = 1;
154         }
155         else {
156                 if (image_preview_active(curarea, NULL, NULL)) {
157                         G.scene->r.scemode |= R_COMP_CROP;
158                         exec = 1;
159                 }
160                 else
161                         G.scene->r.scemode &= ~R_COMP_CROP;
162         }
163
164         if (exec && G.scene->nodetree) {
165                 Scene *scene = G.scene;
166                 /* should work when no node editor in screen..., so we execute right away */
167
168                 ntreeCompositTagGenerators(G.scene->nodetree);
169
170                 G.is_break = false;
171                 G.scene->nodetree->timecursor = set_timecursor;
172                 G.scene->nodetree->test_break = BKE_blender_test_break;
173
174                 BIF_store_spare();
175
176                 /* 1 is do_previews */
177                 ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings);
178
179                 G.scene->nodetree->timecursor = NULL;
180                 G.scene->nodetree->test_break = NULL;
181
182                 scrarea_do_windraw(curarea);
183                 waitcursor(0);
184
185                 WM_event_add_notifier(C, NC_IMAGE, ima_v);
186         }
187 }
188
189
190 /* nothing drawn here, we use it to store values */
191 static void preview_cb(ScrArea *sa, struct uiBlock *block)
192 {
193         SpaceImage *sima = sa->spacedata.first;
194         rctf dispf;
195         rcti *disprect = &G.scene->r.disprect;
196         int winx = (G.scene->r.size * G.scene->r.xsch) / 100;
197         int winy = (G.scene->r.size * G.scene->r.ysch) / 100;
198         int mval[2];
199
200         if (G.scene->r.mode & R_BORDER) {
201                 winx *= BLI_rcti_size_x(&G.scene->r.border);
202                 winy *= BLI_rctf_size_y(&G.scene->r.border);
203         }
204
205         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
206
207         BLI_rctf_init(&dispf, 15.0f, BLI_rcti_size_x(&block->rect) - 15.0f, 15.0f, (BLI_rctf_size_y(&block->rect)) - 15.0f);
208         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
209
210         /* correction for gla draw */
211         BLI_rcti_translate(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
212
213         calc_image_view(sima, 'p');
214 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
215         /* map to image space coordinates */
216         mval[0] = disprect->xmin; mval[1] = disprect->ymin;
217         areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
218         mval[0] = disprect->xmax; mval[1] = disprect->ymax;
219         areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
220
221         /* map to render coordinates */
222         disprect->xmin = dispf.xmin;
223         disprect->xmax = dispf.xmax;
224         disprect->ymin = dispf.ymin;
225         disprect->ymax = dispf.ymax;
226
227         CLAMP(disprect->xmin, 0, winx);
228         CLAMP(disprect->xmax, 0, winx);
229         CLAMP(disprect->ymin, 0, winy);
230         CLAMP(disprect->ymax, 0, winy);
231 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
232
233 }
234
235 static bool is_preview_allowed(ScrArea *cur)
236 {
237         SpaceImage *sima = cur->spacedata.first;
238         ScrArea *sa;
239
240         /* check if another areawindow has preview set */
241         for (sa = G.curscreen->areabase.first; sa; sa = sa->next) {
242                 if (sa != cur && sa->spacetype == SPACE_IMAGE) {
243                         if (image_preview_active(sa, NULL, NULL))
244                                 return 0;
245                 }
246         }
247         /* check image type */
248         if (sima->image == NULL || sima->image->type != IMA_TYPE_COMPOSITE)
249                 return 0;
250
251         return 1;
252 }
253
254
255 static void image_panel_preview(ScrArea *sa, short cntrl)   // IMAGE_HANDLER_PREVIEW
256 {
257         uiBlock *block;
258         SpaceImage *sima = sa->spacedata.first;
259         int ofsx, ofsy;
260
261         if (is_preview_allowed(sa) == 0) {
262                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
263                 G.scene->r.scemode &= ~R_COMP_CROP; /* quite weak */
264                 return;
265         }
266
267         block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
268         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
269         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
270
271         ofsx = -150 + (sa->winx / 2) / sima->blockscale;
272         ofsy = -100 + (sa->winy / 2) / sima->blockscale;
273         if (uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200) == 0) return;
274
275         UI_but_func_drawextra_set(block, preview_cb);
276
277 }
278 #endif
279
280
281 /* ********************* callbacks for standard image buttons *************** */
282
283 static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *image_p)
284 {
285         uiBlock *block = uiLayoutGetBlock(layout);
286         Image *image = image_p;
287         int slot_id;
288
289         uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Slot"),
290                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
291         uiItemS(layout);
292
293         slot_id = BLI_listbase_count(&image->renderslots) - 1;
294         for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) {
295                 char str[64];
296                 if (slot->name[0] != '\0') {
297                         BLI_strncpy(str, slot->name, sizeof(str));
298                 }
299                 else {
300                         BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot_id + 1);
301                 }
302                 uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, str, 0, 0,
303                           UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot_id, 0.0, 0, -1, "");
304                 slot_id--;
305         }
306 }
307
308 static bool ui_imageuser_slot_menu_step(bContext *C, int direction, void *image_p)
309 {
310         Image *image = image_p;
311
312         if (ED_image_slot_cycle(image, direction)) {
313                 WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
314                 return true;
315         }
316         else {
317                 return true;
318         }
319 }
320
321 static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
322 {
323         RenderView *rv = RE_RenderViewGetById(rr, 0);
324         if (rv->rectf) {
325                 return IFACE_("Composite");
326         }
327         else if (rv->rect32) {
328                 return IFACE_("Sequence");
329         }
330         else {
331                 return NULL;
332         }
333 }
334
335 /* workaround for passing many args */
336 struct ImageUI_Data {
337         Image *image;
338         ImageUser *iuser;
339         int rpass_index;
340 };
341
342 static struct ImageUI_Data *ui_imageuser_data_copy(const struct ImageUI_Data *rnd_pt_src)
343 {
344         struct ImageUI_Data *rnd_pt_dst = MEM_mallocN(sizeof(*rnd_pt_src), __func__);
345         memcpy(rnd_pt_dst, rnd_pt_src, sizeof(*rnd_pt_src));
346         return rnd_pt_dst;
347 }
348
349 static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
350 {
351         struct ImageUI_Data *rnd_data = rnd_pt;
352         uiBlock *block = uiLayoutGetBlock(layout);
353         Image *image = rnd_data->image;
354         ImageUser *iuser = rnd_data->iuser;
355         Scene *scene = iuser->scene;
356         RenderResult *rr;
357         RenderLayer *rl;
358         RenderLayer rl_fake = {NULL};
359         const char *fake_name;
360         int nr;
361
362         /* may have been freed since drawing */
363         rr = BKE_image_acquire_renderresult(scene, image);
364         if (UNLIKELY(rr == NULL)) {
365                 return;
366         }
367
368         UI_block_layout_set_current(block, layout);
369         uiLayoutColumn(layout, false);
370
371         uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Layer"),
372                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
373         uiItemS(layout);
374
375         nr = BLI_listbase_count(&rr->layers) - 1;
376         fake_name = ui_imageuser_layer_fake_name(rr);
377
378         if (fake_name) {
379                 BLI_strncpy(rl_fake.name, fake_name, sizeof(rl_fake.name));
380                 nr += 1;
381         }
382
383         for (rl = rr->layers.last; rl; rl = rl->prev, nr--) {
384 final:
385                 uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, rl->name, 0, 0,
386                           UI_UNIT_X * 5, UI_UNIT_X, &iuser->layer, (float) nr, 0.0, 0, -1, "");
387         }
388
389         if (fake_name) {
390                 fake_name = NULL;
391                 rl = &rl_fake;
392                 goto final;
393         }
394
395         BLI_assert(nr == -1);
396
397         BKE_image_release_renderresult(scene, image);
398 }
399
400 static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
401 {
402         struct ImageUI_Data *rnd_data = rnd_pt;
403         uiBlock *block = uiLayoutGetBlock(layout);
404         Image *image = rnd_data->image;
405         ImageUser *iuser = rnd_data->iuser;
406         /* (rpass_index == -1) means composite result */
407         const int rpass_index = rnd_data->rpass_index;
408         Scene *scene = iuser->scene;
409         RenderResult *rr;
410         RenderLayer *rl;
411         RenderPass *rpass;
412         int nr;
413
414         /* may have been freed since drawing */
415         rr = BKE_image_acquire_renderresult(scene, image);
416         if (UNLIKELY(rr == NULL)) {
417                 return;
418         }
419
420         rl = BLI_findlink(&rr->layers, rpass_index);
421
422         UI_block_layout_set_current(block, layout);
423         uiLayoutColumn(layout, false);
424
425         uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Pass"),
426                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
427
428         uiItemS(layout);
429
430         nr = (rl == NULL) ? 1 : 0;
431
432         ListBase added_passes;
433         BLI_listbase_clear(&added_passes);
434
435         /* rendered results don't have a Combined pass */
436         /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
437         for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
438                 /* just show one pass of each kind */
439                 if (BLI_findstring_ptr(&added_passes, rpass->name, offsetof(LinkData, data))) {
440                         continue;
441                 }
442                 BLI_addtail(&added_passes, BLI_genericNodeN(rpass->name));
443
444                 uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->name), 0, 0,
445                           UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
446         }
447
448         BLI_freelistN(&added_passes);
449
450         BKE_image_release_renderresult(scene, image);
451 }
452
453 /**************************** view menus *****************************/
454 static void ui_imageuser_view_menu_rr(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
455 {
456         struct ImageUI_Data *rnd_data = rnd_pt;
457         uiBlock *block = uiLayoutGetBlock(layout);
458         Image *image = rnd_data->image;
459         ImageUser *iuser = rnd_data->iuser;
460         RenderResult *rr;
461         RenderView *rview;
462         int nr;
463         Scene *scene = iuser->scene;
464
465         /* may have been freed since drawing */
466         rr = BKE_image_acquire_renderresult(scene, image);
467         if (UNLIKELY(rr == NULL)) {
468                 return;
469         }
470
471         UI_block_layout_set_current(block, layout);
472         uiLayoutColumn(layout, false);
473
474         uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
475                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
476
477         uiItemS(layout);
478
479         nr = (rr ? BLI_listbase_count(&rr->views) : 0) - 1;
480         for (rview = rr ? rr->views.last : NULL; rview; rview = rview->prev, nr--) {
481                 uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rview->name), 0, 0,
482                           UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
483         }
484
485         BKE_image_release_renderresult(scene, image);
486 }
487
488 static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
489 {
490         struct ImageUI_Data *rnd_data = rnd_pt;
491         uiBlock *block = uiLayoutGetBlock(layout);
492         Image *image = rnd_data->image;
493         ImageUser *iuser = rnd_data->iuser;
494         int nr;
495         ImageView *iv;
496
497         UI_block_layout_set_current(block, layout);
498         uiLayoutColumn(layout, false);
499
500         uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("View"),
501                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
502
503         uiItemS(layout);
504
505         nr = BLI_listbase_count(&image->views) - 1;
506         for (iv = image->views.last; iv; iv = iv->prev, nr--) {
507                 uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(iv->name), 0, 0,
508                           UI_UNIT_X * 5, UI_UNIT_X, &iuser->view, (float) nr, 0.0, 0, -1, "");
509         }
510 }
511
512 /* 5 layer button callbacks... */
513 static void image_multi_cb(bContext *C, void *rnd_pt, void *rr_v)
514 {
515         struct ImageUI_Data *rnd_data = rnd_pt;
516         ImageUser *iuser = rnd_data->iuser;
517
518         BKE_image_multilayer_index(rr_v, iuser);
519         WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
520 }
521
522 static bool ui_imageuser_layer_menu_step(bContext *C, int direction, void *rnd_pt)
523 {
524         Scene *scene = CTX_data_scene(C);
525         struct ImageUI_Data *rnd_data = rnd_pt;
526         Image *image = rnd_data->image;
527         ImageUser *iuser = rnd_data->iuser;
528         RenderResult *rr;
529         bool changed = false;
530
531         rr = BKE_image_acquire_renderresult(scene, image);
532         if (UNLIKELY(rr == NULL)) {
533                 return false;
534         }
535
536         if (direction == -1) {
537                 if (iuser->layer > 0) {
538                         iuser->layer--;
539                         changed = true;
540                 }
541         }
542         else if (direction == 1) {
543                 int tot = BLI_listbase_count(&rr->layers);
544
545                 if (RE_HasCombinedLayer(rr))
546                         tot++;  /* fake compo/sequencer layer */
547
548                 if (iuser->layer < tot - 1) {
549                         iuser->layer++;
550                         changed = true;
551                 }
552         }
553         else {
554                 BLI_assert(0);
555         }
556
557         BKE_image_release_renderresult(scene, image);
558
559         if (changed) {
560                 BKE_image_multilayer_index(rr, iuser);
561                 WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
562         }
563
564         return changed;
565 }
566
567 static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt)
568 {
569         Scene *scene = CTX_data_scene(C);
570         struct ImageUI_Data *rnd_data = rnd_pt;
571         Image *image = rnd_data->image;
572         ImageUser *iuser = rnd_data->iuser;
573         RenderResult *rr;
574         bool changed = false;
575         int layer = iuser->layer;
576         RenderLayer *rl;
577         RenderPass *rpass;
578
579         rr = BKE_image_acquire_renderresult(scene, image);
580         if (UNLIKELY(rr == NULL)) {
581                 BKE_image_release_renderresult(scene, image);
582                 return false;
583         }
584
585         if (RE_HasCombinedLayer(rr)) {
586                 layer -= 1;
587         }
588
589         rl = BLI_findlink(&rr->layers, layer);
590         if (rl == NULL) {
591                 BKE_image_release_renderresult(scene, image);
592                 return false;
593         }
594
595         rpass = BLI_findlink(&rl->passes, iuser->pass);
596         if (rpass == NULL) {
597                 BKE_image_release_renderresult(scene, image);
598                 return false;
599         }
600
601         /* note, this looks reversed, but matches menu direction */
602         if (direction == -1) {
603                 RenderPass *rp;
604                 int rp_index = iuser->pass + 1;
605
606                 for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
607                         if (!STREQ(rp->name, rpass->name)) {
608                                 iuser->pass = rp_index;
609                                 changed = true;
610                                 break;
611                         }
612                 }
613         }
614         else if (direction == 1) {
615                 RenderPass *rp;
616                 int rp_index = 0;
617
618                 if (iuser->pass == 0) {
619                         BKE_image_release_renderresult(scene, image);
620                         return false;
621                 }
622
623                 for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
624                         if (STREQ(rp->name, rpass->name)) {
625                                 iuser->pass = rp_index - 1;
626                                 changed = true;
627                                 break;
628                         }
629                 }
630         }
631         else {
632                 BLI_assert(0);
633         }
634
635         BKE_image_release_renderresult(scene, image);
636
637         if (changed) {
638                 BKE_image_multilayer_index(rr, iuser);
639                 WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
640         }
641
642         return changed;
643 }
644
645 /* 5 view button callbacks... */
646 static void image_multiview_cb(bContext *C, void *rnd_pt, void *UNUSED(arg_v))
647 {
648         struct ImageUI_Data *rnd_data = rnd_pt;
649         Image *ima = rnd_data->image;
650         ImageUser *iuser = rnd_data->iuser;
651
652         BKE_image_multiview_index(ima, iuser);
653         WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
654 }
655
656 #if 0
657 static void image_freecache_cb(bContext *C, void *ima_v, void *unused)
658 {
659         Scene *scene = CTX_data_scene(C);
660         BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
661         WM_event_add_notifier(C, NC_IMAGE, ima_v);
662 }
663 #endif
664
665 #if 0
666 static void image_user_change(bContext *C, void *iuser_v, void *unused)
667 {
668         Scene *scene = CTX_data_scene(C);
669         BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
670 }
671 #endif
672
673 static void uiblock_layer_pass_buttons(
674         uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w,
675         short *render_slot)
676 {
677         struct ImageUI_Data rnd_pt_local, *rnd_pt = NULL;
678         uiBlock *block = uiLayoutGetBlock(layout);
679         uiBut *but;
680         RenderLayer *rl = NULL;
681         int wmenu1, wmenu2, wmenu3, wmenu4;
682         const char *fake_name;
683         const char *display_name = "";
684         const bool show_stereo = (iuser->flag & IMA_SHOW_STEREO) != 0;
685
686         if (iuser->scene == NULL) {
687                 return;
688         }
689
690         uiLayoutRow(layout, true);
691
692         /* layer menu is 1/3 larger than pass */
693         wmenu1 = (2 * w) / 5;
694         wmenu2 = (3 * w) / 5;
695         wmenu3 = (3 * w) / 6;
696         wmenu4 = (3 * w) / 6;
697
698         rnd_pt_local.image = image;
699         rnd_pt_local.iuser = iuser;
700         rnd_pt_local.rpass_index = 0;
701
702         /* menu buts */
703         if (render_slot) {
704                 char str[64];
705                 RenderSlot *slot = BKE_image_get_renderslot(image, *render_slot);
706                 if (slot && slot->name[0] != '\0') {
707                         BLI_strncpy(str, slot->name, sizeof(str));
708                 }
709                 else {
710                         BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1);
711                 }
712
713                 rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
714                 but = uiDefMenuBut(block, ui_imageuser_slot_menu, image, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot"));
715                 UI_but_func_menu_step_set(but, ui_imageuser_slot_menu_step);
716                 UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
717                 UI_but_type_set_menu_from_pulldown(but);
718                 rnd_pt = NULL;
719         }
720
721         if (rr) {
722                 RenderPass *rpass;
723                 RenderView *rview;
724                 int rpass_index;
725
726                 /* layer */
727                 fake_name = ui_imageuser_layer_fake_name(rr);
728                 rpass_index = iuser->layer  - (fake_name ? 1 : 0);
729                 rl = BLI_findlink(&rr->layers, rpass_index);
730                 rnd_pt_local.rpass_index = rpass_index;
731
732                 if (RE_layers_have_name(rr)) {
733                         display_name = rl ? rl->name : (fake_name ? fake_name : "");
734                         rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
735                         but = uiDefMenuBut(
736                                 block, ui_imageuser_layer_menu, rnd_pt, display_name,
737                                 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer"));
738                         UI_but_func_menu_step_set(but, ui_imageuser_layer_menu_step);
739                         UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
740                         UI_but_type_set_menu_from_pulldown(but);
741                         rnd_pt = NULL;
742                 }
743
744                 /* pass */
745                 rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass) : NULL);
746
747                 if (rpass && RE_passes_have_name(rl)) {
748                         display_name = rpass->name;
749                         rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
750                         but = uiDefMenuBut(
751                                 block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name),
752                                 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass"));
753                         UI_but_func_menu_step_set(but, ui_imageuser_pass_menu_step);
754                         UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
755                         UI_but_type_set_menu_from_pulldown(but);
756                         rnd_pt = NULL;
757                 }
758
759                 /* view */
760                 if (BLI_listbase_count_at_most(&rr->views, 2) > 1 &&
761                     ((!show_stereo) || (!RE_RenderResult_is_stereo(rr))))
762                 {
763                         rview = BLI_findlink(&rr->views, iuser->view);
764                         display_name = rview ? rview->name : "";
765
766                         rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
767                         but = uiDefMenuBut(
768                                 block, ui_imageuser_view_menu_rr, rnd_pt, display_name,
769                                 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View"));
770                         UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr);
771                         UI_but_type_set_menu_from_pulldown(but);
772                         rnd_pt = NULL;
773                 }
774         }
775
776         /* stereo image */
777         else if ((BKE_image_is_stereo(image) && (!show_stereo)) ||
778                  (BKE_image_is_multiview(image) && !BKE_image_is_stereo(image)))
779         {
780                 ImageView *iv;
781                 int nr = 0;
782
783                 for (iv = image->views.first; iv; iv = iv->next) {
784                         if (nr++ == iuser->view) {
785                                 display_name = iv->name;
786                                 break;
787                         }
788                 }
789
790                 rnd_pt = ui_imageuser_data_copy(&rnd_pt_local);
791                 but = uiDefMenuBut(
792                         block, ui_imageuser_view_menu_multiview, rnd_pt, display_name,
793                         0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View"));
794                 UI_but_funcN_set(but, image_multiview_cb, rnd_pt, NULL);
795                 UI_but_type_set_menu_from_pulldown(but);
796                 rnd_pt = NULL;
797         }
798 }
799
800 // XXX HACK!
801 // static int packdummy=0;
802
803 typedef struct RNAUpdateCb {
804         PointerRNA ptr;
805         PropertyRNA *prop;
806         ImageUser *iuser;
807 } RNAUpdateCb;
808
809 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
810 {
811         RNAUpdateCb *cb = (RNAUpdateCb *)arg_cb;
812
813         /* ideally this would be done by RNA itself, but there we have
814          * no image user available, so we just update this flag here */
815         cb->iuser->ok = 1;
816
817         /* we call update here on the pointer property, this way the
818          * owner of the image pointer can still define it's own update
819          * and notifier */
820         RNA_property_update(C, &cb->ptr, cb->prop);
821 }
822
823 void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, bool compact, bool multiview)
824 {
825         PropertyRNA *prop;
826         PointerRNA imaptr;
827         RNAUpdateCb *cb;
828         Image *ima;
829         ImageUser *iuser;
830         Scene *scene = CTX_data_scene(C);
831         uiLayout *row, *split, *col;
832         uiBlock *block;
833         char str[MAX_IMAGE_INFO_LEN];
834
835         void *lock;
836
837         if (!ptr->data)
838                 return;
839
840         prop = RNA_struct_find_property(ptr, propname);
841         if (!prop) {
842                 printf("%s: property not found: %s.%s\n",
843                        __func__, RNA_struct_identifier(ptr->type), propname);
844                 return;
845         }
846
847         if (RNA_property_type(prop) != PROP_POINTER) {
848                 printf("%s: expected pointer property for %s.%s\n",
849                        __func__, RNA_struct_identifier(ptr->type), propname);
850                 return;
851         }
852
853         block = uiLayoutGetBlock(layout);
854
855         imaptr = RNA_property_pointer_get(ptr, prop);
856         ima = imaptr.data;
857         iuser = userptr->data;
858
859         BKE_image_user_check_frame_calc(iuser, (int)scene->r.cfra);
860
861         cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
862         cb->ptr = *ptr;
863         cb->prop = prop;
864         cb->iuser = iuser;
865
866         uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
867         uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
868
869         if (!compact) {
870                 uiTemplateID(
871                         layout, C, ptr, propname,
872                         ima ? NULL : "IMAGE_OT_new", "IMAGE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_ALL, false);
873         }
874
875         if (ima) {
876                 UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
877
878                 if (ima->source == IMA_SRC_VIEWER) {
879                         ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
880                         image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
881                         BKE_image_release_ibuf(ima, ibuf, lock);
882
883                         uiItemL(layout, ima->id.name + 2, ICON_NONE);
884                         uiItemL(layout, str, ICON_NONE);
885
886                         if (ima->type == IMA_TYPE_COMPOSITE) {
887                                 // XXX not working yet
888 #if 0
889                                 iuser = ntree_get_active_iuser(scene->nodetree);
890                                 if (iuser) {
891                                         UI_block_align_begin(block);
892                                         uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
893                                         uiDefIconTextBut(block, UI_BTYPE_BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110, 120, 100, 20, 0, 0, 0, 0, 0, "");
894                                         but = uiDefBut(block, UI_BTYPE_BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
895                                         UI_but_func_set(but, image_freecache_cb, ima, NULL);
896
897                                         if (iuser->frames)
898                                                 BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
899                                         else strcpy(str, "Frames:");
900                                         UI_block_align_begin(block);
901                                         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");
902                                         uiDefButI(block, UI_BTYPE_NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
903                                 }
904 #endif
905                         }
906                         else if (ima->type == IMA_TYPE_R_RESULT) {
907                                 /* browse layer/passes */
908                                 RenderResult *rr;
909                                 const float dpi_fac = UI_DPI_FAC;
910                                 const int menus_width = 230 * dpi_fac;
911
912                                 /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
913                                 rr = BKE_image_acquire_renderresult(scene, ima);
914                                 uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
915                                 BKE_image_release_renderresult(scene, ima);
916                         }
917                 }
918                 else {
919                         uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
920
921                         if (ima->source != IMA_SRC_GENERATED) {
922                                 row = uiLayoutRow(layout, true);
923                                 if (BKE_image_has_packedfile(ima))
924                                         uiItemO(row, "", ICON_PACKAGE, "image.unpack");
925                                 else
926                                         uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
927
928                                 row = uiLayoutRow(row, true);
929                                 uiLayoutSetEnabled(row, BKE_image_has_packedfile(ima) == false);
930                                 uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
931                                 uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
932                         }
933
934                         // XXX what was this for?
935 #if 0
936                         /* check for re-render, only buttons */
937                         if (imagechanged == B_IMAGECHANGED) {
938                                 if (iuser->flag & IMA_ANIM_REFRESHED) {
939                                         iuser->flag &= ~IMA_ANIM_REFRESHED;
940                                         WM_event_add_notifier(C, NC_IMAGE, ima);
941                                 }
942                         }
943 #endif
944
945                         /* multilayer? */
946                         if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
947                                 const float dpi_fac = UI_DPI_FAC;
948                                 uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
949                         }
950                         else if (ima->source != IMA_SRC_GENERATED) {
951                                 if (compact == 0) {
952                                         uiTemplateImageInfo(layout, C, ima, iuser);
953                                 }
954                         }
955
956                         col = uiLayoutColumn(layout, false);
957                         uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
958                         uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
959
960                         if (ima->source != IMA_SRC_GENERATED) {
961                                 if (compact == 0) { /* background image view doesn't need these */
962                                         ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
963                                         bool has_alpha = true;
964
965                                         if (ibuf) {
966                                                 int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
967                                                 char valid_channels = BKE_imtype_valid_channels(imtype, false);
968
969                                                 has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
970
971                                                 BKE_image_release_ibuf(ima, ibuf, NULL);
972                                         }
973
974                                         if (multiview) {
975                                                 if ((scene->r.scemode & R_MULTIVIEW) != 0) {
976                                                         uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
977
978                                                         if (RNA_boolean_get(&imaptr, "use_multiview")) {
979                                                                 uiTemplateImageViews(layout, &imaptr);
980                                                         }
981                                                 }
982                                         }
983
984                                         if (has_alpha) {
985                                                 col = uiLayoutColumn(layout, false);
986                                                 uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
987                                                 row = uiLayoutRow(col, false);
988                                                 uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
989                                                 uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
990                                         }
991
992                                         if (ima->source == IMA_SRC_MOVIE) {
993                                                 col = uiLayoutColumn(layout, false);
994                                                 uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
995                                         }
996                                 }
997                         }
998
999                         if (BKE_image_is_animated(ima)) {
1000                                 uiItemS(layout);
1001
1002                                 split = uiLayoutSplit(layout, 0.0f, false);
1003
1004                                 col = uiLayoutColumn(split, false);
1005
1006                                 BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
1007                                 uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
1008                                 uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
1009                                 uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
1010
1011                                 col = uiLayoutColumn(split, false);
1012                                 uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
1013                                 uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
1014                                 uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
1015                         }
1016                         else if (ima->source == IMA_SRC_GENERATED) {
1017                                 split = uiLayoutSplit(layout, 0.0f, false);
1018
1019                                 col = uiLayoutColumn(split, true);
1020                                 uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
1021                                 uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
1022
1023                                 uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
1024
1025                                 uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1026
1027                                 if (ima->gen_type == IMA_GENTYPE_BLANK) {
1028                                         uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE);
1029                                 }
1030                         }
1031
1032                 }
1033
1034                 UI_block_funcN_set(block, NULL, NULL, NULL);
1035         }
1036
1037         MEM_freeN(cb);
1038 }
1039
1040 void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
1041 {
1042         ImageFormatData *imf = imfptr->data;
1043         ID *id = imfptr->id.data;
1044         PointerRNA display_settings_ptr;
1045         PropertyRNA *prop;
1046         const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
1047         /* some settings depend on this being a scene that's rendered */
1048         const bool is_render_out = (id && GS(id->name) == ID_SCE);
1049
1050         uiLayout *col;
1051         bool show_preview = false;
1052
1053         col = uiLayoutColumn(layout, false);
1054
1055         uiLayoutSetPropSep(col, true);
1056         uiLayoutSetPropDecorate(col, false);
1057
1058         uiItemR(col, imfptr, "file_format", 0, NULL, ICON_NONE);
1059         uiItemR(uiLayoutRow(col, true), imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
1060
1061         /* only display depth setting if multiple depths can be used */
1062         if ((ELEM(depth_ok,
1063                   R_IMF_CHAN_DEPTH_1,
1064                   R_IMF_CHAN_DEPTH_8,
1065                   R_IMF_CHAN_DEPTH_10,
1066                   R_IMF_CHAN_DEPTH_12,
1067                   R_IMF_CHAN_DEPTH_16,
1068                   R_IMF_CHAN_DEPTH_24,
1069                   R_IMF_CHAN_DEPTH_32)) == 0)
1070         {
1071                 uiItemR(uiLayoutRow(col, true), imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1072         }
1073
1074         if (BKE_imtype_supports_quality(imf->imtype)) {
1075                 uiItemR(col, imfptr, "quality", 0, NULL, ICON_NONE);
1076         }
1077
1078         if (BKE_imtype_supports_compress(imf->imtype)) {
1079                 uiItemR(col, imfptr, "compression", 0, NULL, ICON_NONE);
1080         }
1081
1082         if (ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
1083                 uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
1084         }
1085
1086         if (BKE_imtype_supports_zbuf(imf->imtype)) {
1087                 uiItemR(col, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
1088         }
1089
1090         if (is_render_out && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
1091                 show_preview = true;
1092                 uiItemR(col, imfptr, "use_preview", 0, NULL, ICON_NONE);
1093         }
1094
1095         if (imf->imtype == R_IMF_IMTYPE_JP2) {
1096                 uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
1097
1098                 uiItemR(col, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
1099                 uiItemR(col, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
1100
1101                 uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE);
1102         }
1103
1104         if (imf->imtype == R_IMF_IMTYPE_DPX) {
1105                 uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
1106         }
1107
1108         if (imf->imtype == R_IMF_IMTYPE_CINEON) {
1109 #if 1
1110                 uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma:1.7"), ICON_NONE);
1111 #else
1112                 uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
1113                 uiItemR(col, imfptr, "cineon_black", 0, NULL, ICON_NONE);
1114                 uiItemR(col, imfptr, "cineon_white", 0, NULL, ICON_NONE);
1115                 uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE);
1116 #endif
1117         }
1118
1119         if (imf->imtype == R_IMF_IMTYPE_TIFF) {
1120                 uiItemR(col, imfptr, "tiff_codec", 0, NULL, ICON_NONE);
1121         }
1122
1123         /* color management */
1124         if (color_management &&
1125             (!BKE_imtype_requires_linear_float(imf->imtype) ||
1126              (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG)))
1127         {
1128                 prop = RNA_struct_find_property(imfptr, "display_settings");
1129                 display_settings_ptr = RNA_property_pointer_get(imfptr, prop);
1130
1131                 col = uiLayoutColumn(layout, false);
1132                 uiItemL(col, IFACE_("Color Management"), ICON_NONE);
1133
1134                 uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
1135
1136                 uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
1137         }
1138 }
1139
1140 void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr)
1141 {
1142         Stereo3dFormat *stereo3d_format = stereo3d_format_ptr->data;
1143         uiLayout *col;
1144
1145         col = uiLayoutColumn(layout, false);
1146         uiItemR(col, stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
1147
1148         switch (stereo3d_format->display_mode) {
1149                 case S3D_DISPLAY_ANAGLYPH:
1150                 {
1151                         uiItemR(col, stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
1152                         break;
1153                 }
1154                 case S3D_DISPLAY_INTERLACE:
1155                 {
1156                         uiItemR(col, stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
1157                         uiItemR(col, stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
1158                         break;
1159                 }
1160                 case S3D_DISPLAY_SIDEBYSIDE:
1161                 {
1162                         uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
1163                         ATTR_FALLTHROUGH;
1164                 }
1165                 case S3D_DISPLAY_TOPBOTTOM:
1166                 {
1167                         uiItemR(col, stereo3d_format_ptr, "use_squeezed_frame", 0, NULL, ICON_NONE);
1168                         break;
1169                 }
1170         }
1171 }
1172
1173 static void uiTemplateViewsFormat(uiLayout *layout, PointerRNA *ptr, PointerRNA *stereo3d_format_ptr)
1174 {
1175         uiLayout *col;
1176
1177         col = uiLayoutColumn(layout, false);
1178
1179         uiLayoutSetPropSep(col, true);
1180         uiLayoutSetPropDecorate(col, false);
1181
1182         uiItemR(col, ptr, "views_format", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1183
1184         if (stereo3d_format_ptr &&
1185             RNA_enum_get(ptr, "views_format") == R_IMF_VIEWS_STEREO_3D)
1186         {
1187                 uiTemplateImageStereo3d(col, stereo3d_format_ptr);
1188         }
1189 }
1190
1191 void uiTemplateImageViews(uiLayout *layout, PointerRNA *imaptr)
1192 {
1193         Image *ima = imaptr->data;
1194
1195         if (ima->type != IMA_TYPE_MULTILAYER) {
1196                 PropertyRNA *prop;
1197                 PointerRNA stereo3d_format_ptr;
1198
1199                 prop = RNA_struct_find_property(imaptr, "stereo_3d_format");
1200                 stereo3d_format_ptr = RNA_property_pointer_get(imaptr, prop);
1201
1202                 uiTemplateViewsFormat(layout, imaptr, &stereo3d_format_ptr);
1203         }
1204         else {
1205                 uiTemplateViewsFormat(layout, imaptr, NULL);
1206         }
1207 }
1208
1209 void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr)
1210 {
1211         ImageFormatData *imf = imfptr->data;
1212
1213         if (ptr == NULL)
1214                 return;
1215
1216         uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
1217
1218         if (RNA_boolean_get(ptr, "use_multiview")) {
1219                 if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
1220                         PropertyRNA *prop;
1221                         PointerRNA stereo3d_format_ptr;
1222
1223                         prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
1224                         stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
1225
1226                         uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr);
1227                 }
1228                 else {
1229                         uiTemplateViewsFormat(layout, imfptr, NULL);
1230                 }
1231         }
1232 }
1233
1234 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
1235 {
1236         Scene *scene = CTX_data_scene(C);
1237
1238         /* render layers and passes */
1239         if (ima && iuser) {
1240                 RenderResult *rr;
1241                 const float dpi_fac = UI_DPI_FAC;
1242                 const int menus_width = 160 * dpi_fac;
1243                 const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT);
1244
1245                 /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
1246                 rr = BKE_image_acquire_renderresult(scene, ima);
1247                 uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width,
1248                                            is_render_result ? &ima->render_slot : NULL);
1249                 BKE_image_release_renderresult(scene, ima);
1250         }
1251 }
1252
1253 void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
1254 {
1255         ImBuf *ibuf;
1256         char str[MAX_IMAGE_INFO_LEN];
1257         void *lock;
1258
1259         if (!ima || !iuser)
1260                 return;
1261
1262         ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
1263
1264         image_info(CTX_data_scene(C), iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
1265         BKE_image_release_ibuf(ima, ibuf, lock);
1266         uiItemL(layout, str, ICON_NONE);
1267 }
1268
1269 #undef MAX_IMAGE_INFO_LEN
1270
1271 static bool metadata_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
1272 {
1273         SpaceImage *space_image = CTX_wm_space_image(C);
1274         return space_image != NULL && space_image->image != NULL;
1275 }
1276
1277 static void metadata_panel_context_draw(const bContext *C, Panel *panel)
1278 {
1279         void *lock;
1280         SpaceImage *space_image = CTX_wm_space_image(C);
1281         Image *image = space_image->image;
1282         ImBuf *ibuf = BKE_image_acquire_ibuf(image, &space_image->iuser, &lock);
1283         if (ibuf != NULL) {
1284                 ED_region_image_metadata_panel_draw(ibuf, panel->layout);
1285         }
1286         BKE_image_release_ibuf(image, ibuf, lock);
1287 }
1288
1289 void image_buttons_register(ARegionType *art)
1290 {
1291         PanelType *pt;
1292
1293         pt = MEM_callocN(sizeof(PanelType), "spacetype image panel metadata");
1294         strcpy(pt->idname, "IMAGE_PT_metadata");
1295         strcpy(pt->label, N_("Metadata"));
1296         strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1297         pt->poll = metadata_panel_context_poll;
1298         pt->draw = metadata_panel_context_draw;
1299         pt->flag |= PNL_DEFAULT_CLOSED;
1300         BLI_addtail(&art->paneltypes, pt);
1301 }
1302
1303 static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1304 {
1305         ScrArea *sa = CTX_wm_area(C);
1306         ARegion *ar = image_has_buttons_region(sa);
1307
1308         if (ar)
1309                 ED_region_toggle_hidden(C, ar);
1310
1311         return OPERATOR_FINISHED;
1312 }
1313
1314 void IMAGE_OT_properties(wmOperatorType *ot)
1315 {
1316         ot->name = "Toggle Sidebar";
1317         ot->idname = "IMAGE_OT_properties";
1318         ot->description = "Toggle the properties region visibility";
1319
1320         ot->exec = image_properties_toggle_exec;
1321         ot->poll = ED_operator_image_active;
1322
1323         /* flags */
1324         ot->flag = 0;
1325 }
1326
1327 static int image_scopes_toggle_exec(bContext *C, wmOperator *UNUSED(op))
1328 {
1329         ScrArea *sa = CTX_wm_area(C);
1330         ARegion *ar = image_has_tools_region(sa);
1331
1332         if (ar)
1333                 ED_region_toggle_hidden(C, ar);
1334
1335         return OPERATOR_FINISHED;
1336 }
1337
1338 void IMAGE_OT_toolshelf(wmOperatorType *ot)
1339 {
1340         ot->name = "Toggle Toolbar";
1341         ot->idname = "IMAGE_OT_toolshelf";
1342         ot->description = "Toggles tool shelf display";
1343
1344         ot->exec = image_scopes_toggle_exec;
1345         ot->poll = ED_operator_image_active;
1346
1347         /* flags */
1348         ot->flag = 0;
1349 }