* Another handful of brilliant new icons by jendryzch
[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 #define B_SIMARANGE                     14
104 #define B_SIMACURVES            15
105
106 #define B_SIMANOTHING           16
107 #define B_SIMABRUSHCHANGE       17      
108 #define B_SIMABRUSHBROWSE       18
109 #define B_SIMABRUSHLOCAL        19
110 #define B_SIMABRUSHDELETE       20
111 #define B_KEEPDATA                      21
112 #define B_SIMABTEXBROWSE        22
113 #define B_SIMABTEXDELETE        23
114 #define B_VPCOLSLI                      24
115 #define B_SIMACLONEBROWSE       25
116 #define B_SIMACLONEDELETE       26
117
118 /* XXX */
119 static int okee() {return 0;}
120 static int simaFaceDraw_Check() {return 0;}
121 static int simaUVSel_Check() {return 0;}
122 static int is_uv_tface_editing_allowed_silent() {return 0;}
123 /* XXX */
124
125 /* proto */
126 static void image_editvertex_buts(const bContext *C, uiBlock *block);
127 static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block);
128
129
130 static void do_image_panel_events(bContext *C, void *arg, int event)
131 {
132         SpaceImage *sima= CTX_wm_space_image(C);
133         ARegion *ar= CTX_wm_region(C);
134         
135         switch(event) {
136                 case B_REDR:
137                         break;
138                 case B_SIMACURVES:
139                         curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima));
140                         break;
141                 case B_SIMARANGE:
142                         curvemapping_set_black_white(sima->cumap, NULL, NULL);
143                         curvemapping_do_ibuf(sima->cumap, ED_space_image_buffer(sima));
144                         break;
145                 case B_TRANS_IMAGE:
146                         image_editvertex_buts(C, NULL);
147                         break;
148                 case B_CURSOR_IMAGE:
149                         image_editcursor_buts(C, &ar->v2d, NULL);
150                         break;
151         }
152         /* all events now */
153         WM_event_add_notifier(C, NC_IMAGE, sima->image);
154 }
155
156
157
158 static void image_info(Image *ima, ImBuf *ibuf, char *str)
159 {
160         int ofs= 0;
161         
162         str[0]= 0;
163         
164         if(ima==NULL) return;
165         if(ibuf==NULL) {
166                 sprintf(str, "Can not get an image");
167                 return;
168         }
169         
170         if(ima->source==IMA_SRC_MOVIE) {
171                 ofs= sprintf(str, "Movie ");
172                 if(ima->anim) 
173                         ofs+= sprintf(str+ofs, "%d frs", IMB_anim_get_duration(ima->anim));
174         }
175         else
176                 ofs= sprintf(str, "Image ");
177         
178         ofs+= sprintf(str+ofs, ": size %d x %d,", ibuf->x, ibuf->y);
179         
180         if(ibuf->rect_float) {
181                 if(ibuf->channels!=4) {
182                         sprintf(str+ofs, "%d float channel(s)", ibuf->channels);
183                 }
184                 else if(ibuf->depth==32)
185                         strcat(str, " RGBA float");
186                 else
187                         strcat(str, " RGB float");
188         }
189         else {
190                 if(ibuf->depth==32)
191                         strcat(str, " RGBA byte");
192                 else
193                         strcat(str, " RGB byte");
194         }
195         if(ibuf->zbuf || ibuf->zbuf_float)
196                 strcat(str, " + Z");
197         
198 }
199
200 /* gets active viewer user */
201 struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
202 {
203         bNode *node;
204         
205         if(ntree)
206                 for(node= ntree->nodes.first; node; node= node->next)
207                         if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
208                                 if(node->flag & NODE_DO_OUTPUT)
209                                         return node->storage;
210         return NULL;
211 }
212
213
214 /* ************ panel stuff ************* */
215
216 /* this function gets the values for cursor and vertex number buttons */
217 static void image_transform_but_attr(SpaceImage *sima, int *imx, int *imy, int *step, int *digits) /*, float *xcoord, float *ycoord)*/
218 {
219         ImBuf *ibuf= ED_space_image_buffer(sima);
220         if(ibuf) {
221                 *imx= ibuf->x;
222                 *imy= ibuf->y;
223         }
224         
225         if (sima->flag & SI_COORDFLOATS) {
226                 *step= 1;
227                 *digits= 3;
228         }
229         else {
230                 *step= 100;
231                 *digits= 2;
232         }
233 }
234
235
236 /* is used for both read and write... */
237 static void image_editvertex_buts(const bContext *C, uiBlock *block)
238 {
239         SpaceImage *sima= CTX_wm_space_image(C);
240         Object *obedit= CTX_data_edit_object(C);
241         static float ocent[2];
242         float cent[2]= {0.0, 0.0};
243         int imx= 256, imy= 256;
244         int nactive= 0, step, digits;
245         EditMesh *em;
246         EditFace *efa;
247         MTFace *tf;
248         
249         if(obedit==NULL || obedit->type!=OB_MESH) return;
250         
251         if( is_uv_tface_editing_allowed_silent()==0 ) return;
252         
253         image_transform_but_attr(sima, &imx, &imy, &step, &digits);
254         
255         em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
256         for (efa= em->faces.first; efa; efa= efa->next) {
257                 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
258                 if (simaFaceDraw_Check(efa, tf)) {
259                         
260                         if (simaUVSel_Check(efa, tf, 0)) {
261                                 cent[0]+= tf->uv[0][0];
262                                 cent[1]+= tf->uv[0][1];
263                                 nactive++;
264                         }
265                         if (simaUVSel_Check(efa, tf, 1)) {
266                                 cent[0]+= tf->uv[1][0];
267                                 cent[1]+= tf->uv[1][1];
268                                 nactive++;
269                         }
270                         if (simaUVSel_Check(efa, tf, 2)) {
271                                 cent[0]+= tf->uv[2][0];
272                                 cent[1]+= tf->uv[2][1];
273                                 nactive++;
274                         }
275                         if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
276                                 cent[0]+= tf->uv[3][0];
277                                 cent[1]+= tf->uv[3][1];
278                                 nactive++;
279                         }
280                 }
281         }
282                 
283         if(block) {     // do the buttons
284                 if (nactive) {
285                         ocent[0]= cent[0]/nactive;
286                         ocent[1]= cent[1]/nactive;
287                         if (sima->flag & SI_COORDFLOATS) {
288                         } else {
289                                 ocent[0] *= imx;
290                                 ocent[1] *= imy;
291                         }
292                         
293                         //uiBlockBeginAlign(block);
294                         if(nactive==1) {
295                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
296                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Vertex Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
297                         }
298                         else {
299                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median X:",       10, 10, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
300                                 uiDefButF(block, NUM, B_TRANS_IMAGE, "Median Y:",       165, 10, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
301                         }
302                         //uiBlockEndAlign(block);
303                 }
304         }
305         else {  // apply event
306                 float delta[2];
307                 
308                 cent[0]= cent[0]/nactive;
309                 cent[1]= cent[1]/nactive;
310                         
311                 if (sima->flag & SI_COORDFLOATS) {
312                         delta[0]= ocent[0]-cent[0];
313                         delta[1]= ocent[1]-cent[1];
314                 }
315                 else {
316                         delta[0]= ocent[0]/imx - cent[0];
317                         delta[1]= ocent[1]/imy - cent[1];
318                 }
319
320                 for (efa= em->faces.first; efa; efa= efa->next) {
321                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
322                         if (simaFaceDraw_Check(efa, tf)) {
323                                 if (simaUVSel_Check(efa, tf, 0)) {
324                                         tf->uv[0][0]+= delta[0];
325                                         tf->uv[0][1]+= delta[1];
326                                 }
327                                 if (simaUVSel_Check(efa, tf, 1)) {
328                                         tf->uv[1][0]+= delta[0];
329                                         tf->uv[1][1]+= delta[1];
330                                 }
331                                 if (simaUVSel_Check(efa, tf, 2)) {
332                                         tf->uv[2][0]+= delta[0];
333                                         tf->uv[2][1]+= delta[1];
334                                 }
335                                 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) {
336                                         tf->uv[3][0]+= delta[0];
337                                         tf->uv[3][1]+= delta[1];
338                                 }
339                         }
340                 }
341                 
342                 WM_event_add_notifier(C, NC_IMAGE, sima->image);
343         }
344
345         BKE_mesh_end_editmesh(obedit->data, em);
346 }
347
348
349 /* is used for both read and write... */
350 static void image_editcursor_buts(const bContext *C, View2D *v2d, uiBlock *block)
351 {
352         SpaceImage *sima= CTX_wm_space_image(C);
353         static float ocent[2];
354         int imx= 256, imy= 256;
355         int step, digits;
356         
357         if( is_uv_tface_editing_allowed_silent()==0 ) return;
358         
359         image_transform_but_attr(sima, &imx, &imy, &step, &digits);
360                 
361         if(block) {     // do the buttons
362                 ocent[0]= v2d->cursor[0];
363                 ocent[1]= v2d->cursor[1];
364                 if (sima->flag & SI_COORDFLOATS) {
365                 } else {
366                         ocent[0] *= imx;
367                         ocent[1] *= imy;
368                 }
369                 
370                 uiBlockBeginAlign(block);
371                 uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor X:",      165, 120, 145, 19, &ocent[0], -10*imx, 10.0*imx, step, digits, "");
372                 uiDefButF(block, NUM, B_CURSOR_IMAGE, "Cursor Y:",      165, 100, 145, 19, &ocent[1], -10*imy, 10.0*imy, step, digits, "");
373                 uiBlockEndAlign(block);
374         }
375         else {  // apply event
376                 if (sima->flag & SI_COORDFLOATS) {
377                         v2d->cursor[0]= ocent[0];
378                         v2d->cursor[1]= ocent[1];
379                 }
380                 else {
381                         v2d->cursor[0]= ocent[0]/imx;
382                         v2d->cursor[1]= ocent[1]/imy;
383                 }
384                 WM_event_add_notifier(C, NC_IMAGE, sima->image);
385         }
386 }
387
388 #if 0
389 static void image_panel_view_properties(const bContext *C, Panel *pa)
390 {
391         SpaceImage *sima= CTX_wm_space_image(C);
392         ARegion *ar= CTX_wm_region(C);
393         Object *obedit= CTX_data_edit_object(C);
394         uiBlock *block;
395
396         block= uiLayoutFreeBlock(pa->layout);
397         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
398         
399         uiDefButBitI(block, TOG, SI_DRAW_TILE, B_REDR, "Repeat Image",  10,160,140,19, &sima->flag, 0, 0, 0, 0, "Repeat/Tile the image display");
400         uiDefButBitI(block, TOG, SI_COORDFLOATS, B_REDR, "Normalized Coords",   165,160,145,19, &sima->flag, 0, 0, 0, 0, "Display coords from 0.0 to 1.0 rather then in pixels");
401         
402         if (sima->image) {
403                 uiDefBut(block, LABEL, B_NOP, "Image Display:",         10,140,140,19, 0, 0, 0, 0, 0, "");
404                 uiBlockBeginAlign(block);
405                 uiDefButF(block, NUM, B_REDR, "AspX:", 10,120,140,19, &sima->image->aspx, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect renderingm 0 disables.");
406                 uiDefButF(block, NUM, B_REDR, "AspY:", 10,100,140,19, &sima->image->aspy, 0.1, 5000.0, 100, 0, "X Display Aspect for this image, does not affect rendering 0 disables.");
407                 uiBlockEndAlign(block);
408         }
409         
410         if (obedit && obedit->type==OB_MESH) {
411                 Mesh *me= obedit->data;
412                 EditMesh *em= BKE_mesh_get_editmesh(me);
413                 
414                 if(EM_texFaceCheck(em)) {
415                         uiDefBut(block, LABEL, B_NOP, "Draw Type:",             10, 80,120,19, 0, 0, 0, 0, 0, "");
416                         uiBlockBeginAlign(block);
417                         uiDefButC(block,  ROW, B_REDR, "Outline",               10,60,58,19, &sima->dt_uv, 0.0, SI_UVDT_OUTLINE, 0, 0, "Outline Wire UV drawtype");
418                         uiDefButC(block,  ROW, B_REDR, "Dash",                  68, 60,58,19, &sima->dt_uv, 0.0, SI_UVDT_DASH, 0, 0, "Dashed Wire UV drawtype");
419                         uiDefButC(block,  ROW, B_REDR, "Black",                 126, 60,58,19, &sima->dt_uv, 0.0, SI_UVDT_BLACK, 0, 0, "Black Wire UV drawtype");
420                         uiDefButC(block,  ROW, B_REDR, "White",                 184,60,58,19, &sima->dt_uv, 0.0, SI_UVDT_WHITE, 0, 0, "White Wire UV drawtype");
421                         
422                         uiBlockEndAlign(block);
423                         uiDefButBitI(block, TOG, SI_SMOOTH_UV, B_REDR, "Smooth",        250,60,60,19,  &sima->flag, 0, 0, 0, 0, "Display smooth lines in the UV view");
424                         
425                         
426                         uiDefButBitI(block, TOG, ME_DRAWFACES, B_REDR, "Faces",         10,30,60,19,  &me->drawflag, 0, 0, 0, 0, "Displays all faces as shades in the 3d view and UV editor");
427                         uiDefButBitI(block, TOG, ME_DRAWEDGES, B_REDR, "Edges", 70, 30,60,19, &me->drawflag, 0, 0, 0, 0, "Displays selected edges using hilights in the 3d view and UV editor");
428                         
429                         uiDefButBitI(block, TOG, SI_DRAWSHADOW, B_REDR, "Final Shadow", 130, 30,110,19, &sima->flag, 0, 0, 0, 0, "Draw the final result from the objects modifiers");
430                         uiDefButBitI(block, TOG, SI_DRAW_OTHER, B_REDR, "Other Objs", 230, 30, 80, 19, &sima->flag, 0, 0, 0, 0, "Also draw all 3d view selected mesh objects that use this image");
431                         
432                         uiDefButBitI(block, TOG, SI_DRAW_STRETCH, B_REDR, "UV Stretch", 10,0,100,19,  &sima->flag, 0, 0, 0, 0, "Difference between UV's and the 3D coords (blue for low distortion, red is high)");
433                         if (sima->flag & SI_DRAW_STRETCH) {
434                                 uiBlockBeginAlign(block);
435                                 uiDefButC(block,  ROW, B_REDR, "Area",                  120,0,60,19, &sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_AREA, 0, 0, "Area distortion between UV's and 3D coords");
436                                 uiDefButC(block,  ROW, B_REDR, "Angle",         180,0,60,19, &sima->dt_uvstretch, 0.0, SI_UVDT_STRETCH_ANGLE, 0, 0, "Angle distortion between UV's and 3D coords");
437                                 uiBlockEndAlign(block);
438                         }
439                 }
440
441                 BKE_mesh_end_editmesh(me, em);
442         }
443         image_editcursor_buts(C, &ar->v2d, block);
444 }
445 #endif
446
447 void brush_buttons(const bContext *C, uiBlock *block, short fromsima,
448                                    int evt_nop, int evt_change,
449                                    int evt_browse, int evt_local,
450                                    int evt_del, int evt_keepdata,
451                                    int evt_texbrowse, int evt_texdel)
452 {
453 //      SpaceImage *sima= CTX_wm_space_image(C);
454         ToolSettings *settings= CTX_data_tool_settings(C);
455         Brush *brush= paint_brush(&settings->imapaint.paint);
456         ID *id;
457         int yco, xco, butw, but_idx;
458 //      short *menupoin = &(sima->menunr); // XXX : &(G.buts->menunr);
459         short do_project = settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE ? 0:1;
460         
461         yco= 160;
462         
463         butw = fromsima ? 80 : 106;
464         
465         uiBlockBeginAlign(block);
466         but_idx = 0;
467         uiDefButS(block, ROW, evt_change, "Draw",               butw*(but_idx++),yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
468         if (fromsima || do_project==0)
469                 uiDefButS(block, ROW, evt_change, "Soften",     butw*(but_idx++),       yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
470         uiDefButS(block, ROW, evt_change, "Smear",              butw*(but_idx++),       yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
471         if (fromsima || do_project)
472                 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");
473         
474         uiBlockEndAlign(block);
475         yco -= 30;
476         
477         id= (ID*)brush;
478         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);
479         
480         if(brush && !brush->id.lib) {
481                 
482                 butw= 320-(xco+10);
483                 
484                 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");
485                 
486                 uiBlockBeginAlign(block);
487                 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)");
488                 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");
489                 uiBlockEndAlign(block);
490                 
491                 if (fromsima) {
492                         uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, evt_change, "Wrap",   xco+10,yco-45,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
493                         yco -= 25;
494                 }
495                 else {
496                         yco -= 25;
497                         uiBlockBeginAlign(block);
498                         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");
499                         
500                         if ((settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0) {
501                                 /* Projection Painting */
502                                 
503                                 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)");
504                                 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)");
505                                 
506                                 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");
507                                 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");
508                                 
509                                 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)");
510                                 uiBlockEndAlign(block);
511                                 
512                                 uiBlockBeginAlign(block);
513                                 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");
514                                 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");
515                                 uiBlockEndAlign(block);
516                                 
517                         }
518                         uiBlockEndAlign(block);
519                 }
520                 
521                 uiBlockBeginAlign(block);
522                 uiDefButF(block, COL, B_VPCOLSLI, "",                                   0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");
523                 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");
524                 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");
525                 uiDefButI(block, NUMSLI, evt_nop, "Size ",              0,yco-40,180,19, &brush->size, 1, 200, 0, 0, "The size of the brush");
526                 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");
527                 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");
528                 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");
529                 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");
530                 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");
531                 uiBlockEndAlign(block);
532                 
533                 yco -= 110;
534                 
535                 if(fromsima && settings->imapaint.tool == PAINT_TOOL_CLONE) {
536                         id= (ID*)brush->clone.image;
537                         xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, B_SIMACLONEBROWSE, ID_IM, 0, id, 0, menupoin, 0, 0, B_SIMACLONEDELETE, 0, 0);
538                         if(id) {
539                                 butw= 320-(xco+5);
540                                 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");
541                         }
542                 }
543                 else {
544                         if (
545                                 (fromsima==0) && /* 3D View */
546                                 (settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0 && /* Projection Painting */
547                                 (settings->imapaint.tool == PAINT_TOOL_CLONE)
548                                 ) {
549                                 butw = 130;
550                                 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");
551                         }
552                         else {
553                                 MTex *mtex= brush->mtex[brush->texact];
554                                 
555                                 id= (mtex)? (ID*)mtex->tex: NULL;
556                                 xco= 200; // std_libbuttons(block, 0, yco, 0, NULL, evt_texbrowse, ID_TE, 0, id, NULL, menupoin, 0, 0, evt_texdel, 0, 0);
557                                 /*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");*/
558                         }
559                 }
560         }
561         
562 #if 0
563         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");
564         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");
565 #endif
566 }
567
568 static int image_panel_paint_poll(const bContext *C, PanelType *pt)
569 {
570         SpaceImage *sima= CTX_wm_space_image(C);
571         
572         return (sima->image && (sima->flag & SI_DRAWTOOL));
573 }
574
575 static void image_panel_paintcolor(const bContext *C, Panel *pa)
576 {
577         SpaceImage *sima= CTX_wm_space_image(C);
578         ToolSettings *settings= CTX_data_tool_settings(C);
579         Brush *brush= paint_brush(&settings->imapaint.paint);
580         uiBlock *block;
581         static float hsv[3], old[3];    // used as temp mem for picker
582         static char hexcol[128];
583         
584         if(!sima->image || (sima->flag & SI_DRAWTOOL)==0)
585                 return;
586         
587         block= uiLayoutFreeBlock(pa->layout);
588         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
589
590         if(brush)
591                 uiBlockPickerButtons(block, brush->rgb, hsv, old, hexcol, 'f', B_REDR);
592 }
593
594 static void image_panel_paint(const bContext *C, Panel *pa)
595 {
596         SpaceImage *sima= CTX_wm_space_image(C);
597         uiBlock *block;
598         
599         if(!sima->image || (sima->flag & SI_DRAWTOOL)==0)
600                 return;
601         
602         block= uiLayoutFreeBlock(pa->layout);
603         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
604         
605         brush_buttons(C, block, 1, B_SIMANOTHING, B_SIMABRUSHCHANGE, B_SIMABRUSHBROWSE, B_SIMABRUSHLOCAL, B_SIMABRUSHDELETE, B_KEEPDATA, B_SIMABTEXBROWSE, B_SIMABTEXDELETE);
606 }
607
608 static void image_panel_curves_reset(bContext *C, void *cumap_v, void *ibuf_v)
609 {
610         SpaceImage *sima= CTX_wm_space_image(C);
611         CurveMapping *cumap = cumap_v;
612         int a;
613         
614         for(a=0; a<CM_TOT; a++)
615                 curvemap_reset(cumap->cm+a, &cumap->clipr);
616         
617         cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
618         cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
619         curvemapping_set_black_white(cumap, NULL, NULL);
620         
621         curvemapping_changed(cumap, 0);
622         curvemapping_do_ibuf(cumap, ibuf_v);
623         
624         WM_event_add_notifier(C, NC_IMAGE, sima->image);
625 }
626
627
628 static void image_panel_curves(const bContext *C, Panel *pa)
629 {
630         SpaceImage *sima= CTX_wm_space_image(C);
631         ImBuf *ibuf;
632         uiBlock *block;
633         uiBut *bt;
634         
635         /* and we check for spare */
636         ibuf= ED_space_image_buffer(sima);
637         
638         block= uiLayoutFreeBlock(pa->layout);
639         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
640         
641         if (ibuf) {
642                 rctf rect;
643                 
644                 if(sima->cumap==NULL)
645                         sima->cumap= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
646                 
647                 rect.xmin= 110; rect.xmax= 310;
648                 rect.ymin= 10; rect.ymax= 200;
649                 curvemap_buttons(block, sima->cumap, 'c', B_SIMACURVES, B_REDR, &rect);
650                 
651                 /* curvemap min/max only works for RGBA */
652                 if(ibuf->channels==4) {
653                         bt=uiDefBut(block, BUT, B_SIMARANGE, "Reset",   10, 160, 90, 19, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
654                         uiButSetFunc(bt, image_panel_curves_reset, sima->cumap, ibuf);
655                 
656                         uiBlockBeginAlign(block);
657                         uiDefButF(block, NUM, B_SIMARANGE, "Min R:",    10, 120, 90, 19, sima->cumap->black, -1000.0f, 1000.0f, 10, 2, "Black level");
658                         uiDefButF(block, NUM, B_SIMARANGE, "Min G:",    10, 100, 90, 19, sima->cumap->black+1, -1000.0f, 1000.0f, 10, 2, "Black level");
659                         uiDefButF(block, NUM, B_SIMARANGE, "Min B:",    10, 80, 90, 19, sima->cumap->black+2, -1000.0f, 1000.0f, 10, 2, "Black level");
660                         
661                         uiBlockBeginAlign(block);
662                         uiDefButF(block, NUM, B_SIMARANGE, "Max R:",    10, 50, 90, 19, sima->cumap->white, -1000.0f, 1000.0f, 10, 2, "White level");
663                         uiDefButF(block, NUM, B_SIMARANGE, "Max G:",    10, 30, 90, 19, sima->cumap->white+1, -1000.0f, 1000.0f, 10, 2, "White level");
664                         uiDefButF(block, NUM, B_SIMARANGE, "Max B:",    10, 10, 90, 19, sima->cumap->white+2, -1000.0f, 1000.0f, 10, 2, "White level");
665                 }
666         }
667 }
668
669 #if 0
670 /* 0: disable preview 
671    otherwise refresh preview
672 */
673 void image_preview_event(int event)
674 {
675         int exec= 0;
676         
677         if(event==0) {
678                 G.scene->r.scemode &= ~R_COMP_CROP;
679                 exec= 1;
680         }
681         else {
682                 if(image_preview_active(curarea, NULL, NULL)) {
683                         G.scene->r.scemode |= R_COMP_CROP;
684                         exec= 1;
685                 }
686                 else
687                         G.scene->r.scemode &= ~R_COMP_CROP;
688         }
689         
690         if(exec && G.scene->nodetree) {
691                 /* should work when no node editor in screen..., so we execute right away */
692                 
693                 ntreeCompositTagGenerators(G.scene->nodetree);
694
695                 G.afbreek= 0;
696                 G.scene->nodetree->timecursor= set_timecursor;
697                 G.scene->nodetree->test_break= blender_test_break;
698                 
699                 BIF_store_spare();
700                 
701                 ntreeCompositExecTree(G.scene->nodetree, &G.scene->r, 1);       /* 1 is do_previews */
702                 
703                 G.scene->nodetree->timecursor= NULL;
704                 G.scene->nodetree->test_break= NULL;
705                 
706                 scrarea_do_windraw(curarea);
707                 waitcursor(0);
708                 
709                 WM_event_add_notifier(C, NC_IMAGE, ima_v);
710         }       
711 }
712
713
714 /* nothing drawn here, we use it to store values */
715 static void preview_cb(struct ScrArea *sa, struct uiBlock *block)
716 {
717         SpaceImage *sima= sa->spacedata.first;
718         rctf dispf;
719         rcti *disprect= &G.scene->r.disprect;
720         int winx= (G.scene->r.size*G.scene->r.xsch)/100;
721         int winy= (G.scene->r.size*G.scene->r.ysch)/100;
722         short mval[2];
723         
724         if(G.scene->r.mode & R_BORDER) {
725                 winx*= (G.scene->r.border.xmax - G.scene->r.border.xmin);
726                 winy*= (G.scene->r.border.ymax - G.scene->r.border.ymin);
727         }
728         
729         /* while dragging we need to update the rects, otherwise it doesn't end with correct one */
730
731         BLI_init_rctf(&dispf, 15.0f, (block->maxx - block->minx)-15.0f, 15.0f, (block->maxy - block->miny)-15.0f);
732         ui_graphics_to_window_rct(sa->win, &dispf, disprect);
733         
734         /* correction for gla draw */
735         BLI_translate_rcti(disprect, -curarea->winrct.xmin, -curarea->winrct.ymin);
736         
737         calc_image_view(sima, 'p');
738 //      printf("winrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
739         /* map to image space coordinates */
740         mval[0]= disprect->xmin; mval[1]= disprect->ymin;
741         areamouseco_to_ipoco(v2d, mval, &dispf.xmin, &dispf.ymin);
742         mval[0]= disprect->xmax; mval[1]= disprect->ymax;
743         areamouseco_to_ipoco(v2d, mval, &dispf.xmax, &dispf.ymax);
744         
745         /* map to render coordinates */
746         disprect->xmin= dispf.xmin;
747         disprect->xmax= dispf.xmax;
748         disprect->ymin= dispf.ymin;
749         disprect->ymax= dispf.ymax;
750         
751         CLAMP(disprect->xmin, 0, winx);
752         CLAMP(disprect->xmax, 0, winx);
753         CLAMP(disprect->ymin, 0, winy);
754         CLAMP(disprect->ymax, 0, winy);
755 //      printf("drawrct %d %d %d %d\n", disprect->xmin, disprect->ymin,disprect->xmax, disprect->ymax);
756
757 }
758
759 static int is_preview_allowed(ScrArea *cur)
760 {
761         SpaceImage *sima= cur->spacedata.first;
762         ScrArea *sa;
763
764         /* check if another areawindow has preview set */
765         for(sa=G.curscreen->areabase.first; sa; sa= sa->next) {
766                 if(sa!=cur && sa->spacetype==SPACE_IMAGE) {
767                         if(image_preview_active(sa, NULL, NULL))
768                            return 0;
769                 }
770         }
771         /* check image type */
772         if(sima->image==NULL || sima->image->type!=IMA_TYPE_COMPOSITE)
773                 return 0;
774         
775         return 1;
776 }
777
778
779 static void image_panel_preview(ScrArea *sa, short cntrl)       // IMAGE_HANDLER_PREVIEW
780 {
781         uiBlock *block;
782         SpaceImage *sima= sa->spacedata.first;
783         int ofsx, ofsy;
784         
785         if(is_preview_allowed(sa)==0) {
786                 rem_blockhandler(sa, IMAGE_HANDLER_PREVIEW);
787                 G.scene->r.scemode &= ~R_COMP_CROP;     /* quite weak */
788                 return;
789         }
790         
791         block= uiBeginBlock(C, ar, "image_panel_preview", UI_EMBOSS);
792         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
793         uiSetPanelHandler(IMAGE_HANDLER_PREVIEW);  // for close and esc
794         
795         ofsx= -150+(sa->winx/2)/sima->blockscale;
796         ofsy= -100+(sa->winy/2)/sima->blockscale;
797         if(uiNewPanel(C, ar, block, "Preview", "Image", ofsx, ofsy, 300, 200)==0) return;
798         
799         uiBlockSetDrawExtraFunc(block, preview_cb);
800         
801 }
802
803 static void image_panel_gpencil(short cntrl)    // IMAGE_HANDLER_GREASEPENCIL
804 {
805         uiBlock *block;
806         SpaceImage *sima;
807         
808         sima= curarea->spacedata.first;
809
810         block= uiBeginBlock(C, ar, "image_panel_gpencil", UI_EMBOSS);
811         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
812         uiSetPanelHandler(IMAGE_HANDLER_GREASEPENCIL);  // for close and esc
813         if (uiNewPanel(C, ar, block, "Grease Pencil", "SpaceImage", 100, 30, 318, 204)==0) return;
814         
815         /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
816         if (sima->flag & SI_DISPGP) {
817                 if (sima->gpd == NULL)
818                         gpencil_data_setactive(curarea, gpencil_data_addnew());
819         }
820         
821         if (sima->flag & SI_DISPGP) {
822                 bGPdata *gpd= sima->gpd;
823                 short newheight;
824                 
825                 /* this is a variable height panel, newpanel doesnt force new size on existing panels */
826                 /* so first we make it default height */
827                 uiNewPanelHeight(block, 204);
828                 
829                 /* draw button for showing gpencil settings and drawings */
830                 uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor (draw using Shift-LMB)");
831                 
832                 /* extend the panel if the contents won't fit */
833                 newheight= draw_gpencil_panel(block, gpd, curarea); 
834                 uiNewPanelHeight(block, newheight);
835         }
836         else {
837                 uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor");
838                 uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
839         }
840 }
841 #endif
842
843
844 /* ********************* callbacks for standard image buttons *************** */
845
846 /* called from fileselect or button */
847 static void load_image_cb(bContext *C, char *str, void *ima_pp_v, void *iuser_v)        
848 {
849         Image **ima_pp= (Image **)ima_pp_v;
850         Image *ima= NULL;
851         
852         ima= BKE_add_image_file(str, 0);
853         if(ima) {
854                 if(*ima_pp) {
855                         (*ima_pp)->id.us--;
856                 }
857                 *ima_pp= ima;
858                 
859                 BKE_image_signal(ima, iuser_v, IMA_SIGNAL_RELOAD);
860                 WM_event_add_notifier(C, NC_IMAGE, ima);
861                 
862                 /* button event gets lost when it goes via filewindow */
863 //              if(G.buts && G.buts->lockpoin) {
864 //                      Tex *tex= G.buts->lockpoin;
865 //                      if(GS(tex->id.name)==ID_TE) {
866 //                              BIF_preview_changed(ID_TE);
867 //                              allqueue(REDRAWBUTSSHADING, 0);
868 //                              allqueue(REDRAWVIEW3D, 0);
869 //                              allqueue(REDRAWOOPS, 0);
870 //                      }
871 //              }
872         }
873         
874         ED_undo_push(C, "Load image");
875 }
876
877 static char *layer_menu(RenderResult *rr, short *curlay)
878 {
879         RenderLayer *rl;
880         int len= 64 + 32*BLI_countlist(&rr->layers);
881         short a, nr= 0;
882         char *str= MEM_callocN(len, "menu layers");
883         
884         strcpy(str, "Layer %t");
885         a= strlen(str);
886         
887         /* compo result */
888         if(rr->rectf) {
889                 a+= sprintf(str+a, "|Composite %%x0");
890                 nr= 1;
891         }
892         for(rl= rr->layers.first; rl; rl= rl->next, nr++) {
893                 a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
894         }
895         
896         /* no curlay clip here, on render (redraws) the amount of layers can be 1 fir single-layer render */
897         
898         return str;
899 }
900
901 /* rl==NULL means composite result */
902 static char *pass_menu(RenderLayer *rl, short *curpass)
903 {
904         RenderPass *rpass;
905         int len= 64 + 32*(rl?BLI_countlist(&rl->passes):1);
906         short a, nr= 0;
907         char *str= MEM_callocN(len, "menu layers");
908         
909         strcpy(str, "Pass %t");
910         a= strlen(str);
911         
912         /* rendered results don't have a Combined pass */
913         if(rl==NULL || rl->rectf) {
914                 a+= sprintf(str+a, "|Combined %%x0");
915                 nr= 1;
916         }
917         
918         if(rl)
919                 for(rpass= rl->passes.first; rpass; rpass= rpass->next, nr++)
920                         a+= sprintf(str+a, "|%s %%x%d", rpass->name, nr);
921         
922         if(*curpass >= nr)
923                 *curpass= 0;
924         
925         return str;
926 }
927
928 static void set_frames_cb(bContext *C, void *ima_v, void *iuser_v)
929 {
930         Scene *scene= CTX_data_scene(C);
931         Image *ima= ima_v;
932         ImageUser *iuser= iuser_v;
933         
934         if(ima->anim) {
935                 iuser->frames = IMB_anim_get_duration(ima->anim);
936                 BKE_image_user_calc_imanr(iuser, scene->r.cfra, 0);
937         }
938 }
939
940 static void image_src_change_cb(bContext *C, void *ima_v, void *iuser_v)
941 {
942         BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_SRC_CHANGE);
943 }
944
945 /* buttons have 2 arg callbacks, filewindow has 3 args... so thats why the wrapper below */
946 static void image_browse_cb1(bContext *C, void *ima_pp_v, void *iuser_v)
947 {
948         Image **ima_pp= (Image **)ima_pp_v;
949         ImageUser *iuser= iuser_v;
950         
951         if(ima_pp) {
952                 Image *ima= *ima_pp;
953                 
954                 if(iuser->menunr== -2) {
955                         // XXX activate_databrowse_args(&ima->id, ID_IM, 0, &iuser->menunr, image_browse_cb1, ima_pp, iuser);
956                 } 
957                 else if (iuser->menunr>0) {
958                         Image *newima= (Image*) BLI_findlink(&CTX_data_main(C)->image, iuser->menunr-1);
959                         
960                         if (newima && newima!=ima) {
961                                 *ima_pp= newima;
962                                 id_us_plus(&newima->id);
963                                 if(ima) ima->id.us--;
964                                 
965                                 BKE_image_signal(newima, iuser, IMA_SIGNAL_USER_NEW_IMAGE);
966                                 
967                                 ED_undo_push(C, "Browse image");
968                         }
969                 }
970         }
971 }
972
973 static void image_browse_cb(bContext *C, void *ima_pp_v, void *iuser_v)
974 {
975         image_browse_cb1(C, ima_pp_v, iuser_v);
976 }
977
978 static void image_reload_cb(bContext *C, void *ima_v, void *iuser_v)
979 {
980         if(ima_v) {
981                 BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_RELOAD);
982         }
983 }
984
985 static void image_field_test(bContext *C, void *ima_v, void *iuser_v)
986 {
987         Image *ima= ima_v;
988         
989         if(ima) {
990                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
991                 if(ibuf) {
992                         short nr= 0;
993                         if( !(ima->flag & IMA_FIELDS) && (ibuf->flags & IB_fields) ) nr= 1;
994                         if( (ima->flag & IMA_FIELDS) && !(ibuf->flags & IB_fields) ) nr= 1;
995                         if(nr) {
996                                 BKE_image_signal(ima, iuser_v, IMA_SIGNAL_FREE);
997                         }
998                 }
999         }
1000 }
1001
1002 static void image_unlink_cb(bContext *C, void *ima_pp_v, void *unused)
1003 {
1004         Image **ima_pp= (Image **)ima_pp_v;
1005         
1006         if(ima_pp && *ima_pp) {
1007                 Image *ima= *ima_pp;
1008                 /* (for time being, texturefaces are no users, conflict in design...) */
1009                 if(ima->id.us>1)
1010                         ima->id.us--;
1011                 *ima_pp= NULL;
1012         }
1013 }
1014
1015 static void image_load_fs_cb(bContext *C, void *ima_pp_v, void *iuser_v)
1016 {
1017         ScrArea *sa= CTX_wm_area(C);
1018 //      Image **ima_pp= (Image **)ima_pp_v;
1019         
1020         if(sa->spacetype==SPACE_IMAGE)
1021                 WM_operator_name_call(C, "IMAGE_OT_open", WM_OP_INVOKE_REGION_WIN, NULL);
1022         else
1023                 printf("not supported yet\n");
1024 }
1025
1026 /* 5 layer button callbacks... */
1027 static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) 
1028 {
1029         BKE_image_multilayer_index(rr_v, iuser_v); 
1030         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
1031 }
1032 static void image_multi_inclay_cb(bContext *C, void *rr_v, void *iuser_v) 
1033 {
1034         RenderResult *rr= rr_v;
1035         ImageUser *iuser= iuser_v;
1036         int tot= BLI_countlist(&rr->layers) + (rr->rectf?1:0);  /* fake compo result layer */
1037
1038         if(iuser->layer<tot-1) {
1039                 iuser->layer++;
1040                 BKE_image_multilayer_index(rr, iuser); 
1041                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
1042         }
1043 }
1044 static void image_multi_declay_cb(bContext *C, void *rr_v, void *iuser_v) 
1045 {
1046         ImageUser *iuser= iuser_v;
1047
1048         if(iuser->layer>0) {
1049                 iuser->layer--;
1050                 BKE_image_multilayer_index(rr_v, iuser); 
1051                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
1052         }
1053 }
1054 static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v) 
1055 {
1056         RenderResult *rr= rr_v;
1057         ImageUser *iuser= iuser_v;
1058         RenderLayer *rl= BLI_findlink(&rr->layers, iuser->layer);
1059
1060         if(rl) {
1061                 int tot= BLI_countlist(&rl->passes) + (rl->rectf?1:0);  /* builtin render result has no combined pass in list */
1062                 if(iuser->pass<tot-1) {
1063                         iuser->pass++;
1064                         BKE_image_multilayer_index(rr, iuser); 
1065                         WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
1066                 }
1067         }
1068 }
1069 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
1070 {
1071         ImageUser *iuser= iuser_v;
1072
1073         if(iuser->pass>0) {
1074                 iuser->pass--;
1075                 BKE_image_multilayer_index(rr_v, iuser); 
1076                 WM_event_add_notifier(C, NC_IMAGE|ND_DRAW, NULL);
1077         }
1078 }
1079
1080 static void image_pack_cb(bContext *C, void *ima_v, void *iuser_v) 
1081 {
1082         if(ima_v) {
1083                 Image *ima= ima_v;
1084                 if(ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE) {
1085                         if (ima->packedfile) {
1086                                 if (G.fileflags & G_AUTOPACK) {
1087                                         if (okee("Disable AutoPack ?")) {
1088                                                 G.fileflags &= ~G_AUTOPACK;
1089                                         }
1090                                 }
1091                                 
1092                                 if ((G.fileflags & G_AUTOPACK) == 0) {
1093                                         unpackImage(NULL, ima, PF_ASK); /* XXX report errors */
1094                                         ED_undo_push(C, "Unpack image");
1095                                 }
1096                         } 
1097                         else {
1098                                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
1099                                 if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
1100                                         // XXX error("Can't pack painted image. Save image or use Repack as PNG.");
1101                                 } else {
1102                                         ima->packedfile = newPackedFile(NULL, ima->name); /* XXX report errors */
1103                                         ED_undo_push(C, "Pack image");
1104                                 }
1105                         }
1106                 }
1107         }
1108 }
1109
1110 static void image_load_cb(bContext *C, void *ima_pp_v, void *iuser_v)
1111 {
1112         if(ima_pp_v) {
1113                 Image *ima= *((Image **)ima_pp_v);
1114                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser_v);
1115                 char str[FILE_MAX];
1116         
1117                 /* name in ima has been changed by button! */
1118                 BLI_strncpy(str, ima->name, FILE_MAX);
1119                 if(ibuf) BLI_strncpy(ima->name, ibuf->name, FILE_MAX);
1120                 
1121                 load_image_cb(C, str, ima_pp_v, iuser_v);
1122         }
1123 }
1124
1125 static void image_freecache_cb(bContext *C, void *ima_v, void *unused) 
1126 {
1127         Scene *scene= CTX_data_scene(C);
1128         BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
1129         WM_event_add_notifier(C, NC_IMAGE, ima_v);
1130 }
1131
1132 static void image_generated_change_cb(bContext *C, void *ima_v, void *iuser_v)
1133 {
1134         BKE_image_signal(ima_v, iuser_v, IMA_SIGNAL_FREE);
1135 }
1136
1137 static void image_user_change(bContext *C, void *iuser_v, void *unused)
1138 {
1139         Scene *scene= CTX_data_scene(C);
1140         BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
1141 }
1142
1143 static void uiblock_layer_pass_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int event, int x, int y, int w)
1144 {
1145         uiBut *but;
1146         RenderLayer *rl= NULL;
1147         int wmenu1, wmenu2;
1148         char *strp;
1149
1150         /* layer menu is 1/3 larger than pass */
1151         wmenu1= (3*w)/5;
1152         wmenu2= (2*w)/5;
1153         
1154         /* menu buts */
1155         strp= layer_menu(rr, &iuser->layer);
1156         but= uiDefButS(block, MENU, event, strp,                                        x, y, wmenu1, 20, &iuser->layer, 0,0,0,0, "Select Layer");
1157         uiButSetFunc(but, image_multi_cb, rr, iuser);
1158         MEM_freeN(strp);
1159         
1160         rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */
1161         strp= pass_menu(rl, &iuser->pass);
1162         but= uiDefButS(block, MENU, event, strp,                                        x+wmenu1, y, wmenu2, 20, &iuser->pass, 0,0,0,0, "Select Pass");
1163         uiButSetFunc(but, image_multi_cb, rr, iuser);
1164         MEM_freeN(strp);        
1165 }
1166
1167 static void uiblock_layer_pass_arrow_buttons(uiBlock *block, RenderResult *rr, ImageUser *iuser, int imagechanged) 
1168 {
1169         uiBut *but;
1170         
1171         if(rr==NULL || iuser==NULL)
1172                 return;
1173         if(rr->layers.first==NULL) {
1174                 uiDefBut(block, LABEL, 0, "No Layers in Render Result,",        10, 107, 300, 20, NULL, 1, 0, 0, 0, "");
1175                 return;
1176         }
1177         
1178         uiBlockBeginAlign(block);
1179
1180         /* decrease, increase arrows */
1181         but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT,     10,107,17,20, NULL, 0, 0, 0, 0, "Previous Layer");
1182         uiButSetFunc(but, image_multi_declay_cb, rr, iuser);
1183         but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT,    27,107,18,20, NULL, 0, 0, 0, 0, "Next Layer");
1184         uiButSetFunc(but, image_multi_inclay_cb, rr, iuser);
1185
1186         uiblock_layer_pass_buttons(block, rr, iuser, imagechanged, 45, 107, 230);
1187
1188         /* decrease, increase arrows */
1189         but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_LEFT,     275,107,17,20, NULL, 0, 0, 0, 0, "Previous Pass");
1190         uiButSetFunc(but, image_multi_decpass_cb, rr, iuser);
1191         but= uiDefIconBut(block, BUT, imagechanged, ICON_TRIA_RIGHT,    292,107,18,20, NULL, 0, 0, 0, 0, "Next Pass");
1192         uiButSetFunc(but, image_multi_incpass_cb, rr, iuser);
1193
1194         uiBlockEndAlign(block);
1195                          
1196 }
1197
1198 // XXX HACK!
1199 static int packdummy=0;
1200
1201 /* The general Image panel with the loadsa callbacks! */
1202 void ED_image_uiblock_panel(const bContext *C, uiBlock *block, Image **ima_pp, ImageUser *iuser, 
1203                                                  short redraw, short imagechanged)
1204 {
1205         Scene *scene= CTX_data_scene(C);
1206         SpaceImage *sima= CTX_wm_space_image(C);
1207         Image *ima= *ima_pp;
1208         uiBut *but;
1209         char str[128], *strp;
1210         
1211         /* different stuff when we show viewer */
1212         if(ima && ima->source==IMA_SRC_VIEWER) {
1213                 ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser);
1214                 
1215                 image_info(ima, ibuf, str);
1216                 uiDefBut(block, LABEL, 0, ima->id.name+2,       10, 180, 300, 20, NULL, 1, 0, 0, 0, "");
1217                 uiDefBut(block, LABEL, 0, str,                          10, 160, 300, 20, NULL, 1, 0, 0, 0, "");
1218                 
1219                 if(ima->type==IMA_TYPE_COMPOSITE) {
1220                         iuser= ntree_get_active_iuser(scene->nodetree);
1221                         if(iuser) {
1222                                 uiBlockBeginAlign(block);
1223                                 uiDefIconTextBut(block, BUT, B_SIMA_RECORD, ICON_REC, "Record", 10,120,100,20, 0, 0, 0, 0, 0, "");
1224                                 uiDefIconTextBut(block, BUT, B_SIMA_PLAY, ICON_PLAY, "Play",    110,120,100,20, 0, 0, 0, 0, 0, "");
1225                                 but= uiDefBut(block, BUT, B_NOP, "Free Cache",  210,120,100,20, 0, 0, 0, 0, 0, "");
1226                                 uiButSetFunc(but, image_freecache_cb, ima, NULL);
1227                                 
1228                                 if(iuser->frames)
1229                                         sprintf(str, "(%d) Frames:", iuser->framenr);
1230                                 else strcpy(str, "Frames:");
1231                                 uiBlockBeginAlign(block);
1232                                 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");
1233                                 uiDefButI(block, NUM, imagechanged, "StartFr:", 160,90,150,20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
1234                         }
1235                 }
1236                 else if(ima->type==IMA_TYPE_R_RESULT) {
1237                         /* browse layer/passes */
1238                         uiblock_layer_pass_arrow_buttons(block, RE_GetResult(RE_GetRender(scene->id.name)), iuser, imagechanged);
1239                 }
1240                 return;
1241         }
1242         
1243         /* the main ima source types */
1244         if(ima) {
1245 // XXX          uiSetButLock(ima->id.lib!=NULL, ERROR_LIBDATA_MESSAGE);
1246                 uiBlockBeginAlign(block);
1247                 uiBlockSetFunc(block, image_src_change_cb, ima, iuser);
1248                 uiDefButS(block, ROW, imagechanged, "Still",            0, 180, 105, 20, &ima->source, 0.0, IMA_SRC_FILE, 0, 0, "Single Image file");
1249                 uiDefButS(block, ROW, imagechanged, "Movie",            105, 180, 105, 20, &ima->source, 0.0, IMA_SRC_MOVIE, 0, 0, "Movie file");
1250                 uiDefButS(block, ROW, imagechanged, "Sequence",         210, 180, 105, 20, &ima->source, 0.0, IMA_SRC_SEQUENCE, 0, 0, "Multiple Image files, as a sequence");
1251                 uiDefButS(block, ROW, imagechanged, "Generated",        315, 180, 105, 20, &ima->source, 0.0, IMA_SRC_GENERATED, 0, 0, "Generated Image");
1252                 uiBlockSetFunc(block, NULL, NULL, NULL);
1253         }
1254         else
1255                 uiDefBut(block, LABEL, 0, " ",                                  0, 180, 440, 20, 0, 0, 0, 0, 0, "");    /* for align in panel */
1256                                  
1257          /* Browse */
1258          IMAnames_to_pupstring(&strp, NULL, NULL, &(CTX_data_main(C)->image), NULL, &iuser->menunr);
1259          
1260          uiBlockBeginAlign(block);
1261          but= uiDefButS(block, MENU, imagechanged, strp,                0,155,40,20, &iuser->menunr, 0, 0, 0, 0, "Selects an existing Image or Movie");
1262          uiButSetFunc(but, image_browse_cb, ima_pp, iuser);
1263          
1264          MEM_freeN(strp);
1265          
1266          /* name + options, or only load */
1267          if(ima) {
1268                  int drawpack= (ima->source!=IMA_SRC_SEQUENCE && ima->source!=IMA_SRC_MOVIE && ima->ok);
1269
1270                  but= uiDefBut(block, TEX, B_IDNAME, "IM:",                             40, 155, 220, 20, ima->id.name+2, 0.0, 21.0, 0, 0, "Current Image Datablock name.");
1271                  uiButSetFunc(but, test_idbutton_cb, ima->id.name, NULL);
1272                  but= uiDefBut(block, BUT, imagechanged, "Reload",              260, 155, 70, 20, NULL, 0, 0, 0, 0, "Reloads Image or Movie");
1273                  uiButSetFunc(but, image_reload_cb, ima, iuser);
1274                  
1275                  but= uiDefIconBut(block, BUT, imagechanged, ICON_X,    330, 155, 40, 20, 0, 0, 0, 0, 0, "Unlink Image block");
1276                  uiButSetFunc(but, image_unlink_cb, ima_pp, NULL);
1277                  sprintf(str, "%d", ima->id.us);
1278                  uiDefBut(block, BUT, B_NOP, str,                                       370, 155, 40, 20, 0, 0, 0, 0, 0, "Only displays number of users of Image block");
1279                  uiBlockEndAlign(block);
1280                  
1281                  uiBlockBeginAlign(block);
1282                  but= uiDefIconBut(block, BUT, imagechanged, ICON_FILESEL,      0, 130, 40, 20, 0, 0, 0, 0, 0, "Open Fileselect to load new Image");
1283                  uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser);
1284                  but= uiDefBut(block, TEX, imagechanged, "",                            40,130, 340+(drawpack?0:20),20, ima->name, 0.0, 239.0, 0, 0, "Image/Movie file name, change to load new");
1285                  uiButSetFunc(but, image_load_cb, ima_pp, iuser);
1286                  uiBlockEndAlign(block);
1287                  
1288                  if(drawpack) {
1289                          if (ima->packedfile) packdummy = 1;
1290                          else packdummy = 0;
1291                          but= uiDefIconButBitI(block, TOG, 1, redraw, ICON_PACKAGE, 380, 130, 40, 20, &packdummy, 0, 0, 0, 0, "Toggles Packed status of this Image");
1292                          uiButSetFunc(but, image_pack_cb, ima, iuser);
1293                  }
1294                  
1295          }
1296          else {
1297                  but= uiDefBut(block, BUT, imagechanged, "Load",                33, 155, 200,20, NULL, 0, 0, 0, 0, "Load new Image of Movie");
1298                  uiButSetFunc(but, image_load_fs_cb, ima_pp, iuser);
1299          }
1300          uiBlockEndAlign(block);
1301          
1302          if(ima) {
1303                  ImBuf *ibuf= BKE_image_get_ibuf(ima, iuser);
1304                  
1305                  /* check for re-render, only buttons */
1306                  if(imagechanged==B_IMAGECHANGED) {
1307                          if(iuser->flag & IMA_ANIM_REFRESHED) {
1308                                  iuser->flag &= ~IMA_ANIM_REFRESHED;
1309                                  WM_event_add_notifier(C, NC_IMAGE, ima);
1310                          }
1311                  }
1312                  
1313                  /* multilayer? */
1314                  if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
1315                          uiblock_layer_pass_arrow_buttons(block, ima->rr, iuser, imagechanged);
1316                  }
1317                  else {
1318                          image_info(ima, ibuf, str);
1319                          uiDefBut(block, LABEL, 0, str,         10, 112, 300, 20, NULL, 1, 0, 0, 0, "");
1320                  }
1321                  
1322                  /* exception, let's do because we only use this panel 3 times in blender... but not real good code! */
1323                  if( (paint_facesel_test(CTX_data_active_object(C))) && sima && &sima->iuser==iuser)
1324                          return;
1325                  /* left side default per-image options, right half the additional options */
1326                  
1327                  /* fields */
1328                  
1329                  but= uiDefButBitS(block, TOGBUT, IMA_FIELDS, imagechanged, "Fields",   0, 80, 200, 20, &ima->flag, 0, 0, 0, 0, "Click to enable use of fields in Image");
1330                  uiButSetFunc(but, image_field_test, ima, iuser);
1331                  uiDefButBitS(block, TOGBUT, IMA_STD_FIELD, B_NOP, "Odd",                               0, 55, 200, 20, &ima->flag, 0, 0, 0, 0, "Standard Field Toggle");
1332                 
1333                  
1334                  uiBlockSetFunc(block, image_reload_cb, ima, iuser);
1335                  uiDefButBitS(block, TOGBUT, IMA_ANTIALI, B_NOP, "Anti",                                0, 5, 200, 20, &ima->flag, 0, 0, 0, 0, "Toggles Image anti-aliasing, only works with solid colors");
1336                  uiDefButBitS(block, TOGBUT, IMA_DO_PREMUL, imagechanged, "Premul",             0, -20, 200, 20, &ima->flag, 0, 0, 0, 0, "Toggles premultiplying alpha");
1337                  
1338                  
1339                  if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
1340                          sprintf(str, "(%d) Frames:", iuser->framenr);
1341                          
1342                          //uiBlockBeginAlign(block);
1343                          uiBlockSetFunc(block, image_user_change, iuser, NULL);
1344                                                  
1345                          if(ima->anim) {
1346                                  uiBlockBeginAlign(block);
1347                                  uiDefButI(block, NUM, imagechanged, str,                                               220, 80, 160, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
1348                                  but= uiDefBut(block, BUT, redraw, "<",                                                 380, 80, 40, 20, 0, 0, 0, 0, 0, "Copies number of frames in movie file to Frames: button");
1349                                  uiButSetFunc(but, set_frames_cb, ima, iuser);
1350                                  uiBlockEndAlign(block);
1351                          }
1352                          else 
1353                                  uiDefButI(block, NUM, imagechanged, str,                                               220, 80, 200, 20, &iuser->frames, 0.0, MAXFRAMEF, 0, 0, "Sets the number of images of a movie to use");
1354                          
1355                          uiDefButI(block, NUM, imagechanged, "Start Frame:",                            220, 55, 200, 20, &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Sets the global starting frame of the movie");
1356                          uiDefButI(block, NUM, imagechanged, "Offset:",                                         220, 30, 200, 20, &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation");
1357                          uiDefButS(block, NUM, imagechanged, "Fields:",                                         0, 30, 200, 20, &iuser->fie_ima, 1.0, 200.0, 0, 0, "The number of fields per rendered frame (2 fields is 1 image)");
1358                          
1359                         uiDefButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NOP, "Auto Refresh",        220, 5, 200, 20, &iuser->flag, 0, 0, 0, 0, "Always refresh Image on frame changes");
1360
1361                          uiDefButS(block, TOG, imagechanged, "Cyclic",                                          220, -20, 200, 20, &iuser->cycl, 0.0, 1.0, 0, 0, "Cycle the images in the movie");
1362                          
1363                          uiBlockSetFunc(block, NULL, iuser, NULL);
1364                  }
1365                  else if(ima->source==IMA_SRC_GENERATED) {
1366                          
1367                          uiDefBut(block, LABEL, 0, "Size:",                                     220, 80, 200, 20, 0, 0, 0, 0, 0, "");   
1368
1369                          uiBlockBeginAlign(block);
1370                          uiBlockSetFunc(block, image_generated_change_cb, ima, iuser);
1371                          uiDefButS(block, NUM, imagechanged, "X:",      220, 55,200,20, &ima->gen_x, 1.0, 5000.0, 0, 0, "Image size x");
1372                          uiDefButS(block, NUM, imagechanged, "Y:",      220, 35,200,20, &ima->gen_y, 1.0, 5000.0, 0, 0, "Image size y");
1373                          uiBlockEndAlign(block);
1374                          
1375                          uiDefButS(block, TOGBUT, imagechanged, "UV Test grid", 220,10,200,20, &ima->gen_type, 0.0, 1.0, 0, 0, "");
1376                          uiBlockSetFunc(block, NULL, NULL, NULL);
1377                  }
1378          }
1379          uiBlockEndAlign(block);
1380 }       
1381
1382 void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
1383 {
1384         uiBlock *block= uiLayoutFreeBlock(layout);
1385         Scene *scene= CTX_data_scene(C);
1386         RenderResult *rr;
1387
1388         /* render layers and passes */
1389         if(ima && iuser) {
1390                 rr= BKE_image_get_renderresult(scene, ima);
1391
1392                 if(rr) {
1393                         uiBlockBeginAlign(block);
1394                         uiblock_layer_pass_buttons(block, rr, iuser, 0, 0, 0, 160);
1395                         uiBlockEndAlign(block);
1396                 }
1397         }
1398 }
1399
1400 static void image_panel_properties(const bContext *C, Panel *pa)
1401 {
1402         SpaceImage *sima= CTX_wm_space_image(C);
1403         uiBlock *block;
1404         
1405         block= uiLayoutFreeBlock(pa->layout);
1406         uiBlockSetHandleFunc(block, do_image_panel_events, NULL);
1407
1408         /* note, it draws no bottom half in facemode, for vertex buttons */
1409         ED_image_uiblock_panel(C, block, &sima->image, &sima->iuser, B_REDR, B_REDR);
1410         image_editvertex_buts(C, block);
1411 }       
1412
1413 void image_buttons_register(ARegionType *art)
1414 {
1415         PanelType *pt;
1416
1417         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel properties");
1418         strcpy(pt->idname, "IMAGE_PT_properties");
1419         strcpy(pt->label, "Image Properties");
1420         pt->draw= image_panel_properties;
1421         BLI_addtail(&art->paneltypes, pt);
1422
1423         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel paint");
1424         strcpy(pt->idname, "IMAGE_PT_paint");
1425         strcpy(pt->label, "Paint");
1426         pt->draw= image_panel_paint;
1427         pt->poll= image_panel_paint_poll;
1428         BLI_addtail(&art->paneltypes, pt);
1429
1430         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel paint color");
1431         strcpy(pt->idname, "IMAGE_PT_paint_color");
1432         strcpy(pt->label, "Paint Color");
1433         pt->draw= image_panel_paintcolor;
1434         pt->poll= image_panel_paint_poll;
1435         BLI_addtail(&art->paneltypes, pt);
1436
1437         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel curves");
1438         strcpy(pt->idname, "IMAGE_PT_curves");
1439         strcpy(pt->label, "Curves");
1440         pt->draw= image_panel_curves;
1441         BLI_addtail(&art->paneltypes, pt);
1442         
1443         pt= MEM_callocN(sizeof(PanelType), "spacetype image panel gpencil");
1444         strcpy(pt->idname, "IMAGE_PT_gpencil");
1445         strcpy(pt->label, "Grease Pencil");
1446         pt->draw= gpencil_panel_standard;
1447         BLI_addtail(&art->paneltypes, pt);
1448 }
1449
1450 static int image_properties(bContext *C, wmOperator *op)
1451 {
1452         ScrArea *sa= CTX_wm_area(C);
1453         ARegion *ar= image_has_buttons_region(sa);
1454         
1455         if(ar) {
1456                 ar->flag ^= RGN_FLAG_HIDDEN;
1457                 ar->v2d.flag &= ~V2D_IS_INITIALISED; /* XXX should become hide/unhide api? */
1458                 
1459                 ED_area_initialize(CTX_wm_manager(C), CTX_wm_window(C), sa);
1460                 ED_area_tag_redraw(sa);
1461         }
1462         return OPERATOR_FINISHED;
1463 }
1464
1465 void IMAGE_OT_properties(wmOperatorType *ot)
1466 {
1467         ot->name= "Properties";
1468         ot->idname= "IMAGE_OT_properties";
1469         
1470         ot->exec= image_properties;
1471         ot->poll= ED_operator_image_active;
1472         
1473         /* flags */
1474         ot->flag= 0;
1475 }
1476
1477
1478