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