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