Update MSVC project files
[blender.git] / source / blender / src / buttons_editing.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <time.h>
31 #include <math.h>
32 #include <stdlib.h>
33 #include <stddef.h>
34 #include <string.h>
35
36 #ifdef WIN32
37 #ifndef snprintf
38 #define snprintf _snprintf
39 #endif
40 #endif
41
42 #include "MEM_guardedalloc.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_space_types.h"
45 #include "DNA_scene_types.h"
46
47 #include "DNA_action_types.h"
48 #include "DNA_armature_types.h"
49 #include "DNA_brush_types.h"
50 #include "DNA_camera_types.h"
51 #include "DNA_cloth_types.h"
52 #include "DNA_color_types.h"
53 #include "DNA_constraint_types.h"
54 #include "DNA_curve_types.h"
55 #include "DNA_effect_types.h"
56 #include "DNA_group_types.h"
57 #include "DNA_key_types.h"
58 #include "DNA_lamp_types.h"
59 #include "DNA_lattice_types.h"
60 #include "DNA_material_types.h"
61 #include "DNA_meta_types.h"
62 #include "DNA_mesh_types.h"
63 #include "DNA_meshdata_types.h"
64 #include "DNA_modifier_types.h"
65 #include "DNA_nla_types.h"
66 #include "DNA_object_types.h"
67 #include "DNA_object_force.h"
68 #include "DNA_particle_types.h"
69 #include "DNA_radio_types.h"
70 #include "DNA_screen_types.h"
71 #include "DNA_texture_types.h"
72 #include "DNA_userdef_types.h"
73 #include "DNA_vfont_types.h"
74 #include "DNA_view3d_types.h"
75 #include "DNA_world_types.h"
76 #include "DNA_packedFile_types.h"
77
78 #include "BKE_blender.h"
79 #include "BKE_brush.h"
80 #include "BKE_cloth.h"
81 #include "BKE_curve.h"
82 #include "BKE_customdata.h"
83 #include "BKE_colortools.h"
84 #include "BKE_deform.h"
85 #include "BKE_depsgraph.h"
86 #include "BKE_global.h"
87 #include "BKE_key.h"
88 #include "BKE_library.h"
89 #include "BKE_main.h"
90 #include "BKE_mesh.h"
91 #include "BKE_modifier.h"
92 #include "BKE_multires.h"
93 #include "BKE_packedFile.h"
94 #include "BKE_particle.h"
95 #include "BKE_scene.h"
96 #include "BKE_bmesh.h"
97
98 #include "BLI_blenlib.h"
99 #include "BLI_arithb.h"
100 #include "BLI_vfontdata.h"
101 #include "BLI_editVert.h"
102 #include "BLI_dynstr.h"
103
104 #include "BSE_filesel.h"
105
106 #include "BIF_gl.h"
107 #include "BIF_editaction.h"
108 #include "BIF_editarmature.h"
109 #include "BIF_editconstraint.h"
110 #include "BIF_editdeform.h"
111 #include "BIF_editfont.h"
112 #include "BIF_editkey.h"
113 #include "BIF_editmesh.h"
114 #include "BIF_editparticle.h"
115 #include "BIF_imasel.h"
116 #include "BIF_interface.h"
117 #include "BIF_meshtools.h"
118 #include "BIF_mywindow.h"
119 #include "BIF_poselib.h"
120 #include "BIF_poseobject.h"
121 #include "BIF_renderwin.h"
122 #include "BIF_resources.h"
123 #include "BIF_retopo.h"
124 #include "BIF_screen.h"
125 #include "BIF_scrarea.h"
126 #include "BIF_space.h"
127 #include "BIF_toets.h"
128 #include "BIF_toolbox.h"
129 #include "BIF_previewrender.h"
130 #include "BIF_butspace.h"
131
132 #ifdef WITH_VERSE
133 #include "BIF_verse.h"
134 #endif
135
136 #include "mydevice.h"
137 #include "blendef.h"
138
139 #include "BKE_action.h"
140 #include "BKE_anim.h"
141 #include "BKE_armature.h"
142 #include "BKE_constraint.h"
143 #include "BKE_curve.h"
144 #include "BKE_displist.h"
145 #include "BKE_DerivedMesh.h"
146 #include "BKE_effect.h"
147 #include "BKE_font.h"
148 #include "BKE_icons.h"
149 #include "BKE_image.h"
150 #include "BKE_ipo.h"
151 #include "BKE_lattice.h"
152 #include "BKE_material.h"
153 #include "BKE_mball.h"
154 #include "BKE_mesh.h"
155 #include "BKE_object.h"
156 #include "BKE_texture.h"
157 #include "BKE_utildefines.h"
158
159 #include "BIF_poseobject.h"
160
161 #include "BDR_drawobject.h"
162 #include "BDR_editcurve.h"
163 #include "BDR_editface.h"
164 #include "BDR_editobject.h"
165 #include "BDR_sculptmode.h"
166 #include "BDR_vpaint.h"
167 #include "BDR_unwrapper.h"
168
169 #include "BSE_drawview.h"
170 #include "BSE_editipo.h"
171 #include "BSE_edit.h"
172 #include "BSE_filesel.h"
173 #include "BSE_headerbuttons.h"
174 #include "BSE_trans_types.h"
175 #include "BSE_view.h"
176 #include "BSE_seqaudio.h"
177
178 #include "RE_render_ext.h"              // make_sticky
179
180 #include "butspace.h" // own module
181 #include "multires.h"
182
183 static float editbutweight= 1.0;
184 float editbutvweight= 1;
185 static int actmcol= 0, acttface= 0, acttface_rnd = 0, actmcol_rnd = 0;
186
187 extern ListBase editNurb;
188
189 /* *************************** Unicode Character Groups ****************** */
190 unicodect uctabname[125] = {
191         {"All", "All", 0x0000, 0xffff},
192         {"Basic Latin", "Basic Latin", 0x0000, 0x007f},
193         {"Latin 1 Supp", "Latin-1 Supplement", 0x0080, 0x00ff}, 
194
195         {"Latin Ext. A.", "Latin Extended-A", 0x0100, 0x017F},
196         {"Latin Ext. B.", "Latin Extended-B", 0x0180,0x024F}, 
197         {"Latin Ext. Add.", "Latin Extended Additional", 0x1e00, 0x1eff},
198
199         {"IPA Ext", "IPA Extensions", 0x0250, 0x02AF},
200         {"Spacing Mod.", "Spacing Modifier Letters", 0x02b0, 0x02ff},
201
202         {"Comb. Dia.", "Combining Diacritical Marks", 0x0300, 0x036F},
203         {"Greek, Coptic", "Greek and Coptic", 0x0370, 0x03ff},
204         {"Greek Ext.", "Greek Extended", 0x1f00, 0x1fff},
205
206         {"Cyrillic", "Cyrillic", 0x0400, 0x04ff},
207         {"Cyrillic Supp.", "Cyrillic Supplementary", 0x0500, 0x052f},
208
209         {"Armenian", "Armenian", 0x0530, 0x058f},
210         {"Hebrew", "Hebrew", 0x0590, 0x05ff},
211
212         
213         {"Arabic", "Arabic", 0x0600, 0x06ff},
214         {"Syriac", "Syriac", 0x0700, 0x074f},
215
216         {"Thaana", "Thaana", 0x0780, 0x07bf},
217         {"Devanagari", "Devanagari", 0x0900, 0x097f},
218
219         {"Bengali", "Bengali", 0x0980, 0x09ff},
220         {"Gurmukhi", "Gurmukhi", 0x0a00, 0x0a7f},
221
222         {"Gujarati", "Gujarati", 0x0a80, 0x0aff},
223         {"Oriya", "Oriya", 0x0b00, 0x0b7f},
224
225         {"Tamil", "Tamil", 0x0b80, 0x0bff},
226         {"Tegulu", "Tegulu", 0x0c00, 0x0c7f},
227
228         {"Kannada", "Kannada", 0x0c80, 0x0cff},
229         {"Malayalam", "Malayalam", 0x0d00, 0x0d7f},
230
231         {"Sinhala", "Sinhala", 0x0d80, 0x0dff},
232         {"Thai", "Thai", 0x0e00, 0x0e7f},
233
234         {"Lao", "Lao", 0x0e80, 0x0eff},
235         {"Tibetan", "Tibetan", 0x0f00, 0x0fff},
236
237         {"Myanmar", "Myanmar", 0x1000, 0x109f},
238         {"Georgian", "Georgian", 0x10a0, 0x10ff},
239
240         {"Ethiopic", "Ethiopic", 0x1200, 0x137f},
241
242         {"Cherokee", "Cherokee", 0x13a0, 0x13ff},
243         {"Unif. Canadian", "Unified Canadian Aboriginal Syllabics", 0x1400, 0x167f},
244
245         {"Ogham", "Ogham", 0x1680, 0x169f},
246         {"Runic", "Runic", 0x16a0, 0x16ff},
247
248         {"Tagalog", "Tagalog", 0x1700, 0x171f},
249         {"Hanunoo", "Hanunoo", 0x1720, 0x173f},
250
251         {"Buhid", "Buhid", 0x1740, 0x175f},
252         {"Tagbanwa", "Tagbanwa", 0x1760, 0x177f},
253
254         {"Khmer", "Khmer", 0x1780, 0x17ff},
255         {"Khmer Symb", "Khmer Symbols", 0x19e0, 0x19ff},
256
257         {"Mongolian", "Mongolian", 0x1800, 0x18af},
258
259         {"Limbu", "Limbu", 0x1900, 0x194f},
260         {"Tai Le", "Tai Le", 0x1950, 0x197f},
261
262         {"Phon. Ext.", "Phonetic Extensions", 0x1d00, 0x1d7f},
263
264
265         {"Gen. Punct.", "General Punctutation", 0x2000, 0x206f},
266         {"Super, Sub", "Superscripts and Subscripts", 0x2070, 0x209f},
267
268         {"Curr. Symb.", "Currency Symbols", 0x20a0, 0x20cf},
269         {"Comb. Diacrit.", "Combining Diacritical Marks for Symbols", 0x20d0, 0x20ff},
270
271         {"Letter Symb", "Letterlike Symbols", 0x2100, 0x214f},
272         {"Numb. Forms", "Number Forms", 0x2150, 0x218f},
273
274         {"Arrows", "Arrows", 0x2190, 0x21ff},
275         {"Math Oper.", "Mathematical Operators", 0x2200, 0x22ff},
276
277         {"Misc. Tech.", "Miscellaneous Technical", 0x2300, 0x23ff},
278         {"Ctrl. Pict.", "Control Pictures", 0x2400, 0x243f},
279
280         {"OCR", "Optical Character Recognition", 0x2440, 0x245f},
281         {"Enc. Alpha", "Enclosed Alphanumerics", 0x2460, 0x24ff},
282
283         {"Bow Drawing", "Box Drawing", 0x2500, 0x257f},
284         {"BLock Elem.", "Block Elements", 0x2580, 0x259f},
285
286         {"Geom. Shapes", "Geometric Shapes", 0x25a0, 0x25ff},
287         {"Misc. Symb.", "Miscellaneous Symbols", 0x2600, 0x26ff},
288
289         {"Dingbats", "Dingbats", 0x2700, 0x27bf},
290         {"Misc. Math A", "Miscellaneous Mathematical Symbols-A", 0x27c0, 0x27ef},
291
292         {"Supp. Arrows-A", "Supplemental Arrows-A", 0x27f0, 0x27ff},
293         {"Braille Pat.", "Braille Patterns", 0x2800, 0x28ff},
294
295         {"Supp. Arrows-B", "Supplemental Arrows-B", 0x2900, 0x297f},
296         {"Misc. Math B", "Miscellaneous Mathematical Symbols-B", 0x2980, 0x29ff},
297
298         {"Supp. Math Op.", "Supplemental Mathematical Operators", 0x2a00, 0x2aff},
299         {"Misc. Symb.", "Miscellaneous Symbols and Arrows", 0x2b00, 0x2bff},
300
301         {"Kangxi Rad.", "Kangxi Radicals", 0x2f00, 0x2fdf},
302
303         {"Ideographic", "Ideographic Description Characters", 0x2ff0, 0x2fff},
304
305         {"Hiragana", "Hiragana", 0x3040, 0x309f},
306         {"Katakana", "Katakana", 0x30a0, 0x30ff},
307         {"Katakana Ext.", "Katakana Phonetic Extensions", 0x31f0, 0x31ff},
308
309         {"Bopomofo", "Bopomofo", 0x3100, 0x312f},
310         {"Bopomofo Ext.", "Bopomofo Extended", 0x31a0, 0x31bf},
311
312         {"Hangul", "Hangul Jamo", 0x1100, 0x11ff},
313         {"Hangul Comp.", "Hangul Compatibility Jamo", 0x3130, 0x318f},
314         {"Hangul Syll.", "Hangul Syllables", 0xac00, 0xd7af},
315
316         {"Kanbun", "Kanbun", 0x3190, 0x319f},
317
318
319
320         {"Yijing Hex.", "Yijing Hexagram Symbols", 0x4dc0, 0x4dff},
321
322         {"Yi Syllables", "Yi Syllables", 0xa000, 0xa48f},
323         {"Yi Radicals", "Yi Radicals", 0xa490, 0xa4cf},
324
325         {"High Surr.", "High Surrogate Area", 0xd800, 0xdbff},
326
327         {"Low Surr.", "Low Surrogates", 0xdc00, 0xdfff},
328         {"Priv. Use Area", "Private Use Area", 0xe000, 0xf8ff},
329
330         {"CJK Rad. Supp.", "CJK Radicals Supplement", 0x2e80, 0x2eff},
331         {"CJK Ideographs", "CJK Unified Ideographs", 0x4e00, 0x9faf},
332         {"CJK Ideog. Ext. A", "CJK Unified Ideographs Extension A", 0x3400, 0x4dbf},
333         {"CJK Ideog. Ext. B", "CJK Unified Ideographs Extension B", 0x20000, 0x2a6df},
334         {"CJK Symbols.", "CJK Symbols and Punctuation", 0x3000, 0x303f},
335         {"Enclosed CJK", "Enclosed CJK Letters and Months", 0x3200, 0x32ff},
336         {"CJK Comp.", "CJK Compatibility", 0x3300, 0x33ff},
337         {"CJK Comp. Ideog.", "CJK Compatibility Ideographs", 0xf900, 0xfaff},
338         {"CJK Comp. Forms", "CJK Compatibility Forms", 0xfe30, 0xfe4f},
339         {"CJK Comp. Supp.", "CJK Compatibility Ideographs Supplement", 0x2f800, 0x2fa1f},
340
341         {"Alpha. Pres. Forms", "Alphabetic Presentation Forms", 0xfb00, 0xfb4f},
342
343         {"Arabic Pres. A", "Arabic Presentation Forms-A", 0xfb50, 0xfdff},
344         {"Arabic Pres. B", "Arabic Presentation Forms-B", 0xfe70, 0xfeff},
345
346         {"Var. Sel.", "Variation Selectors", 0xfe00, 0xfe0f},
347
348         {"Comb. Half", "Combining Half Marks", 0xfe20, 0xfe2f},
349
350         {"Sml. From Var.", "Small Form Variants", 0xfe50, 0xfe6f},
351
352         {"Half, Full Forms", "Halfwidth and Fullwidth Forms", 0xff00, 0xffef},
353         {"Specials", "Specials", 0xfff0, 0xffff},
354
355         {"Lin. B Syllab.", "Linear B Syllabary", 0x10000, 0x1007f},
356         {"Lin. B Idog.", "Linear B Ideograms", 0x10080, 0x100ff},
357
358         {"Aegean Num.", "Aegean Numbers", 0x10100, 0x1013f},
359         {"Old Italic", "Old Italic", 0x10300, 0x1032f},
360
361         {"Gothic", "Gothic", 0x10330, 0x1034f},
362         {"Ugaritic", "Ugaritic", 0x10380, 0x1039f},
363
364         {"Deseret", "Deseret", 0x10400, 0x1044f},
365         {"Shavian", "Shavian", 0x10450, 0x1047f},
366
367         {"Osmanya", "Osmanya", 0x10480, 0x104af},
368         {"Cypriot Syll", "Cypriot Syllabary", 0x10800, 0x1083f},
369
370         {"Bysantine Mus.", "Bysantine Musical Symbols", 0x1d000, 0x1d0ff},
371         {"Music Symb.", "Musical Symbols", 0x1d100, 0x1d1ff},
372
373         {"Tai Xuan Symb", "Tai Xuan Jing Symbols", 0x1d300, 0x1d35f},
374         {"Math. Alpha Symb.", "Mathematical Alpanumeric Symbols", 0x1d400, 0x1d7ff},
375
376
377         {"Tags", "Tags", 0xe0000, 0xe007f},
378         {"Var. Supp", "Variation Selectors Supplement", 0xe0100, 0xe01ef},
379
380         {"Supp. Priv. A", "Supplementary Private Use Area-A", 0xf0000, 0xffffd},
381         {"Supp. Priv. B", "Supplementary Private Use Area-B", 0x100000, 0x10fffd}
382 };
383
384
385 /* *************************** static functions prototypes ****************** */
386 VFont *exist_vfont(char *str);
387
388 /* *************** */
389
390 void do_common_editbuts(unsigned short event) // old name, is a mix of object and editing events.... 
391 {
392         EditMesh *em = G.editMesh;
393         EditFace *efa;
394         Base *base;
395         Object *ob= OBACT;
396         Material *ma;
397         Nurb *nu;
398         Curve *cu;
399         BezTriple *bezt;
400         BPoint *bp;
401         unsigned int local;
402         int a, bit, index= -1;
403
404         switch(event) {
405                 
406         case B_MATWICH:
407                 if(G.obedit && G.obedit->actcol>0) {
408                         if(G.obedit->type == OB_MESH) {
409                                 for(efa= em->faces.first; efa; efa= efa->next) {
410                                         if(efa->f & SELECT) {
411                                                 if(index== -1) index= efa->mat_nr;
412                                                 else if(index!=efa->mat_nr) {
413                                                         error("Mixed colors");
414                                                         return;
415                                                 }
416                                         }
417                                 }
418                         }
419                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
420                                 nu= editNurb.first;
421                                 while(nu) {
422                                         if( isNurbsel(nu) ) {
423                                                 if(index== -1) index= nu->mat_nr;
424                                                 else if(index!=nu->mat_nr) {
425                                                         error("Mixed colors");
426                                                         return;
427                                                 }
428                                         }
429                                         nu= nu->next;
430                                 }                               
431                         }
432                         if(index>=0) {
433                                 G.obedit->actcol= index+1;
434                                 scrarea_queue_winredraw(curarea);
435                         }
436                 }
437                 break;
438         case B_MATNEW:
439                 new_material_to_objectdata(ob);
440                 scrarea_queue_winredraw(curarea);
441                 BIF_undo_push("New material");
442                 allqueue(REDRAWBUTSSHADING, 0);
443                 allqueue(REDRAWVIEW3D_Z, 0);
444                 allqueue(REDRAWOOPS, 0);
445                 break;
446         case B_MATDEL:
447                 delete_material_index();
448                 scrarea_queue_winredraw(curarea);
449                 BIF_undo_push("Delete material index");
450                 allqueue(REDRAWBUTSSHADING, 0);
451                 allqueue(REDRAWVIEW3D_Z, 0);
452                 allqueue(REDRAWOOPS, 0);
453                 break;
454         case B_MATASS:
455                 if(G.obedit && G.obedit->actcol>0) {
456                         if(G.obedit->type == OB_MESH) {
457                                 efa= em->faces.first;
458                                 while(efa) {
459                                         if(efa->f & SELECT)
460                                                 efa->mat_nr= G.obedit->actcol-1;
461                                         efa= efa->next;
462                                 }
463                         }
464                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
465                                 nu= editNurb.first;
466                                 while(nu) {
467                                         if( isNurbsel(nu) )
468                                                 nu->mat_nr= nu->charidx= G.obedit->actcol-1;
469                                         nu= nu->next;
470                                 }
471                         }
472                         else if (G.obedit->type == OB_FONT) {
473                         if (mat_to_sel()) {
474                                 allqueue(REDRAWVIEW3D, 0);
475                         }
476                         }
477                         allqueue(REDRAWVIEW3D_Z, 0);
478                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
479                         shade_buttons_change_3d();
480                         BIF_undo_push("Assign material index");
481                 }
482                 break;
483         case B_MATASS_BROWSE:
484                 /* if slot available, make that index active, and assign */
485                 /* else, make new slot, and assign */
486                 ma= BLI_findlink(&G.main->mat, G.buts->menunr-1);
487                 if(ma) {
488                         ob->actcol= find_material_index(ob, ma);
489                         if(ob->actcol==0) {
490                                 assign_material(ob, ma, ob->totcol+1);
491                                 ob->actcol= ob->totcol;
492                         }
493                 }
494                 else {
495                         do_common_editbuts(B_MATNEW);
496                 }
497                 do_common_editbuts(B_MATASS);
498                 break;
499                 
500         case B_MATCOL2:
501                 ma= give_current_material(ob, ob->actcol);
502                 BKE_icon_changed(BKE_icon_getid((ID *)ma));
503                 allqueue(REDRAWVIEW3D, 0);
504                 allqueue(REDRAWBUTSEDIT, 0);
505                 break;
506                 
507         case B_MATSEL:
508         case B_MATDESEL:
509                 if(G.obedit) {
510                         if(G.obedit->type == OB_MESH) {
511                                 if (event==B_MATSEL) {
512                                         editmesh_select_by_material(G.obedit->actcol-1);
513                                 } else {
514                                         editmesh_deselect_by_material(G.obedit->actcol-1);
515                                 }
516                         }
517                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
518                                 nu= editNurb.first;
519                                 while(nu) {
520                                         if(nu->mat_nr==G.obedit->actcol-1) {
521                                                 if(nu->bezt) {
522                                                         a= nu->pntsu;
523                                                         bezt= nu->bezt;
524                                                         while(a--) {
525                                                                 if(bezt->hide==0) {
526                                                                         if(event==B_MATSEL) {
527                                                                                 bezt->f1 |= SELECT;
528                                                                                 bezt->f2 |= SELECT;
529                                                                                 bezt->f3 |= SELECT;
530                                                                         }
531                                                                         else {
532                                                                                 bezt->f1 &= ~SELECT;
533                                                                                 bezt->f2 &= ~SELECT;
534                                                                                 bezt->f3 &= ~SELECT;
535                                                                         }
536                                                                 }
537                                                                 bezt++;
538                                                         }
539                                                 }
540                                                 else if(nu->bp) {
541                                                         a= nu->pntsu*nu->pntsv;
542                                                         bp= nu->bp;
543                                                         while(a--) {
544                                                                 if(bp->hide==0) {
545                                                                         if(event==B_MATSEL) bp->f1 |= SELECT;
546                                                                         else bp->f1 &= ~SELECT;
547                                                                 }
548                                                                 bp++;
549                                                         }
550                                                 }
551                                         }
552                                         nu= nu->next;
553                                 }
554                                 BIF_undo_push("Select material index");
555                         }
556                         allqueue(REDRAWIMAGE, 0);
557                         allqueue(REDRAWVIEW3D, 0);
558                 }
559                 countall();
560                 break;
561         case B_HIDE:
562                 if(G.obedit) {
563                         if(G.obedit->type == OB_MESH) hide_mesh(0);
564                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) hideNurb(0);
565                 }
566                 break;
567         case B_REVEAL:
568                 if(G.obedit) {
569                         if(G.obedit->type == OB_MESH) reveal_mesh();
570                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) revealNurb();
571                 }
572                 else if(FACESEL_PAINT_TEST) reveal_tface();
573                 
574                 break;
575         case B_SELSWAP:
576                 if(G.obedit) {
577                         if(G.obedit->type == OB_MESH) selectswap_mesh();
578                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) selectswapNurb();
579                 }
580                 break;
581         case B_AUTOTEX:
582                 if(ob && G.obedit==0) {
583                         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) tex_space_curve(ob->data);
584                 }
585                 break;
586         case B_DOCENTER:
587                 docenter(0);
588                 break;
589         case B_DOCENTERNEW:
590                 docenter_new();
591                 break;
592         case B_DOCENTERCURSOR:
593                 docenter_cursor();
594                 break;
595         case B_SETSMOOTH:
596         case B_SETSOLID:
597                 if(G.obedit) {
598                         if(G.obedit->type == OB_MESH) {
599                                 mesh_set_smooth_faces((event==B_SETSMOOTH));
600                         }
601                         else {
602                                 nurb_set_smooth((event==B_SETSMOOTH));
603                         }
604                 }
605                 else if(G.vd) {
606                         base= FIRSTBASE;
607                         while(base) {
608                                 if(TESTBASELIB(base)) {
609                                         if(base->object->type==OB_MESH) {
610                                                 mesh_set_smooth_flag(base->object, (event==B_SETSMOOTH));
611                                         }
612                                         else if ELEM(base->object->type, OB_SURF, OB_CURVE) {
613                                                 cu= base->object->data;
614                                                 nu= cu->nurb.first;
615                                                 while(nu) {
616                                                         if(event==B_SETSMOOTH) nu->flag |= ME_SMOOTH;
617                                                         else nu->flag &= ~ME_SMOOTH;
618                                                         nu= nu->next;
619                                                 }
620                                                 makeDispListCurveTypes(base->object, 0);
621                                         }
622                                 }
623                                 base= base->next;
624                         }
625                         allqueue(REDRAWVIEW3D, 0);
626                         
627                         if(event == B_SETSMOOTH) BIF_undo_push("Set Smooth");
628                         else BIF_undo_push("Set Solid");
629                 }
630                 break;
631         case B_CHANGEDEP:
632                 DAG_scene_sort(G.scene); // makes new dag
633                 if(ob) ob->recalc |= OB_RECALC;
634                 allqueue(REDRAWVIEW3D, 0);
635                 break;
636         
637         case B_ADDKEY:
638                 insert_shapekey(ob);
639                 break;
640         case B_SETKEY:
641                 ob->shapeflag |= OB_SHAPE_TEMPLOCK;
642                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
643                 allqueue(REDRAWVIEW3D, 0);
644                 allqueue(REDRAWIPO, 0);
645                 allqueue(REDRAWBUTSEDIT, 0);
646                 break;
647         case B_LOCKKEY:
648                 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
649                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
650                 allqueue(REDRAWVIEW3D, 0);
651                 allqueue(REDRAWIPO, 0);
652                 allqueue(REDRAWBUTSEDIT, 0);
653                 break;
654         case B_NEXTKEY:
655         {
656                 Key *key= ob_get_key(ob);
657                 if(ob->shapenr == BLI_countlist(&key->block))
658                    ob->shapenr= 1;
659                 else ob->shapenr++;
660                 do_common_editbuts(B_SETKEY);
661                 break;
662         }
663         case B_PREVKEY:
664         {
665                 Key *key= ob_get_key(ob);
666                 if(ob->shapenr <= 1)
667                         ob->shapenr= BLI_countlist(&key->block);
668                 else ob->shapenr--;
669                 do_common_editbuts(B_SETKEY);
670                 break;
671         }
672         case B_NAMEKEY:
673                 allspace(REMAKEIPO, 0);
674         allqueue (REDRAWIPO, 0);
675                 break;
676         case B_DELKEY:
677                 delete_key(OBACT);
678                 allqueue(REDRAWACTION, 0);
679                 break;
680                 
681                 
682         default:
683                 if (G.vd==NULL)
684                         break;
685                 
686                 if(event>=B_OBLAY && event<=B_OBLAY+31) {
687                         local= BASACT->lay & 0xFF000000;
688                         BASACT->lay -= local;
689                         if(BASACT->lay==0 || (G.qual & LR_SHIFTKEY)==0) {
690                                 bit= event-B_OBLAY;
691                                 BASACT->lay= 1<<bit;
692                                 scrarea_queue_winredraw(curarea);
693                         }
694                         BASACT->lay += local;
695                         /* optimal redraw */
696                         if( (ob->lay & G.vd->lay) && (BASACT->lay & G.vd->lay) );
697                         else if( (ob->lay & G.vd->lay)==0 && (BASACT->lay & G.vd->lay)==0 );
698                         else {
699                                 allqueue(REDRAWVIEW3D, 0);
700                                 DAG_scene_sort(G.scene);
701                         }
702                         ob->lay= BASACT->lay;
703                 }
704         }
705
706 }
707
708 /* *************************** MESH  ******************************** */
709
710 static void verify_customdata_name_func(void *data1, void *data2)
711 {
712         CustomData *data= (CustomData*)data1;
713         CustomDataLayer *layer= (CustomDataLayer*)data2;
714
715         CustomData_set_layer_unique_name(data, layer - data->layers);
716 }
717
718 static void delete_customdata_layer(void *data1, void *data2)
719 {
720         Mesh *me= (Mesh*)data1;
721         CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
722         CustomDataLayer *layer= (CustomDataLayer*)data2;
723         void *actlayerdata, *rndlayerdata, *layerdata=layer->data;
724         int type= layer->type;
725         int index= CustomData_get_layer_index(data, type);
726         int i, actindex, rndindex;
727         
728         /*ok, deleting a non-active layer needs to preserve the active layer indices.
729           to do this, we store a pointer to the .data member of both layer and the active layer,
730           (to detect if we're deleting the active layer or not), then use the active
731           layer data pointer to find where the active layer has ended up.
732           
733           this is necassary because the deletion functions only support deleting the active
734           layer. */
735         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
736         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
737         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
738
739         /* Multires is handled seperately because the display data is separate
740            from the data stored in multires */
741         if(me && me->mr) {
742                 multires_delete_layer(me, &me->mr->fdata, type, layer - &data->layers[index]);
743                 multires_level_to_editmesh(OBACT, me, 0);
744                 multires_finish_mesh_update(OBACT);
745         }
746         else if(G.obedit) {
747                 EM_free_data_layer(data, type);
748         }
749         else if(me) {
750                 CustomData_free_layer_active(data, type, me->totface);
751                 mesh_update_customdata_pointers(me);
752         }
753
754         if(!CustomData_has_layer(data, type)) {
755                 if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
756                         G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
757         }
758
759         /*reconstruct active layer*/
760         if (actlayerdata != layerdata) {
761                 /*find index. . .*/
762                 actindex = CustomData_get_layer_index(data, type);
763                 for (i=actindex; i<data->totlayer; i++) {
764                         if (data->layers[i].data == actlayerdata) {
765                                 actindex = i - actindex;
766                                 break;
767                         }
768                 }
769                 
770                 /*set index. . .*/
771                 CustomData_set_layer_active(data, type, actindex);
772         }
773         
774         if (rndlayerdata != layerdata) {
775                 /*find index. . .*/
776                 rndindex = CustomData_get_layer_index(data, type);
777                 for (i=rndindex; i<data->totlayer; i++) {
778                         if (data->layers[i].data == rndlayerdata) {
779                                 rndindex = i - rndindex;
780                                 break;
781                         }
782                 }
783                 
784                 /*set index. . .*/
785                 CustomData_set_layer_render(data, type, rndindex);
786         }
787         
788         
789         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
790         
791         if(type == CD_MTFACE)
792                 BIF_undo_push("Delete UV Texture");
793         else if(type == CD_MCOL)
794                 BIF_undo_push("Delete Vertex Color");
795
796         allqueue(REDRAWVIEW3D, 0);
797         allqueue(REDRAWIMAGE, 0);
798         allqueue(REDRAWBUTSEDIT, 0);
799 }
800
801 static int customdata_buttons(
802         uiBlock *block, Mesh *me, CustomData *data,
803         int type, int *activep, int *renderp,
804         int setevt, int setevt_rnd, int newevt,
805         char *label, char *shortlabel, char *browsetip, char *browsetip_rnd,
806         char *newtip, char *deltip, int x, int y)
807 {
808         CustomDataLayer *layer;
809         uiBut *but;
810         int i, count= CustomData_number_of_layers(data, type);
811
812         if(count >= MAX_MTFACE) {
813                 uiDefBut(block, LABEL, 0, label, x,y,220,19, 0, 0.0, 0, 0, 0, "");
814         }
815         else {
816                 uiDefBut(block, LABEL, 0, label, x,y,140,19, 0, 0.0, 0, 0, 0, "");
817                 uiBlockBeginAlign(block);
818                 uiDefBut(block, BUT, newevt, "New", x+140,y,80,19, 0,0,0,0,0, newtip);
819                 uiBlockEndAlign(block);
820         }
821
822         y -= (count)? 24: 19;
823
824         uiBlockBeginAlign(block);
825         for (count=1, i=0; i<data->totlayer; i++) {
826                 layer= &data->layers[i];
827
828                 if(layer->type == type) {
829                         *activep= layer->active + 1;
830                         *renderp= layer->active_rnd + 1;
831                         
832                         uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
833                         uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd);
834                         but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label);
835                         uiButSetFunc(but, verify_customdata_name_func, data, layer);
836                         but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
837                         uiButSetFunc(but, delete_customdata_layer, me, layer);
838
839
840                         count++;
841                         y -= 19;
842                 }
843         }
844         uiBlockEndAlign(block);
845
846         return y;
847 }
848
849 static void editing_panel_mesh_type(Object *ob, Mesh *me)
850 {
851         uiBlock *block;
852         uiBut *but;
853         float val;
854         CustomData *fdata;
855         int yco;
856
857         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win);
858         if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return;
859         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
860
861         uiBlockBeginAlign(block);
862         uiDefButBitS(block, TOG, ME_AUTOSMOOTH, REDRAWVIEW3D, "Auto Smooth",10,180,170,19, &me->flag, 0, 0, 0, 0, "Treats all set-smoothed faces with angles less than Degr: as 'smooth' during render");
863         uiDefButS(block, NUM, B_DIFF, "Degr:",                          10,160,170,19, &me->smoothresh, 1, 80, 0, 0, "Defines maximum angle between face normals that 'Auto Smooth' will operate on");
864         uiBlockEndAlign(block);
865
866         /* Retopo */
867         if(G.obedit) {
868                 uiBlockBeginAlign(block);
869                 but= uiDefButBitC(block,TOG,RETOPO,B_NOP, "Retopo", 10,130,170,19, &G.scene->toolsettings->retopo_mode, 0,0,0,0, "Turn on the re-topology tool");
870                 uiButSetFunc(but,retopo_toggle,ob,me);
871                 if(G.scene->toolsettings->retopo_mode) {
872                         but= uiDefButBitC(block,TOG,RETOPO_PAINT,B_NOP,"Paint", 10,110,55,19, &G.scene->toolsettings->retopo_mode,0,0,0,0, "Draw intersecting lines in the 3d view, ENTER creates quad or tri faces, wrapped onto other objects in the 3d view.");
873                         uiButSetFunc(but,retopo_paint_toggle,ob,me);
874                         but= uiDefBut(block,BUT,B_NOP,"Retopo All", 65,110,115,19, 0,0,0,0,0, "Apply the re-topology tool to all selected vertices");
875                         uiButSetFunc(but,retopo_do_all_cb,ob,me);
876                 }
877                 uiBlockEndAlign(block);
878         }
879
880         uiBlockBeginAlign(block);
881         uiDefBut(block, BUT,B_DOCENTER, "Center",                                       10, 80, 65, 19, 0, 0, 0, 0, 0, "Shifts object data to be centered about object's origin");
882         uiDefBut(block, BUT,B_DOCENTERNEW, "Center New",                        75, 80, 105, 19, 0, 0, 0, 0, 0, "Shifts object's origin to center of object data");
883         uiDefBut(block, BUT,B_DOCENTERCURSOR, "Center Cursor",          10, 60, 170, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
884         uiBlockEndAlign(block);
885
886         uiBlockBeginAlign(block);
887         uiDefButBitS(block, TOG, ME_TWOSIDED, REDRAWVIEW3D, "Double Sided",     10,30,170,19, &me->flag, 0, 0, 0, 0, "Render/display the mesh as double or single sided");
888         uiDefButBitS(block, TOG, ME_NOPUNOFLIP, REDRAWVIEW3D, "No V.Normal Flip", 10,10,170,19, &me->flag, 0, 0, 0, 0, "Disables flipping of vertexnormals during render");
889         uiBlockEndAlign(block);
890
891         uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ",    190,180,220,19, &me->texcomesh, "Derive texture coordinates from another mesh.");
892
893         if(me->msticky) val= 1.0; else val= 0.0;
894         uiDefBut(block, LABEL, 0, "Sticky",                             190,155,140,19, 0, val, 0, 0, 0, "");
895         uiBlockBeginAlign(block);
896         if(me->msticky==NULL) {
897                 uiDefBut(block, BUT, B_MAKESTICKY, "Make",              330,155, 80,19, 0, 0, 0, 0, 0, "Creates Sticky coordinates from the current camera view background picture");
898         }
899         else uiDefBut(block, BUT, B_DELSTICKY, "Delete",        330,155, 80,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates");
900         uiBlockEndAlign(block);
901
902         fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
903         yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd,
904                 B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:",
905                 "Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer",
906                 "Removes the current UV texture layer", 190, 130);
907
908         yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd,
909                 B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:",
910                 "Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer",
911                 "Removes the current vertex color layer", 190, yco-5);
912
913         if(yco < 0)
914                 uiNewPanelHeight(block, 204 - yco);
915 }
916
917 /* *************************** MODIFIERS ******************************** */
918
919 void do_modifier_panels(unsigned short event)
920 {
921         Object *ob = OBACT;
922
923         switch(event) {
924         case B_MODIFIER_REDRAW:
925                 allqueue(REDRAWBUTSEDIT, 0);
926                 allqueue(REDRAWOOPS, 0);
927                 break;
928
929         case B_MODIFIER_RECALC:
930                 allqueue(REDRAWBUTSEDIT, 0);
931                 allqueue(REDRAWVIEW3D, 0);
932                 allqueue(REDRAWIMAGE, 0);
933                 allqueue(REDRAWOOPS, 0);
934                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
935                 object_handle_update(ob);
936                 countall();
937                 break;
938         }
939 }
940
941 static void modifiers_add(void *ob_v, int type)
942 {
943         Object *ob = ob_v;
944         ModifierTypeInfo *mti = modifierType_getInfo(type);
945         
946         if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
947                 ModifierData *md = ob->modifiers.first;
948
949                 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
950                         md = md->next;
951                 }
952
953                 BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(type));
954         } else {
955                 BLI_addtail(&ob->modifiers, modifier_new(type));
956         }
957         BIF_undo_push("Add modifier");
958 }
959
960 typedef struct MenuEntry {
961         char *name;
962         int ID;
963 } MenuEntry;
964
965 static int menuEntry_compare_names(const void *entry1, const void *entry2)
966 {
967         return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
968 }
969
970 static uiBlock *modifiers_add_menu(void *ob_v)
971 {
972         Object *ob = ob_v;
973         uiBlock *block;
974         int i, yco=0;
975         int numEntries = 0;
976         MenuEntry entries[NUM_MODIFIER_TYPES];
977         
978         block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
979                           UI_EMBOSSP, UI_HELV, curarea->win);
980         uiBlockSetButmFunc(block, modifiers_add, ob);
981
982         for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
983                 ModifierTypeInfo *mti = modifierType_getInfo(i);
984
985                 /* Only allow adding through appropriate other interfaces */
986                 if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
987                 
988                 if(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim)) continue;
989
990                 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
991                    (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
992                         entries[numEntries].name = mti->name;
993                         entries[numEntries].ID = i;
994
995                         ++numEntries;
996                 }
997         }
998
999         qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
1000
1001
1002         for(i = 0; i < numEntries; ++i)
1003                 uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
1004                          0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
1005
1006         uiTextBoundsBlock(block, 50);
1007         uiBlockSetDirection(block, UI_DOWN);
1008
1009         return block;
1010 }
1011
1012 static void modifiers_del(void *ob_v, void *md_v)
1013 {
1014         Object *ob = ob_v;
1015         ModifierData *md;
1016
1017                 /* It seems on rapid delete it is possible to
1018                  * get called twice on same modifier, so make
1019                  * sure it is in list.
1020                  */
1021         for (md=ob->modifiers.first; md; md=md->next)
1022                 if (md==md_v)
1023                         break;
1024         
1025         if (!md)
1026                 return;
1027
1028         if(md->type==eModifierType_ParticleSystem){
1029                 ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
1030                 BLI_remlink(&ob->particlesystem, psmd->psys);
1031                 psys_free(ob,psmd->psys);
1032         }
1033
1034         BLI_remlink(&ob->modifiers, md_v);
1035
1036         modifier_free(md_v);
1037
1038         BIF_undo_push("Del modifier");
1039 }
1040
1041 int mod_moveUp(void *ob_v, void *md_v)
1042 {
1043         Object *ob = ob_v;
1044         ModifierData *md = md_v;
1045
1046         if (md->prev) {
1047                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1048
1049                 if (mti->type!=eModifierTypeType_OnlyDeform) {
1050                         ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1051
1052                         if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1053                                 return -1;
1054                 }
1055
1056                 BLI_remlink(&ob->modifiers, md);
1057                 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1058         }
1059
1060         return 0;
1061 }
1062
1063 static void modifiers_moveUp(void *ob_v, void *md_v)
1064 {
1065         if( mod_moveUp( ob_v, md_v ) )
1066                 error("Cannot move above a modifier requiring original data.");
1067         else
1068                 BIF_undo_push("Move modifier");
1069 }
1070
1071 int mod_moveDown(void *ob_v, void *md_v)
1072 {
1073         Object *ob = ob_v;
1074         ModifierData *md = md_v;
1075
1076         if (md->next) {
1077                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1078
1079                 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1080                         ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1081
1082                         if (nmti->type!=eModifierTypeType_OnlyDeform)
1083                                 return -1;
1084                 }
1085
1086                 BLI_remlink(&ob->modifiers, md);
1087                 BLI_insertlink(&ob->modifiers, md->next, md);
1088         }
1089
1090         return 0;
1091 }
1092
1093 static void modifiers_moveDown(void *ob_v, void *md_v)
1094 {
1095         if( mod_moveDown( ob_v, md_v ) )
1096                 error("Cannot move beyond a non-deforming modifier.");
1097         else
1098                 BIF_undo_push("Move modifier");
1099 }
1100
1101 static void modifier_testLatticeObj(char *name, ID **idpp)
1102 {
1103         ID *id;
1104
1105         for (id= G.main->object.first; id; id= id->next) {
1106                 if( strcmp(name, id->name+2)==0 ) {
1107                         if (((Object *)id)->type != OB_LATTICE) {
1108                                 error ("Lattice deform object must be a lattice");
1109                                 break;
1110                         } 
1111                         *idpp= id;
1112                         return;
1113                 }
1114         }
1115         *idpp= 0;
1116 }
1117
1118 static void modifier_testCurveObj(char *name, ID **idpp)
1119 {
1120         ID *id;
1121
1122         for (id= G.main->object.first; id; id= id->next) {
1123                 if( strcmp(name, id->name+2)==0 ) {
1124                         if (((Object *)id)->type != OB_CURVE) {
1125                                 error ("Curve deform object must be a curve");
1126                                 break;
1127                         } 
1128                         *idpp= id;
1129                         return;
1130                 }
1131         }
1132         *idpp= 0;
1133 }
1134
1135 static void modifier_testMeshObj(char *name, ID **idpp)
1136 {
1137         ID *id;
1138
1139         for (id= G.main->object.first; id; id= id->next) {
1140                 /* no boolean on its own object */
1141                 if(id != (ID *)OBACT) {
1142                         if( strcmp(name, id->name+2)==0 ) {
1143                                 if (((Object *)id)->type != OB_MESH) {
1144                                         error ("Boolean modifier object must be a mesh");
1145                                         break;
1146                                 } 
1147                                 *idpp= id;
1148                                 return;
1149                         }
1150                 }
1151         }
1152         *idpp= NULL;
1153 }
1154
1155 static void modifier_testArmatureObj(char *name, ID **idpp)
1156 {
1157         ID *id;
1158
1159         for (id= G.main->object.first; id; id= id->next) {
1160                 if( strcmp(name, id->name+2)==0 ) {
1161                         if (((Object *)id)->type != OB_ARMATURE) {
1162                                 error ("Armature deform object must be an armature");
1163                                 break;
1164                         } 
1165                         *idpp= id;
1166                         return;
1167                 }
1168         }
1169         *idpp= 0;
1170 }
1171
1172 static void modifier_testTexture(char *name, ID **idpp)
1173 {
1174         ID *id;
1175
1176         for(id = G.main->tex.first; id; id = id->next) {
1177                 if(strcmp(name, id->name + 2) == 0) {
1178                         *idpp = id;
1179                         /* texture gets user, objects not: delete object = clear modifier */
1180                         id_us_plus(id);
1181                         return;
1182                 }
1183         }
1184         *idpp = 0;
1185 }
1186
1187 #if 0 /* this is currently unused, but could be useful in the future */
1188 static void modifier_testMaterial(char *name, ID **idpp)
1189 {
1190         ID *id;
1191
1192         for(id = G.main->mat.first; id; id = id->next) {
1193                 if(strcmp(name, id->name + 2) == 0) {
1194                         *idpp = id;
1195                         return;
1196                 }
1197         }
1198         *idpp = 0;
1199 }
1200 #endif
1201
1202 static void modifier_testImage(char *name, ID **idpp)
1203 {
1204         ID *id;
1205
1206         for(id = G.main->image.first; id; id = id->next) {
1207                 if(strcmp(name, id->name + 2) == 0) {
1208                         *idpp = id;
1209                         return;
1210                 }
1211         }
1212         *idpp = 0;
1213 }
1214
1215 /* autocomplete callback for ID buttons */
1216 void autocomplete_image(char *str, void *arg_v)
1217 {
1218         /* search if str matches the beginning of an ID struct */
1219         if(str[0]) {
1220                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1221                 ID *id;
1222
1223                 for(id = G.main->image.first; id; id = id->next)
1224                         autocomplete_do_name(autocpl, id->name+2);
1225
1226                 autocomplete_end(autocpl, str);
1227         }
1228 }
1229
1230 /* autocomplete callback for ID buttons */
1231 void autocomplete_meshob(char *str, void *arg_v)
1232 {
1233         /* search if str matches the beginning of an ID struct */
1234         if(str[0]) {
1235                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1236                 ID *id;
1237
1238                 for(id = G.main->object.first; id; id = id->next)
1239                         if(((Object *)id)->type == OB_MESH)
1240                                 autocomplete_do_name(autocpl, id->name+2);
1241
1242                 autocomplete_end(autocpl, str);
1243         }
1244 }
1245 static void modifiers_convertParticles(void *obv, void *mdv)
1246 {
1247         Object *obn;
1248         ModifierData *md = mdv;
1249         ParticleSystem *psys;
1250         ParticleCacheKey *key, **cache;
1251         Mesh *me;
1252         MVert *mvert;
1253         MEdge *medge;
1254         int a, k, kmax;
1255         int totvert=0, totedge=0, cvert=0;
1256         int totpart=0, totchild=0;
1257
1258         if(md->type != eModifierType_ParticleSystem) return;
1259
1260         if(G.f & G_PARTICLEEDIT) return;
1261
1262         psys=((ParticleSystemModifierData *)md)->psys;
1263
1264         if(psys->part->draw_as != PART_DRAW_PATH || psys->pathcache == 0) return;
1265
1266         totpart= psys->totcached;
1267         totchild= psys->totchildcache;
1268
1269         if(totchild && (psys->part->draw&PART_DRAW_PARENT)==0)
1270                 totpart= 0;
1271
1272         /* count */
1273         cache= psys->pathcache;
1274         for(a=0; a<totpart; a++) {
1275                 key= cache[a];
1276                 totvert+= key->steps+1;
1277                 totedge+= key->steps;
1278         }
1279
1280         cache= psys->childcache;
1281         for(a=0; a<totchild; a++) {
1282                 key= cache[a];
1283                 totvert+= key->steps+1;
1284                 totedge+= key->steps;
1285         }
1286
1287         if(totvert==0) return;
1288
1289         /* add new mesh */
1290         obn= add_object(OB_MESH);
1291         me= obn->data;
1292         
1293         me->totvert= totvert;
1294         me->totedge= totedge;
1295         
1296         me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
1297         me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
1298         me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
1299         
1300         mvert= me->mvert;
1301         medge= me->medge;
1302
1303         /* copy coordinates */
1304         cache= psys->pathcache;
1305         for(a=0; a<totpart; a++) {
1306                 key= cache[a];
1307                 kmax= key->steps;
1308                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1309                         VECCOPY(mvert->co,key->co);
1310                         if(k) {
1311                                 medge->v1= cvert-1;
1312                                 medge->v2= cvert;
1313                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1314                                 medge++;
1315                         }
1316                 }
1317         }
1318
1319         cache=psys->childcache;
1320         for(a=0; a<totchild; a++) {
1321                 key=cache[a];
1322                 kmax=key->steps;
1323                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1324                         VECCOPY(mvert->co,key->co);
1325                         if(k) {
1326                                 medge->v1=cvert-1;
1327                                 medge->v2=cvert;
1328                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1329                                 medge++;
1330                         }
1331                 }
1332         }
1333
1334         DAG_scene_sort(G.scene);
1335 }
1336
1337 static void modifiers_applyModifier(void *obv, void *mdv)
1338 {
1339         Object *ob = obv;
1340         ModifierData *md = mdv;
1341         DerivedMesh *dm;
1342         Mesh *me = ob->data;
1343         int converted = 0;
1344
1345         if (G.obedit) {
1346                 error("Modifiers cannot be applied in editmode");
1347                 return;
1348         } else if (((ID*) ob->data)->us>1) {
1349                 error("Modifiers cannot be applied to multi-user data");
1350                 return;
1351         }
1352
1353         if (md!=ob->modifiers.first) {
1354                 if (!okee("Modifier is not first"))
1355                         return;
1356         }
1357
1358         if (ob->type==OB_MESH) {
1359                 if(me->mr && multires_modifier_warning()) {
1360                         error("Modifier changes topology; cannot apply with multires active");
1361                         return;
1362                 }
1363                 if(me->key) {
1364                         error("Modifier cannot be applied to Mesh with Shape Keys");
1365                         return;
1366                 }
1367         
1368                 mesh_pmv_off(ob, me);
1369         
1370                 dm = mesh_create_derived_for_modifier(ob, md);
1371                 if (!dm) {
1372                         error("Modifier is disabled or returned error, skipping apply");
1373                         return;
1374                 }
1375
1376                 DM_to_mesh(dm, me);
1377                 converted = 1;
1378
1379                 dm->release(dm);
1380         } 
1381         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1382                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1383                 Curve *cu = ob->data;
1384                 int numVerts;
1385                 float (*vertexCos)[3];
1386
1387                 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1388                         return;
1389
1390                 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1391                         error("Modifier is disabled, skipping apply");
1392                         return;
1393                 }
1394
1395                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1396                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1397                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1398
1399                 converted = 1;
1400
1401                 MEM_freeN(vertexCos);
1402
1403                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1404         }
1405         else {
1406                 error("Cannot apply modifier for this object type");
1407                 return;
1408         }
1409
1410         if (converted) {
1411                 BLI_remlink(&ob->modifiers, md);
1412                 modifier_free(md);
1413
1414                 BIF_undo_push("Apply modifier");
1415         }
1416 }
1417
1418 static void modifiers_copyModifier(void *ob_v, void *md_v)
1419 {
1420         Object *ob = ob_v;
1421         ModifierData *md = md_v;
1422         ModifierData *nmd = modifier_new(md->type);
1423
1424         modifier_copyData(md, nmd);
1425
1426         BLI_insertlink(&ob->modifiers, md, nmd);
1427
1428         BIF_undo_push("Copy modifier");
1429 }
1430
1431 static void modifiers_setOnCage(void *ob_v, void *md_v)
1432 {
1433         Object *ob = ob_v;
1434         ModifierData *md;
1435         
1436         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1437
1438         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1439                 if( md == md_v ) {
1440                         if( i >= cageIndex )
1441                                 md->mode ^= eModifierMode_OnCage;
1442                         break;
1443                 }
1444 }
1445
1446 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1447 {
1448         Object *ob = ob_v;
1449         ModifierData *md = md_v;
1450         HookModifierData *hmd = (HookModifierData*) md;
1451         
1452         if (hmd->object) {
1453                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1454                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1455                 BIF_undo_push("Clear hook offset");
1456         }
1457 }
1458
1459 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1460 {
1461         Object *ob = ob_v;
1462         ModifierData *md = md_v;
1463         HookModifierData *hmd = (HookModifierData*) md;
1464
1465         if (G.vd) {
1466                 float *curs = give_cursor();
1467                 float bmat[3][3], imat[3][3];
1468
1469                 where_is_object(ob);
1470         
1471                 Mat3CpyMat4(bmat, ob->obmat);
1472                 Mat3Inv(imat, bmat);
1473
1474                 curs= give_cursor();
1475                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1476                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1477                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1478                 Mat3MulVecfl(imat, hmd->cent);
1479
1480                 BIF_undo_push("Hook cursor center");
1481         }
1482 }
1483
1484 static void modifiers_selectHook(void *ob_v, void *md_v)
1485 {
1486         ModifierData *md = md_v;
1487         HookModifierData *hmd = (HookModifierData*) md;
1488
1489         hook_select(hmd);
1490 }
1491
1492 static void modifiers_reassignHook(void *ob_v, void *md_v)
1493 {
1494         ModifierData *md = md_v;
1495         HookModifierData *hmd = (HookModifierData*) md;
1496         float cent[3];
1497         int *indexar, tot, ok;
1498         char name[32];
1499                 
1500         ok= hook_getIndexArray(&tot, &indexar, name, cent);
1501
1502         if (!ok) {
1503                 error("Requires selected vertices or active Vertex Group");
1504         } else {
1505                 if (hmd->indexar) {
1506                         MEM_freeN(hmd->indexar);
1507                 }
1508
1509                 VECCOPY(hmd->cent, cent);
1510                 hmd->indexar = indexar;
1511                 hmd->totindex = tot;
1512         }
1513 }
1514
1515 static void modifiers_convertToReal(void *ob_v, void *md_v)
1516 {
1517         Object *ob = ob_v;
1518         ModifierData *md = md_v;
1519         ModifierData *nmd = modifier_new(md->type);
1520
1521         modifier_copyData(md, nmd);
1522         nmd->mode &= ~eModifierMode_Virtual;
1523
1524         BLI_addhead(&ob->modifiers, nmd);
1525
1526         ob->partype = PAROBJECT;
1527
1528         BIF_undo_push("Modifier convert to real");
1529 }
1530
1531 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1532                                     int *uvlayer_tmp, char *uvlayer_name)
1533 {
1534         char strtmp[38];
1535         int totuv, i;
1536         CustomDataLayer *layer
1537                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1538
1539         *uvlayer_tmp = -1;
1540
1541         totuv = CustomData_number_of_layers(data, CD_MTFACE);
1542
1543         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1544                                    "menu_string");
1545         sprintf(*menu_string, "UV Layer%%t");
1546         for(i = 0; i < totuv; i++) {
1547                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1548                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1549                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1550                 strcat(*menu_string, strtmp);
1551                 layer++;
1552         }
1553
1554         /* there is no uvlayer defined, or else it was deleted. Assign active
1555          * layer, then recalc modifiers.
1556          */
1557         if(*uvlayer_tmp == -1) {
1558                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1559                         *uvlayer_tmp = 1;
1560                         layer = data->layers;
1561                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1562                             i++, layer++) {
1563                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1564                         }
1565                         strcpy(uvlayer_name, layer->name);
1566
1567                         /* update the modifiers */
1568                         do_modifier_panels(B_MODIFIER_RECALC);
1569                 } else {
1570                         /* ok we have no uv layers, so make sure menu button knows that.*/
1571                         *uvlayer_tmp = 0;
1572                 }
1573         }
1574 }
1575
1576 void set_wave_uvlayer(void *arg1, void *arg2)
1577 {
1578         WaveModifierData *wmd=arg1;
1579         CustomDataLayer *layer = arg2;
1580
1581         /*check we have UV layers*/
1582         if (wmd->uvlayer_tmp < 1) return;
1583         layer = layer + (wmd->uvlayer_tmp-1);
1584         
1585         strcpy(wmd->uvlayer_name, layer->name);
1586 }
1587
1588 void set_displace_uvlayer(void *arg1, void *arg2)
1589 {
1590         DisplaceModifierData *dmd=arg1;
1591         CustomDataLayer *layer = arg2;
1592
1593         /*check we have UV layers*/
1594         if (dmd->uvlayer_tmp < 1) return;
1595         layer = layer + (dmd->uvlayer_tmp-1);
1596         
1597         strcpy(dmd->uvlayer_name, layer->name);
1598 }
1599
1600 void set_uvproject_uvlayer(void *arg1, void *arg2)
1601 {
1602         UVProjectModifierData *umd=arg1;
1603         CustomDataLayer *layer = arg2;
1604
1605         /*check we have UV layers*/
1606         if (umd->uvlayer_tmp < 1) return;
1607         layer = layer + (umd->uvlayer_tmp-1);
1608         
1609         strcpy(umd->uvlayer_name, layer->name);
1610 }
1611
1612 static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
1613 {
1614         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
1615         Object *ob = (Object*)ob_v;
1616
1617         if(mmd->bindcos) {
1618                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1619                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1620                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1621                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1622                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1623                 mmd->bindweights= NULL;
1624                 mmd->bindcos= NULL;
1625                 mmd->dyngrid= NULL;
1626                 mmd->dyninfluences= NULL;
1627                 mmd->dynverts= NULL;
1628                 mmd->totvert= 0;
1629                 mmd->totcagevert= 0;
1630                 mmd->totinfluence= 0;
1631         }
1632         else {
1633                 DerivedMesh *dm;
1634                 int mode= mmd->modifier.mode;
1635
1636                 /* force modifier to run, it will call binding routine */
1637                 mmd->needbind= 1;
1638                 mmd->modifier.mode |= eModifierMode_Realtime;
1639
1640                 if(ob->type == OB_MESH) {
1641                         dm= mesh_create_derived_view(ob, 0);
1642                         dm->release(dm);
1643                 }
1644                 else if(ob->type == OB_LATTICE) {
1645                         lattice_calc_modifiers(ob);
1646                 }
1647                 else if(ob->type==OB_MBALL) {
1648                         makeDispListMBall(ob);
1649                 }
1650                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1651                         makeDispListCurveTypes(ob, 0);
1652                 }
1653
1654                 mmd->needbind= 0;
1655                 mmd->modifier.mode= mode;
1656         }
1657 }
1658
1659 void modifiers_explodeFacepa(void *arg1, void *arg2)
1660 {
1661         ExplodeModifierData *emd=arg1;
1662
1663         emd->flag |= eExplodeFlag_CalcFaces;
1664 }
1665
1666 void modifiers_explodeDelVg(void *arg1, void *arg2)
1667 {
1668         ExplodeModifierData *emd=arg1;
1669         emd->vgroup = 0;
1670 }
1671
1672 static int modifier_is_fluid_particles(ModifierData *md) {
1673         if(md->type == eModifierType_ParticleSystem) {
1674                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
1675                         return 1;
1676         }
1677         return 0;
1678 }
1679 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1680 {
1681         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1682         uiBut *but;
1683         int isVirtual = md->mode&eModifierMode_Virtual;
1684         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1685         int editing = (G.obedit==ob);
1686         short height=26, width = 295, buttonWidth = width-120-10;
1687         char str[128];
1688
1689         /* rounded header */
1690         uiBlockSetCol(block, color);
1691                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1692         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1693                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1694         uiBlockSetCol(block, TH_AUTO);
1695         
1696         /* open/close icon */
1697         if (!isVirtual) {
1698                 uiBlockSetEmboss(block, UI_EMBOSSN);
1699                 uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, B_MODIFIER_REDRAW, VICON_DISCLOSURE_TRI_RIGHT, x-10, y-2, 20, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
1700         }
1701
1702         uiBlockSetEmboss(block, UI_EMBOSS);
1703         
1704         if (isVirtual) {
1705                 sprintf(str, "%s parent deform", md->name);
1706                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1707
1708                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Make Real", x+width-100, y, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
1709                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1710         } else {
1711                 uiBlockBeginAlign(block);
1712                 uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
1713
1714                 /* Softbody not allowed in this situation, enforce! */
1715                 if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
1716                         uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
1717                         but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
1718                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1719                                 uiDefIconButBitI(block, TOG, eModifierMode_Editmode, B_MODIFIER_RECALC, VICON_EDIT, x+10+buttonWidth-20, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during Editmode (only if enabled for display)");
1720                         }
1721                 }
1722                 uiBlockEndAlign(block);
1723
1724                 uiBlockSetEmboss(block, UI_EMBOSSR);
1725
1726                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1727                         int icon, color;
1728
1729                         if (index==cageIndex) {
1730                                 color = TH_BUT_SETTING;
1731                                 icon = VICON_EDITMODE_HLT;
1732                         } else if (index<cageIndex) {
1733                                 color = TH_BUT_NEUTRAL;
1734                                 icon = VICON_EDITMODE_DEHLT;
1735                         } else {
1736                                 color = TH_BUT_NEUTRAL;
1737                                 icon = ICON_BLANK1;
1738                         }
1739                         uiBlockSetCol(block, color);
1740                         but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, icon, x+width-105, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
1741                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1742                         uiBlockSetCol(block, TH_AUTO);
1743                 }
1744
1745                 uiBlockSetCol(block, TH_BUT_ACTION);
1746
1747                 but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_UP, x+width-75, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier up in stack");
1748                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1749
1750                 but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_MOVE_DOWN, x+width-75+20, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Move modifier down in stack");
1751                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1752                 
1753                 uiBlockSetEmboss(block, UI_EMBOSSN);
1754                 
1755                 // deletion over the deflection panel
1756                 // fluid particle modifier can't be deleted here
1757                 if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
1758                 {
1759                         but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
1760                         uiButSetFunc(but, modifiers_del, ob, md);
1761                 }
1762                 uiBlockSetCol(block, TH_AUTO);
1763         }
1764
1765         uiBlockSetEmboss(block, UI_EMBOSS);
1766
1767         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1768                 y -= 18;
1769         } else {
1770                 int cy = y - 8;
1771                 int lx = x + width - 60 - 15;
1772
1773                 if (md->type==eModifierType_Subsurf) {
1774                         height = 105;
1775                 } else if (md->type==eModifierType_Lattice) {
1776                         height = 48;
1777                 } else if (md->type==eModifierType_Curve) {
1778                         height = 72;
1779                 } else if (md->type==eModifierType_Build) {
1780                         height = 86;
1781                 } else if (md->type==eModifierType_Mirror) {
1782                         height = 105;
1783                 } else if (md->type==eModifierType_Bevel) {
1784                         BevelModifierData *bmd = (BevelModifierData*) md;
1785                         height = 105; /* height = 124; */
1786                         if ((bmd->lim_flags & BME_BEVEL_ANGLE) || ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT))) height += 19;
1787                 } else if (md->type==eModifierType_EdgeSplit) {
1788                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1789                         height = 48;
1790                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1791                 } else if (md->type==eModifierType_Displace) {
1792                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1793                         height = 124;
1794                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1795                            dmd->texmapping == MOD_DISP_MAP_UV)
1796                                 height += 19;
1797                 } else if (md->type==eModifierType_UVProject) {
1798                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1799                 } else if (md->type==eModifierType_Decimate) {
1800                         height = 48;
1801                 } else if (md->type==eModifierType_Smooth) {
1802                         height = 86;
1803                 } else if (md->type==eModifierType_Cast) {
1804                         height = 143;
1805                 } else if (md->type==eModifierType_Wave) {
1806                         WaveModifierData *wmd = (WaveModifierData *)md;
1807                         height = 315;
1808                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1809                            wmd->texmapping == MOD_WAV_MAP_UV)
1810                                 height += 19;
1811                         if(wmd->flag & MOD_WAVE_NORM)
1812                                 height += 19;
1813                 } else if (md->type==eModifierType_Armature) {
1814                         height = 105;
1815                 } else if (md->type==eModifierType_Hook) {
1816                         HookModifierData *hmd = (HookModifierData*) md;
1817                         height = 86;
1818                         if (editing)
1819                                 height += 20;
1820                         if(hmd->indexar==NULL)
1821                                 height += 20;
1822                 } else if (md->type==eModifierType_Softbody) {
1823                         height = 31;
1824                 } else if (md->type==eModifierType_Cloth) {
1825                         height = 31;
1826                 } else if (md->type==eModifierType_Collision) {
1827                         height = 31;
1828                 } else if (md->type==eModifierType_Fluidsim) {
1829                         height = 31;
1830                 } else if (md->type==eModifierType_Boolean) {
1831                         height = 48;
1832                 } else if (md->type==eModifierType_Array) {
1833                         height = 211;
1834                 } else if (md->type==eModifierType_MeshDeform) {
1835                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1836                         height = (mmd->bindcos)? 73: 93;
1837                 } else if (md->type==eModifierType_ParticleSystem) {
1838                         height = 31;
1839                 } else if (md->type==eModifierType_ParticleInstance) {
1840                         height = 94;
1841                 } else if (md->type==eModifierType_Explode) {
1842                         height = 94;
1843                 } else if (md->type==eModifierType_Shrinkwrap) {
1844                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
1845                         height = 86 + 3;
1846                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT)
1847                         {
1848                                 height += 19*5;
1849                                 if(smd->projAxis == 0) height += 19;
1850                         }
1851                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE)
1852                                 height += 19;
1853                 } else if (md->type == eModifierType_Mask) {
1854                         height = 66;
1855                 }
1856                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1857                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1858
1859                 y -= 18;
1860
1861                 if (!isVirtual && (md->type!=eModifierType_Collision)) {
1862                         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */
1863
1864                         uiBlockBeginAlign(block);
1865                         if (md->type==eModifierType_ParticleSystem) {
1866                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert",        lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
1867                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1868                         }
1869                         else{
1870                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
1871                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1872                         }
1873                         
1874                         if (md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
1875                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy",   lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
1876                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1877                         }
1878                         uiBlockEndAlign(block);
1879                         
1880                         uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
1881                 }
1882
1883                 lx = x + 10;
1884                 cy = y + 10 - 1;
1885                 uiBlockBeginAlign(block);
1886                 if (md->type==eModifierType_Subsurf) {
1887                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1888                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1889                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1890                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1891                         uiDefButS(block, NUM, B_MODIFIER_REDRAW, "Render Levels:",              lx, (cy-=19), buttonWidth,19, &smd->renderLevels, 1, 6, 0, 0, "Number subdivisions to perform when rendering");
1892
1893                         /* Disabled until non-EM DerivedMesh implementation is complete */
1894
1895                         /*
1896                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_Incremental, B_MODIFIER_RECALC, "Incremental", lx, (cy-=19),90,19,&smd->flags, 0, 0, 0, 0, "Use incremental calculation, even outside of mesh mode");
1897                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_DebugIncr, B_MODIFIER_RECALC, "Debug", lx+90, cy,buttonWidth-90,19,&smd->flags, 0, 0, 0, 0, "Visualize the subsurf incremental calculation, for debugging effect of other modifiers");
1898                         */
1899
1900                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_ControlEdges, B_MODIFIER_RECALC, "Optimal Draw", lx, (cy-=19), buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Skip drawing/rendering of interior subdivided edges");
1901                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_SubsurfUv, B_MODIFIER_RECALC, "Subsurf UV", lx, (cy-=19),buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Use subsurf to subdivide UVs");
1902                 } else if (md->type==eModifierType_Lattice) {
1903                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1904                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1905                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1906                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1907                 } else if (md->type==eModifierType_Curve) {
1908                         CurveModifierData *cmd = (CurveModifierData*) md;
1909                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1910                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1911                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1912                         
1913                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"X",             lx, (cy-=19), 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSX, 0, 0, "The axis that the curve deforms along");
1914                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"Y",             (lx+buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSY, 0, 0, "The axis that the curve deforms along");
1915                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"Z",             (lx+2*buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSZ, 0, 0, "The axis that the curve deforms along");
1916                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-X",            (lx+3*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGX, 0, 0, "The axis that the curve deforms along");
1917                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Y",            (lx+4*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGY, 0, 0, "The axis that the curve deforms along");
1918                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Z",            (lx+buttonWidth-buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGZ, 0, 0, "The axis that the curve deforms along");
1919                 } else if (md->type==eModifierType_Build) {
1920                         BuildModifierData *bmd = (BuildModifierData*) md;
1921                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Start:", lx, (cy-=19), buttonWidth,19, &bmd->start, 1.0, MAXFRAMEF, 100, 0, "Specify the start frame of the effect");
1922                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:", lx, (cy-=19), buttonWidth,19, &bmd->length, 1.0, MAXFRAMEF, 100, 0, "Specify the total time the build effect requires");
1923                         uiDefButI(block, TOG, B_MODIFIER_RECALC, "Randomize", lx, (cy-=19), buttonWidth,19, &bmd->randomize, 0, 0, 1, 0, "Randomize the faces or edges during build.");
1924                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Seed:", lx, (cy-=19), buttonWidth,19, &bmd->seed, 1.0, MAXFRAMEF, 100, 0, "Specify the seed for random if used.");
1925                 } else if (md->type==eModifierType_Mirror) {
1926                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1927                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Limit:", lx, (cy-=19), buttonWidth,19, &mmd->tolerance, 0.0, 1.0, 10, 10, "Distance from axis within which mirrored vertices are merged");
1928                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_X, B_MODIFIER_RECALC, "X",        lx,(cy-=19),20,19, &mmd->flag, 0, 0, 0, 0, "Enable X axis mirror");
1929                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_Y, B_MODIFIER_RECALC, "Y",        lx+20,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Y axis mirror");
1930                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_Z, B_MODIFIER_RECALC, "Z",        lx+40,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Z axis mirror");
1931                         uiDefButBitS(block, TOG, MOD_MIR_CLIPPING, B_MODIFIER_RECALC, "Do Clipping",    lx+60, cy, buttonWidth-60,19, &mmd->flag, 1, 2, 0, 0, "Prevents during Transform vertices to go through Mirror");
1932                         uiDefButBitS(block, TOG, MOD_MIR_VGROUP, B_MODIFIER_RECALC, "Mirror Vgroups",   lx, (cy-=19), buttonWidth,19, &mmd->flag, 1, 2, 0, 0, "Mirror vertex groups (e.g. .R->.L)");
1933                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1934                                      "Mirror U",
1935                                      lx, (cy-=19), buttonWidth/2, 19,
1936                                      &mmd->flag, 0, 0, 0, 0,
1937                                      "Mirror the U texture coordinate around "
1938                                      "the 0.5 point");
1939                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1940                                      "Mirror V",
1941                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1942                                      &mmd->flag, 0, 0, 0, 0,
1943                                      "Mirror the V texture coordinate around "
1944                                      "the 0.5 point");
1945                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1946                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1947                                        &mmd->mirror_ob,
1948                                        "Object to use as mirror");
1949                 } else if (md->type==eModifierType_Bevel) {
1950                         BevelModifierData *bmd = (BevelModifierData*) md;
1951                         /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
1952                                           lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
1953                                           11.0, 0, 0, 0,
1954                                           "Interpret bevel value as a constant distance from each edge");
1955                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
1956                                           (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
1957                                           11.0, BME_BEVEL_RADIUS, 0, 0,
1958                                           "Interpret bevel value as a radius - smaller angles will be beveled more");*/
1959                         uiBlockBeginAlign(block);
1960                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
1961                                           lx, (cy -= 19), buttonWidth, 19, &bmd->value,
1962                                           0.0, 0.5, 5, 4,
1963                                           "Bevel value/amount");
1964                         /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
1965                                           lx, (cy -= 19), buttonWidth, 19, &bmd->res,
1966                                           1, 4, 5, 2,
1967                                           "Number of times to bevel");*/
1968                         uiDefButBitS(block, TOG, BME_BEVEL_VERT,
1969                                           B_MODIFIER_RECALC, "Only Vertices",
1970                                           lx, (cy -= 19), buttonWidth, 19,
1971                                           &bmd->flags, 0, 0, 0, 0,
1972                                           "Bevel only verts/corners; not edges");
1973                         uiBlockEndAlign(block);
1974                                           
1975                         uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1976                         uiBlockBeginAlign(block);
1977                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
1978                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
1979                                           12.0, 0, 0, 0,
1980                                           "Bevel the entire mesh by a constant amount");
1981                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
1982                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
1983                                           12.0, BME_BEVEL_ANGLE, 0, 0,
1984                                           "Only bevel edges with sharp enough angles between faces");
1985                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
1986                                           lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
1987                                           12.0, BME_BEVEL_WEIGHT, 0, 0,
1988                                           "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
1989                         if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
1990                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
1991                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
1992                                           13.0, BME_BEVEL_EMIN, 0, 0,
1993                                           "The sharpest edge's weight is used when weighting a vert");
1994                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
1995                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
1996                                           13.0, 0, 0, 0,
1997                                           "The edge weights are averaged when weighting a vert");
1998                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
1999                                           (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
2000                                           13.0, BME_BEVEL_EMAX, 0, 0,
2001                                           "The largest edge's wieght is used when weighting a vert");
2002                         }
2003                         else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
2004                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
2005                                           lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
2006                                           0.0, 180.0, 100, 2,
2007                                           "Angle above which to bevel edges");
2008                         }
2009                 } else if (md->type==eModifierType_EdgeSplit) {
2010                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2011                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
2012                                      B_MODIFIER_RECALC, "From Edge Angle",
2013                                      lx, (cy -= 19), buttonWidth, 19,
2014                                      &emd->flags, 0, 0, 0, 0,
2015                                      "Split edges with high angle between faces");
2016                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
2017                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
2018                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
2019                                           0.0, 180.0, 100, 2,
2020                                           "Angle above which to split edges");
2021                         }
2022                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
2023                                      B_MODIFIER_RECALC, "From Marked As Sharp",
2024                                      lx, (cy -= 19), buttonWidth, 19,
2025                                      &emd->flags, 0, 0, 0, 0,
2026                                      "Split edges that are marked as sharp");
2027                 } else if (md->type==eModifierType_Displace) {
2028                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2029                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
2030                                        lx, (cy -= 19), buttonWidth, 19,
2031                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
2032                                        "Name of vertex group to displace"
2033                                        " (displace whole mesh if blank)");
2034                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2035                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
2036                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
2037                                        &dmd->texture,
2038                                        "Texture to use as displacement input");
2039                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
2040                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
2041                                   0, 1, 10, 3,
2042                                   "Material value that gives no displacement");
2043                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
2044                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
2045                                   -1000, 1000, 10, 0.1,
2046                                   "Strength of displacement");
2047                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
2048                                 "Z%%x%d|Y%%x%d|X%%x%d",
2049                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
2050                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
2051                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2052                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
2053                                   0.0, 1.0, 0, 0, "Displace direction");
2054                         sprintf(str, "Texture Coordinates%%t"
2055                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2056                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
2057                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
2058                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2059                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
2060                                   0.0, 1.0, 0, 0,
2061                                   "Texture coordinates used for displacement input");
2062                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
2063                                 char *strtmp;
2064                                 int i;
2065                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2066                                                              : &((Mesh*)ob->data)->fdata;
2067                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
2068                                                         dmd->uvlayer_name);
2069                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2070                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
2071                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2072                                 MEM_freeN(strtmp);
2073                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2074                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
2075                                              &fdata->layers[i]);
2076                         }
2077                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
2078                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2079                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2080                                                &dmd->map_object,
2081                                                "Object to get texture coordinates from");
2082                         }
2083                 } else if (md->type==eModifierType_UVProject) {
2084                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
2085                         int i;
2086                         char *strtmp;
2087                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
2088                                                      : &((Mesh*)ob->data)->fdata;
2089                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
2090                                                 umd->uvlayer_name);
2091                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2092                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
2093                               0.0, 1.0, 0, 0, "Set the UV layer to use");
2094                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
2095                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
2096                         MEM_freeN(strtmp);
2097                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
2098                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
2099                                   1, 1000, 100, 2,
2100                                   "Horizontal Aspect Ratio");
2101                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
2102                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
2103                                   &umd->aspecty,
2104                                   1, 1000, 100, 2,
2105                                   "Vertical Aspect Ratio");
2106                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
2107                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
2108                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
2109                                   "Number of objects to use as projectors");
2110                         for(i = 0; i < umd->num_projectors; ++i) {
2111                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2112                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2113                                                &umd->projectors[i],
2114                                                "Object to use as projector");
2115                         }
2116                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
2117                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
2118                                        &umd->image,
2119                                        "Image to project (only faces with this image "
2120                                        "will be altered");
2121                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
2122                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
2123                                      B_MODIFIER_RECALC, "Override Image",
2124                                      lx, (cy -= 19), buttonWidth, 19,
2125                                      &umd->flags, 0, 0, 0, 0,
2126                                      "Override faces' current images with the "
2127                                      "given image");
2128                 } else if (md->type==eModifierType_Decimate) {
2129                         DecimateModifierData *dmd = (DecimateModifierData*) md;
2130                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Ratio:",      lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to");
2131                         sprintf(str, "Face Count: %d", dmd->faceCount);
2132                         uiDefBut(block, LABEL, 1, str,  lx, (cy-=19), 160,19, NULL, 0.0, 0.0, 0, 0, "Displays the current number of faces in the decimated mesh");
2133                 } else if (md->type==eModifierType_Mask) {
2134                         MaskModifierData *mmd = (MaskModifierData *)md;
2135                         
2136                         sprintf(str, "Mask Mode%%t|Vertex Group%%x%d|Selected Bones%%x%d|",
2137                                 MOD_MASK_MODE_VGROUP,MOD_MASK_MODE_ARM);
2138                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2139                                 lx, (cy -= 19), buttonWidth, 19, &mmd->mode,
2140                                 0.0, 1.0, 0, 0, "How masking region is defined");
2141                                           
2142                         if (mmd->mode == MOD_MASK_MODE_ARM) {
2143                                 uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP,
2144                                     "Ob: ", lx, (cy -= 19), buttonWidth, 19, &mmd->ob_arm,
2145                                     "Armature to use as source of bones to mask");
2146                         }
2147                         else {
2148                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", 
2149                                         lx, (cy-=19), buttonWidth, 19, &mmd->vgroup, 
2150                                         0.0, 31.0, 0, 0, "Vertex Group name");
2151                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2152                         }
2153                         
2154                         uiDefButBitI(block, TOG, MOD_MASK_INV, B_MODIFIER_RECALC, "Inverse",            
2155                                 lx, (cy-=19), buttonWidth, 19, &mmd->flag, 
2156                                 0, 0, 0, 0, "Use vertices that are not part of region defined");
2157                 } else if (md->type==eModifierType_Smooth) {
2158                         SmoothModifierData *smd = (SmoothModifierData*) md;
2159
2160                         uiDefButBitS(block, TOG, MOD_SMOOTH_X, B_MODIFIER_RECALC, "X",          lx,(cy-=19),45,19, &smd->flag, 0, 0, 0, 0, "Enable X axis smoothing");
2161                         uiDefButBitS(block, TOG, MOD_SMOOTH_Y, B_MODIFIER_RECALC, "Y",          lx+45,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Y axis smoothing");
2162                         uiDefButBitS(block, TOG, MOD_SMOOTH_Z, B_MODIFIER_RECALC, "Z",          lx+90,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Z axis smoothing");
2163
2164                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &smd->fac, -10.0, 10.0, 0.5, 0, "Define the amount of smoothing, from 0.0 to 1.0 (lower / higher values can deform the mesh)");
2165                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
2166                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &smd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
2167                 } else if (md->type==eModifierType_Cast) {
2168                         CastModifierData *cmd = (CastModifierData*) md;
2169
2170                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
2171                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
2172                         uiDefButBitS(block, TOG, MOD_CAST_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) X axis deformation");
2173                         uiDefButBitS(block, TOG, MOD_CAST_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Y axis deformation");
2174                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
2175                                 uiDefButBitS(block, TOG, MOD_CAST_Z, B_MODIFIER_RECALC, "Z",            lx+90,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Z axis deformation");
2176                         }
2177                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &cmd->fac, -10.0, 10.0, 5, 0, "Define the amount of deformation");
2178                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Radius:",     lx,(cy-=19),buttonWidth, 19, &cmd->radius, 0.0, 100.0, 10.0, 0, "Only deform vertices within this distance from the center of the effect (leave as 0 for infinite)");
2179                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Size:",       lx,(cy-=19),buttonWidth, 19, &cmd->size, 0.0, 100.0, 10.0, 0, "Size of projection shape (leave as 0 for auto)");
2180                         uiDefButBitS(block, TOG, MOD_CAST_SIZE_FROM_RADIUS, B_MODIFIER_RECALC, "From radius",           lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use radius as size of projection shape (0 = auto)");
2181                         if (ob->type == OB_MESH) {
2182                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
2183                         }
2184                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx,(cy-=19), buttonWidth,19, &cmd->object, "Control object: if available, its location determines the center of the effect");
2185                         if(cmd->object) {
2186                                 uiDefButBitS(block, TOG, MOD_CAST_USE_OB_TRANSFORM, B_MODIFIER_RECALC, "Use transform",         lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use object transform to control projection shape");
2187                         }
2188                 } else if (md->type==eModifierType_Wave) {
2189                         WaveModifierData *wmd = (WaveModifierData*) md;
2190                         uiDefButBitS(block, TOG, MOD_WAVE_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &wmd->flag, 0, 0, 0, 0, "Enable X axis motion");
2191                         uiDefButBitS(block, TOG, MOD_WAVE_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &wmd->flag, 0, 0, 0, 0, "Enable Y axis motion");
2192                         uiDefButBitS(block, TOG, MOD_WAVE_CYCL, B_MODIFIER_RECALC, "Cycl",      lx+90,cy,buttonWidth-90,19, &wmd->flag, 0, 0, 0, 0, "Enable cyclic wave effect");
2193                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2194                         if (wmd->flag & MOD_WAVE_NORM){
2195                                 if (ob->type==OB_MESH) {
2196                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_X, B_MODIFIER_RECALC, "X",       lx,(cy-=19),buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the X normal");
2197                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_Y, B_MODIFIER_RECALC, "Y",       lx+(buttonWidth/3),cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Y normal");
2198                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_Z, B_MODIFIER_RECALC, "Z",       lx+(buttonWidth/3)*2,cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Z normal");
2199                                 }
2200                                 else
2201                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
2202                         }
2203
2204                         uiBlockBeginAlign(block);
2205                         if(wmd->speed >= 0)
2206                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time sta:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify starting frame of the wave");
2207                         else
2208                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time end:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify ending frame of the wave");
2209                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2210                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2211                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff:",    lx,(cy-=19),buttonWidth,19, &wmd->falloff,  0, 100, 100, 0, "Specify the falloff radius of the waves");
2212
2213                         cy -= 9;
2214                         uiBlockBeginAlign(block);
2215                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta x:",              lx,(cy-=19),113,19, &wmd->startx, -100.0, 100.0, 100, 0, "Starting position for the X axis");
2216                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta y:",              lx+115,cy,105,19, &wmd->starty, -100.0, 100.0, 100, 0, "Starting position for the Y axis");
2217                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MODIFIER_RECALC, "Ob: ", lx, (cy-=19), 220,19, &wmd->objectcenter, "Object to use as Starting Position (leave blank to disable)");
2218                         uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",lx, (cy -= 19), 220, 19,&wmd->defgrp_name, 0.0, 31.0, 0, 0, "Name of vertex group with which to modulate displacement");
2219                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2220                         sprintf(str, "Texture Coordinates%%t"
2221                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2222                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2223                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2224                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2225                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
2226                                   0.0, 1.0, 0, 0,
2227                                   "Texture coordinates used for modulation input");
2228                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
2229                                 char *strtmp;
2230                                 int i;
2231                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2232                                                              : &((Mesh*)ob->data)->fdata;
2233                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2234                                                         wmd->uvlayer_name);
2235                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2236                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2237                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2238                                 MEM_freeN(strtmp);
2239                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2240                                 uiButSetFunc(but, set_wave_uvlayer, wmd,
2241                                              &fdata->layers[i]);
2242                         }
2243                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2244                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2245                                                "Ob: ", lx, (cy -= 19), 220, 19,
2246                                                &wmd->map_object,
2247                                                "Object to get texture coordinates from");
2248                         }
2249                         cy -= 9;
2250                         uiBlockBeginAlign(block);
2251                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2252                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Height:",  lx,(cy-=19),220,19, &wmd->height, -2.0, 2.0, 0, 0, "Specify the amplitude of the wave");
2253                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Width:",   lx,(cy-=19),220,19, &wmd->width, 0.0, 5.0, 0, 0, "Specify the width of the wave");
2254                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Narrow:",  lx,(cy-=19),220,19, &wmd->narrow, 0.0, 10.0, 0, 0, "Specify how narrow the wave follows");
2255                 } else if (md->type==eModifierType_Armature) {
2256                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
2257                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2258                         
2259                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth-40,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
2260                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2261                         uiDefButBitS(block, TOG, ARM_DEF_INVERT_VGROUP, B_ARM_RECALCDATA, "Inv",        lx+buttonWidth-40,cy, 40, 20, &amd->deformflag, 0, 0, 0, 0, "Invert vertex group influence");
2262                         
2263                         uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups",       lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform");
2264                         uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes",       lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
2265                         uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion",    lx,(cy-=19),buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
2266                         uiDefButBitS(block, TOG, ARM_DEF_B_BONE_REST, B_ARM_RECALCDATA, "B-Bone Rest", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Make B-Bones deform already in rest position");
2267                         
2268                         uiDefButS(block, TOG, B_ARM_RECALCDATA, "MultiModifier",        lx,cy-=19, buttonWidth, 20, &amd->multi, 0, 0, 0, 0, "Use same input as previous modifier, and mix results using overall vgroup");
2269
2270                 } else if (md->type==eModifierType_Hook) {
2271                         HookModifierData *hmd = (HookModifierData*) md;
2272                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ",           lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends");
2273                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Force: ",          lx, (cy-=19), buttonWidth,19, &hmd->force, 0.0, 1.0, 100, 0, "Set relative force of hook");
2274                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &hmd->object, "Parent Object for hook, also recalculates and clears offset"); 
2275                         if(hmd->indexar==NULL) {
2276                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2277                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2278                         }
2279                         uiBlockBeginAlign(block);
2280                         but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reset",          lx, (cy-=19), 80,19,                    NULL, 0.0, 0.0, 0, 0, "Recalculate and clear offset (transform) of hook");
2281                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2282                         but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Recenter",       lx+80, cy, buttonWidth-80,19,   NULL, 0.0, 0.0, 0, 0, "Sets hook center to cursor position");
2283                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2284
2285                         if (editing) {
2286                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Select",                 lx, (cy-=19), 80,19, NULL, 0.0, 0.0, 0, 0, "Selects effected vertices on mesh");
2287                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
2288                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reassign",               lx+80, cy, buttonWidth-80,19, NULL, 0.0, 0.0, 0, 0, "Reassigns selected vertices to hook");
2289                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2290                         }
2291                 } else if (md->type==eModifierType_Softbody) {
2292                         uiDefBut(block, LABEL, 1, "See Soft Body panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2293                 } else if (md->type==eModifierType_Cloth) {
2294                         uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2295
2296                 } else if (md->type==eModifierType_Collision) {
2297                         uiDefBut(block, LABEL, 1, "See Collision panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2298                 } else if (md->type==eModifierType_Fluidsim) {
2299                         uiDefBut(block, LABEL, 1, "See Fluidsim panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2300                 } else if (md->type==eModifierType_Boolean) {
2301                         BooleanModifierData *bmd = (BooleanModifierData*) md;
2302                         uiDefButI(block, MENU, B_MODIFIER_RECALC, "Operation%t|Intersect%x0|Union%x1|Difference%x2",    lx,(cy-=19),buttonWidth,19, &bmd->operation, 0.0, 1.0, 0, 0, "Boolean operation to perform");
2303                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2304                 } else if (md->type==eModifierType_Array) {
2305                         ArrayModifierData *amd = (ArrayModifierData*) md;
2306                         float range = 10000;
2307                         int cytop, halfwidth = (width - 5)/2 - 15;
2308                         int halflx = lx + halfwidth + 10;
2309
2310                         uiBlockSetEmboss(block, UI_EMBOSSX);
2311                         uiBlockEndAlign(block);
2312
2313                         /* length parameters */
2314                         uiBlockBeginAlign(block);
2315                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2316                                 "|Fit To Curve Length%%x%d",
2317                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2318                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2319                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2320                                   0.0, 1.0, 0, 0, "Array length calculation method");
2321                         switch(amd->fit_type)
2322                         {
2323                         case MOD_ARR_FIXEDCOUNT:
2324                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2325                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2326                                           1, 1000, 0, 0, "Number of duplicates to make");
2327                                 break;
2328                         case MOD_ARR_FITLENGTH:
2329                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2330                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2331                                           0, range, 10, 2,
2332                                           "Length to fit array within");
2333                                 break;
2334                         case MOD_ARR_FITCURVE:
2335                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2336                                                B_CHANGEDEP, "Ob: ",
2337                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2338                                                "Curve object to fit array length to");
2339                                 break;
2340                         }
2341                         uiBlockEndAlign(block);
2342
2343                         /* offset parameters */
2344                         cy -= 10;
2345                         cytop= cy;
2346                         uiBlockBeginAlign(block);
2347                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2348                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2349                                      &amd->offset_type, 0, 0, 0, 0,
2350                                      "Constant offset between duplicates "
2351                                      "(local coordinates)");
2352                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2353                                   lx, (cy-=19), halfwidth, 19,
2354                                   &amd->offset[0],
2355                                   -range, range, 10, 3,
2356                                   "Constant component for duplicate offsets "
2357                                   "(local coordinates)");
2358                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2359                                   lx, (cy-=19), halfwidth, 19,
2360                                   &amd->offset[1],
2361                                   -range, range, 10, 3,
2362                                   "Constant component for duplicate offsets "
2363                                   "(local coordinates)");
2364                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2365                                   lx, (cy-=19), halfwidth, 19,
2366                                   &amd->offset[2],
2367                                   -range, range, 10, 3,
2368                                   "Constant component for duplicate offsets "
2369                                   "(local coordinates)");
2370                         uiBlockEndAlign(block);
2371
2372                         cy= cytop;
2373                         uiBlockBeginAlign(block);
2374                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2375                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2376                                      &amd->offset_type, 0, 0, 0, 0,
2377                                      "Offset between duplicates relative to object width "
2378                                      "(local coordinates)");
2379                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2380                                   halflx, (cy-=19), halfwidth, 19,
2381                                   &amd->scale[0],
2382                                   -range, range, 10, 3,
2383                                   "Component for duplicate offsets relative to object "
2384                                   "width (local coordinates)");
2385                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2386                                   halflx, (cy-=19), halfwidth, 19,
2387                                   &amd->scale[1],
2388                                   -range, range, 10, 3,
2389                                   "Component for duplicate offsets relative to object "
2390                                   "width (local coordinates)");
2391                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2392                                   halflx, (cy-=19), halfwidth, 19,
2393                                   &amd->scale[2],
2394                                   -range, range, 10, 3,
2395                                   "Component for duplicate offsets relative to object "
2396                                   "width (local coordinates)");
2397                         uiBlockEndAlign(block);
2398
2399                         /* vertex merging parameters */
2400                         cy -= 10;
2401                         cytop= cy;
2402
2403                         uiBlockBeginAlign(block);
2404                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2405                                      "Merge",
2406                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2407                                      0, 0, 0, 0,
2408                                      "Merge vertices in adjacent duplicates");
2409                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2410                                      "First Last",
2411                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2412                                      &amd->flags,
2413                                      0, 0, 0, 0,
2414                                      "Merge vertices in first duplicate with vertices"
2415                                      " in last duplicate");
2416                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2417                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2418                                           0, 1.0f, 1, 4,
2419                                           "Limit below which to merge vertices");
2420
2421                         /* offset ob */
2422                         cy = cytop;
2423                         uiBlockBeginAlign(block);
2424                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2425                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2426                                      &amd->offset_type, 0, 0, 0, 0,
2427                                      "Add an object transformation to the total offset");
2428                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2429                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2430                                        &amd->offset_ob,
2431                                        "Object from which to take offset transformation");
2432                         uiBlockEndAlign(block);
2433
2434                         cy -= 10;
2435                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2436                                              B_CHANGEDEP, "Start cap: ",
2437                                              lx, (cy -= 19), halfwidth, 19,
2438                                              &amd->start_cap,
2439                                              "Mesh object to use as start cap");
2440                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2441                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2442                                              B_CHANGEDEP, "End cap: ",
2443                                              halflx, cy, halfwidth, 19,
2444                                              &amd->end_cap,
2445                                              "Mesh object to use as end cap");
2446                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2447                 } else if (md->type==eModifierType_MeshDeform) {
2448                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2449
2450                         uiBlockBeginAlign(block);
2451                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2452                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-19), buttonWidth-40,19, &mmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall meshdeform influence");
2453                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2454                         uiDefButBitS(block, TOG, MOD_MDEF_INVERT_VGROUP, B_MODIFIER_RECALC, "Inv", lx+buttonWidth-40, (cy-=19), 40,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
2455
2456                         uiBlockBeginAlign(block);
2457                         if(mmd->bindcos) {
2458                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2459                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2460                         }
2461                         else {
2462                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2463                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2464                                 uiDefButS(block, NUM, B_NOP, "Precision:", lx,(cy-19), buttonWidth/2 + 20,19, &mmd->gridsize, 2, 10, 0.5, 0, "The grid size for binding");
2465                                 uiDefButBitS(block, TOG, MOD_MDEF_DYNAMIC_BIND, B_MODIFIER_RECALC, "Dynamic", lx+(buttonWidth+1)/2 + 20, (cy-=19), buttonWidth/2 - 20,19, &mmd->flag, 0.0, 31.0, 0, 0, "Recompute binding dynamically on top of other deformers like Shape Keys (slower and more memory consuming!)");
2466                         }
2467                         uiBlockEndAlign(block);
2468                 } else if (md->type==eModifierType_ParticleSystem) {
2469                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2470                 } else if (md->type==eModifierType_ParticleInstance) {
2471                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2472                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2473                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2474                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Parents, B_MODIFIER_RECALC, "Normal",    lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from normal particles");
2475                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Children, B_MODIFIER_RECALC, "Children", lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances from child particles");
2476                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Path, B_MODIFIER_RECALC, "Path", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Create instances along particle paths");
2477                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Unborn, B_MODIFIER_RECALC, "Unborn",     lx, (cy -= 19), buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are unborn");
2478                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Alive, B_MODIFIER_RECALC, "Alive",       lx+buttonWidth/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are alive");
2479                         uiDefButBitS(block, TOG, eParticleInstanceFlag_Dead, B_MODIFIER_RECALC, "Dead", lx+buttonWidth*2/3, cy, buttonWidth/3,19, &pimd->flag, 0, 0, 0, 0, "Show instances when particles are dead");
2480                 } else if (md->type==eModifierType_Explode) {
2481                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
2482                         uiBut *but;
2483                         char *menustr= get_vertexgroup_menustr(ob);
2484                         int defCount=BLI_countlist(&ob->defbase);
2485                         if(defCount==0) emd->vgroup=0;
2486                         uiBlockBeginAlign(block);
2487                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth-20,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2488                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2489                         MEM_freeN(menustr);
2490                         
2491                         but=uiDefIconBut(block, BUT, B_MODIFIER_RECALC, ICON_X, (lx+buttonWidth)-20, cy, 20,19, 0, 0, 0, 0, 0, "Disable use of vertex group");
2492                         uiButSetFunc(but, modifiers_explodeDelVg, (void *)emd, (void *)NULL);
2493                         
2494
2495                         but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx, (cy-=19), buttonWidth,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
2496                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2497
2498                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2499                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2500
2501                         uiDefButBitS(block, TOG, eExplodeFlag_EdgeSplit, B_MODIFIER_RECALC, "Split Edges",      lx+buttonWidth/2, cy, buttonWidth/2,19, &emd->flag, 0, 0, 0, 0, "Split face edges for nicer shrapnel");
2502                         uiDefButBitS(block, TOG, eExplodeFlag_Unborn, B_MODIFIER_RECALC, "Unborn",      lx, (cy-=19), buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are unborn");
2503                         uiDefButBitS(block, TOG, eExplodeFlag_Alive, B_MODIFIER_RECALC, "Alive",        lx+buttonWidth/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are alive");
2504                         uiDefButBitS(block, TOG, eExplodeFlag_Dead, B_MODIFIER_RECALC, "Dead",  lx+buttonWidth*2/3, cy, buttonWidth/3,19, &emd->flag, 0, 0, 0, 0, "Show mesh when particles are dead");
2505                         uiBlockEndAlign(block);
2506                 } else if (md->type==eModifierType_Shrinkwrap) {
2507                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
2508
2509                         char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2";
2510
2511                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
2512
2513                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2514                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2515
2516                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Offset:",     lx,(cy-=19),buttonWidth,19, &smd->keepDist, 0.0f, 100.0f, 1.0f, 0, "Specify distance to keep from the target");
2517
2518                         cy -= 3;
2519                         uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position.");
2520
2521                         if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){
2522
2523
2524                                 /* UI for projection axis */
2525                                 uiBlockBeginAlign(block);
2526                                 uiDefButC(block, ROW, B_MODIFIER_RECALC, "Normal"    , lx,(cy-=19),buttonWidth,19, &smd->projAxis, 18.0, MOD_SHRINKWRAP_PROJECT_OVER_NORMAL, 0, 0, "Projection over X axis");
2527                                 if(smd->projAxis == 0)
2528                                 {
2529                                         uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:",          lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals");
2530                                 }
2531
2532                                 uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_MODIFIER_RECALC, "X",    lx+buttonWidth/3*0,(cy-=19),buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over X axis");
2533                                 uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_MODIFIER_RECALC, "Y",    lx+buttonWidth/3*1,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Y axis");
2534                                 uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS, B_MODIFIER_RECALC, "Z",    lx+buttonWidth/3*2,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Z axis");
2535
2536
2537                                 /* allowed directions of projection axis */
2538                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR, B_MODIFIER_RECALC, "Negative",   lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the negative direction of axis");
2539                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR, B_MODIFIER_RECALC, "Positive",   lx + buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows to move the vertex in the positive direction of axis");
2540
2541                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE, B_MODIFIER_RECALC, "Cull frontfaces",lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a front face on target");
2542                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_CULL_TARGET_BACKFACE,  B_MODIFIER_RECALC, "Cull backfaces",     lx+buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Controls whether a vertex can be projected to a back face on target");
2543                                 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob2: ",        lx, (cy-=19), buttonWidth,19, &smd->auxTarget, "Aditional mesh to project over");
2544                         }
2545                         else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE){
2546                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE, B_MODIFIER_RECALC, "Above surface", lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Vertices are kept on the front side of faces");
2547                         }
2548
2549                         uiBlockEndAlign(block);
2550
2551                 }
2552
2553                 uiBlockEndAlign(block);
2554
2555                 y-=height;
2556         }
2557
2558         if (md->error) {
2559                 y -= 6;
2560
2561                 uiBlockSetCol(block, color);
2562                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2563                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2564                 uiBlockSetCol(block, TH_AUTO);
2565
2566                 uiDefIconBut(block,LABEL,B_NOP,ICON_ERROR, x-9, y,19,19, 0,0,0,0,0, "");
2567                 uiDefBut(block, LABEL, B_NOP, md->error, x+5, y, width-15, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2568
2569                 y -= 18;
2570         }
2571
2572         uiClearButLock();
2573
2574         y -= 3+6;
2575
2576         *xco = x;
2577         *yco = y;
2578 }
2579
2580 static void editing_panel_modifiers(Object *ob)
2581 {
2582         ModifierData *md;
2583         uiBlock *block;
2584         char str[64];
2585         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2586
2587         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2588         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2589         
2590         uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
2591         uiNewPanelHeight(block, 204);
2592
2593         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2594
2595         sprintf(str, "To: %s", ob->id.name+2);
2596         uiDefBut(block, LABEL, 1, str,  140, 190, 160, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2597
2598         xco = 0;
2599         yco = 160;
2600
2601         md = modifiers_getVirtualModifierList(ob);
2602
2603         for (i=0; md; i++, md=md->next) {
2604                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2605                 if (md->mode&eModifierMode_Virtual) i--;
2606         }
2607         
2608         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2609 }
2610
2611 static char *make_key_menu(Key *key, int startindex)
2612 {
2613         KeyBlock *kb;
2614         int index= 1;
2615         char *str, item[64];
2616
2617         for (kb = key->block.first; kb; kb=kb->next, index++);
2618         str= MEM_mallocN(index*40, "key string");
2619         str[0]= 0;
2620         
2621         index= startindex;
2622         for (kb = key->block.first; kb; kb=kb->next, index++) {
2623                 sprintf (item,  "|%s%%x%d", kb->name, index);
2624                 strcat(str, item);
2625         }
2626         
2627         return str;
2628 }
2629
2630 static void editing_panel_shapes(Object *ob)
2631 {
2632         uiBlock *block;
2633         Key *key= NULL;
2634         KeyBlock *kb;
2635         int icon;
2636         char *strp;
2637         
2638         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2639         uiNewPanelTabbed("Modifiers", "Editing");
2640         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2641         
2642         /* Todo check data is library here */
2643         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2644         
2645         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2646         
2647         key= ob_get_key(ob);
2648         if(key==NULL) {
2649                 /* label aligns add button */
2650                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2651                 return;
2652         }
2653         
2654         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2655
2656         kb= BLI_findlink(&key->block, ob->shapenr-1);
2657         if(kb==NULL) {
2658                 ob->shapenr= 1;
2659                 kb= key->block.first;
2660         }
2661
2662         uiBlockBeginAlign(block);
2663         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2664         uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
2665         if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
2666         uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
2667         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2668         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2669         strp= make_key_menu(key, 1);
2670         uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2671         MEM_freeN(strp);
2672         
2673         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2674         uiClearButLock();
2675         uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2676         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2677         uiBlockEndAlign(block);
2678
2679         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2680                 uiBlockBeginAlign(block);
2681                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2682                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2683                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2684                 uiBlockEndAlign(block);
2685         }
2686         if(key->type && ob->shapenr!=1) {
2687                 uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",     10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape");
2688
2689                 strp= make_key_menu(key, 0);
2690                 uiDefButS(block, MENU, B_MODIFIER_RECALC, strp,         160, 90, 150,19, &kb->relative, 0.0, 0.0, 0, 0, "Shape used as a relative key");
2691                 MEM_freeN(strp);
2692         }
2693         
2694         if(key->type==0)
2695                 uiDefButS(block, NUM, B_DIFF, "Slurph:",                        10, 60, 150, 19, &(key->slurph), -500.0, 500.0, 0, 0, "Creates a delay in amount of frames in applying keypositions, first vertex goes first");
2696         
2697 }
2698
2699 /* *************************** FONT ******************************** */
2700
2701 static short give_vfontnr(VFont *vfont)
2702 {
2703         VFont *vf;
2704         short nr= 1;
2705
2706         vf= G.main->vfont.first;
2707         while(vf) {
2708                 if(vf==vfont) return nr;
2709                 nr++;
2710                 vf= vf->id.next;
2711         }
2712         return -1;
2713 }
2714
2715 static VFont *give_vfontpointer(int nr) /* nr= button */
2716 {
2717         VFont *vf;
2718         short tel= 1;
2719
2720         vf= G.main->vfont.first;
2721         while(vf) {
2722                 if(tel==nr) return vf;
2723                 tel++;
2724                 vf= vf->id.next;
2725         }
2726         return G.main->vfont.first;
2727 }
2728
2729 VFont *exist_vfont(char *str)
2730 {
2731         VFont *vf;
2732
2733         vf= G.main->vfont.first;
2734         while(vf) {
2735                 if(strcmp(vf->name, str)==0) return vf;
2736                 vf= vf->id.next;
2737         }
2738         return 0;
2739 }
2740
2741 static char *give_vfontbutstr(void)
2742 {
2743         VFont *vf;
2744         int len= 0;
2745         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2746
2747         vf= G.main->vfont.first;
2748         while(vf) {
2749                 strcpy(di, vf->name);
2750                 BLI_splitdirstring(di, fi);
2751                 len+= strlen(fi)+4;
2752                 vf= vf->id.next;
2753         }
2754
2755         str= MEM_callocN(len+21, "vfontbutstr");
2756         strcpy(str, "FONTS %t");
2757         vf= G.main->vfont.first;
2758         while(vf) {
2759
2760                 if(vf->id.us==0) strcat(str, "|0 ");
2761                 else strcat(str, "|   ");
2762
2763                 strcpy(di, vf->name);
2764                 BLI_splitdirstring(di, fi);
2765
2766                 strcat(str, fi);
2767                 vf= vf->id.next;
2768         }
2769         return str;
2770 }
2771
2772 static void load_buts_vfont(char *name)
2773 {
2774         VFont *vf;
2775         Curve *cu;
2776
2777         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2778         else return;
2779
2780         vf= exist_vfont(name);
2781         if(vf==0) {
2782                 vf= load_vfont(name);
2783                 if(vf==0) return;
2784         }
2785         else id_us_plus((ID *)vf);
2786         
2787         switch(cu->curinfo.flag & CU_STYLE) {
2788                 case CU_BOLD:
2789                         if(cu->vfontb) cu->vfontb->id.us--;
2790                         cu->vfontb= vf;
2791                         break;
2792                 case CU_ITALIC:
2793                         if(cu->vfonti) cu->vfonti->id.us--;             
2794                         cu->vfonti= vf;
2795                         break;                                          
2796                 case (CU_BOLD|CU_ITALIC):
2797                         if(cu->vfontbi) cu->vfontbi->id.us--;
2798                         cu->vfontbi= vf;
2799                         break;
2800                 default:
2801                         if(cu->vfont) cu->vfont->id.us--;
2802                         cu->vfont= vf;
2803                         break;                                          
2804         }       
2805
2806         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2807         BIF_undo_push("Load vector font");
2808         allqueue(REDRAWVIEW3D, 0);
2809         allqueue(REDRAWBUTSEDIT, 0);
2810 }
2811
2812 static void set_unicode_text_fs(char *file)
2813 {
2814         if (file) paste_unicodeText(file); 
2815 }
2816
2817 void do_fontbuts(unsigned short event)
2818 {
2819         Curve *cu;
2820         VFont *vf;
2821         Object *ob;
2822         ScrArea *sa;
2823         char str[80];
2824         int ctevt;
2825         char *ctmenu;
2826         DynStr *ds;
2827         int i, style=0;
2828
2829         ob= OBACT;
2830
2831         switch(event) {
2832         case B_MAKEFONT:
2833                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2834                 allqueue(REDRAWVIEW3D, 0);
2835                 break;
2836
2837         case B_STYLETOSELU:     
2838         case B_STYLETOSELB:
2839         case B_STYLETOSELI:
2840                 switch (event) {
2841                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2842                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2843                         case B_STYLETOSELI: style = CU_ITALIC; break;
2844                 }
2845                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2846                         text_to_curve(ob, 0);
2847                         makeDispListCurveTypes(ob, 0);
2848                         allqueue(REDRAWVIEW3D, 0);
2849                 }
2850                 allqueue(REDRAWBUTSEDIT, 0);
2851                 break;          
2852                 
2853         case B_FASTFONT:
2854                 if (G.obedit) {
2855                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2856                         allqueue(REDRAWVIEW3D, 0);
2857                 }
2858                 break;
2859         case B_INSTB:
2860                 cu= ob->data;
2861                 if (cu->totbox < 256) {
2862                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2863                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2864                         cu->actbox++;
2865                         cu->totbox++;
2866                         allqueue(REDRAWBUTSEDIT, 0);
2867                         allqueue(REDRAWVIEW3D, 0);
2868                         text_to_curve(ob, 0);
2869                         makeDispListCurveTypes(ob, 0);
2870                 }
2871                 else {
2872                         error("Do you really need that many text frames?");
2873                 }
2874                 break;
2875         case B_DELTB:
2876                 cu= ob->data;
2877                 if (cu->totbox > 1) {
2878                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2879                         cu->totbox--;
2880                         cu->actbox--;
2881                         allqueue(REDRAWBUTSEDIT, 0);
2882                         allqueue(REDRAWVIEW3D, 0);
2883                         text_to_curve(ob, 0);
2884                         makeDispListCurveTypes(ob, 0);
2885                 }
2886                 break;
2887         case B_TOUPPER:
2888                 to_upper();
2889                 break;
2890         case B_LOADFONT:
2891                 vf= give_vfontpointer(G.buts->texnr);
2892                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2893                 else strcpy(str, U.fontdir);
2894
2895                 sa= closest_bigger_area();
2896                 areawinset(sa->win);
2897
2898                 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2899