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