Use tabs for image editor.
[blender.git] / source / blender / editors / space_image / image_buttons.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2002-2009
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_image/image_buttons.c
27  *  \ingroup spimage
28  */
29
30 #include <string.h>
31 #include <stdio.h>
32
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_node_types.h"
36 #include "DNA_scene_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43
44 #include "BLF_translation.h"
45
46 #include "BKE_colortools.h"
47 #include "BKE_context.h"
48 #include "BKE_customdata.h"
49 #include "BKE_image.h"
50 #include "BKE_mesh.h"
51 #include "BKE_node.h"
52 #include "BKE_screen.h"
53
54 #include "RE_pipeline.h"
55
56 #include "IMB_imbuf.h"
57 #include "IMB_imbuf_types.h"
58
59 #include "ED_gpencil.h"
60 #include "ED_image.h"
61 #include "ED_screen.h"
62
63 #include "RNA_access.h"
64
65 #include "WM_api.h"
66 #include "WM_types.h"
67
68 #include "UI_interface.h"
69 #include "UI_resources.h"
70
71 #include "image_intern.h"
72
73 #define B_NOP -1
74
75 /* proto */
76
77 static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len)
78 {
79         size_t ofs = 0;
80
81         str[0] = 0;
82         if (ima == NULL)
83                 return;
84
85         if (ibuf == NULL) {
86                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs);
87         }
88         else {
89                 if (ima->source == IMA_SRC_MOVIE) {
90                         ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
91                         if (ima->anim)
92                                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"),
93                                                     IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN));
94                 }
95                 else {
96                         ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
97                 }
98
99                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y);
100
101                 if (ibuf->rect_float) {
102                         if (ibuf->channels != 4) {
103                                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
104                         }
105                         else if (ibuf->planes == R_IMF_PLANES_RGBA)
106                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
107                         else
108                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
109                 }
110                 else {
111                         if (ibuf->planes == R_IMF_PLANES_RGBA)
112                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
113                         else
114                                 ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
115                 }
116                 if (ibuf->zbuf || ibuf->zbuf_float)
117                         ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
118
119                 if (ima->source == IMA_SRC_SEQUENCE) {
120                         const char *file = BLI_last_slash(ibuf->name);
121                         if (file == NULL)
122                                 file = ibuf->name;
123                         else
124                                 file++;
125                         ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file);
126                 }
127         }
128
129         /* the frame number, even if we cant */
130         if (ima->source == IMA_SRC_SEQUENCE) {
131                 /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
132                 const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0, NULL);
133                 ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr);
134         }
135 }
136
137 /* gets active viewer user */
138 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
139 {
140         bNode *node;
141         
142         if (ntree)
143                 for (node = ntree->nodes.first; node; node = node->next)
144                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
145                                 if (node->flag & NODE_DO_OUTPUT)
146                                         return node->storage;
147         return NULL;
148 }
149
150
151 /* ************ panel stuff ************* */
152
153 #if 0
154 /* 0: disable preview 
155  * otherwise refresh preview
156  *
157  * XXX if you put this back, also check XXX in image_main_area_draw() */
158  * /
159 void image_preview_event(int event)
160 {
161         int exec = 0;
162         
163         if (event == 0) {
164                 G.scene->r.scemode &= ~R_COMP_CROP;
165                 exec = 1;
166         }
167         else {
168                 if (image_preview_active(curarea, NULL, NULL)) {
169                         G.scene->r.scemode |= R_COMP_CROP;
170                         exec = 1;
171                 }
172                 else
173                         G.scene->r.scemode &= ~R_COMP_CROP;
174         }
175         
176         if (exec && G.scene->nodetree) {
177                 Scene *scene = G.scene;
178                 /* should work when no node editor in screen..., so we execute right away */
179                 
180                 ntreeCompositTagGenerators(G.scene->nodetree);
181
182                 G.is_break = FALSE;
183                 G.scene->nodetree->timecursor = set_timecursor;
184                 G.scene->nodetree->test_break = blender_test_break;
185                 
186                 BIF_store_spare();
187                 
188                 ntreeCompositExecTree(scene->nodetree, &scene->r, 1, &scene->view_settings, &scene->display_settings);   /* 1 is do_previews */
189                 
190                 G.scene->nodetree->timecursor = NULL;
191                 G.scene->nodetree->test_break = NULL;
192                 
193                 scrarea_do_windraw(curarea);
194                 waitcursor(0);
195                 
196                 WM_event_add_notifier(C, NC_IMAGE, ima_v);
197         }
198 }
199
200
201 /* nothing drawn here, we use it to store values */
202 static void preview_cb(ScrArea *sa, struct uiBlock *block)
203 {
204         SpaceImage *sima = sa->spacedata.first;
205         rctf dispf;
206         rcti *disprect = &G.scene->r.disprect;
207         int winx = (G.scene->r.size * G.scene->r.xsch) / 100;
208         int winy = (G.scene->r.size * G.scene->r.ysch) / 100;
209         int mval[2];
210         
211         if (G.scene->r.mode & R_BORDER) {
212                 winx *= BLI_rcti_size_x(&G.scene->r.border);
213                 winy *= BLI_rctf_size_y(&G.scene->r.border);
214         }
215         
216         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
217
218         BLI_rctf_init(&dispf, 15.0f, BLI_rcti_size_x(&block->rect) - 15.0f, 15.0f, (BLI_rctf_size_y(&block->rect)) - 15.0f);
219         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
220         
221         /* correction for gla draw */
222         BLI_rcti_translate(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
223         
224         calc_image_view(sima, 'p');
225 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
226         /* map to image space coordinates */
227         mval[0] = disprect->xmin; mval[1] = disprect->ymin;
228         areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
229         mval[0] = disprect->xmax; mval[1] = disprect->ymax;
230         areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
231         
232         /* map to render coordinates */
233         disprect->xmin = dispf.xmin;
234         disprect->xmax = dispf.xmax;
235         disprect->ymin = dispf.ymin;
236         disprect->ymax = dispf.ymax;
237         
238         CLAMP(disprect->xmin, 0, winx);
239         CLAMP(disprect->xmax, 0, winx);
240         CLAMP(disprect->ymin, 0, winy);
241         CLAMP(disprect->ymax, 0, winy);
242 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin, disprect->xmax, disprect->ymax);
243
244 }
245
246 static bool is_preview_allowed(ScrArea *cur)
247 {
248         SpaceImage *sima = cur->spacedata.first;
249         ScrArea *sa;
250
251         /* check if another areawindow has preview set */
252         for (sa = G.curscreen->areabase.first; sa; sa = sa->next) {
253                 if (sa != cur && sa->spacetype == SPACE_IMAGE) {
254                         if (image_preview_active(sa, NULL, NULL))
255                                 return 0;
256                 }
257         }
258         /* check image type */
259         if (sima->image == NULL || sima->image->type != IMA_TYPE_COMPOSITE)
260                 return 0;
261         
262         return 1;
263 }
264
265
266 static void image_panel_preview(ScrArea *sa, short cntrl)   // IMAGE_HANDLER_PREVIEW
267 {
268         uiBlock *block;
269         SpaceImage *sima = sa->spacedata.first;
270         int ofsx, ofsy;
271         
272         if (is_preview_allowed(sa) == 0) {
273                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
274                 G.scene->r.scemode &= ~R_COMP_CROP; /* quite weak */
275                 return;
276         }
277         
278         block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
279         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
280         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
281         
282         ofsx = -150 + (sa->winx / 2) / sima->blockscale;
283         ofsy = -100 + (sa->winy / 2) / sima->blockscale;
284         if (uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200) == 0) return;
285         
286         uiBlockSetDrawExtraFunc(block, preview_cb);
287         
288 }
289 #endif
290
291
292 /* ********************* callbacks for standard image buttons *************** */
293
294 static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *render_slot_p)
295 {
296         uiBlock *block = uiLayoutGetBlock(layout);
297         short *render_slot = render_slot_p;
298         int slot;
299
300         uiDefBut(block, LABEL, 0, IFACE_("Slot"),
301                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
302         uiItemS(layout);
303
304         slot = IMA_MAX_RENDER_SLOT;
305         while (slot--) {
306                 char str[32];
307                 BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot + 1);
308                 uiDefButS(block, BUTM, B_NOP, str, 0, 0,
309                           UI_UNIT_X * 5, UI_UNIT_X, render_slot, (float) slot, 0.0, 0, -1, "");
310         }
311 }
312
313 static const char *ui_imageuser_layer_fake_name(RenderResult *rr)
314 {
315         if (rr->rectf) {
316                 return IFACE_("Composite");
317         }
318         else if (rr->rect32) {
319                 return IFACE_("Sequence");
320         }
321         else {
322                 return NULL;
323         }
324 }
325
326 static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt)
327 {
328         void **rnd_data = rnd_pt;
329         uiBlock *block = uiLayoutGetBlock(layout);
330         RenderResult *rr = rnd_data[0];
331         ImageUser *iuser = rnd_data[1];
332         RenderLayer *rl;
333         RenderLayer rl_fake = {NULL};
334         const char *fake_name;
335         int nr;
336
337         uiBlockSetCurLayout(block, layout);
338         uiLayoutColumn(layout, false);
339
340         uiDefBut(block, LABEL, 0, IFACE_("Layer"),
341                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
342         uiItemS(layout);
343
344         nr = BLI_countlist(&rr->layers) - 1;
345         fake_name = ui_imageuser_layer_fake_name(rr);
346
347         if (fake_name) {
348                 BLI_strncpy(rl_fake.name, fake_name, sizeof(rl_fake.name));
349                 nr += 1;
350         }
351
352         for (rl = rr->layers.last; rl; rl = rl->prev, nr--) {
353 final:
354                 uiDefButS(block, BUTM, B_NOP, IFACE_(rl->name), 0, 0,
355                           UI_UNIT_X * 5, UI_UNIT_X, &iuser->layer, (float) nr, 0.0, 0, -1, "");
356         }
357
358         if (fake_name) {
359                 fake_name = NULL;
360                 rl = &rl_fake;
361                 goto final;
362         }
363
364         BLI_assert(nr == -1);
365 }
366
367 static const char *ui_imageuser_pass_fake_name(RenderLayer *rl)
368 {
369         if (rl == NULL || rl->rectf) {
370                 return IFACE_("Combined");
371         }
372         else {
373                 return NULL;
374         }
375 }
376
377 static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *ptrpair_p)
378 {
379         void **ptrpair = ptrpair_p;
380         uiBlock *block = uiLayoutGetBlock(layout);
381         // RenderResult *rr = ptrpair[0];
382         ImageUser *iuser = ptrpair[1];
383         /* rl==NULL means composite result */
384         RenderLayer *rl = ptrpair[2];
385         RenderPass rpass_fake = {NULL};
386         RenderPass *rpass;
387         const char *fake_name;
388         int nr;
389
390         uiBlockSetCurLayout(block, layout);
391         uiLayoutColumn(layout, false);
392
393         uiDefBut(block, LABEL, 0, IFACE_("Pass"),
394                  0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
395
396         uiItemS(layout);
397
398         nr = (rl ? BLI_countlist(&rl->passes) : 0) - 1;
399         fake_name = ui_imageuser_pass_fake_name(rl);
400
401         if (fake_name) {
402                 BLI_strncpy(rpass_fake.name, fake_name, sizeof(rpass_fake.name));
403                 nr += 1;
404         }
405
406         /* rendered results don't have a Combined pass */
407         for (rpass = rl ? rl->passes.last : NULL; rpass; rpass = rpass->prev, nr--) {
408 final:
409                 uiDefButS(block, BUTM, B_NOP, IFACE_(rpass->name), 0, 0,
410                           UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
411         }
412
413         if (fake_name) {
414                 fake_name = NULL;
415                 rpass = &rpass_fake;
416                 goto final;
417         }
418
419         BLI_assert(nr == -1);
420 }
421
422 /* 5 layer button callbacks... */
423 static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) 
424 {
425         ImageUser *iuser = iuser_v;
426
427         BKE_image_multilayer_index(rr_v, iuser); 
428         WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
429 }
430 static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) 
431 {
432         RenderResult *rr = rr_v;
433         ImageUser *iuser = iuser_v;
434         int tot = BLI_countlist(&rr->layers);
435
436         if (rr->rectf || rr->rect32)
437                 tot++;  /* fake compo/sequencer layer */
438
439         if (iuser->layer < tot - 1) {
440                 iuser->layer++;
441                 BKE_image_multilayer_index(rr, iuser); 
442                 WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
443         }
444 }
445 static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) 
446 {
447         ImageUser *iuser = iuser_v;
448
449         if (iuser->layer > 0) {
450                 iuser->layer--;
451                 BKE_image_multilayer_index(rr_v, iuser); 
452                 WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
453         }
454 }
455 static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) 
456 {
457         RenderResult *rr = rr_v;
458         ImageUser *iuser = iuser_v;
459         RenderLayer *rl = BLI_findlink(&rr->layers, iuser->layer);
460
461         if (rl) {
462                 int tot = BLI_countlist(&rl->passes);
463
464                 if (rr->rectf || rr->rect32)
465                         tot++;  /* fake compo/sequencer layer */
466
467                 if (iuser->pass < tot - 1) {
468                         iuser->pass++;
469                         BKE_image_multilayer_index(rr, iuser); 
470                         WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
471                 }
472         }
473 }
474 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
475 {
476         ImageUser *iuser = iuser_v;
477
478         if (iuser->pass > 0) {
479                 iuser->pass--;
480                 BKE_image_multilayer_index(rr_v, iuser); 
481                 WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
482         }
483 }
484
485 #if 0
486 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) 
487 {
488         Scene *scene = CTX_data_scene(C);
489         BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
490         WM_event_add_notifier(C, NC_IMAGE, ima_v);
491 }
492 #endif
493
494 #if 0
495 static void image_user_change(bContext *C, void *iuser_v, void *unused)
496 {
497         Scene *scene = CTX_data_scene(C);
498         BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
499 }
500 #endif
501
502 static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
503 {
504         static void *rnd_pt[3];  /* XXX, workaround */
505         uiBlock *block = uiLayoutGetBlock(layout);
506         uiBut *but;
507         RenderLayer *rl = NULL;
508         int wmenu1, wmenu2, wmenu3;
509         const char *fake_name;
510         const char *display_name;
511
512         uiLayoutRow(layout, TRUE);
513
514         /* layer menu is 1/3 larger than pass */
515         wmenu1 = (2 * w) / 5;
516         wmenu2 = (3 * w) / 5;
517         wmenu3 = (3 * w) / 6;
518         
519         rnd_pt[0] = rr;
520         rnd_pt[1] = iuser;
521         rnd_pt[2] = NULL;
522
523         /* menu buts */
524         if (render_slot) {
525                 char str[64];
526                 BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1);
527                 but = uiDefMenuBut(block, ui_imageuser_slot_menu, render_slot, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot"));
528                 uiButSetFunc(but, image_multi_cb, rr, iuser);
529                 uiButSetMenuFromPulldown(but);
530         }
531
532         if (rr) {
533                 RenderPass *rpass;
534
535                 /* layer */
536                 fake_name = ui_imageuser_layer_fake_name(rr);
537                 rl = BLI_findlink(&rr->layers, iuser->layer  - (fake_name ? 1 : 0));
538                 rnd_pt[2] = rl;
539
540                 display_name = rl ? rl->name : (fake_name ? fake_name : "");
541                 but = uiDefMenuBut(block, ui_imageuser_layer_menu, rnd_pt, display_name, 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer"));
542                 uiButSetFunc(but, image_multi_cb, rr, iuser);
543                 uiButSetMenuFromPulldown(but);
544
545
546                 /* pass */
547                 fake_name = ui_imageuser_pass_fake_name(rl);
548                 rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass  - (fake_name ? 1 : 0)) : NULL);
549
550                 display_name = rpass ? rpass->name : (fake_name ? fake_name : "");
551                 but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, display_name, 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass"));
552                 uiButSetFunc(but, image_multi_cb, rr, iuser);
553                 uiButSetMenuFromPulldown(but);
554         }
555 }
556
557 static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, short *render_slot)
558 {
559         uiBlock *block = uiLayoutGetBlock(layout);
560         uiLayout *row;
561         uiBut *but;
562         const float dpi_fac = UI_DPI_FAC;
563         
564         row = uiLayoutRow(layout, TRUE);
565
566         if (rr == NULL || iuser == NULL)
567                 return;
568         if (BLI_listbase_is_empty(&rr->layers)) {
569                 uiItemL(row, IFACE_("No Layers in Render Result"), ICON_NONE);
570                 return;
571         }
572
573         /* decrease, increase arrows */
574         but = uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,   0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Layer"));
575         uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
576         but = uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,  0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Layer"));
577         uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
578
579         uiblock_layer_pass_buttons(row, rr, iuser, 230 * dpi_fac, render_slot);
580
581         /* decrease, increase arrows */
582         but = uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,   0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Pass"));
583         uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
584         but = uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,  0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Pass"));
585         uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
586
587         uiBlockEndAlign(block);
588 }
589
590 // XXX HACK!
591 // static int packdummy=0;
592
593 typedef struct RNAUpdateCb {
594         PointerRNA ptr;
595         PropertyRNA *prop;
596         ImageUser *iuser;
597 } RNAUpdateCb;
598
599 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
600 {
601         RNAUpdateCb *cb = (RNAUpdateCb *)arg_cb;
602
603         /* ideally this would be done by RNA itself, but there we have
604          * no image user available, so we just update this flag here */
605         cb->iuser->ok = 1;
606
607         /* we call update here on the pointer property, this way the
608          * owner of the image pointer can still define it's own update
609          * and notifier */
610         RNA_property_update(C, &cb->ptr, cb->prop);
611 }
612
613 void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact)
614 {
615 #define MAX_INFO_LEN  128
616
617         PropertyRNA *prop;
618         PointerRNA imaptr;
619         RNAUpdateCb *cb;
620         Image *ima;
621         ImageUser *iuser;
622         Scene *scene = CTX_data_scene(C);
623         uiLayout *row, *split, *col;
624         uiBlock *block;
625         char str[MAX_INFO_LEN];
626
627         void *lock;
628
629         if (!ptr->data)
630                 return;
631
632         prop = RNA_struct_find_property(ptr, propname);
633         if (!prop) {
634                 printf("%s: property not found: %s.%s\n",
635                        __func__, RNA_struct_identifier(ptr->type), propname);
636                 return;
637         }
638
639         if (RNA_property_type(prop) != PROP_POINTER) {
640                 printf("%s: expected pointer property for %s.%s\n",
641                        __func__, RNA_struct_identifier(ptr->type), propname);
642                 return;
643         }
644
645         block = uiLayoutGetBlock(layout);
646
647         imaptr = RNA_property_pointer_get(ptr, prop);
648         ima = imaptr.data;
649         iuser = userptr->data;
650
651         BKE_image_user_check_frame_calc(iuser, (int)scene->r.cfra, 0);
652
653         cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
654         cb->ptr = *ptr;
655         cb->prop = prop;
656         cb->iuser = iuser;
657
658         uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
659         uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
660
661         if (!compact)
662                 uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
663
664         if (ima) {
665                 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
666
667                 if (ima->source == IMA_SRC_VIEWER) {
668                         ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
669                         image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
670                         BKE_image_release_ibuf(ima, ibuf, lock);
671
672                         uiItemL(layout, ima->id.name + 2, ICON_NONE);
673                         uiItemL(layout, str, ICON_NONE);
674
675                         if (ima->type == IMA_TYPE_COMPOSITE) {
676                                 // XXX not working yet
677 #if 0
678                                 iuser = ntree_get_active_iuser(scene->nodetree);
679                                 if (iuser) {
680                                         uiBlockBeginAlign(block);
681                                         uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10, 120, 100, 20, 0, 0, 0, 0, 0, "");
682                                         uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110, 120, 100, 20, 0, 0, 0, 0, 0, "");
683                                         but = uiDefBut(block, BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
684                                         uiButSetFunc(but, image_freecache_cb, ima, NULL);
685                                         
686                                         if (iuser->frames)
687                                                 BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
688                                         else strcpy(str, "Frames:");
689                                         uiBlockBeginAlign(block);
690                                         uiDefButI(block, NUM, imagechanged, str,        10, 90, 150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Number of images of a movie to use");
691                                         uiDefButI(block, NUM, imagechanged, "StartFr:", 160, 90, 150, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Global starting frame of the movie");
692                                 }
693 #endif
694                         }
695                         else if (ima->type == IMA_TYPE_R_RESULT) {
696                                 /* browse layer/passes */
697                                 RenderResult *rr;
698
699                                 /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
700                                 rr = BKE_image_acquire_renderresult(scene, ima);
701                                 uiblock_layer_pass_arrow_buttons(layout, rr, iuser, &ima->render_slot);
702                                 BKE_image_release_renderresult(scene, ima);
703                         }
704                 }
705                 else {
706                         uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
707
708                         if (ima->source != IMA_SRC_GENERATED) {
709                                 row = uiLayoutRow(layout, TRUE);
710                                 if (ima->packedfile)
711                                         uiItemO(row, "", ICON_PACKAGE, "image.unpack");
712                                 else
713                                         uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
714                                 
715                                 row = uiLayoutRow(row, TRUE);
716                                 uiLayoutSetEnabled(row, ima->packedfile == NULL);
717                                 uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
718                                 uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
719                         }
720
721                         // XXX what was this for?
722 #if 0
723                         /* check for re-render, only buttons */
724                         if (imagechanged == B_IMAGECHANGED) {
725                                 if (iuser->flag & IMA_ANIM_REFRESHED) {
726                                         iuser->flag &= ~IMA_ANIM_REFRESHED;
727                                         WM_event_add_notifier(C, NC_IMAGE, ima);
728                                 }
729                         }
730 #endif
731
732                         /* multilayer? */
733                         if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
734                                 uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser, NULL);
735                         }
736                         else if (ima->source != IMA_SRC_GENERATED) {
737                                 if (compact == 0) {
738                                         ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
739                                         image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN);
740                                         BKE_image_release_ibuf(ima, ibuf, lock);
741                                         uiItemL(layout, str, ICON_NONE);
742                                 }
743                         }
744
745                         col = uiLayoutColumn(layout, FALSE);
746                         uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
747                         uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
748
749                         if (ima->source != IMA_SRC_GENERATED) {
750                                 if (compact == 0) { /* background image view doesnt need these */
751                                         ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
752                                         bool has_alpha = true;
753
754                                         if (ibuf) {
755                                                 int imtype = BKE_ftype_to_imtype(ibuf->ftype);
756                                                 char valid_channels = BKE_imtype_valid_channels(imtype);
757
758                                                 has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
759
760                                                 BKE_image_release_ibuf(ima, ibuf, NULL);
761                                         }
762
763                                         if (has_alpha) {
764                                                 col = uiLayoutColumn(layout, FALSE);
765                                                 uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
766                                                 uiItemR(col, &imaptr, "alpha_mode", 0, "Alpha", ICON_NONE);
767                                         }
768
769                                         uiItemS(layout);
770
771                                         split = uiLayoutSplit(layout, 0.0f, FALSE);
772
773                                         col = uiLayoutColumn(split, FALSE);
774                                         /* XXX Why only display fields_per_frame only for video image types?
775                                          *     And why allow fields for non-video image types at all??? */
776                                         if (BKE_image_is_animated(ima)) {
777                                                 uiLayout *subsplit = uiLayoutSplit(col, 0.0f, FALSE);
778                                                 uiLayout *subcol = uiLayoutColumn(subsplit, FALSE);
779                                                 uiItemR(subcol, &imaptr, "use_fields", 0, NULL, ICON_NONE);
780                                                 subcol = uiLayoutColumn(subsplit, FALSE);
781                                                 uiLayoutSetActive(subcol, RNA_boolean_get(&imaptr, "use_fields"));
782                                                 uiItemR(subcol, userptr, "fields_per_frame", 0, IFACE_("Fields"), ICON_NONE);
783                                         }
784                                         else
785                                                 uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE);
786                                         row = uiLayoutRow(col, FALSE);
787                                         uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields"));
788                                         uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
789                                 }
790                         }
791
792                         if (BKE_image_is_animated(ima)) {
793                                 uiItemS(layout);
794
795                                 split = uiLayoutSplit(layout, 0.0f, FALSE);
796
797                                 col = uiLayoutColumn(split, FALSE);
798
799                                 BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
800                                 uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
801                                 uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
802                                 uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
803
804                                 col = uiLayoutColumn(split, FALSE);
805                                 uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
806                                 uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
807                                 uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
808                         }
809                         else if (ima->source == IMA_SRC_GENERATED) {
810                                 split = uiLayoutSplit(layout, 0.0f, FALSE);
811
812                                 col = uiLayoutColumn(split, TRUE);
813                                 uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
814                                 uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
815                                 
816                                 uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
817
818                                 uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
819                         }
820
821                 }
822
823                 uiBlockSetNFunc(block, NULL, NULL, NULL);
824         }
825
826         MEM_freeN(cb);
827
828 #undef MAX_INFO_LEN
829 }
830
831 void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management)
832 {
833         ImageFormatData *imf = imfptr->data;
834         ID *id = imfptr->id.data;
835         PointerRNA display_settings_ptr;
836         PropertyRNA *prop;
837         const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
838         /* some settings depend on this being a scene thats rendered */
839         const bool is_render_out = (id && GS(id->name) == ID_SCE);
840
841         uiLayout *col, *row, *split, *sub;
842         int show_preview = FALSE;
843
844         col = uiLayoutColumn(layout, FALSE);
845
846         split = uiLayoutSplit(col, 0.5f, FALSE);
847         
848         uiItemR(split, imfptr, "file_format", 0, "", ICON_NONE);
849         sub = uiLayoutRow(split, FALSE);
850         uiItemR(sub, imfptr, "color_mode", UI_ITEM_R_EXPAND, IFACE_("Color"), ICON_NONE);
851
852         /* only display depth setting if multiple depths can be used */
853         if ((ELEM7(depth_ok,
854                    R_IMF_CHAN_DEPTH_1,
855                    R_IMF_CHAN_DEPTH_8,
856                    R_IMF_CHAN_DEPTH_10,
857                    R_IMF_CHAN_DEPTH_12,
858                    R_IMF_CHAN_DEPTH_16,
859                    R_IMF_CHAN_DEPTH_24,
860                    R_IMF_CHAN_DEPTH_32)) == 0)
861         {
862                 row = uiLayoutRow(col, FALSE);
863
864                 uiItemL(row, IFACE_("Color Depth:"), ICON_NONE);
865                 uiItemR(row, imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
866         }
867
868         if (BKE_imtype_supports_quality(imf->imtype)) {
869                 uiItemR(col, imfptr, "quality", 0, NULL, ICON_NONE);
870         }
871
872         if (BKE_imtype_supports_compress(imf->imtype)) {
873                 uiItemR(col, imfptr, "compression", 0, NULL, ICON_NONE);
874         }
875
876         if (ELEM(imf->imtype, R_IMF_IMTYPE_OPENEXR, R_IMF_IMTYPE_MULTILAYER)) {
877                 uiItemR(col, imfptr, "exr_codec", 0, NULL, ICON_NONE);
878         }
879         
880         row = uiLayoutRow(col, FALSE);
881         if (BKE_imtype_supports_zbuf(imf->imtype)) {
882                 uiItemR(row, imfptr, "use_zbuffer", 0, NULL, ICON_NONE);
883         }
884
885         if (is_render_out && (imf->imtype == R_IMF_IMTYPE_OPENEXR)) {
886                 show_preview = TRUE;
887                 uiItemR(row, imfptr, "use_preview", 0, NULL, ICON_NONE);
888         }
889
890         if (imf->imtype == R_IMF_IMTYPE_JP2) {
891                 uiItemR(col, imfptr, "jpeg2k_codec", 0, NULL, ICON_NONE);
892
893                 row = uiLayoutRow(col, FALSE);
894                 uiItemR(row, imfptr, "use_jpeg2k_cinema_preset", 0, NULL, ICON_NONE);
895                 uiItemR(row, imfptr, "use_jpeg2k_cinema_48", 0, NULL, ICON_NONE);
896                 
897                 uiItemR(col, imfptr, "use_jpeg2k_ycc", 0, NULL, ICON_NONE);
898         }
899
900         if (imf->imtype == R_IMF_IMTYPE_DPX) {
901                 uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
902         }
903
904         if (imf->imtype == R_IMF_IMTYPE_CINEON) {
905 #if 1
906                 uiItemL(col, IFACE_("Hard coded Non-Linear, Gamma:1.7"), ICON_NONE);
907 #else
908                 uiItemR(col, imfptr, "use_cineon_log", 0, NULL, ICON_NONE);
909                 uiItemR(col, imfptr, "cineon_black", 0, NULL, ICON_NONE);
910                 uiItemR(col, imfptr, "cineon_white", 0, NULL, ICON_NONE);
911                 uiItemR(col, imfptr, "cineon_gamma", 0, NULL, ICON_NONE);
912 #endif
913         }
914
915         /* color management */
916         if (color_management &&
917             (!BKE_imtype_requires_linear_float(imf->imtype) ||
918              (show_preview && imf->flag & R_IMF_FLAG_PREVIEW_JPG)))
919         {
920                 prop = RNA_struct_find_property(imfptr, "display_settings");
921                 display_settings_ptr = RNA_property_pointer_get(imfptr, prop);
922
923                 col = uiLayoutColumn(layout, FALSE);
924                 uiItemL(col, IFACE_("Color Management"), ICON_NONE);
925
926                 uiItemR(col, &display_settings_ptr, "display_device", 0, NULL, ICON_NONE);
927
928                 uiTemplateColormanagedViewSettings(col, NULL, imfptr, "view_settings");
929         }
930 }
931
932 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
933 {
934         Scene *scene = CTX_data_scene(C);
935
936         /* render layers and passes */
937         if (ima && iuser) {
938                 const float dpi_fac = UI_DPI_FAC;
939                 RenderResult *rr;
940
941                 /* use BKE_image_acquire_renderresult  so we get the correct slot in the menu */
942                 rr = BKE_image_acquire_renderresult(scene, ima);
943                 uiblock_layer_pass_buttons(layout, rr, iuser, 160 * dpi_fac, (ima->type == IMA_TYPE_R_RESULT) ? &ima->render_slot : NULL);
944                 BKE_image_release_renderresult(scene, ima);
945         }
946 }
947
948 void image_buttons_register(ARegionType *art)
949 {
950         PanelType *pt;
951         const char *category = "Grease Pencil";
952
953         pt = MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
954         strcpy(pt->idname, "IMAGE_PT_gpencil");
955         strcpy(pt->label, N_("Grease Pencil"));
956         strcpy(pt->translation_context, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
957         pt->draw_header = gpencil_panel_standard_header;
958         pt->draw = gpencil_panel_standard;
959         BLI_strncpy(pt->category, category, BLI_strlen_utf8(category));
960         BLI_addtail(&art->paneltypes, pt);
961 }
962
963 static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
964 {
965         ScrArea *sa = CTX_wm_area(C);
966         ARegion *ar = image_has_buttons_region(sa);
967         
968         if (ar)
969                 ED_region_toggle_hidden(C, ar);
970
971         return OPERATOR_FINISHED;
972 }
973
974 void IMAGE_OT_properties(wmOperatorType *ot)
975 {
976         ot->name = "Properties";
977         ot->idname = "IMAGE_OT_properties";
978         ot->description = "Toggle display properties panel";
979         
980         ot->exec = image_properties_toggle_exec;
981         ot->poll = ED_operator_image_active;
982         
983         /* flags */
984         ot->flag = 0;
985 }
986
987 static int image_scopes_toggle_exec(bContext *C, wmOperator *UNUSED(op))
988 {
989         ScrArea *sa = CTX_wm_area(C);
990         ARegion *ar = image_has_tools_region(sa);
991         
992         if (ar)
993                 ED_region_toggle_hidden(C, ar);
994         
995         return OPERATOR_FINISHED;
996 }
997
998 void IMAGE_OT_toolshelf(wmOperatorType *ot)
999 {
1000         ot->name = "Tool Shelf";
1001         ot->idname = "IMAGE_OT_toolshelf";
1002         ot->description = "Toggles tool shelf display";
1003
1004         ot->exec = image_scopes_toggle_exec;
1005         ot->poll = ED_operator_image_active;
1006         
1007         /* flags */
1008         ot->flag = 0;
1009 }
1010