2.5: UI Layout Engine, initial code.
[blender.git] / source / blender / editors / interface / interface_utils.c
1 /**
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation.
19  * All rights reserved.
20  * 
21  * Contributor(s): Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include <math.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_action_types.h"
33 #include "DNA_color_types.h"
34 #include "DNA_listBase.h"
35 #include "DNA_material_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_screen_types.h"
38 #include "DNA_windowmanager_types.h"
39
40 #include "BKE_colortools.h"
41 #include "BKE_context.h"
42 #include "BKE_idprop.h"
43 #include "BKE_library.h"
44 #include "BKE_main.h"
45 #include "BKE_utildefines.h"
46
47 #include "RNA_access.h"
48
49 #include "UI_interface.h"
50 #include "UI_resources.h"
51
52 #include "ED_screen.h"
53 #include "ED_util.h"
54
55 #include "WM_api.h"
56 #include "WM_types.h"
57
58 #define DEF_BUT_WIDTH           150
59 #define DEF_ICON_BUT_WIDTH      20
60 #define DEF_BUT_HEIGHT          20
61
62 /*************************** RNA Utilities ******************************/
63
64 int UI_GetIconRNA(PointerRNA *ptr)
65 {
66         StructRNA *rnatype= ptr->type;
67
68         if(rnatype == &RNA_Scene)
69                 return ICON_SCENE_DATA;
70         else if(rnatype == &RNA_World)
71                 return ICON_WORLD_DATA;
72         else if(rnatype == &RNA_Object)
73                 return ICON_OBJECT_DATA;
74         else if(rnatype == &RNA_Mesh)
75                 return ICON_MESH_DATA;
76         else if(rnatype == &RNA_MeshVertex)
77                 return ICON_VERTEXSEL;
78         else if(rnatype == &RNA_MeshEdge)
79                 return ICON_EDGESEL;
80         else if(rnatype == &RNA_MeshFace)
81                 return ICON_FACESEL;
82         else if(rnatype == &RNA_MeshTextureFace)
83                 return ICON_FACESEL_HLT;
84         else if(rnatype == &RNA_VertexGroup)
85                 return ICON_VGROUP;
86         else if(rnatype == &RNA_VertexGroupElement)
87                 return ICON_VGROUP;
88         else if(rnatype == &RNA_Curve)
89                 return ICON_CURVE_DATA;
90         else if(rnatype == &RNA_MetaBall)
91                 return ICON_MBALL_DATA;
92         else if(rnatype == &RNA_MetaElement)
93                 return ICON_OUTLINER_DATA_META;
94         else if(rnatype == &RNA_Lattice)
95                 return ICON_LATTICE_DATA;
96         else if(rnatype == &RNA_Armature)
97                 return ICON_ARMATURE_DATA;
98         else if(rnatype == &RNA_Bone)
99                 return ICON_BONE_DATA;
100         else if(rnatype == &RNA_Camera)
101                 return ICON_CAMERA_DATA;
102         else if(rnatype == &RNA_LocalLamp)
103                 return ICON_LAMP_DATA;
104         else if(rnatype == &RNA_AreaLamp)
105                 return ICON_LAMP_DATA;
106         else if(rnatype == &RNA_SpotLamp)
107                 return ICON_LAMP_DATA;
108         else if(rnatype == &RNA_SunLamp)
109                 return ICON_LAMP_DATA;
110         else if(rnatype == &RNA_HemiLamp)
111                 return ICON_LAMP_DATA;
112         else if(rnatype == &RNA_Lamp)
113                 return ICON_LAMP_DATA;
114         else if(rnatype == &RNA_Group)
115                 return ICON_GROUP;
116         else if(rnatype == &RNA_ParticleSystem)
117                 return ICON_PARTICLE_DATA;
118         else if(rnatype == &RNA_ParticleSettings)
119                 return ICON_PARTICLE_DATA;
120         else if(rnatype == &RNA_Material)
121                 return ICON_MATERIAL_DATA;
122         else if(rnatype == &RNA_Texture)
123                 return ICON_TEXTURE_DATA;
124         else if(rnatype == &RNA_TextureSlot)
125                 return ICON_TEXTURE_DATA;
126         else if(rnatype == &RNA_WorldTextureSlot)
127                 return ICON_TEXTURE_DATA;
128         else if(rnatype == &RNA_MaterialTextureSlot)
129                 return ICON_TEXTURE_DATA;
130         else if(rnatype == &RNA_Image)
131                 return ICON_IMAGE_DATA;
132         else if(rnatype == &RNA_Screen)
133                 return ICON_SPLITSCREEN;
134         else if(rnatype == &RNA_NodeTree)
135                 return ICON_NODE;
136         else if(rnatype == &RNA_Text)
137                 return ICON_TEXT;
138         else if(rnatype == &RNA_Sound)
139                 return ICON_SOUND;
140         else if(rnatype == &RNA_Brush)
141                 return ICON_BRUSH_DATA;
142         else if(rnatype == &RNA_VectorFont)
143                 return ICON_FONT;
144         else if(rnatype == &RNA_Library)
145                 return ICON_LIBRARY_DATA_DIRECT;
146         else if(rnatype == &RNA_Action)
147                 return ICON_ACTION;
148         else if(rnatype == &RNA_FCurve)
149                 return ICON_ANIM_DATA;
150         //else if(rnatype == &RNA_Ipo)
151         //      return ICON_ANIM_DATA;
152         else if(rnatype == &RNA_Key)
153                 return ICON_SHAPEKEY_DATA;
154         else if(rnatype == &RNA_Main)
155                 return ICON_BLENDER;
156         else if(rnatype == &RNA_Struct)
157                 return ICON_RNA;
158         else if(rnatype == &RNA_Property)
159                 return ICON_RNA;
160         else if(rnatype == &RNA_BooleanProperty)
161                 return ICON_RNA;
162         else if(rnatype == &RNA_IntProperty)
163                 return ICON_RNA;
164         else if(rnatype == &RNA_FloatProperty)
165                 return ICON_RNA;
166         else if(rnatype == &RNA_StringProperty)
167                 return ICON_RNA;
168         else if(rnatype == &RNA_EnumProperty)
169                 return ICON_RNA;
170         else if(rnatype == &RNA_EnumPropertyItem)
171                 return ICON_RNA;
172         else if(rnatype == &RNA_PointerProperty)
173                 return ICON_RNA;
174         else if(rnatype == &RNA_CollectionProperty)
175                 return ICON_RNA;
176         else if(rnatype == &RNA_GameObjectSettings)
177                 return ICON_GAME;
178         else if(rnatype == &RNA_ScriptLink)
179                 return ICON_PYTHON;
180         
181         /* modifiers */
182         else if(rnatype == &RNA_SubsurfModifier)
183                 return ICON_MOD_SUBSURF;
184         else if(rnatype == &RNA_ArmatureModifier)
185                 return ICON_MOD_ARMATURE;
186         else if(rnatype == &RNA_LatticeModifier)
187                 return ICON_MOD_LATTICE;
188         else if(rnatype == &RNA_CurveModifier)
189                 return ICON_MOD_CURVE;
190         else if(rnatype == &RNA_BuildModifier)
191                 return ICON_MOD_BUILD;
192         else if(rnatype == &RNA_MirrorModifier)
193                 return ICON_MOD_MIRROR;
194         else if(rnatype == &RNA_DecimateModifier)
195                 return ICON_MOD_DECIM;
196         else if(rnatype == &RNA_WaveModifier)
197                 return ICON_MOD_WAVE;
198         else if(rnatype == &RNA_HookModifier)
199                 return ICON_HOOK;
200         else if(rnatype == &RNA_SoftbodyModifier)
201                 return ICON_MOD_SOFT;
202         else if(rnatype == &RNA_BooleanModifier)
203                 return ICON_MOD_BOOLEAN;
204         else if(rnatype == &RNA_ParticleInstanceModifier)
205                 return ICON_MOD_PARTICLEINSTANCE;
206         else if(rnatype == &RNA_ParticleSystemModifier)
207                 return ICON_MOD_PARTICLES;
208         else if(rnatype == &RNA_EdgeSplitModifier)
209                 return ICON_MOD_EDGESPLIT;
210         else if(rnatype == &RNA_ArrayModifier)
211                 return ICON_MOD_ARRAY;
212         else if(rnatype == &RNA_UVProjectModifier)
213                 return ICON_MOD_UVPROJECT;
214         else if(rnatype == &RNA_DisplaceModifier)
215                 return ICON_MOD_DISPLACE;
216         else
217                 return ICON_DOT;
218 }
219
220 uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2)
221 {
222         uiBut *but=NULL;
223         const char *propname= RNA_property_identifier(ptr, prop);
224         int arraylen= RNA_property_array_length(ptr, prop);
225
226         switch(RNA_property_type(ptr, prop)) {
227                 case PROP_BOOLEAN: {
228                         int value, length;
229
230                         if(arraylen && index == -1)
231                                 return NULL;
232
233                         length= RNA_property_array_length(ptr, prop);
234
235                         if(length)
236                                 value= RNA_property_boolean_get_index(ptr, prop, index);
237                         else
238                                 value= RNA_property_boolean_get(ptr, prop);
239
240                         if(icon && name && strcmp(name, "") == 0)
241                                 but= uiDefIconButR(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
242                         else if(icon)
243                                 but= uiDefIconTextButR(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
244                         else
245                                 but= uiDefButR(block, TOG, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
246                         break;
247                 }
248                 case PROP_INT:
249                 case PROP_FLOAT:
250                         if(arraylen && index == -1) {
251                                 if(RNA_property_subtype(ptr, prop) == PROP_COLOR)
252                                         but= uiDefButR(block, COL, 0, name, x1, y1, x2, y2, ptr, propname, 0, 0, 0, -1, -1, NULL);
253                         }
254                         else if(RNA_property_subtype(ptr, prop) == PROP_PERCENTAGE)
255                                 but= uiDefButR(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
256                         else
257                                 but= uiDefButR(block, NUM, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
258                         break;
259                 case PROP_ENUM:
260                         but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
261                         break;
262                 case PROP_STRING:
263                         but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
264                         break;
265                 case PROP_POINTER: {
266                         PointerRNA pptr;
267                         PropertyRNA *nameprop;
268                         char *text, *descr, textbuf[256];
269                         int icon;
270
271                         pptr= RNA_property_pointer_get(ptr, prop);
272                         descr= (char*)RNA_property_ui_description(ptr, prop);
273
274                         if(!pptr.type)
275                                 pptr.type= RNA_property_pointer_type(ptr, prop);
276
277                         icon= UI_GetIconRNA(&pptr);
278
279                         if(pptr.data == NULL) {
280                                 but= uiDefIconTextBut(block, LABEL, 0, icon, "", x1, y1, x2, y2, NULL, 0, 0, 0, 0, "");
281                         }
282                         else {
283                                 nameprop= RNA_struct_name_property(&pptr);
284
285                                 if(nameprop) {
286                                         text= RNA_property_string_get_alloc(&pptr, nameprop, textbuf, sizeof(textbuf));
287                                         but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
288                                         if(text != textbuf)
289                                                 MEM_freeN(text);
290                                 }
291                                 else {
292                                         text= (char*)RNA_struct_ui_name(&pptr);
293                                         but= uiDefIconTextBut(block, LABEL, 0, icon, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, descr);
294                                 }
295                         }
296                         break;
297                 }
298                 case PROP_COLLECTION: {
299                         char text[256];
300                         sprintf(text, "%d items", RNA_property_collection_length(ptr, prop));
301                         but= uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
302                         uiButSetFlag(but, UI_BUT_DISABLED);
303                         break;
304                 }
305                 default:
306                         but= NULL;
307                         break;
308         }
309
310         return but;
311 }
312
313 int uiDefAutoButsRNA(uiBlock *block, PointerRNA *ptr)
314 {
315         CollectionPropertyIterator iter;
316         PropertyRNA *iterprop, *prop;
317         PropertySubType subtype;
318         char *name, namebuf[128];
319         int a= 0, length, x= 0, y= 0;
320
321         x= 0;
322         y= 0;
323
324         /* create buttons */
325         uiSetCurFont(block, UI_HELVB);
326         uiDefBut(block, LABEL, 0, (char*)RNA_struct_ui_name(ptr), x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
327         y -= DEF_BUT_HEIGHT;
328         uiSetCurFont(block, UI_HELV);
329
330         iterprop= RNA_struct_iterator_property(ptr);
331         RNA_property_collection_begin(ptr, iterprop, &iter);
332
333         for(; iter.valid; RNA_property_collection_next(&iter)) {
334                 prop= iter.ptr.data;
335
336                 if(strcmp(RNA_property_identifier(ptr, prop), "rna_type") == 0)
337                         continue;
338
339                 if((length= RNA_property_array_length(ptr, prop))) {
340                         name= (char*)RNA_property_ui_name(ptr, prop);
341                         uiDefBut(block, LABEL, 0, name, x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
342                 }
343                 else
344                         length= 1;
345
346                 subtype= RNA_property_subtype(ptr, prop);
347
348                 if(RNA_property_type(ptr, prop) != PROP_BOOLEAN) {
349                         name= (char*)RNA_property_ui_name(ptr, prop);
350                         uiDefBut(block, LABEL, 0, name, x, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1, NULL, 0, 0, 0, 0, "");
351                 }
352
353                 uiBlockBeginAlign(block);
354
355                 if(length <= 16 && subtype == PROP_MATRIX) {
356                         /* matrix layout */
357                         int size, row, col, butwidth;
358
359                         size= ceil(sqrt(length));
360                         butwidth= DEF_BUT_WIDTH*2/size;
361                         y -= DEF_BUT_HEIGHT;
362
363                         for(a=0; a<length; a++) {
364                                 col= a%size;
365                                 row= a/size;
366
367                                 uiDefAutoButR(block, ptr, prop, a, "", 0, x+butwidth*col, y-row*DEF_BUT_HEIGHT, butwidth, DEF_BUT_HEIGHT-1);
368                         }
369
370                         y -= DEF_BUT_HEIGHT*(length/size);
371                 }
372                 else if(length <= 4 && ELEM3(subtype, PROP_ROTATION, PROP_VECTOR, PROP_COLOR)) {
373                         static char *vectoritem[4]= {"X:", "Y:", "Z:", "W:"};
374                         static char *quatitem[4]= {"W:", "X:", "Y:", "Z:"};
375                         static char *coloritem[4]= {"R:", "G:", "B:", "A:"};
376                         int butwidth;
377
378                         butwidth= DEF_BUT_WIDTH*2/length;
379                         y -= DEF_BUT_HEIGHT;
380
381                         for(a=0; a<length; a++) {
382                                 if(length == 4 && subtype == PROP_ROTATION)
383                                         name= quatitem[a];
384                                 else if(subtype == PROP_VECTOR || subtype == PROP_ROTATION)
385                                         name= vectoritem[a];
386                                 else
387                                         name= coloritem[a];
388
389                                 uiDefAutoButR(block, ptr, prop, a, name, 0, x+butwidth*a, y, butwidth, DEF_BUT_HEIGHT-1);
390                         }
391                         y -= DEF_BUT_HEIGHT;
392                 }
393                 else {
394                         if(RNA_property_array_length(ptr, prop)) {
395                                 sprintf(namebuf, "%d:", a+1);
396                                 name= namebuf;
397                         }
398                         else if(RNA_property_type(ptr, prop) == PROP_BOOLEAN)
399                                 name= (char*)RNA_property_ui_name(ptr, prop);
400                         else
401                                 name= "";
402
403                         uiDefAutoButR(block, ptr, prop, 0, name, 0, x+DEF_BUT_WIDTH, y, DEF_BUT_WIDTH, DEF_BUT_HEIGHT-1);
404                         y -= DEF_BUT_HEIGHT;
405                 }
406
407                 uiBlockEndAlign(block);
408         }
409
410         RNA_property_collection_end(&iter);
411
412         return -y;
413 }
414
415 /***************************** ID Utilities *******************************/
416
417 typedef struct uiIDPoinParams {
418         uiIDPoinFunc func;
419         ID *id;
420         short id_code;
421         short browsenr;
422 } uiIDPoinParams;
423
424 static void idpoin_cb(bContext *C, void *arg_params, void *arg_event)
425 {
426         Main *bmain;
427         ListBase *lb;
428         uiIDPoinParams *params= (uiIDPoinParams*)arg_params;
429         uiIDPoinFunc func= params->func;
430         ID *id= params->id, *idtest;
431         int nr, event= GET_INT_FROM_POINTER(arg_event);
432
433         bmain= CTX_data_main(C);
434         lb= wich_libbase(bmain, params->id_code);
435         
436         if(event == UI_ID_BROWSE && params->browsenr == 32767)
437                 event= UI_ID_ADD_NEW;
438         else if(event == UI_ID_BROWSE && params->browsenr == 32766)
439                 event= UI_ID_OPEN;
440
441         switch(event) {
442                 case UI_ID_RENAME:
443                         if(id) test_idbutton(id->name+2);
444                         else return;
445                         break;
446                 case UI_ID_BROWSE: {
447                         if(id==0) id= lb->first;
448                         if(id==0) return;
449
450                         if(params->browsenr== -2) {
451                                 /* XXX implement or find a replacement
452                                  * activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, &params->browsenr, do_global_buttons); */
453                                 return;
454                         }
455                         if(params->browsenr < 0)
456                                 return;
457
458                         for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) {
459                                 if(nr==params->browsenr) {
460                                         if(id == idtest)
461                                                 return;
462
463                                         id= idtest;
464
465                                         break;
466                                 }
467                         }
468                         break;
469                 }
470                 case UI_ID_DELETE:
471                         id= NULL;
472                         break;
473                 case UI_ID_FAKE_USER:
474                         if(id) {
475                                 if(id->flag & LIB_FAKEUSER) id->us++;
476                                 else id->us--;
477                         }
478                         else return;
479                         break;
480                 case UI_ID_PIN:
481                         break;
482                 case UI_ID_ADD_NEW:
483                         break;
484                 case UI_ID_OPEN:
485                         break;
486                 case UI_ID_ALONE:
487                         if(!id || id->us < 1)
488                                 return;
489                         break;
490                 case UI_ID_LOCAL:
491                         if(!id || id->us < 1)
492                                 return;
493                         break;
494                 case UI_ID_AUTO_NAME:
495                         break;
496         }
497
498         if(func)
499                 func(C, id, event);
500 }
501
502 int uiDefIDPoinButs(uiBlock *block, Main *bmain, ID *parid, ID *id, int id_code, short *pin_p, int x, int y, uiIDPoinFunc func, int events)
503 {
504         ListBase *lb;
505         uiBut *but;
506         uiIDPoinParams *params, *dup_params;
507         char *str=NULL, str1[10];
508         int len, oldcol, add_addbutton=0;
509
510         /* setup struct that we will pass on with the buttons */
511         params= MEM_callocN(sizeof(uiIDPoinParams), "uiIDPoinParams");
512         params->id= id;
513         params->id_code= id_code;
514         params->func= func;
515
516         lb= wich_libbase(bmain, id_code);
517
518         /* create buttons */
519         uiBlockBeginAlign(block);
520         oldcol= uiBlockGetCol(block);
521
522         if(id && id->us>1)
523                 uiBlockSetCol(block, TH_BUT_SETTING1);
524
525         if((events & UI_ID_PIN) && *pin_p)
526                 uiBlockSetCol(block, TH_BUT_SETTING2);
527
528         /* pin button */
529         if(id && (events & UI_ID_PIN)) {
530                 but= uiDefIconButS(block, ICONTOG, (events & UI_ID_PIN), ICON_KEY_DEHLT, x, y ,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, pin_p, 0, 0, 0, 0, "Keeps this view displaying the current data regardless of what object is selected");
531                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_PIN));
532                 x+= DEF_ICON_BUT_WIDTH;
533         }
534
535         /* browse menu */
536         if(events & UI_ID_BROWSE) {
537                 char *extrastr= NULL;
538                 
539                 if(ELEM4(id_code, ID_MA, ID_TE, ID_BR, ID_PA))
540                         add_addbutton= 1;
541                 
542                 if(ELEM8(id_code, ID_SCE, ID_SCR, ID_MA, ID_TE, ID_WO, ID_IP, ID_AC, ID_BR) || id_code == ID_PA)
543                         extrastr= "ADD NEW %x 32767";
544                 else if(id_code==ID_TXT)
545                         extrastr= "OPEN NEW %x 32766 |ADD NEW %x 32767";
546                 else if(id_code==ID_SO)
547                         extrastr= "OPEN NEW %x 32766";
548
549                 /* XXX should be moved out of this function
550                 uiBlockSetButLock(block, G.scene->id.lib!=0, "Can't edit external libdata");
551                 if( id_code==ID_SCE || id_code==ID_SCR ) uiBlockClearButLock(block); */
552                 
553                 /* XXX should be moved out of this function
554                 if(curarea->spacetype==SPACE_BUTS)
555                         uiBlockSetButLock(block, id_code!=ID_SCR && G.obedit!=0 && G.buts->mainb==CONTEXT_EDITING, "Cannot perform in EditMode"); */
556                 
557                 if(parid)
558                         uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata");
559
560                 if(lb) {
561                         if(id_code!=ID_IM || (events & UI_ID_BROWSE_RENDER))
562                                 IDnames_to_pupstring(&str, NULL, extrastr, lb, id, &params->browsenr);
563                         else
564                                 IMAnames_to_pupstring(&str, NULL, extrastr, lb, id, &params->browsenr);
565                 }
566
567                 dup_params= MEM_dupallocN(params);
568                 but= uiDefButS(block, MENU, 0, str, x, y, DEF_ICON_BUT_WIDTH, DEF_BUT_HEIGHT, &dup_params->browsenr, 0, 0, 0, 0, "Browse existing choices, or add new");
569                 uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_BROWSE));
570                 x+= DEF_ICON_BUT_WIDTH;
571                 
572                 uiBlockClearButLock(block);
573         
574                 MEM_freeN(str);
575         }
576
577         uiBlockSetCol(block, oldcol);
578
579         /* text button with name */
580         if(id) {
581                 /* name */
582                 if(id->us > 1)
583                         uiBlockSetCol(block, TH_BUT_SETTING1);
584
585                 /* pinned data? */
586                 if((events & UI_ID_PIN) && *pin_p)
587                         uiBlockSetCol(block, TH_BUT_SETTING2);
588
589                 /* redalert overrides pin color */
590                 if(id->us<=0)
591                         uiBlockSetCol(block, TH_REDALERT);
592
593                 uiBlockSetButLock(block, id->lib!=0, "Can't edit external libdata");
594                 
595                 /* name button */
596                 if(GS(id->name)==ID_SCE)
597                         strcpy(str1, "SCE:");
598                 else if(GS(id->name)==ID_SCE)
599                         strcpy(str1, "SCR:");
600                 else if(GS(id->name)==ID_MA && ((Material*)id)->use_nodes)
601                         strcpy(str1, "NT:");
602                 else {
603                         str1[0]= id->name[0];
604                         str1[1]= id->name[1];
605                         str1[2]= ':';
606                         str1[3]= 0;
607                 }
608                 
609                 if(GS(id->name)==ID_IP) len= 110;
610                 else if((y) && (GS(id->name)==ID_AC)) len= 100; // comes from button panel (poselib)
611                 else if(y) len= 140;    // comes from button panel
612                 else len= 120;
613                 
614                 but= uiDefBut(block, TEX, 0, str1,x, y, (short)len, DEF_BUT_HEIGHT, id->name+2, 0.0, 21.0, 0, 0, "Displays current Datablock name. Click to change.");
615                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_RENAME));
616
617                 x+= len;
618
619                 uiBlockClearButLock(block);
620                 
621                 /* lib make local button */
622                 if(id->lib) {
623                         if(id->flag & LIB_INDIRECT) uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_DATALIB */,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Indirect Library Datablock. Cannot change.");
624                         else {
625                                 but= uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_PARLIB */, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, 
626                                                           (events & UI_ID_LOCAL)? "Direct linked Library Datablock. Click to make local.": "Direct linked Library Datablock, cannot make local.");
627                                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
628                         }
629                         
630                         x+= DEF_ICON_BUT_WIDTH;
631                 }
632                 
633                 /* number of users / make local button */
634                 if((events & UI_ID_ALONE) && id->us>1) {
635                         int butwidth;
636
637                         uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't make pinned data single-user");
638                         
639                         sprintf(str1, "%d", id->us);
640                         butwidth= (id->us<10)? DEF_ICON_BUT_WIDTH: DEF_ICON_BUT_WIDTH+10;
641
642                         but= uiDefBut(block, BUT, 0, str1, x, y, butwidth, DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
643                         uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
644                         x+= butwidth;
645                         
646                         uiBlockClearButLock(block);
647                 }
648                 
649                 /* delete button */
650                 if(events & UI_ID_DELETE) {
651                         uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't unlink pinned data");
652                         if(parid && parid->lib);
653                         else {
654                                 but= uiDefIconBut(block, BUT, 0, ICON_X, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Deletes link to this Datablock");
655                                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_DELETE));
656                                 x+= DEF_ICON_BUT_WIDTH;
657                         }
658                         
659                         uiBlockClearButLock(block);
660                 }
661
662                 /* auto name button */
663                 if(events & UI_ID_AUTO_NAME) {
664                         if(parid && parid->lib);
665                         else {
666                                 but= uiDefIconBut(block, BUT, 0, ICON_AUTO,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Generates an automatic name");
667                                 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_AUTO_NAME));
668                                 x+= DEF_ICON_BUT_WIDTH;
669                         }
670                 }
671
672                 /* fake user button */
673                 if(events & UI_ID_FAKE_USER) {
674                         but= uiDefButBitS(block, TOG, LIB_FAKEUSER, 0, "F", x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, &id->flag, 0, 0, 0, 0, "Saves this datablock even if it has no users");
675                         uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_FAKE_USER));
676                         x+= DEF_ICON_BUT_WIDTH;
677                 }
678         }
679         /* add new button */
680         else if(add_addbutton) {
681                 uiBlockSetCol(block, oldcol);
682                 if(parid) uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata");
683                 dup_params= MEM_dupallocN(params);
684                 but= uiDefButS(block, TOG, 0, "Add New", x, y, 110, DEF_BUT_HEIGHT, &dup_params->browsenr, params->browsenr, 32767.0, 0, 0, "Add new data block");
685                 uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_ADD_NEW));
686                 x+= 110;
687         }
688         
689         uiBlockSetCol(block, oldcol);
690         uiBlockEndAlign(block);
691
692         MEM_freeN(params);
693
694         return x;
695 }
696
697 /* ****************************** default button callbacks ******************* */
698 /* ************ LEGACY WARNING, only to get things work with 2.48 code! ****** */
699
700 void test_idbutton_cb(struct bContext *C, void *namev, void *arg2)
701 {
702         char *name= namev;
703         
704         test_idbutton(name+2);
705 }
706
707
708 void test_scriptpoin_but(struct bContext *C, char *name, ID **idpp)
709 {
710         ID *id;
711         
712         id= CTX_data_main(C)->text.first;
713         while(id) {
714                 if( strcmp(name, id->name+2)==0 ) {
715                         *idpp= id;
716                         return;
717                 }
718                 id= id->next;
719         }
720         *idpp= NULL;
721 }
722
723 void test_actionpoin_but(struct bContext *C, char *name, ID **idpp)
724 {
725         ID *id;
726         
727         id= CTX_data_main(C)->action.first;
728         while(id) {
729                 if( strcmp(name, id->name+2)==0 ) {
730                         id_us_plus(id);
731                         *idpp= id;
732                         return;
733                 }
734                 id= id->next;
735         }
736         *idpp= NULL;
737 }
738
739
740 void test_obpoin_but(struct bContext *C, char *name, ID **idpp)
741 {
742         ID *id;
743         
744 // XXX  if(idpp == (ID **)&(emptytex.object)) {
745 //              error("You must add a texture first");
746 //              *idpp= 0;
747 //              return;
748 //      }
749         
750         id= CTX_data_main(C)->object.first;
751         while(id) {
752                 if( strcmp(name, id->name+2)==0 ) {
753                         *idpp= id;
754                         id_lib_extern(id);      /* checks lib data, sets correct flag for saving then */
755                         return;
756                 }
757                 id= id->next;
758         }
759         *idpp= NULL;
760 }
761
762 /* tests for an object of type OB_MESH */
763 void test_meshobpoin_but(struct bContext *C, char *name, ID **idpp)
764 {
765         ID *id;
766
767         id = CTX_data_main(C)->object.first;
768         while(id) {
769                 Object *ob = (Object *)id;
770                 if(ob->type == OB_MESH && strcmp(name, id->name + 2) == 0) {
771                         *idpp = id;
772                         /* checks lib data, sets correct flag for saving then */
773                         id_lib_extern(id);
774                         return;
775                 }
776                 id = id->next;
777         }
778         *idpp = NULL;
779 }
780
781 void test_meshpoin_but(struct bContext *C, char *name, ID **idpp)
782 {
783         ID *id;
784
785         if( *idpp ) (*idpp)->us--;
786         
787         id= CTX_data_main(C)->mesh.first;
788         while(id) {
789                 if( strcmp(name, id->name+2)==0 ) {
790                         *idpp= id;
791                         id_us_plus(id);
792                         return;
793                 }
794                 id= id->next;
795         }
796         *idpp= NULL;
797 }
798
799 void test_matpoin_but(struct bContext *C, char *name, ID **idpp)
800 {
801         ID *id;
802
803         if( *idpp ) (*idpp)->us--;
804         
805         id= CTX_data_main(C)->mat.first;
806         while(id) {
807                 if( strcmp(name, id->name+2)==0 ) {
808                         *idpp= id;
809                         id_us_plus(id);
810                         return;
811                 }
812                 id= id->next;
813         }
814         *idpp= NULL;
815 }
816
817 void test_scenepoin_but(struct bContext *C, char *name, ID **idpp)
818 {
819         ID *id;
820         
821         if( *idpp ) (*idpp)->us--;
822         
823         id= CTX_data_main(C)->scene.first;
824         while(id) {
825                 if( strcmp(name, id->name+2)==0 ) {
826                         *idpp= id;
827                         id_us_plus(id);
828                         return;
829                 }
830                 id= id->next;
831         }
832         *idpp= NULL;
833 }
834
835 void test_grouppoin_but(struct bContext *C, char *name, ID **idpp)
836 {
837         ID *id;
838         
839         if( *idpp ) (*idpp)->us--;
840         
841         id= CTX_data_main(C)->group.first;
842         while(id) {
843                 if( strcmp(name, id->name+2)==0 ) {
844                         *idpp= id;
845                         id_us_plus(id);
846                         return;
847                 }
848                 id= id->next;
849         }
850         *idpp= NULL;
851 }
852
853 void test_texpoin_but(struct bContext *C, char *name, ID **idpp)
854 {
855         ID *id;
856         
857         if( *idpp ) (*idpp)->us--;
858         
859         id= CTX_data_main(C)->tex.first;
860         while(id) {
861                 if( strcmp(name, id->name+2)==0 ) {
862                         *idpp= id;
863                         id_us_plus(id);
864                         return;
865                 }
866                 id= id->next;
867         }
868         *idpp= NULL;
869 }
870
871 void test_imapoin_but(struct bContext *C, char *name, ID **idpp)
872 {
873         ID *id;
874         
875         if( *idpp ) (*idpp)->us--;
876         
877         id= CTX_data_main(C)->image.first;
878         while(id) {
879                 if( strcmp(name, id->name+2)==0 ) {
880                         *idpp= id;
881                         id_us_plus(id);
882                         return;
883                 }
884                 id= id->next;
885         }
886         *idpp= NULL;
887 }
888
889 /* autocomplete callback for  buttons */
890 void autocomplete_bone(struct bContext *C, char *str, void *arg_v)
891 {
892         Object *ob= (Object *)arg_v;
893         
894         if(ob==NULL || ob->pose==NULL) return;
895         
896         /* search if str matches the beginning of name */
897         if(str[0]) {
898                 AutoComplete *autocpl= autocomplete_begin(str, 32);
899                 bPoseChannel *pchan;
900                 
901                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
902                         autocomplete_do_name(autocpl, pchan->name);
903                 
904                 autocomplete_end(autocpl, str);
905         }
906 }
907
908 /* autocomplete callback for buttons */
909 void autocomplete_vgroup(struct bContext *C, char *str, void *arg_v)
910 {
911         Object *ob= (Object *)arg_v;
912         
913         if(ob==NULL) return;
914         
915         /* search if str matches the beginning of a name */
916         if(str[0]) {
917                 AutoComplete *autocpl= autocomplete_begin(str, 32);
918                 bDeformGroup *dg;
919                 
920                 for(dg= ob->defbase.first; dg; dg= dg->next)
921                         if(dg->name!=str)
922                                 autocomplete_do_name(autocpl, dg->name);
923                 
924                 autocomplete_end(autocpl, str);
925         }
926 }
927
928
929 /* ----------- custom button group ---------------------- */
930
931 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused)
932 {
933         CurveMapping *cumap = cumap_v;
934         float d;
935         
936         /* we allow 20 times zoom */
937         if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
938                 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
939                 cumap->curr.xmin+= d;
940                 cumap->curr.xmax-= d;
941                 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
942                 cumap->curr.ymin+= d;
943                 cumap->curr.ymax-= d;
944         }
945 }
946
947 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused)
948 {
949         CurveMapping *cumap = cumap_v;
950         float d, d1;
951         
952         /* we allow 20 times zoom, but dont view outside clip */
953         if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
954                 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
955                 
956                 if(cumap->flag & CUMA_DO_CLIP) 
957                         if(cumap->curr.xmin-d < cumap->clipr.xmin)
958                                 d1= cumap->curr.xmin - cumap->clipr.xmin;
959                 cumap->curr.xmin-= d1;
960                 
961                 d1= d;
962                 if(cumap->flag & CUMA_DO_CLIP) 
963                         if(cumap->curr.xmax+d > cumap->clipr.xmax)
964                                 d1= -cumap->curr.xmax + cumap->clipr.xmax;
965                 cumap->curr.xmax+= d1;
966                 
967                 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
968                 
969                 if(cumap->flag & CUMA_DO_CLIP) 
970                         if(cumap->curr.ymin-d < cumap->clipr.ymin)
971                                 d1= cumap->curr.ymin - cumap->clipr.ymin;
972                 cumap->curr.ymin-= d1;
973                 
974                 d1= d;
975                 if(cumap->flag & CUMA_DO_CLIP) 
976                         if(cumap->curr.ymax+d > cumap->clipr.ymax)
977                                 d1= -cumap->curr.ymax + cumap->clipr.ymax;
978                 cumap->curr.ymax+= d1;
979         }
980 }
981
982 static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused)
983 {
984         CurveMapping *cumap = cumap_v;
985         
986         curvemapping_changed(cumap, 0);
987 }       
988
989 static void curvemap_buttons_delete(bContext *C, void *cumap_v, void *unused)
990 {
991         CurveMapping *cumap = cumap_v;
992         
993         curvemap_remove(cumap->cm+cumap->cur, SELECT);
994         curvemapping_changed(cumap, 0);
995 }
996
997 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
998 static uiBlock *curvemap_clipping_func(struct bContext *C, struct ARegion *ar, void *cumap_v)
999 {
1000         CurveMapping *cumap = cumap_v;
1001         uiBlock *block;
1002         uiBut *bt;
1003         
1004         block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS, UI_HELV);
1005         
1006         /* use this for a fake extra empy space around the buttons */
1007         uiDefBut(block, LABEL, 0, "",                   -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
1008         
1009         bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",    
1010                                                                                 0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
1011         uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1012
1013         uiBlockBeginAlign(block);
1014         uiDefButF(block, NUM, 0, "Min X ",       0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
1015         uiDefButF(block, NUM, 0, "Min Y ",       0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
1016         uiDefButF(block, NUM, 0, "Max X ",       0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
1017         uiDefButF(block, NUM, 0, "Max Y ",       0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
1018         
1019         uiBlockSetDirection(block, UI_RIGHT);
1020         
1021         uiEndBlock(C, block);
1022         return block;
1023 }
1024
1025
1026 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1027 {
1028         CurveMapping *cumap = cumap_v;
1029         CurveMap *cuma= cumap->cm+cumap->cur;
1030         
1031         switch(event) {
1032                 case 0:
1033                         curvemap_reset(cuma, &cumap->clipr);
1034                         curvemapping_changed(cumap, 0);
1035                         break;
1036                 case 1:
1037                         cumap->curr= cumap->clipr;
1038                         break;
1039                 case 2: /* set vector */
1040                         curvemap_sethandle(cuma, 1);
1041                         curvemapping_changed(cumap, 0);
1042                         break;
1043                 case 3: /* set auto */
1044                         curvemap_sethandle(cuma, 0);
1045                         curvemapping_changed(cumap, 0);
1046                         break;
1047                 case 4: /* extend horiz */
1048                         cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1049                         curvemapping_changed(cumap, 0);
1050                         break;
1051                 case 5: /* extend extrapolate */
1052                         cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1053                         curvemapping_changed(cumap, 0);
1054                         break;
1055         }
1056         ED_region_tag_redraw(CTX_wm_region(C));
1057 }
1058
1059 static uiBlock *curvemap_tools_func(struct bContext *C, struct ARegion *ar, void *cumap_v)
1060 {
1061         uiBlock *block;
1062         short yco= 0, menuwidth=120;
1063         
1064         block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSSP, UI_HELV);
1065         uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1066         
1067         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
1068         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
1069         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
1070         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
1071         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated",    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
1072         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
1073         
1074         uiBlockSetDirection(block, UI_RIGHT);
1075         uiTextBoundsBlock(block, 50);
1076         
1077         uiEndBlock(C, block);
1078         return block;
1079 }
1080
1081 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1082 void curvemap_buttons(uiBlock *block, CurveMapping *cumap, char labeltype, short event, short redraw, rctf *rect)
1083 {
1084         uiBut *bt;
1085         float dx, fy= rect->ymax-18.0f;
1086         int icon;
1087         short xco, yco;
1088         
1089         yco= (short)(rect->ymax-18.0f);
1090         
1091         /* curve choice options + tools/settings, 8 icons + spacer */
1092         dx= (rect->xmax-rect->xmin)/(9.0f);
1093         
1094         uiBlockBeginAlign(block);
1095         if(labeltype=='v') {    /* vector */
1096                 xco= (short)rect->xmin;
1097                 if(cumap->cm[0].curve)
1098                         uiDefButI(block, ROW, redraw, "X", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1099                 xco= (short)(rect->xmin+1.0f*dx);
1100                 if(cumap->cm[1].curve)
1101                         uiDefButI(block, ROW, redraw, "Y", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1102                 xco= (short)(rect->xmin+2.0f*dx);
1103                 if(cumap->cm[2].curve)
1104                         uiDefButI(block, ROW, redraw, "Z", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1105         }
1106         else if(labeltype=='c') { /* color */
1107                 xco= (short)rect->xmin;
1108                 if(cumap->cm[3].curve)
1109                         uiDefButI(block, ROW, redraw, "C", xco, yco+2, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1110                 xco= (short)(rect->xmin+1.0f*dx);
1111                 if(cumap->cm[0].curve)
1112                         uiDefButI(block, ROW, redraw, "R", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1113                 xco= (short)(rect->xmin+2.0f*dx);
1114                 if(cumap->cm[1].curve)
1115                         uiDefButI(block, ROW, redraw, "G", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1116                 xco= (short)(rect->xmin+3.0f*dx);
1117                 if(cumap->cm[2].curve)
1118                         uiDefButI(block, ROW, redraw, "B", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1119         }
1120         /* else no channels ! */
1121         uiBlockEndAlign(block);
1122
1123         xco= (short)(rect->xmin+4.5f*dx);
1124         uiBlockSetEmboss(block, UI_EMBOSSN);
1125         bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMIN, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
1126         uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1127         
1128         xco= (short)(rect->xmin+5.25f*dx);
1129         bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMOUT, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
1130         uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1131         
1132         xco= (short)(rect->xmin+6.0f*dx);
1133         bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, event, ICON_MODIFIER, xco, yco, dx, 18, "Tools");
1134         
1135         xco= (short)(rect->xmin+7.0f*dx);
1136         if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1137         bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, event, icon, xco, yco, dx, 18, "Clipping Options");
1138         
1139         xco= (short)(rect->xmin+8.0f*dx);
1140         bt= uiDefIconBut(block, BUT, event, ICON_X, xco, yco, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
1141         uiButSetFunc(bt, curvemap_buttons_delete, cumap, NULL);
1142         
1143         uiBlockSetEmboss(block, UI_EMBOSS);
1144         
1145         uiDefBut(block, BUT_CURVE, event, "", 
1146                           rect->xmin, rect->ymin, rect->xmax-rect->xmin, fy-rect->ymin, 
1147                           cumap, 0.0f, 1.0f, 0, 0, "");
1148 }
1149