Image Panels
[blender.git] / source / blender / editors / space_image / image_buttons.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, 2002-2009
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "DNA_color_types.h"
33 #include "DNA_image_types.h"
34 #include "DNA_mesh_types.h"
35 #include "DNA_meshdata_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_packedFile_types.h"
38 #include "DNA_node_types.h"
39 #include "DNA_space_types.h"
40 #include "DNA_scene_types.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_userdef_types.h"
43
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_arithb.h"
48 #include "BLI_editVert.h"
49 #include "BLI_rand.h"
50
51 #include "BKE_colortools.h"
52 #include "BKE_context.h"
53 #include "BKE_customdata.h"
54 #include "BKE_image.h"
55 #include "BKE_global.h"
56 #include "BKE_library.h"
57 #include "BKE_main.h"
58 #include "BKE_mesh.h"
59 #include "BKE_node.h"
60 #include "BKE_packedFile.h"
61 #include "BKE_paint.h"
62 #include "BKE_screen.h"
63 #include "BKE_utildefines.h"
64
65 #include "RE_pipeline.h"
66
67 #include "IMB_imbuf.h"
68 #include "IMB_imbuf_types.h"
69
70 #include "ED_gpencil.h"
71 #include "ED_image.h"
72 #include "ED_mesh.h"
73 #include "ED_space_api.h"
74 #include "ED_screen.h"
75 #include "ED_uvedit.h"
76 #include "ED_util.h"
77
78 #include "BIF_gl.h"
79 #include "BIF_glutil.h"
80
81 #include "RNA_access.h"
82
83 #include "WM_api.h"
84 #include "WM_types.h"
85
86 #include "UI_interface.h"
87 #include "UI_resources.h"
88 #include "UI_view2d.h"
89
90 #include "image_intern.h"
91
92 #define B_REDR                          1
93 #define B_IMAGECHANGED          2
94 #define B_TRANS_IMAGE           3
95 #define B_CURSOR_IMAGE          4
96 #define B_NOP                           0
97 #define B_TWINANIM                      5
98 #define B_SIMAGETILE            6
99 #define B_IDNAME                        10
100 #define B_FACESEL_PAINT_TEST    11
101 #define B_SIMA_RECORD           12
102 #define B_SIMA_PLAY                     13
103
104 #define B_SIMANOTHING           16
105 #define B_SIMABRUSHCHANGE       17      
106 #define B_SIMABRUSHBROWSE       18
107 #define B_SIMABRUSHLOCAL        19
108 #define B_SIMABRUSHDELETE       20
109 #define B_KEEPDATA                      21
110 #define B_SIMABTEXBROWSE        22
111 #define B_SIMABTEXDELETE        23
112 #define B_VPCOLSLI                      24
113 #define B_SIMACLONEBROWSE       25
114 #define B_SIMACLONEDELETE       26
115
116 /* XXX */
117 static int simaFaceDraw_Check() {return 0;}
118 static int simaUVSel_Check() {return 0;}
119 /* XXX */
120
121 /* proto */
122 static void image_editvertex_buts(const bContext *C, uiBlock *block);
123 static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block);
124
125
126 static void do_image_panel_events(bContext *C, void *arg, int event)
127 {
128         SpaceImage *sima= CTX_wm_space_image(C);
129         ARegion *ar= CTX_wm_region(C);
130         
131         switch(event) {
132                 case B_REDR:
133                         break;
134                 case B_TRANS_IMAGE:
135                         image_editvertex_buts(C, NULL);
136                         break;
137                 case B_CURSOR_IMAGE:
138                         image_editcursor_buts(C, &ar->v2d, NULL);
139                         break;
140         }
141
142         /* all events now */
143         WM_event_add_notifier(C, NC_IMAGE, sima->image);
144 }
145
146 static void image_info(Image *ima, ImBuf *ibuf, char *str)
147 {
148         int ofs= 0;
149         
150         str[0]= 0;
151         
152         if(ima==NULL) return;
153         if(ibuf==NULL) {
154                 sprintf(str, "Can not get an image");
155                 return;
156         }
157         
158         if(ima->source==IMA_SRC_MOVIE) {
159                 ofs= sprintf(str, "Movie");
160                 if(ima->anim) 
161                         ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
162         }
163         else
164                 ofs= sprintf(str, "Image");
165         
166         ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
167         
168         if(ibuf->rect_float) {
169                 if(ibuf->channels!=4) {
170                         sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
171                 }
172                 else if(ibuf->depth==32)
173                         strcat(str, " RGBA float");
174                 else
175                         strcat(str, " RGB float");
176         }
177         else {
178                 if(ibuf->depth==32)
179                         strcat(str, " RGBA byte");
180                 else
181                         strcat(str, " RGB byte");
182         }
183         if(ibuf->zbuf || ibuf->zbuf_float)
184                 strcat(str, " + Z");
185         
186 }
187
188 /* gets active viewer user */
189 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
190 {
191         bNode *node;
192         
193         if(ntree)
194                 for(node= ntree->nodes.first; node; node= node->next)
195                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
196                                 if(node->flag & NODE_DO_OUTPUT)
197                                         return node->storage;
198         return NULL;
199 }
200
201
202 /* ************ panel stuff ************* */
203
204 /* this function gets the values for cursor and vertex number buttons */
205 static void image_transform_but_attr(SpaceImage *sima, int *imx, int *imy, int *step, int *digits) /*, float *xcoord, float *ycoord)*/
206 {
207         ImBuf *ibuf= ED_space_image_buffer(sima);
208         if(ibuf) {
209                 *imx= ibuf->x;
210                 *imy= ibuf->y;
211         }
212         
213         if (sima->flag & SI_COORDFLOATS) {
214                 *step= 1;
215                 *digits= 3;
216         }
217         else {
218                 *step= 100;
219                 *digits= 2;
220         }
221 }
222
223
224 /* is used for both read and write... */
225 static void image_editvertex_buts(const bContext *C, uiBlock *block)
226 {
227         SpaceImage *sima= CTX_wm_space_image(C);
228         Object *obedit= CTX_data_edit_object(C);
229         static float ocent[2];
230         float cent[2]= {0.0, 0.0};
231         int imx= 256, imy= 256;
232         int nactive= 0, step, digits;
233         EditMesh *em;
234         EditFace *efa;
235         MTFace *tf;
236         
237         image_transform_but_attr(sima, &imx, &imy, &step, &digits);
238         
239         em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
240         for (efa= em->faces.first; efa; efa= efa->next) {
241                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
242                 if (simaFaceDraw_Check(efa, tf)) {
243                         
244                         if (simaUVSel_Check(efa, tf, 0)) {
245                                 cent[0]+= tf->uv[0][0];
246                                 cent[1]+= tf->uv[0][1];
247                                 nactive++;
248                         }
249                         if (simaUVSel_Check(efa, tf, 1)) {
250                                 cent[0]+= tf->uv[1][0];
251                                 cent[1]+= tf->uv[1][1];
252                                 nactive++;
253                         }
254                         if (simaUVSel_Check(efa, tf, 2)) {
255                                 cent[0]+= tf->uv[2][0];
256                                 cent[1]+= tf->uv[2][1];
257                                 nactive++;
258                         }
259                         if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
260                                 cent[0]+= tf->uv[3][0];
261                                 cent[1]+= tf->uv[3][1];
262                                 nactive++;
263                         }
264                 }
265         }
266                 
267         if(block) {     // do the buttons
268                 if (nactive) {
269                         ocent[0]= cent[0]/nactive;
270                         ocent[1]= cent[1]/nactive;
271                         if (sima->flag & SI_COORDFLOATS) {
272                         } else {
273                                 ocent[0] *= imx;
274                                 ocent[1] *= imy;
275                         }
276                         
277                         //uiBlockBeginAlign(block);
278                         if(nactive==1) {
279                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
280                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
281                         }
282                         else {
283                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
284                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
285                         }
286                         //uiBlockEndAlign(block);
287                 }
288         }
289         else {  // apply event
290                 float delta[2];
291                 
292                 cent[0]= cent[0]/nactive;
293                 cent[1]= cent[1]/nactive;
294                         
295                 if (sima->flag & SI_COORDFLOATS) {
296                         delta[0]= ocent[0]-cent[0];
297                         delta[1]= ocent[1]-cent[1];
298                 }
299                 else {
300                         delta[0]= ocent[0]/imx - cent[0];
301                         delta[1]= ocent[1]/imy - cent[1];
302                 }
303
304                 for (efa= em->faces.first; efa; efa= efa->next) {
305                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
306                         if (simaFaceDraw_Check(efa, tf)) {
307                                 if (simaUVSel_Check(efa, tf, 0)) {
308                                         tf->uv[0][0]+= delta[0];
309                                         tf->uv[0][1]+= delta[1];
310                                 }
311                                 if (simaUVSel_Check(efa, tf, 1)) {
312                                         tf->uv[1][0]+= delta[0];
313                                         tf->uv[1][1]+= delta[1];
314                                 }
315                                 if (simaUVSel_Check(efa, tf, 2)) {
316                                         tf->uv[2][0]+= delta[0];
317                                         tf->uv[2][1]+= delta[1];
318                                 }
319                                 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
320                                         tf->uv[3][0]+= delta[0];
321                                         tf->uv[3][1]+= delta[1];
322                                 }
323                         }
324                 }
325                 
326                 WM_event_add_notifier(C, NC_IMAGE, sima->image);
327         }
328
329         BKE_mesh_end_editmesh(obedit->data, em);
330 }
331
332
333 /* is used for both read and write... */
334 static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block)
335 {
336         SpaceImage *sima= CTX_wm_space_image(C);
337         static float ocent[2];
338         int imx= 256, imy= 256;
339         int step, digits;
340         
341         image_transform_but_attr(sima, &imx, &imy, &step, &digits);
342                 
343         if(block) {     // do the buttons
344                 ocent[0]= v2d->cursor[0];
345                 ocent[1]= v2d->cursor[1];
346                 if (sima->flag & SI_COORDFLOATS) {
347                 } else {
348                         ocent[0] *= imx;
349                         ocent[1] *= imy;
350                 }
351                 
352                 uiBlockBeginAlign(block);
353                 uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor X:",      165, 120, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
354                 uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor Y:",      165, 100, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
355                 uiBlockEndAlign(block);
356         }
357         else {  // apply event
358                 if (sima->flag & SI_COORDFLOATS) {
359                         v2d->cursor[0]= ocent[0];
360                         v2d->cursor[1]= ocent[1];
361                 }
362                 else {
363                         v2d->cursor[0]= ocent[0]/imx;
364                         v2d->cursor[1]= ocent[1]/imy;
365                 }
366                 WM_event_add_notifier(C, NC_IMAGE, sima->image);
367         }
368 }
369
370 #if 0
371 static void image_panel_view_properties(const bContext *C, Panel *pa)
372 {
373 }
374 #endif
375
376 void brush_buttons(const bContext *C, uiBlock *block, short fromsima,
377                                    int evt_nop, int evt_change,
378                                    int evt_browse, int evt_local,
379                                    int evt_del, int evt_keepdata,
380                                    int evt_texbrowse, int evt_texdel)
381 {
382 //      SpaceImage *sima= CTX_wm_space_image(C);
383         ToolSettings *settings= CTX_data_tool_settings(C);
384         Brush *brush= paint_brush(&settings->imapaint.paint);
385         ID *id;
386         int yco, xco, butw, but_idx;
387 //      short *menupoin = &(sima->menunr); // XXX : &(G.buts->menunr);
388         short do_project = settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE ? 0:1;
389         
390         yco= 160;
391         
392         butw = fromsima ? 80 : 106;
393         
394         uiBlockBeginAlign(block);
395         but_idx = 0;
396         uiDefButS(block, ROW, evt_change, "Draw",               butw*(but_idx++),yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
397         if (fromsima || do_project==0)
398                 uiDefButS(block, ROW, evt_change, "Soften",     butw*(but_idx++),       yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
399         uiDefButS(block, ROW, evt_change, "Smear",              butw*(but_idx++),       yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
400         if (fromsima || do_project)
401                 uiDefButS(block, ROW, evt_change, "Clone",      butw*(but_idx++),       yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image");
402         
403         uiBlockEndAlign(block);
404         yco -= 30;
405         
406         id= (ID*)brush;
407         xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, evt_browse, ID_BR, 0, id, NULL, menupoin, 0, evt_local, evt_del, 0, evt_keepdata);
408         
409         if(brush && !brush->id.lib) {
410                 
411                 butw= 320-(xco+10);
412                 
413                 uiDefButS(block, MENU, evt_nop, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes");
414                 
415                 uiBlockBeginAlign(block);
416                 uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, evt_change, "Airbrush",    xco+10,yco-25,butw/2,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
417                 uiDefButF(block, NUM, evt_nop, "", xco+10 + butw/2,yco-25,butw/2,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
418                 uiBlockEndAlign(block);
419                 
420                 if (fromsima) {
421                         uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, evt_change, "Wrap",   xco+10,yco-45,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
422                         yco -= 25;
423                 }
424                 else {
425                         yco -= 25;
426                         uiBlockBeginAlign(block);
427                         uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_DISABLE, B_REDR, "Project Paint",      xco+10,yco-25,butw,19, &settings->imapaint.flag, 0, 0, 0, 0, "Use projection painting for improved consistency in the brush strokes");
428                         
429                         if ((settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0) {
430                                 /* Projection Painting */
431                                 
432                                 uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_XRAY, B_NOP, "Occlude",        xco+10,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Only paint onto the faces directly under the brush (slower)");
433                                 uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_BACKFACE, B_NOP, "Cull",       xco+10+butw/2,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Ignore faces pointing away from the view (faster)");
434                                 
435                                 uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_FLAT, B_NOP, "Normal", xco+10,yco-65,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Paint most on faces pointing towards the view");
436                                 uiDefButS(block, NUM, B_NOP, "", xco+10 +(butw/2),yco-65,butw/2,19, &settings->imapaint.normal_angle, 10.0, 90.0, 0, 0, "Paint most on faces pointing towards the view acording to this angle");
437                                 
438                                 uiDefButS(block, NUM, B_NOP, "Bleed: ", xco+10,yco-85,butw,19, &settings->imapaint.seam_bleed, 0.0, 8.0, 0, 0, "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)");
439                                 uiBlockEndAlign(block);
440                                 
441                                 uiBlockBeginAlign(block);
442                                 uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK, B_NOP, "Stencil Layer",     xco+10,yco-110,butw-30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Set the mask layer from the UV layer buttons");
443                                 uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK_INV, B_NOP, "Inv",   xco+10 + butw-30,yco-110,30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Invert the mask");
444                                 uiBlockEndAlign(block);
445                                 
446                         }
447                         uiBlockEndAlign(block);
448                 }
449                 
450                 uiBlockBeginAlign(block);
451                 uiDefButF(block, COL, B_VPCOLSLI, "",                                   0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");
452                 uiDefButF(block, NUMSLI, evt_nop, "Opacity ",           0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
453                 uiDefIconButBitS(block, TOG|BIT, BRUSH_ALPHA_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE,   180,yco-20,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
454                 uiDefButI(block, NUMSLI, evt_nop, "Size ",              0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush");
455                 uiDefIconButBitS(block, TOG|BIT, BRUSH_SIZE_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE,    180,yco-40,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
456                 uiDefButF(block, NUMSLI, evt_nop, "Falloff ",           0,yco-60,180,19, &brush->innerradius, 0.0, 1.0, 0, 0, "The fall off radius of the brush");
457                 uiDefIconButBitS(block, TOG|BIT, BRUSH_RAD_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE,     180,yco-60,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
458                 uiDefButF(block, NUMSLI, evt_nop, "Spacing ",0,yco-80,180,19, &brush->spacing, 1.0, 100.0, 0, 0, "Repeating paint on %% of brush diameter");
459                 uiDefIconButBitS(block, TOG|BIT, BRUSH_SPACING_PRESSURE, evt_nop, ICON_STYLUS_PRESSURE, 180,yco-80,20,19, &brush->flag, 0, 0, 0, 0, "Enables pressure sensitivity for tablets");
460                 uiBlockEndAlign(block);
461                 
462                 yco -= 110;
463                 
464                 if(fromsima && settings->imapaint.tool == PAINT_TOOL_CLONE) {
465                         id= (ID*)brush->clone.image;
466                         xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, menupoin, 0, 0, B_SIMACLONEDELETE, 0, 0);
467                         if(id) {
468                                 butw= 320-(xco+5);
469                                 uiDefButF(block, NUMSLI, evt_change, "B ",xco+5,yco,butw,19, &brush->clone.alpha , 0.0, 1.0, 0, 0, "Opacity of clone image display");
470                         }
471                 }
472                 else {
473                         if (
474                                 (fromsima==0) && /* 3D View */
475                                 (settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0 && /* Projection Painting */
476                                 (settings->imapaint.tool == PAINT_TOOL_CLONE)
477                                 ) {
478                                 butw = 130;
479                                 uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_CLONE, B_REDR, "Clone Layer",     0,yco,butw,20, &settings->imapaint.flag, 0, 0, 0, 0, "Use another UV layer as clone source, otherwise use 3D the cursor as the source");
480                         }
481                         else {
482                                 MTex *mtex= brush->mtex[brush->texact];
483                                 
484                                 id= (mtex)? (ID*)mtex->tex: NULL;
485                                 xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, evt_texbrowse, ID_TE, 0, id, NULL, menupoin, 0, 0, evt_texdel, 0, 0);
486                                 /*uiDefButBitS(block, TOG|BIT, BRUSH_FIXED_TEX, evt_change, "Fixed",    xco+5,yco,butw,19, &brush->flag, 0, 0, 0, 0, "Keep texture origin in fixed position");*/
487                         }
488                 }
489         }
490         
491 #if 0
492         uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL_DRAWING, B_SIMABRUSHCHANGE, "TD", 0,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while drawing");
493         uiDefButBitS(block, TOG|BIT, IMAGEPAINT_DRAW_TOOL, B_SIMABRUSHCHANGE, "TP", 50,1,50,19, &settings->imapaint.flag.flag, 0, 0, 0, 0, "Enables brush shape while not drawing");
494 #endif
495 }
496
497 static int image_panel_poll(const bContext *C, PanelType *pt)
498 {
499         SpaceImage *sima= CTX_wm_space_image(C);
500         ImBuf *ibuf= ED_space_image_buffer(sima);
501         
502         return (ibuf != NULL);
503 }
504
505 static void image_panel_curves(const bContext *C, Panel *pa)
506 {
507         bScreen *sc= CTX_wm_screen(C);
508         SpaceImage *sima= CTX_wm_space_image(C);
509         ImBuf *ibuf;
510         PointerRNA simaptr;
511         int levels;
512         
513         ibuf= ED_space_image_buffer(sima);
514         
515         if(ibuf) {
516                 if(sima->cumap==NULL)
517                         sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
518
519                 /* curvemap black/white levels only works for RGBA */
520                 levels= (ibuf->channels==4);
521
522                 RNA_pointer_create(&sc->id, &RNA_SpaceImageEditor, sima, &simaptr);
523                 uiTemplateCurveMapping(pa->layout, &simaptr, "curves", 'c', levels);
524         }
525 }
526
527 #if 0
528 /* 0: disable preview 
529    otherwise refresh preview
530 */
531 void image_preview_event(int event)
532 {
533         int exec= 0;
534         
535         if(event==0) {
536                 G.scene->r.scemode &= ~R_COMP_CROP;
537                 exec= 1;
538         }
539         else {
540                 if(image_preview_active(curarea, NULL, NULL)) {
541                         G.scene->r.scemode |= R_COMP_CROP;
542                         exec= 1;
543                 }
544                 else
545                         G.scene->r.scemode &= ~R_COMP_CROP;
546         }
547         
548         if(exec && G.scene->nodetree) {
549                 /* should work when no node editor in screen..., so we execute right away */
550                 
551                 ntreeCompositTagGenerators(G.scene->nodetree);
552
553                 G.afbreek= 0;
554                 G.scene->nodetree->timecursor= set_timecursor;
555                 G.scene->nodetree->test_break= blender_test_break;
556                 
557                 BIF_store_spare();
558                 
559                 ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1);       /* 1 is do_previews */
560                 
561                 G.scene->nodetree->timecursor= NULL;
562                 G.scene->nodetree->test_break= NULL;
563                 
564                 scrarea_do_windraw(curarea);
565                 waitcursor(0);
566                 
567                 WM_event_add_notifier(C, NC_IMAGE, ima_v);
568         }       
569 }
570
571
572 /* nothing drawn here, we use it to store values */
573 static void preview_cb(struct ScrArea *sa, struct uiBlock *block)
574 {
575         SpaceImage *sima= sa->spacedata.first;
576         rctf dispf;
577         rcti *disprect= &G.scene->r.disprect;
578         int winx= (G.scene->r.size*G.scene->r.xsch)/100;
579         int winy= (G.scene->r.size*G.scene->r.ysch)/100;
580         short mval[2];
581         
582         if(G.scene->r.mode & R_BORDER) {
583                 winx*= (G.scene->r.border.xmax - G.scene->r.border.xmin);
584                 winy*= (G.scene->r.border.ymax - G.scene->r.border.ymin);
585         }
586         
587         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
588
589         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
590         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
591         
592         /* correction for gla draw */
593         BLI_translate_rcti(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
594         
595         calc_image_view(sima, 'p');
596 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
597         /* map to image space coordinates */
598         mval[0]= disprect->xmin; mval[1]= disprect->ymin;
599         areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
600         mval[0]= disprect->xmax; mval[1]= disprect->ymax;
601         areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
602         
603         /* map to render coordinates */
604         disprect->xmin= dispf.xmin;
605         disprect->xmax= dispf.xmax;
606         disprect->ymin= dispf.ymin;
607         disprect->ymax= dispf.ymax;
608         
609         CLAMP(disprect->xmin, 0, winx);
610         CLAMP(disprect->xmax, 0, winx);
611         CLAMP(disprect->ymin, 0, winy);
612         CLAMP(disprect->ymax, 0, winy);
613 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
614
615 }
616
617 static int is_preview_allowed(ScrArea *cur)
618 {
619         SpaceImage *sima= cur->spacedata.first;
620         ScrArea *sa;
621
622         /* check if another areawindow has preview set */
623         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
624                 if(sa!=cur && sa->spacetype==SPACE_IMAGE) {
625                         if(image_preview_active(sa, NULL, NULL))
626                            return 0;
627                 }
628         }
629         /* check image type */
630         if(sima->image==NULL || sima->image->type!=IMA_TYPE_COMPOSITE)
631                 return 0;
632         
633         return 1;
634 }
635
636
637 static void image_panel_preview(ScrArea *sa, short cntrl)       // IMAGE_HANDLER_PREVIEW
638 {
639         uiBlock *block;
640         SpaceImage *sima= sa->spacedata.first;
641         int ofsx, ofsy;
642         
643         if(is_preview_allowed(sa)==0) {
644                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
645                 G.scene->r.scemode &= ~R_COMP_CROP;     /* quite weak */
646                 return;
647         }
648         
649         block= uiBeginBlock(C, ar, "image_panel_preview", UI_EMBOSS);
650         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
651         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
652         
653         ofsx= -150+(sa->winx/2)/sima->blockscale;
654         ofsy= -100+(sa->winy/2)/sima->blockscale;
655         if(uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200)==0) return;
656         
657         uiBlockSetDrawExtraFunc(block, preview_cb);
658         
659 }
660 #endif
661
662
663 /* ********************* callbacks for standard image buttons *************** */
664
665 static char *layer_menu(RenderResult *rr, short *curlay)
666 {
667         RenderLayer *rl;
668         int len= 64 + 32*BLI_countlist(&rr->layers);
669         short a, nr= 0;
670         char *str= MEM_callocN(len, "menu layers");
671         
672         strcpy(str, "Layer %t");
673         a= strlen(str);
674         
675         /* compo result */
676         if(rr->rectf) {
677                 a+= sprintf(str+a, "|Composite %%x0");
678                 nr= 1;
679         }
680         for(rl= rr->layers.first; rl; rl= rl->next, nr++) {
681                 a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
682         }
683         
684         /* no curlay clip here, on render (redraws) the amount of layers can be 1 fir single-layer render */
685         
686         return str;
687 }
688
689 /* rl==NULL means composite result */
690 static char *pass_menu(RenderLayer *rl, short *curpass)
691 {
692         RenderPass *rpass;
693         int len= 64 + 32*(rl?BLI_countlist(&rl->passes):1);
694         short a, nr= 0;
695         char *str= MEM_callocN(len, "menu layers");
696         
697         strcpy(str, "Pass %t");
698         a= strlen(str);
699         
700         /* rendered results don't have a Combined pass */
701         if(rl==NULL || rl->rectf) {
702                 a+= sprintf(str+a, "|Combined %%x0");
703                 nr= 1;
704         }
705         
706         if(rl)
707                 for(rpass= rl->passes.first; rpass; rpass= rpass->next, nr++)
708                         a+= sprintf(str+a, "|%s %%x%d", rpass->name, nr);
709         
710         if(*curpass >= nr)
711                 *curpass= 0;
712         
713         return str;
714 }
715
716 static void set_frames_cb(bContext *C, void *ima_v, void *iuser_v)
717 {
718         Scene *scene= CTX_data_scene(C);
719         Image *ima= ima_v;
720         ImageUser *iuser= iuser_v;
721         
722         if(ima->anim) {
723                 iuser->frames = IMB_anim_get_duration(ima->anim);
724                 BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
725         }
726 }
727
728 /* 5 layer button callbacks... */
729 static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) 
730 {
731         BKE_image_multilayer_index(rr_v, iuser_v); 
732         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
733 }
734 static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) 
735 {
736         RenderResult *rr= rr_v;
737         ImageUser *iuser= iuser_v;
738         int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0);  /* fake compo result layer */
739
740         if(iuser->layer<tot-1) {
741                 iuser->layer++;
742                 BKE_image_multilayer_index(rr, iuser); 
743                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
744         }
745 }
746 static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) 
747 {
748         ImageUser *iuser= iuser_v;
749
750         if(iuser->layer>0) {
751                 iuser->layer--;
752                 BKE_image_multilayer_index(rr_v, iuser); 
753                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
754         }
755 }
756 static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) 
757 {
758         RenderResult *rr= rr_v;
759         ImageUser *iuser= iuser_v;
760         RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
761
762         if(rl) {
763                 int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0);  /* builtin render result has no combined pass in list */
764                 if(iuser->pass<tot-1) {
765                         iuser->pass++;
766                         BKE_image_multilayer_index(rr, iuser); 
767                         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
768                 }
769         }
770 }
771 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
772 {
773         ImageUser *iuser= iuser_v;
774
775         if(iuser->pass>0) {
776                 iuser->pass--;
777                 BKE_image_multilayer_index(rr_v, iuser); 
778                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
779         }
780 }
781
782 #if 0
783 static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) 
784 {
785         if(ima_v) {
786                 Image *ima= ima_v;
787                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
788                         if (ima->packedfile) {
789                                 if (G.fileflags & G_AUTOPACK) {
790                                         if (okee("Disable AutoPack ?")) {
791                                                 G.fileflags &= ~G_AUTOPACK;
792                                         }
793                                 }
794                                 
795                                 if ((G.fileflags & G_AUTOPACK) == 0) {
796                                         unpackImage(NULL, ima, PF_ASK); /* XXX report errors */
797                                         ED_undo_push(C, "Unpack image");
798                                 }
799                         } 
800                         else {
801                                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
802                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
803                                         // XXX error("Can't pack painted image. Save image or use Repack as PNG.");
804                                 } else {
805                                         ima->packedfile = newPackedFile(NULL, ima->name); /* XXX report errors */
806                                         ED_undo_push(C, "Pack image");
807                                 }
808                         }
809                 }
810         }
811 }
812 #endif
813
814 #if 0
815 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) 
816 {
817         Scene *scene= CTX_data_scene(C);
818         BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
819         WM_event_add_notifier(C, NC_IMAGE, ima_v);
820 }
821 #endif
822
823 #if 0
824 static void image_user_change(bContext *C, void *iuser_v, void *unused)
825 {
826         Scene *scene= CTX_data_scene(C);
827         BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
828 }
829 #endif
830
831 static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser, int w)
832 {
833         uiBlock *block= uiLayoutGetBlock(layout);
834         uiBut *but;
835         RenderLayer *rl= NULL;
836         int wmenu1, wmenu2;
837         char *strp;
838
839         uiLayoutRow(layout, 1);
840
841         /* layer menu is 1/3 larger than pass */
842         wmenu1= (3*w)/5;
843         wmenu2= (2*w)/5;
844         
845         /* menu buts */
846         strp= layer_menu(rr, &iuser->layer);
847         but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu1, 20, &iuser->layer, 0,0,0,0, "Select Layer");
848         uiButSetFunc(but, image_multi_cb, rr, iuser);
849         MEM_freeN(strp);
850         
851         rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */
852         strp= pass_menu(rl, &iuser->pass);
853         but= uiDefButS(block, MENU, 0, strp,                                    0, 0, wmenu2, 20, &iuser->pass, 0,0,0,0, "Select Pass");
854         uiButSetFunc(but, image_multi_cb, rr, iuser);
855         MEM_freeN(strp);        
856 }
857
858 static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, RenderResult *rr, ImageUser *iuser) 
859 {
860         uiBlock *block= uiLayoutGetBlock(layout);
861         uiLayout *row;
862         uiBut *but;
863         
864         row= uiLayoutRow(layout, 1);
865
866         if(rr==NULL || iuser==NULL)
867                 return;
868         if(rr->layers.first==NULL) {
869                 uiItemL(row, "No Layers in Render Result.", 0);
870                 return;
871         }
872
873         /* decrease, increase arrows */
874         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Layer");
875         uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
876         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Layer");
877         uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
878
879         uiblock_layer_pass_buttons(row, rr, iuser, 230);
880
881         /* decrease, increase arrows */
882         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_LEFT,        0,0,17,20, NULL, 0, 0, 0, 0, "Previous Pass");
883         uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
884         but= uiDefIconBut(block, BUT, 0, ICON_TRIA_RIGHT,       0,0,18,20, NULL, 0, 0, 0, 0, "Next Pass");
885         uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
886
887         uiBlockEndAlign(block);
888 }
889
890 // XXX HACK!
891 // static int packdummy=0;
892
893 typedef struct RNAUpdateCb {
894         PointerRNA ptr;
895         PropertyRNA *prop;
896         ImageUser *iuser;
897 } RNAUpdateCb;
898
899 static void rna_update_cb(bContext *C, void *arg_cb, void *arg_unused)
900 {
901         RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
902
903         /* ideally this would be done by RNA itself, but there we have
904            no image user available, so we just update this flag here */
905         cb->iuser->ok= 1;
906
907         /* we call update here on the pointer property, this way the
908            owner of the image pointer can still define it's own update
909            and notifier */
910         RNA_property_update(C, &cb->ptr, cb->prop);
911 }
912
913 void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *userptr, int compact)
914 {
915         PropertyRNA *prop;
916         PointerRNA imaptr;
917         RNAUpdateCb *cb;
918         Image *ima;
919         ImageUser *iuser;
920         ImBuf *ibuf;
921         Scene *scene= CTX_data_scene(C);
922         uiLayout *row, *split, *col;
923         uiBlock *block;
924         uiBut *but;
925         char str[128];
926
927         if(!ptr->data)
928                 return;
929         
930         prop= RNA_struct_find_property(ptr, propname);
931         if(!prop) {
932                 printf("uiTemplateImage: property not found: %s\n", propname);
933                 return;
934         }
935
936         block= uiLayoutGetBlock(layout);
937
938         imaptr= RNA_property_pointer_get(ptr, prop);
939         ima= imaptr.data;
940         iuser= userptr->data;
941
942         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
943         cb->ptr= *ptr;
944         cb->prop= prop;
945         cb->iuser= iuser;
946
947         if(!compact)
948                 uiTemplateID(layout, C, ptr, propname, "IMAGE_OT_new", "IMAGE_OT_open", NULL);
949
950         // XXX missing: reload, pack
951
952         if(ima) {
953                 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
954
955                 if(ima->source == IMA_SRC_VIEWER) {
956                         ibuf= BKE_image_get_ibuf(ima, iuser);
957                         image_info(ima, ibuf, str);
958
959                         uiItemL(layout, ima->id.name+2, 0);
960                         uiItemL(layout, str, 0);
961
962                         if(ima->type==IMA_TYPE_COMPOSITE) {
963                                 // XXX not working yet
964 #if 0
965                                 iuser= ntree_get_active_iuser(scene->nodetree);
966                                 if(iuser) {
967                                         uiBlockBeginAlign(block);
968                                         uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, "");
969                                         uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110,120,100,20, 0, 0, 0, 0, 0, "");
970                                         but= uiDefBut(block, BUT, B_NOP, "Free Cache",  210,120,100,20, 0, 0, 0, 0, 0, "");
971                                         uiButSetFunc(but, image_freecache_cb, ima, NULL);
972                                         
973                                         if(iuser->frames)
974                                                 sprintf(str, "(%d) Frames:", iuser->framenr);
975                                         else strcpy(str, "Frames:");
976                                         uiBlockBeginAlign(block);
977                                         uiDefButI(block, NUM, imagechanged, str,                10, 90,150, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
978                                         uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
979                                 }
980 #endif
981                         }
982                         else if(ima->type==IMA_TYPE_R_RESULT) {
983                                 /* browse layer/passes */
984                                 uiblock_layer_pass_arrow_buttons(layout, RE_GetResult(RE_GetRender(scene->id.name)), iuser);
985                         }
986                 }
987                 else {
988                         row= uiLayoutRow(layout, 0);
989                         uiItemR(row, NULL, 0, &imaptr, "source", (compact)? 0: UI_ITEM_R_EXPAND);
990
991                         if(ima->source != IMA_SRC_GENERATED) {
992                                 row= uiLayoutRow(layout, 0);
993                                 uiItemR(row, "", 0, &imaptr, "filename", 0);
994                                 //uiItemO(row, "Reload", 0, "image.reload");
995                         }
996
997                         // XXX what was this for?
998 #if 0
999                          /* check for re-render, only buttons */
1000                         if(imagechanged==B_IMAGECHANGED) {
1001                                 if(iuser->flag & IMA_ANIM_REFRESHED) {
1002                                         iuser->flag &= ~IMA_ANIM_REFRESHED;
1003                                         WM_event_add_notifier(C, NC_IMAGE, ima);
1004                                 }
1005                         }
1006 #endif
1007
1008                         /* multilayer? */
1009                         if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
1010                                 uiblock_layer_pass_arrow_buttons(layout, ima->rr, iuser);
1011                         }
1012                         else if(ima->source != IMA_SRC_GENERATED) {
1013                                 ibuf= BKE_image_get_ibuf(ima, iuser);
1014                                 image_info(ima, ibuf, str);
1015                                 uiItemL(layout, str, 0);
1016                         }
1017                 
1018                         if(ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
1019                                 split= uiLayoutSplit(layout, 0);
1020
1021                                 col= uiLayoutColumn(split, 0);
1022                                  
1023                                 sprintf(str, "(%d) Frames:", iuser->framenr);
1024                                 row= uiLayoutRow(col, 1);
1025                                 uiItemR(col, str, 0, userptr, "frames", 0);
1026                                 if(ima->anim) {
1027                                         block= uiLayoutGetBlock(row);
1028                                         but= uiDefBut(block, BUT, 0, "<", 0, 0, UI_UNIT_X*2, UI_UNIT_Y, 0, 0, 0, 0, 0, "Set the number of frames from the movie or sequence.");
1029                                         uiButSetFunc(but, set_frames_cb, ima, iuser);
1030                                 }
1031
1032                                 uiItemR(col, "Start", 0, userptr, "start_frame", 0);
1033                                 uiItemR(col, NULL, 0, userptr, "offset", 0);
1034
1035                                 col= uiLayoutColumn(split, 0);
1036                                 uiItemR(col, "Fields", 0, userptr, "fields_per_frame", 0);
1037                                 uiItemR(col, NULL, 0, userptr, "auto_refresh", 0);
1038                                 uiItemR(col, NULL, 0, userptr, "cyclic", 0);
1039                         }
1040                         else if(ima->source==IMA_SRC_GENERATED) {
1041                                 split= uiLayoutSplit(layout, 0);
1042
1043                                 col= uiLayoutColumn(split, 1);
1044                                 uiItemR(col, "X", 0, &imaptr, "generated_width", 0);
1045                                 uiItemR(col, "Y", 0, &imaptr, "generated_height", 0);
1046
1047                                 col= uiLayoutColumn(split, 0);
1048                                 uiItemR(col, NULL, 0, &imaptr, "generated_type", UI_ITEM_R_EXPAND);
1049                         }
1050
1051                         if(ima->source != IMA_SRC_GENERATED) {
1052                                 uiItemS(layout);
1053
1054                                 split= uiLayoutSplit(layout, 0);
1055
1056                                 col= uiLayoutColumn(split, 0);
1057                                 uiItemR(col, NULL, 0, &imaptr, "fields", 0);
1058                                 row= uiLayoutRow(col, 0);
1059                                 uiItemR(row, "Odd", 0, &imaptr, "odd_fields", 0);
1060                                 uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "fields"));
1061
1062                                 col= uiLayoutColumn(split, 0);
1063                                 uiItemR(col, NULL, 0, &imaptr, "antialias", 0);
1064                                 uiItemR(col, NULL, 0, &imaptr, "premultiply", 0);
1065                         }
1066                 }
1067
1068                 uiBlockSetNFunc(block, NULL, NULL, NULL);
1069         }
1070
1071         MEM_freeN(cb);
1072 }
1073
1074 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
1075 {
1076         Scene *scene= CTX_data_scene(C);
1077         RenderResult *rr;
1078
1079         /* render layers and passes */
1080         if(ima && iuser) {
1081                 rr= BKE_image_get_renderresult(scene, ima);
1082
1083                 if(rr)
1084                         uiblock_layer_pass_buttons(layout, rr, iuser, 160);
1085         }
1086 }
1087
1088 static int image_panel_uv_poll(const bContext *C, PanelType *pt)
1089 {
1090         Object *obedit= CTX_data_edit_object(C);
1091         return ED_uvedit_test(obedit);
1092 }
1093
1094 static void image_panel_uv(const bContext *C, Panel *pa)
1095 {
1096         ARegion *ar= CTX_wm_region(C);
1097         uiBlock *block;
1098         
1099         block= uiLayoutFreeBlock(pa->layout);
1100         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
1101
1102         image_editvertex_buts(C, block);
1103         image_editcursor_buts(C, &ar->v2d, block);
1104 }       
1105
1106 void image_buttons_register(ARegionType *art)
1107 {
1108         PanelType *pt;
1109
1110         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel uv");
1111         strcpy(pt->idname, "IMAGE_PT_uv");
1112         strcpy(pt->label, "UV");
1113         pt->draw= image_panel_uv;
1114         pt->poll= image_panel_uv_poll;
1115         BLI_addtail(&art->paneltypes, pt);
1116
1117         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel curves");
1118         strcpy(pt->idname, "IMAGE_PT_curves");
1119         strcpy(pt->label, "Curves");
1120         pt->draw= image_panel_curves;
1121         pt->poll= image_panel_poll;
1122         pt->flag |= PNL_DEFAULT_CLOSED;
1123         BLI_addtail(&art->paneltypes, pt);
1124         
1125         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
1126         strcpy(pt->idname, "IMAGE_PT_gpencil");
1127         strcpy(pt->label, "Grease Pencil");
1128         pt->draw= gpencil_panel_standard;
1129         BLI_addtail(&art->paneltypes, pt);
1130 }
1131
1132 static int image_properties(bContext *C, wmOperator *op)
1133 {
1134         ScrArea *sa= CTX_wm_area(C);
1135         ARegion *ar= image_has_buttons_region(sa);
1136         
1137         if(ar)
1138                 ED_region_toggle_hidden(C, ar);
1139
1140         return OPERATOR_FINISHED;
1141 }
1142
1143 void IMAGE_OT_properties(wmOperatorType *ot)
1144 {
1145         ot->name= "Properties";
1146         ot->idname= "IMAGE_OT_properties";
1147         
1148         ot->exec= image_properties;
1149         ot->poll= ED_operator_image_active;
1150         
1151         /* flags */
1152         ot->flag= 0;
1153 }
1154
1155
1156