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