Cleanup: remove unused image code
[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   uiLayout *row, *split, *col;
840   uiBlock *block;
841   char str[MAX_IMAGE_INFO_LEN];
842
843   void *lock;
844
845   if (!ptr->data) {
846     return;
847   }
848
849   prop = RNA_struct_find_property(ptr, propname);
850   if (!prop) {
851     printf(
852         "%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
853     return;
854   }
855
856   if (RNA_property_type(prop) != PROP_POINTER) {
857     printf("%s: expected pointer property for %s.%s\n",
858            __func__,
859            RNA_struct_identifier(ptr->type),
860            propname);
861     return;
862   }
863
864   block = uiLayoutGetBlock(layout);
865
866   imaptr = RNA_property_pointer_get(ptr, prop);
867   ima = imaptr.data;
868   iuser = userptr->data;
869
870   BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
871
872   cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
873   cb->ptr = *ptr;
874   cb->prop = prop;
875   cb->iuser = iuser;
876
877   uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
878   uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
879
880   if (!compact) {
881     uiTemplateID(layout,
882                  C,
883                  ptr,
884                  propname,
885                  ima ? NULL : "IMAGE_OT_new",
886                  "IMAGE_OT_open",
887                  NULL,
888                  UI_TEMPLATE_ID_FILTER_ALL,
889                  false);
890   }
891
892   if (ima) {
893     UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
894
895     if (ima->source == IMA_SRC_VIEWER) {
896       ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
897       image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
898       BKE_image_release_ibuf(ima, ibuf, lock);
899
900       uiItemL(layout, ima->id.name + 2, ICON_NONE);
901       uiItemL(layout, str, ICON_NONE);
902
903       if (ima->type == IMA_TYPE_COMPOSITE) {
904       }
905       else if (ima->type == IMA_TYPE_R_RESULT) {
906         /* browse layer/passes */
907         RenderResult *rr;
908         const float dpi_fac = UI_DPI_FAC;
909         const int menus_width = 230 * dpi_fac;
910
911         /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
912         rr = BKE_image_acquire_renderresult(scene, ima);
913         uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
914         BKE_image_release_renderresult(scene, ima);
915       }
916     }
917     else {
918       uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
919
920       if (ima->source != IMA_SRC_GENERATED) {
921         row = uiLayoutRow(layout, true);
922         if (BKE_image_has_packedfile(ima)) {
923           uiItemO(row, "", ICON_PACKAGE, "image.unpack");
924         }
925         else {
926           uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
927         }
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       /* multilayer? */
936       if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
937         const float dpi_fac = UI_DPI_FAC;
938         uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
939       }
940       else if (ima->source != IMA_SRC_GENERATED) {
941         if (compact == 0) {
942           uiTemplateImageInfo(layout, C, ima, iuser);
943         }
944       }
945
946       col = uiLayoutColumn(layout, false);
947       uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
948       uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
949
950       if (ima->source != IMA_SRC_GENERATED) {
951         if (compact == 0) { /* background image view doesn't need these */
952           ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
953           bool has_alpha = true;
954
955           if (ibuf) {
956             int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
957             char valid_channels = BKE_imtype_valid_channels(imtype, false);
958
959             has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
960
961             BKE_image_release_ibuf(ima, ibuf, NULL);
962           }
963
964           if (multiview) {
965             if ((scene->r.scemode & R_MULTIVIEW) != 0) {
966               uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
967
968               if (RNA_boolean_get(&imaptr, "use_multiview")) {
969                 uiTemplateImageViews(layout, &imaptr);
970               }
971             }
972           }
973
974           if (has_alpha) {
975             col = uiLayoutColumn(layout, false);
976             uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
977             row = uiLayoutRow(col, false);
978             uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
979             uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
980           }
981
982           if (ima->source == IMA_SRC_MOVIE) {
983             col = uiLayoutColumn(layout, false);
984             uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
985           }
986         }
987       }
988
989       if (BKE_image_is_animated(ima)) {
990         uiItemS(layout);
991
992         split = uiLayoutSplit(layout, 0.0f, false);
993
994         col = uiLayoutColumn(split, false);
995
996         BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
997         uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
998         uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
999         uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
1000
1001         col = uiLayoutColumn(split, false);
1002         uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
1003         uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
1004         uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
1005       }
1006       else if (ima->source == IMA_SRC_GENERATED) {
1007         split = uiLayoutSplit(layout, 0.0f, false);
1008
1009         col = uiLayoutColumn(split, true);
1010         uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
1011         uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
1012
1013         uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
1014
1015         uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1016
1017         if (ima->gen_type == IMA_GENTYPE_BLANK) {
1018           uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE);
1019         }
1020       }
1021     }
1022
1023     UI_block_funcN_set(block, NULL, NULL, NULL);
1024   }
1025
1026   MEM_freeN(cb);
1027 }
1028
1029 void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
1030 {
1031   ImageFormatData *imf = imfptr->data;
1032   ID *id = imfptr->id.data;
1033   PointerRNA display_settings_ptr;
1034   PropertyRNA *prop;
1035   const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
1036   /* some settings depend on this being a scene that's rendered */
1037   const bool is_render_out = (id && GS(id->name) == ID_SCE);
1038
1039   uiLayout *col;
1040   bool show_preview = false;
1041
1042   col = uiLayoutColumn(layout, false);
1043
1044   uiLayoutSetPropSep(col, true);
1045   uiLayoutSetPropDecorate(col, false);
1046
1047   uiItemR(col, imfptr, "file_format", 0, NULL, ICON_NONE);
1048   uiItemR(
1049       uiLayoutRow(col, true), imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
1050
1051   /* only display depth setting if multiple depths can be used */
1052   if ((ELEM(depth_ok,
1053             R_IMF_CHAN_DEPTH_1,
1054             R_IMF_CHAN_DEPTH_8,
1055             R_IMF_CHAN_DEPTH_10,
1056             R_IMF_CHAN_DEPTH_12,
1057             R_IMF_CHAN_DEPTH_16,
1058             R_IMF_CHAN_DEPTH_24,
1059             R_IMF_CHAN_DEPTH_32)) == 0) {
1060     uiItemR(uiLayoutRow(col, true), imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1061   }
1062
1063   if (BKE_imtype_supports_quality(imf->imtype)) {
1064     uiItemR(col, imfptr, "quality", 0, NULL, ICON_NONE);
1065   }
1066
1067   if (BKE_imtype_supports_compress(imf->imtype)) {
1068     uiItemR(col, imfptr, "compression", 0, NULL, ICON_NONE);
1069   }
1070
1071   if (ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
1072     uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
1073   }
1074
1075   if (BKE_imtype_supports_zbuf(imf->imtype)) {
1076     uiItemR(col, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
1077   }
1078
1079   if (is_render_out && ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
1080     show_preview = true;
1081     uiItemR(col, imfptr, "use_preview", 0, NULL, ICON_NONE);
1082   }
1083
1084   if (imf->imtype == R_IMF_IMTYPE_JP2) {
1085     uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
1086
1087     uiItemR(col, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
1088     uiItemR(col, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
1089
1090     uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE);
1091   }
1092
1093   if (imf->imtype == R_IMF_IMTYPE_DPX) {
1094     uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
1095   }
1096
1097   if (imf->imtype == R_IMF_IMTYPE_CINEON) {
1098 #if 1
1099     uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma:1.7"), ICON_NONE);
1100 #else
1101     uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
1102     uiItemR(col, imfptr, "cineon_black", 0, NULL, ICON_NONE);
1103     uiItemR(col, imfptr, "cineon_white", 0, NULL, ICON_NONE);
1104     uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE);
1105 #endif
1106   }
1107
1108   if (imf->imtype == R_IMF_IMTYPE_TIFF) {
1109     uiItemR(col, imfptr, "tiff_codec", 0, NULL, ICON_NONE);
1110   }
1111
1112   /* color management */
1113   if (color_management && (!BKE_imtype_requires_linear_float(imf->imtype) ||
1114                            (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG))) {
1115     prop = RNA_struct_find_property(imfptr, "display_settings");
1116     display_settings_ptr = RNA_property_pointer_get(imfptr, prop);
1117
1118     col = uiLayoutColumn(layout, false);
1119     uiItemL(col, IFACE_("Color Management"), ICON_NONE);
1120
1121     uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
1122
1123     uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
1124   }
1125 }
1126
1127 void uiTemplateImageStereo3d(uiLayout *layout, PointerRNA *stereo3d_format_ptr)
1128 {
1129   Stereo3dFormat *stereo3d_format = stereo3d_format_ptr->data;
1130   uiLayout *col;
1131
1132   col = uiLayoutColumn(layout, false);
1133   uiItemR(col, stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
1134
1135   switch (stereo3d_format->display_mode) {
1136     case S3D_DISPLAY_ANAGLYPH: {
1137       uiItemR(col, stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
1138       break;
1139     }
1140     case S3D_DISPLAY_INTERLACE: {
1141       uiItemR(col, stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
1142       uiItemR(col, stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
1143       break;
1144     }
1145     case S3D_DISPLAY_SIDEBYSIDE: {
1146       uiItemR(col, stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
1147       ATTR_FALLTHROUGH;
1148     }
1149     case S3D_DISPLAY_TOPBOTTOM: {
1150       uiItemR(col, stereo3d_format_ptr, "use_squeezed_frame", 0, NULL, ICON_NONE);
1151       break;
1152     }
1153   }
1154 }
1155
1156 static void uiTemplateViewsFormat(uiLayout *layout,
1157                                   PointerRNA *ptr,
1158                                   PointerRNA *stereo3d_format_ptr)
1159 {
1160   uiLayout *col;
1161
1162   col = uiLayoutColumn(layout, false);
1163
1164   uiLayoutSetPropSep(col, true);
1165   uiLayoutSetPropDecorate(col, false);
1166
1167   uiItemR(col, ptr, "views_format", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1168
1169   if (stereo3d_format_ptr && RNA_enum_get(ptr, "views_format") == R_IMF_VIEWS_STEREO_3D) {
1170     uiTemplateImageStereo3d(col, stereo3d_format_ptr);
1171   }
1172 }
1173
1174 void uiTemplateImageViews(uiLayout *layout, PointerRNA *imaptr)
1175 {
1176   Image *ima = imaptr->data;
1177
1178   if (ima->type != IMA_TYPE_MULTILAYER) {
1179     PropertyRNA *prop;
1180     PointerRNA stereo3d_format_ptr;
1181
1182     prop = RNA_struct_find_property(imaptr, "stereo_3d_format");
1183     stereo3d_format_ptr = RNA_property_pointer_get(imaptr, prop);
1184
1185     uiTemplateViewsFormat(layout, imaptr, &stereo3d_format_ptr);
1186   }
1187   else {
1188     uiTemplateViewsFormat(layout, imaptr, NULL);
1189   }
1190 }
1191
1192 void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA *ptr)
1193 {
1194   ImageFormatData *imf = imfptr->data;
1195
1196   if (ptr == NULL) {
1197     return;
1198   }
1199
1200   uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
1201
1202   if (RNA_boolean_get(ptr, "use_multiview")) {
1203     if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
1204       PropertyRNA *prop;
1205       PointerRNA stereo3d_format_ptr;
1206
1207       prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
1208       stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
1209
1210       uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr);
1211     }
1212     else {
1213       uiTemplateViewsFormat(layout, imfptr, NULL);
1214     }
1215   }
1216 }
1217
1218 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
1219 {
1220   Scene *scene = CTX_data_scene(C);
1221
1222   /* render layers and passes */
1223   if (ima && iuser) {
1224     RenderResult *rr;
1225     const float dpi_fac = UI_DPI_FAC;
1226     const int menus_width = 160 * dpi_fac;
1227     const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT);
1228
1229     /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
1230     rr = BKE_image_acquire_renderresult(scene, ima);
1231     uiblock_layer_pass_buttons(
1232         layout, ima, rr, iuser, menus_width, is_render_result ? &ima->render_slot : NULL);
1233     BKE_image_release_renderresult(scene, ima);
1234   }
1235 }
1236
1237 void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
1238 {
1239   Scene *scene = CTX_data_scene(C);
1240   ImBuf *ibuf;
1241   char str[MAX_IMAGE_INFO_LEN];
1242   void *lock;
1243
1244   if (!ima || !iuser) {
1245     return;
1246   }
1247
1248   ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
1249
1250   BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
1251   image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
1252   BKE_image_release_ibuf(ima, ibuf, lock);
1253   uiItemL(layout, str, ICON_NONE);
1254 }
1255
1256 #undef MAX_IMAGE_INFO_LEN
1257
1258 static bool metadata_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
1259 {
1260   SpaceImage *space_image = CTX_wm_space_image(C);
1261   return space_image != NULL && space_image->image != NULL;
1262 }
1263
1264 static void metadata_panel_context_draw(const bContext *C, Panel *panel)
1265 {
1266   void *lock;
1267   SpaceImage *space_image = CTX_wm_space_image(C);
1268   Image *image = space_image->image;
1269   ImBuf *ibuf = BKE_image_acquire_ibuf(image, &space_image->iuser, &lock);
1270   if (ibuf != NULL) {
1271     ED_region_image_metadata_panel_draw(ibuf, panel->layout);
1272   }
1273   BKE_image_release_ibuf(image, ibuf, lock);
1274 }
1275
1276 void image_buttons_register(ARegionType *art)
1277 {
1278   PanelType *pt;
1279
1280   pt = MEM_callocN(sizeof(PanelType), "spacetype image panel metadata");
1281   strcpy(pt->idname, "IMAGE_PT_metadata");
1282   strcpy(pt->label, N_("Metadata"));
1283   strcpy(pt->category, "Image");
1284   strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1285   pt->poll = metadata_panel_context_poll;
1286   pt->draw = metadata_panel_context_draw;
1287   pt->flag |= PNL_DEFAULT_CLOSED;
1288   BLI_addtail(&art->paneltypes, pt);
1289 }