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