a21dc8b0f5dc8904f716f89716971bffa46ff484
[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                                 allqueue(REDRAWVIEW3D, 0);
517                         }
518                         else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
519                                 nu= editNurb.first;
520                                 while(nu) {
521                                         if(nu->mat_nr==G.obedit->actcol-1) {
522                                                 if(nu->bezt) {
523                                                         a= nu->pntsu;
524                                                         bezt= nu->bezt;
525                                                         while(a--) {
526                                                                 if(bezt->hide==0) {
527                                                                         if(event==B_MATSEL) {
528                                                                                 bezt->f1 |= SELECT;
529                                                                                 bezt->f2 |= SELECT;
530                                                                                 bezt->f3 |= SELECT;
531                                                                         }
532                                                                         else {
533                                                                                 bezt->f1 &= ~SELECT;
534                                                                                 bezt->f2 &= ~SELECT;
535                                                                                 bezt->f3 &= ~SELECT;
536                                                                         }
537                                                                 }
538                                                                 bezt++;
539                                                         }
540                                                 }
541                                                 else if(nu->bp) {
542                                                         a= nu->pntsu*nu->pntsv;
543                                                         bp= nu->bp;
544                                                         while(a--) {
545                                                                 if(bp->hide==0) {
546                                                                         if(event==B_MATSEL) bp->f1 |= SELECT;
547                                                                         else bp->f1 &= ~SELECT;
548                                                                 }
549                                                                 bp++;
550                                                         }
551                                                 }
552                                         }
553                                         nu= nu->next;
554                                 }
555                                 BIF_undo_push("Select material index");
556                                 allqueue(REDRAWVIEW3D, 0);
557                         }
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 object_add_modifier(Object *ob, ModifierData *md)
942 {
943         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
944         if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
945                 ModifierData *iter = ob->modifiers.first;
946
947                 while (iter && modifierType_getInfo(iter->type)->type==eModifierTypeType_OnlyDeform) {
948                         iter = iter->next;
949                 }
950
951                 BLI_insertlinkbefore(&ob->modifiers, iter, md);
952         } else {
953                 BLI_addtail(&ob->modifiers, md);
954         }
955 }
956
957 static void modifiers_add(void *ob_v, int type)
958 {
959         object_add_modifier((Object*) ob_v, modifier_new(type));
960         BIF_undo_push("Add modifier");
961 }
962
963 static void do_modifiers_select_simpledeform_typemenu(void *ob_v, int event)
964 {
965         static const char *default_name[] = { "", "Twist", "Bend", "Taper X", "Taper XY", "Strech", "Squash" };
966         SimpleDeformModifierData *smd = (SimpleDeformModifierData*)modifier_new(eModifierType_SimpleDeform);
967         smd->mode = event;
968
969         if(smd->mode >= 0 && smd->mode < sizeof(default_name)/sizeof(*default_name))
970                 strncpy( smd->modifier.name, default_name[ smd->mode ], sizeof(smd->modifier.name));
971
972         object_add_modifier((Object*) ob_v, (ModifierData*)smd);
973         BIF_undo_push("Add modifier");
974         do_modifier_panels(B_MODIFIER_RECALC);
975 }
976
977 static uiBlock *modifiers_select_simpledeform_typemenu(void *ob_v)
978 {
979         uiBlock *block;
980         short yco = 20, menuwidth = 120;
981
982         block= uiNewBlock(&curarea->uiblocks, "modifiers_select_simpledeform_typemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
983         uiBlockSetButmFunc(block, do_modifiers_select_simpledeform_typemenu, ob_v);
984
985         uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Twist",               0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_TWIST, "");
986         uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Bend",                0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_BEND, "");
987         uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Tapper X",    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_TAPER_X, "");
988         uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Tapper XY",   0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_TAPER_XY, "");
989         uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Strech",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_STRECH, "");
990         uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Squash",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_SQUASH, "");
991         
992         uiBlockSetDirection(block, UI_RIGHT);
993         uiTextBoundsBlock(block, 50);
994         return block;
995 }
996
997
998 typedef struct MenuEntry {
999         char *name;
1000         int ID;
1001 } MenuEntry;
1002
1003 static int menuEntry_compare_names(const void *entry1, const void *entry2)
1004 {
1005         return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
1006 }
1007
1008 static uiBlock *modifiers_add_menu(void *ob_v)
1009 {
1010         Object *ob = ob_v;
1011         uiBlock *block;
1012         int i, yco=0;
1013         int numEntries = 0;
1014         MenuEntry entries[NUM_MODIFIER_TYPES];
1015         
1016         block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
1017                           UI_EMBOSSP, UI_HELV, curarea->win);
1018         uiBlockSetButmFunc(block, modifiers_add, ob);
1019
1020         for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
1021                 ModifierTypeInfo *mti = modifierType_getInfo(i);
1022
1023                 /* Only allow adding through appropriate other interfaces */
1024                 if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
1025                 
1026                 if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
1027
1028                 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
1029                    (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
1030                         entries[numEntries].name = mti->name;
1031                         entries[numEntries].ID = i;
1032
1033                         ++numEntries;
1034                 }
1035         }
1036
1037         qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
1038
1039
1040         for(i = 0; i < numEntries; ++i)
1041         {
1042                 if(entries[i].ID == eModifierType_SimpleDeform)
1043                 {
1044                         //TODO: this menu has a left space.. which loooks ugly :S
1045                         uiDefIconTextBlockBut(block, modifiers_select_simpledeform_typemenu, ob_v, ICON_RIGHTARROW_THIN, entries[i].name, 0, yco-=20, 160, 19, "");
1046                 }
1047                 else
1048                 {
1049                         uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
1050                                  0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
1051                 }
1052         }
1053
1054         uiTextBoundsBlock(block, 50);
1055         uiBlockSetDirection(block, UI_DOWN);
1056
1057         return block;
1058 }
1059
1060 static void modifiers_del(void *ob_v, void *md_v)
1061 {
1062         Object *ob = ob_v;
1063         ModifierData *md;
1064
1065                 /* It seems on rapid delete it is possible to
1066                  * get called twice on same modifier, so make
1067                  * sure it is in list.
1068                  */
1069         for (md=ob->modifiers.first; md; md=md->next)
1070                 if (md==md_v)
1071                         break;
1072         
1073         if (!md)
1074                 return;
1075
1076         if(md->type==eModifierType_ParticleSystem){
1077                 ParticleSystemModifierData *psmd=(ParticleSystemModifierData*)md;
1078                 BLI_remlink(&ob->particlesystem, psmd->psys);
1079                 psys_free(ob,psmd->psys);
1080         }
1081
1082         BLI_remlink(&ob->modifiers, md_v);
1083
1084         modifier_free(md_v);
1085
1086         BIF_undo_push("Del modifier");
1087 }
1088
1089 int mod_moveUp(void *ob_v, void *md_v)
1090 {
1091         Object *ob = ob_v;
1092         ModifierData *md = md_v;
1093
1094         if (md->prev) {
1095                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1096
1097                 if (mti->type!=eModifierTypeType_OnlyDeform) {
1098                         ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1099
1100                         if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1101                                 return -1;
1102                 }
1103
1104                 BLI_remlink(&ob->modifiers, md);
1105                 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1106         }
1107
1108         return 0;
1109 }
1110
1111 static void modifiers_moveUp(void *ob_v, void *md_v)
1112 {
1113         if( mod_moveUp( ob_v, md_v ) )
1114                 error("Cannot move above a modifier requiring original data.");
1115         else
1116                 BIF_undo_push("Move modifier");
1117 }
1118
1119 int mod_moveDown(void *ob_v, void *md_v)
1120 {
1121         Object *ob = ob_v;
1122         ModifierData *md = md_v;
1123
1124         if (md->next) {
1125                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1126
1127                 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1128                         ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1129
1130                         if (nmti->type!=eModifierTypeType_OnlyDeform)
1131                                 return -1;
1132                 }
1133
1134                 BLI_remlink(&ob->modifiers, md);
1135                 BLI_insertlink(&ob->modifiers, md->next, md);
1136         }
1137
1138         return 0;
1139 }
1140
1141 static void modifiers_moveDown(void *ob_v, void *md_v)
1142 {
1143         if( mod_moveDown( ob_v, md_v ) )
1144                 error("Cannot move beyond a non-deforming modifier.");
1145         else
1146                 BIF_undo_push("Move modifier");
1147 }
1148
1149 static void modifier_testLatticeObj(char *name, ID **idpp)
1150 {
1151         ID *id;
1152
1153         for (id= G.main->object.first; id; id= id->next) {
1154                 if( strcmp(name, id->name+2)==0 ) {
1155                         if (((Object *)id)->type != OB_LATTICE) {
1156                                 error ("Lattice deform object must be a lattice");
1157                                 break;
1158                         } 
1159                         *idpp= id;
1160                         return;
1161                 }
1162         }
1163         *idpp= 0;
1164 }
1165
1166 static void modifier_testCurveObj(char *name, ID **idpp)
1167 {
1168         ID *id;
1169
1170         for (id= G.main->object.first; id; id= id->next) {
1171                 if( strcmp(name, id->name+2)==0 ) {
1172                         if (((Object *)id)->type != OB_CURVE) {
1173                                 error ("Curve deform object must be a curve");
1174                                 break;
1175                         } 
1176                         *idpp= id;
1177                         return;
1178                 }
1179         }
1180         *idpp= 0;
1181 }
1182
1183 static void modifier_testMeshObj(char *name, ID **idpp)
1184 {
1185         ID *id;
1186
1187         for (id= G.main->object.first; id; id= id->next) {
1188                 /* no boolean on its own object */
1189                 if(id != (ID *)OBACT) {
1190                         if( strcmp(name, id->name+2)==0 ) {
1191                                 if (((Object *)id)->type != OB_MESH) {
1192                                         error ("Boolean modifier object must be a mesh");
1193                                         break;
1194                                 } 
1195                                 *idpp= id;
1196                                 return;
1197                         }
1198                 }
1199         }
1200         *idpp= NULL;
1201 }
1202
1203 static void modifier_testArmatureObj(char *name, ID **idpp)
1204 {
1205         ID *id;
1206
1207         for (id= G.main->object.first; id; id= id->next) {
1208                 if( strcmp(name, id->name+2)==0 ) {
1209                         if (((Object *)id)->type != OB_ARMATURE) {
1210                                 error ("Armature deform object must be an armature");
1211                                 break;
1212                         } 
1213                         *idpp= id;
1214                         return;
1215                 }
1216         }
1217         *idpp= 0;
1218 }
1219
1220 static void modifier_testTexture(char *name, ID **idpp)
1221 {
1222         ID *id;
1223
1224         for(id = G.main->tex.first; id; id = id->next) {
1225                 if(strcmp(name, id->name + 2) == 0) {
1226                         *idpp = id;
1227                         /* texture gets user, objects not: delete object = clear modifier */
1228                         id_us_plus(id);
1229                         return;
1230                 }
1231         }
1232         *idpp = 0;
1233 }
1234
1235 #if 0 /* this is currently unused, but could be useful in the future */
1236 static void modifier_testMaterial(char *name, ID **idpp)
1237 {
1238         ID *id;
1239
1240         for(id = G.main->mat.first; id; id = id->next) {
1241                 if(strcmp(name, id->name + 2) == 0) {
1242                         *idpp = id;
1243                         return;
1244                 }
1245         }
1246         *idpp = 0;
1247 }
1248 #endif
1249
1250 static void modifier_testImage(char *name, ID **idpp)
1251 {
1252         ID *id;
1253
1254         for(id = G.main->image.first; id; id = id->next) {
1255                 if(strcmp(name, id->name + 2) == 0) {
1256                         *idpp = id;
1257                         return;
1258                 }
1259         }
1260         *idpp = 0;
1261 }
1262
1263 /* autocomplete callback for ID buttons */
1264 void autocomplete_image(char *str, void *arg_v)
1265 {
1266         /* search if str matches the beginning of an ID struct */
1267         if(str[0]) {
1268                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1269                 ID *id;
1270
1271                 for(id = G.main->image.first; id; id = id->next)
1272                         autocomplete_do_name(autocpl, id->name+2);
1273
1274                 autocomplete_end(autocpl, str);
1275         }
1276 }
1277
1278 /* autocomplete callback for ID buttons */
1279 void autocomplete_meshob(char *str, void *arg_v)
1280 {
1281         /* search if str matches the beginning of an ID struct */
1282         if(str[0]) {
1283                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1284                 ID *id;
1285
1286                 for(id = G.main->object.first; id; id = id->next)
1287                         if(((Object *)id)->type == OB_MESH)
1288                                 autocomplete_do_name(autocpl, id->name+2);
1289
1290                 autocomplete_end(autocpl, str);
1291         }
1292 }
1293 static void modifiers_convertParticles(void *obv, void *mdv)
1294 {
1295         Object *obn;
1296         ModifierData *md = mdv;
1297         ParticleSystem *psys;
1298         ParticleCacheKey *key, **cache;
1299         Mesh *me;
1300         MVert *mvert;
1301         MEdge *medge;
1302         int a, k, kmax;
1303         int totvert=0, totedge=0, cvert=0;
1304         int totpart=0, totchild=0;
1305
1306         if(md->type != eModifierType_ParticleSystem) return;
1307
1308         if(G.f & G_PARTICLEEDIT) return;
1309
1310         psys=((ParticleSystemModifierData *)md)->psys;
1311
1312         if(psys->part->draw_as != PART_DRAW_PATH || psys->pathcache == 0) return;
1313
1314         totpart= psys->totcached;
1315         totchild= psys->totchildcache;
1316
1317         if(totchild && (psys->part->draw&PART_DRAW_PARENT)==0)
1318                 totpart= 0;
1319
1320         /* count */
1321         cache= psys->pathcache;
1322         for(a=0; a<totpart; a++) {
1323                 key= cache[a];
1324                 totvert+= key->steps+1;
1325                 totedge+= key->steps;
1326         }
1327
1328         cache= psys->childcache;
1329         for(a=0; a<totchild; a++) {
1330                 key= cache[a];
1331                 totvert+= key->steps+1;
1332                 totedge+= key->steps;
1333         }
1334
1335         if(totvert==0) return;
1336
1337         /* add new mesh */
1338         obn= add_object(OB_MESH);
1339         me= obn->data;
1340         
1341         me->totvert= totvert;
1342         me->totedge= totedge;
1343         
1344         me->mvert= CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
1345         me->medge= CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
1346         me->mface= CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, 0);
1347         
1348         mvert= me->mvert;
1349         medge= me->medge;
1350
1351         /* copy coordinates */
1352         cache= psys->pathcache;
1353         for(a=0; a<totpart; a++) {
1354                 key= cache[a];
1355                 kmax= key->steps;
1356                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1357                         VECCOPY(mvert->co,key->co);
1358                         if(k) {
1359                                 medge->v1= cvert-1;
1360                                 medge->v2= cvert;
1361                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1362                                 medge++;
1363                         }
1364                 }
1365         }
1366
1367         cache=psys->childcache;
1368         for(a=0; a<totchild; a++) {
1369                 key=cache[a];
1370                 kmax=key->steps;
1371                 for(k=0; k<=kmax; k++,key++,cvert++,mvert++) {
1372                         VECCOPY(mvert->co,key->co);
1373                         if(k) {
1374                                 medge->v1=cvert-1;
1375                                 medge->v2=cvert;
1376                                 medge->flag= ME_EDGEDRAW|ME_EDGERENDER|ME_LOOSEEDGE;
1377                                 medge++;
1378                         }
1379                 }
1380         }
1381
1382         DAG_scene_sort(G.scene);
1383 }
1384
1385 static void modifiers_applyModifier(void *obv, void *mdv)
1386 {
1387         Object *ob = obv;
1388         ModifierData *md = mdv;
1389         DerivedMesh *dm;
1390         Mesh *me = ob->data;
1391         int converted = 0;
1392
1393         if (G.obedit) {
1394                 error("Modifiers cannot be applied in editmode");
1395                 return;
1396         } else if (((ID*) ob->data)->us>1) {
1397                 error("Modifiers cannot be applied to multi-user data");
1398                 return;
1399         }
1400
1401         if (md!=ob->modifiers.first) {
1402                 if (!okee("Modifier is not first"))
1403                         return;
1404         }
1405
1406         if (ob->type==OB_MESH) {
1407                 if(me->mr && multires_modifier_warning()) {
1408                         error("Modifier changes topology; cannot apply with multires active");
1409                         return;
1410                 }
1411                 if(me->key) {
1412                         error("Modifier cannot be applied to Mesh with Shape Keys");
1413                         return;
1414                 }
1415         
1416                 mesh_pmv_off(ob, me);
1417         
1418                 dm = mesh_create_derived_for_modifier(ob, md);
1419                 if (!dm) {
1420                         error("Modifier is disabled or returned error, skipping apply");
1421                         return;
1422                 }
1423
1424                 DM_to_mesh(dm, me);
1425                 converted = 1;
1426
1427                 dm->release(dm);
1428         } 
1429         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1430                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1431                 Curve *cu = ob->data;
1432                 int numVerts;
1433                 float (*vertexCos)[3];
1434
1435                 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1436                         return;
1437
1438                 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1439                         error("Modifier is disabled, skipping apply");
1440                         return;
1441                 }
1442
1443                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1444                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1445                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1446
1447                 converted = 1;
1448
1449                 MEM_freeN(vertexCos);
1450
1451                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1452         }
1453         else {
1454                 error("Cannot apply modifier for this object type");
1455                 return;
1456         }
1457
1458         if (converted) {
1459                 BLI_remlink(&ob->modifiers, md);
1460                 modifier_free(md);
1461
1462                 BIF_undo_push("Apply modifier");
1463         }
1464 }
1465
1466 static void modifiers_copyModifier(void *ob_v, void *md_v)
1467 {
1468         Object *ob = ob_v;
1469         ModifierData *md = md_v;
1470         ModifierData *nmd = modifier_new(md->type);
1471
1472         modifier_copyData(md, nmd);
1473
1474         BLI_insertlink(&ob->modifiers, md, nmd);
1475
1476         BIF_undo_push("Copy modifier");
1477 }
1478
1479 static void modifiers_setOnCage(void *ob_v, void *md_v)
1480 {
1481         Object *ob = ob_v;
1482         ModifierData *md;
1483         
1484         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1485
1486         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1487                 if( md == md_v ) {
1488                         if( i >= cageIndex )
1489                                 md->mode ^= eModifierMode_OnCage;
1490                         break;
1491                 }
1492 }
1493
1494 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1495 {
1496         Object *ob = ob_v;
1497         ModifierData *md = md_v;
1498         HookModifierData *hmd = (HookModifierData*) md;
1499         
1500         if (hmd->object) {
1501                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1502                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1503                 BIF_undo_push("Clear hook offset");
1504         }
1505 }
1506
1507 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1508 {
1509         Object *ob = ob_v;
1510         ModifierData *md = md_v;
1511         HookModifierData *hmd = (HookModifierData*) md;
1512
1513         if (G.vd) {
1514                 float *curs = give_cursor();
1515                 float bmat[3][3], imat[3][3];
1516
1517                 where_is_object(ob);
1518         
1519                 Mat3CpyMat4(bmat, ob->obmat);
1520                 Mat3Inv(imat, bmat);
1521
1522                 curs= give_cursor();
1523                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1524                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1525                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1526                 Mat3MulVecfl(imat, hmd->cent);
1527
1528                 BIF_undo_push("Hook cursor center");
1529         }
1530 }
1531
1532 static void modifiers_selectHook(void *ob_v, void *md_v)
1533 {
1534         ModifierData *md = md_v;
1535         HookModifierData *hmd = (HookModifierData*) md;
1536
1537         hook_select(hmd);
1538 }
1539
1540 static void modifiers_reassignHook(void *ob_v, void *md_v)
1541 {
1542         ModifierData *md = md_v;
1543         HookModifierData *hmd = (HookModifierData*) md;
1544         float cent[3];
1545         int *indexar, tot, ok;
1546         char name[32];
1547                 
1548         ok= hook_getIndexArray(&tot, &indexar, name, cent);
1549
1550         if (!ok) {
1551                 error("Requires selected vertices or active Vertex Group");
1552         } else {
1553                 if (hmd->indexar) {
1554                         MEM_freeN(hmd->indexar);
1555                 }
1556
1557                 VECCOPY(hmd->cent, cent);
1558                 hmd->indexar = indexar;
1559                 hmd->totindex = tot;
1560         }
1561 }
1562
1563 static void modifiers_convertToReal(void *ob_v, void *md_v)
1564 {
1565         Object *ob = ob_v;
1566         ModifierData *md = md_v;
1567         ModifierData *nmd = modifier_new(md->type);
1568
1569         modifier_copyData(md, nmd);
1570         nmd->mode &= ~eModifierMode_Virtual;
1571
1572         BLI_addhead(&ob->modifiers, nmd);
1573
1574         ob->partype = PAROBJECT;
1575
1576         BIF_undo_push("Modifier convert to real");
1577 }
1578
1579 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1580                                     int *uvlayer_tmp, char *uvlayer_name)
1581 {
1582         char strtmp[38];
1583         int totuv, i;
1584         CustomDataLayer *layer
1585                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1586
1587         *uvlayer_tmp = -1;
1588
1589         totuv = CustomData_number_of_layers(data, CD_MTFACE);
1590
1591         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1592                                    "menu_string");
1593         sprintf(*menu_string, "UV Layer%%t");
1594         for(i = 0; i < totuv; i++) {
1595                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1596                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1597                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1598                 strcat(*menu_string, strtmp);
1599                 layer++;
1600         }
1601
1602         /* there is no uvlayer defined, or else it was deleted. Assign active
1603          * layer, then recalc modifiers.
1604          */
1605         if(*uvlayer_tmp == -1) {
1606                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1607                         *uvlayer_tmp = 1;
1608                         layer = data->layers;
1609                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1610                             i++, layer++) {
1611                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1612                         }
1613                         strcpy(uvlayer_name, layer->name);
1614
1615                         /* update the modifiers */
1616                         do_modifier_panels(B_MODIFIER_RECALC);
1617                 } else {
1618                         /* ok we have no uv layers, so make sure menu button knows that.*/
1619                         *uvlayer_tmp = 0;
1620                 }
1621         }
1622 }
1623
1624 void set_displace_uvlayer(void *arg1, void *arg2)
1625 {
1626         DisplaceModifierData *dmd=arg1;
1627         CustomDataLayer *layer = arg2;
1628
1629         /*check we have UV layers*/
1630         if (dmd->uvlayer_tmp < 1) return;
1631         layer = layer + (dmd->uvlayer_tmp-1);
1632         
1633         strcpy(dmd->uvlayer_name, layer->name);
1634 }
1635
1636 void set_uvproject_uvlayer(void *arg1, void *arg2)
1637 {
1638         UVProjectModifierData *umd=arg1;
1639         CustomDataLayer *layer = arg2;
1640
1641         /*check we have UV layers*/
1642         if (umd->uvlayer_tmp < 1) return;
1643         layer = layer + (umd->uvlayer_tmp-1);
1644         
1645         strcpy(umd->uvlayer_name, layer->name);
1646 }
1647
1648 static void modifiers_bindMeshDeform(void *ob_v, void *md_v)
1649 {
1650         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md_v;
1651         Object *ob = (Object*)ob_v;
1652
1653         if(mmd->bindcos) {
1654                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1655                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1656                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1657                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1658                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1659                 mmd->bindweights= NULL;
1660                 mmd->bindcos= NULL;
1661                 mmd->dyngrid= NULL;
1662                 mmd->dyninfluences= NULL;
1663                 mmd->dynverts= NULL;
1664                 mmd->totvert= 0;
1665                 mmd->totcagevert= 0;
1666                 mmd->totinfluence= 0;
1667         }
1668         else {
1669                 DerivedMesh *dm;
1670                 int mode= mmd->modifier.mode;
1671
1672                 /* force modifier to run, it will call binding routine */
1673                 mmd->needbind= 1;
1674                 mmd->modifier.mode |= eModifierMode_Realtime;
1675
1676                 if(ob->type == OB_MESH) {
1677                         dm= mesh_create_derived_view(ob, 0);
1678                         dm->release(dm);
1679                 }
1680                 else if(ob->type == OB_LATTICE) {
1681                         lattice_calc_modifiers(ob);
1682                 }
1683                 else if(ob->type==OB_MBALL) {
1684                         makeDispListMBall(ob);
1685                 }
1686                 else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1687                         makeDispListCurveTypes(ob, 0);
1688                 }
1689
1690                 mmd->needbind= 0;
1691                 mmd->modifier.mode= mode;
1692         }
1693 }
1694
1695 void modifiers_explodeFacepa(void *arg1, void *arg2)
1696 {
1697         ExplodeModifierData *emd=arg1;
1698
1699         emd->flag |= eExplodeFlag_CalcFaces;
1700 }
1701
1702 void modifiers_explodeDelVg(void *arg1, void *arg2)
1703 {
1704         ExplodeModifierData *emd=arg1;
1705         emd->vgroup = 0;
1706 }
1707
1708 static int modifier_is_fluid_particles(ModifierData *md) {
1709         if(md->type == eModifierType_ParticleSystem) {
1710                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
1711                         return 1;
1712         }
1713         return 0;
1714 }
1715
1716 static void modifier_link_new_empty(void *pp_empty, void *p_parent)
1717 {
1718         Object **empty = (Object**)pp_empty;
1719         Object *parent = (Object*) p_parent;
1720
1721         /* Add object but witouth chaing layers and or changing active object */
1722         Base *base= BASACT, *newbase;
1723
1724         (*empty) = add_object(OB_EMPTY);
1725
1726         newbase= BASACT;
1727         newbase->lay= base->lay;
1728         (*empty)->lay= newbase->lay;
1729
1730         /* restore, add_object sets active */
1731         BASACT= base;
1732
1733         /* Makes parent relation and positions empty on center of object */
1734         (*empty)->partype= PAROBJECT;
1735         (*empty)->parent = parent;
1736         Mat4CpyMat4( (*empty)->obmat, parent->obmat );
1737         Mat4Invert(  (*empty)->parentinv, parent->obmat);
1738         apply_obmat( (*empty) );
1739         DAG_scene_sort(G.scene);
1740 }
1741
1742 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1743 {
1744         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1745         uiBut *but;
1746         int isVirtual = md->mode&eModifierMode_Virtual;
1747         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1748         int editing = (G.obedit==ob);
1749         short height=26, width = 295, buttonWidth = width-120-10;
1750         char str[128];
1751
1752         /* rounded header */
1753         uiBlockSetCol(block, color);
1754                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1755         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1756                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1757         uiBlockSetCol(block, TH_AUTO);
1758         
1759         /* open/close icon */
1760         if (!isVirtual) {
1761                 uiBlockSetEmboss(block, UI_EMBOSSN);
1762                 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");
1763         }
1764
1765         uiBlockSetEmboss(block, UI_EMBOSS);
1766         
1767         if (isVirtual) {
1768                 sprintf(str, "%s parent deform", md->name);
1769                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1770
1771                 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");
1772                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1773         } else {
1774                 uiBlockBeginAlign(block);
1775                 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"); 
1776
1777                 /* Softbody not allowed in this situation, enforce! */
1778                 if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
1779                         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");
1780                         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");
1781                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1782                                 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)");
1783                         }
1784                 }
1785                 uiBlockEndAlign(block);
1786
1787                 uiBlockSetEmboss(block, UI_EMBOSSR);
1788
1789                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1790                         int icon, color;
1791
1792                         if (index==cageIndex) {
1793                                 color = TH_BUT_SETTING;
1794                                 icon = VICON_EDITMODE_HLT;
1795                         } else if (index<cageIndex) {
1796                                 color = TH_BUT_NEUTRAL;
1797                                 icon = VICON_EDITMODE_DEHLT;
1798                         } else {
1799                                 color = TH_BUT_NEUTRAL;
1800                                 icon = ICON_BLANK1;
1801                         }
1802                         uiBlockSetCol(block, color);
1803                         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");
1804                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1805                         uiBlockSetCol(block, TH_AUTO);
1806                 }
1807
1808                 uiBlockSetCol(block, TH_BUT_ACTION);
1809
1810                 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");
1811                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1812
1813                 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");
1814                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1815                 
1816                 uiBlockSetEmboss(block, UI_EMBOSSN);
1817                 
1818                 // deletion over the deflection panel
1819                 // fluid particle modifier can't be deleted here
1820                 if(md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md))
1821                 {
1822                         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");
1823                         uiButSetFunc(but, modifiers_del, ob, md);
1824                 }
1825                 uiBlockSetCol(block, TH_AUTO);
1826         }
1827
1828         uiBlockSetEmboss(block, UI_EMBOSS);
1829
1830         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1831                 y -= 18;
1832         } else {
1833                 int cy = y - 8;
1834                 int lx = x + width - 60 - 15;
1835
1836                 if (md->type==eModifierType_Subsurf) {
1837                         height = 105;
1838                 } else if (md->type==eModifierType_Lattice) {
1839                         height = 48;
1840                 } else if (md->type==eModifierType_Curve) {
1841                         height = 72;
1842                 } else if (md->type==eModifierType_Build) {
1843                         height = 86;
1844                 } else if (md->type==eModifierType_Mirror) {
1845                         height = 105;
1846                 } else if (md->type==eModifierType_Bevel) {
1847                         BevelModifierData *bmd = (BevelModifierData*) md;
1848                         height = 105; /* height = 124; */
1849                         if ((bmd->lim_flags & BME_BEVEL_ANGLE) || ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT))) height += 19;
1850                 } else if (md->type==eModifierType_EdgeSplit) {
1851                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1852                         height = 48;
1853                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1854                 } else if (md->type==eModifierType_Displace) {
1855                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1856                         height = 124;
1857                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1858                            dmd->texmapping == MOD_DISP_MAP_UV)
1859                                 height += 19;
1860                 } else if (md->type==eModifierType_UVProject) {
1861                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1862                 } else if (md->type==eModifierType_Decimate) {
1863                         height = 48;
1864                 } else if (md->type==eModifierType_Smooth) {
1865                         height = 86;
1866                 } else if (md->type==eModifierType_Cast) {
1867                         height = 143;
1868                 } else if (md->type==eModifierType_Wave) {
1869                         WaveModifierData *wmd = (WaveModifierData *)md;
1870                         height = 315;
1871                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1872                            wmd->texmapping == MOD_WAV_MAP_UV)
1873                                 height += 19;
1874                         if(wmd->flag & MOD_WAVE_NORM)
1875                                 height += 19;
1876                 } else if (md->type==eModifierType_Armature) {
1877                         height = 105;
1878                 } else if (md->type==eModifierType_Hook) {
1879                         HookModifierData *hmd = (HookModifierData*) md;
1880                         height = 86;
1881                         if (editing)
1882                                 height += 20;
1883                         if(hmd->indexar==NULL)
1884                                 height += 20;
1885                 } else if (md->type==eModifierType_Softbody) {
1886                         height = 31;
1887                 } else if (md->type==eModifierType_Cloth) {
1888                         height = 31;
1889                 } else if (md->type==eModifierType_Collision) {
1890                         height = 31;
1891                 } else if (md->type==eModifierType_Boolean) {
1892                         height = 48;
1893                 } else if (md->type==eModifierType_Array) {
1894                         height = 211;
1895                 } else if (md->type==eModifierType_MeshDeform) {
1896                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1897                         height = (mmd->bindcos)? 73: 93;
1898                 } else if (md->type==eModifierType_ParticleSystem) {
1899                         height = 31;
1900                 } else if (md->type==eModifierType_ParticleInstance) {
1901                         height = 94;
1902                 } else if (md->type==eModifierType_Explode) {
1903                         height = 94;
1904                 } else if (md->type==eModifierType_Shrinkwrap) {
1905                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
1906                         height = 86;
1907                         if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL)
1908                                 height += 19*5;
1909                 } else if (md->type==eModifierType_SimpleDeform) {
1910                         height += 19*5;
1911                 }
1912                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1913                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1914
1915                 y -= 18;
1916
1917                 if (!isVirtual && (md->type!=eModifierType_Collision)) {
1918                         uiBlockBeginAlign(block);
1919                         if (md->type==eModifierType_ParticleSystem) {
1920                                 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");
1921                                 uiButSetFunc(but, modifiers_convertParticles, ob, md);
1922                         }
1923                         else{
1924                                 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");
1925                                 uiButSetFunc(but, modifiers_applyModifier, ob, md);
1926                         }
1927                         
1928                         if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
1929                                 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");
1930                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1931                         }
1932                         uiBlockEndAlign(block);
1933                 }
1934
1935                 lx = x + 10;
1936                 cy = y + 10 - 1;
1937                 uiBlockBeginAlign(block);
1938                 if (md->type==eModifierType_Subsurf) {
1939                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1940                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1941                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1942                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1943                         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");
1944
1945                         /* Disabled until non-EM DerivedMesh implementation is complete */
1946
1947                         /*
1948                         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");
1949                         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");
1950                         */
1951
1952                         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");
1953                         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");
1954                 } else if (md->type==eModifierType_Lattice) {
1955                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1956                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1957                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1958                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1959                 } else if (md->type==eModifierType_Curve) {
1960                         CurveModifierData *cmd = (CurveModifierData*) md;
1961                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1962                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1963                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1964                         
1965                         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");
1966                         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");
1967                         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");
1968                         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");
1969                         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");
1970                         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");
1971                 } else if (md->type==eModifierType_Build) {
1972                         BuildModifierData *bmd = (BuildModifierData*) md;
1973                         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");
1974                         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");
1975                         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.");
1976                         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.");
1977                 } else if (md->type==eModifierType_Mirror) {
1978                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1979                         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");
1980                         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");
1981                         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");
1982                         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");
1983                         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");
1984                         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)");
1985                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1986                                      "Mirror U",
1987                                      lx, (cy-=19), buttonWidth/2, 19,
1988                                      &mmd->flag, 0, 0, 0, 0,
1989                                      "Mirror the U texture coordinate around "
1990                                      "the 0.5 point");
1991                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1992                                      "Mirror V",
1993                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1994                                      &mmd->flag, 0, 0, 0, 0,
1995                                      "Mirror the V texture coordinate around "
1996                                      "the 0.5 point");
1997                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1998                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1999                                        &mmd->mirror_ob,
2000                                        "Object to use as mirror");
2001                 } else if (md->type==eModifierType_Bevel) {
2002                         BevelModifierData *bmd = (BevelModifierData*) md;
2003                         /*uiDefButS(block, ROW, B_MODIFIER_RECALC, "Distance",
2004                                           lx, (cy -= 19), (buttonWidth/2), 19, &bmd->val_flags,
2005                                           11.0, 0, 0, 0,
2006                                           "Interpret bevel value as a constant distance from each edge");
2007                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Radius",
2008                                           (lx+buttonWidth/2), cy, (buttonWidth - buttonWidth/2), 19, &bmd->val_flags,
2009                                           11.0, BME_BEVEL_RADIUS, 0, 0,
2010                                           "Interpret bevel value as a radius - smaller angles will be beveled more");*/
2011                         uiBlockBeginAlign(block);
2012                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Width: ",
2013                                           lx, (cy -= 19), buttonWidth, 19, &bmd->value,
2014                                           0.0, 0.5, 5, 2,
2015                                           "Bevel value/amount");
2016                         /*uiDefButI(block, NUM, B_MODIFIER_RECALC, "Recurs",
2017                                           lx, (cy -= 19), buttonWidth, 19, &bmd->res,
2018                                           1, 4, 5, 2,
2019                                           "Number of times to bevel");*/
2020                         uiDefButBitS(block, TOG, BME_BEVEL_VERT,
2021                                           B_MODIFIER_RECALC, "Only Vertices",
2022                                           lx, (cy -= 19), buttonWidth, 19,
2023                                           &bmd->flags, 0, 0, 0, 0,
2024                                           "Bevel only verts/corners; not edges");
2025                         uiBlockEndAlign(block);
2026                                           
2027                         uiDefBut(block, LABEL, 1, "Limit using:",       lx, (cy-=25), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2028                         uiBlockBeginAlign(block);
2029                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "None",
2030                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->lim_flags,
2031                                           12.0, 0, 0, 0,
2032                                           "Bevel the entire mesh by a constant amount");
2033                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "Angle",
2034                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->lim_flags,
2035                                           12.0, BME_BEVEL_ANGLE, 0, 0,
2036                                           "Only bevel edges with sharp enough angles between faces");
2037                         uiDefButS(block, ROW, B_MODIFIER_RECALC, "BevWeight",
2038                                           lx+(2*buttonWidth/3), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->lim_flags,
2039                                           12.0, BME_BEVEL_WEIGHT, 0, 0,
2040                                           "Use bevel weights to determine how much bevel is applied; apply them separately in vert/edge select mode");
2041                         if ((bmd->lim_flags & BME_BEVEL_WEIGHT) && !(bmd->flags & BME_BEVEL_VERT)) {
2042                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Min",
2043                                           lx, (cy -= 19), (buttonWidth/3), 19, &bmd->e_flags,
2044                                           13.0, BME_BEVEL_EMIN, 0, 0,
2045                                           "The sharpest edge's weight is used when weighting a vert");
2046                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Average",
2047                                           (lx+buttonWidth/3), cy, (buttonWidth/3), 19, &bmd->e_flags,
2048                                           13.0, 0, 0, 0,
2049                                           "The edge weights are averaged when weighting a vert");
2050                                 uiDefButS(block, ROW, B_MODIFIER_RECALC, "Max",
2051                                           (lx+2*(buttonWidth/3)), cy, buttonWidth-2*(buttonWidth/3), 19, &bmd->e_flags,
2052                                           13.0, BME_BEVEL_EMAX, 0, 0,
2053                                           "The largest edge's wieght is used when weighting a vert");
2054                         }
2055                         else if (bmd->lim_flags & BME_BEVEL_ANGLE) {
2056                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Angle:",
2057                                           lx, (cy -= 19), buttonWidth, 19, &bmd->bevel_angle,
2058                                           0.0, 180.0, 100, 2,
2059                                           "Angle above which to bevel edges");
2060                         }
2061                 } else if (md->type==eModifierType_EdgeSplit) {
2062                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
2063                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
2064                                      B_MODIFIER_RECALC, "From Edge Angle",
2065                                      lx, (cy -= 19), buttonWidth, 19,
2066                                      &emd->flags, 0, 0, 0, 0,
2067                                      "Split edges with high angle between faces");
2068                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
2069                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
2070                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
2071                                           0.0, 180.0, 100, 2,
2072                                           "Angle above which to split edges");
2073                         }
2074                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
2075                                      B_MODIFIER_RECALC, "From Marked As Sharp",
2076                                      lx, (cy -= 19), buttonWidth, 19,
2077                                      &emd->flags, 0, 0, 0, 0,
2078                                      "Split edges that are marked as sharp");
2079                 } else if (md->type==eModifierType_Displace) {
2080                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
2081                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
2082                                        lx, (cy -= 19), buttonWidth, 19,
2083                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
2084                                        "Name of vertex group to displace"
2085                                        " (displace whole mesh if blank)");
2086                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2087                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
2088                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
2089                                        &dmd->texture,
2090                                        "Texture to use as displacement input");
2091                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
2092                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
2093                                   0, 1, 10, 3,
2094                                   "Material value that gives no displacement");
2095                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
2096                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
2097                                   -1000, 1000, 10, 0.1,
2098                                   "Strength of displacement");
2099                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
2100                                 "Z%%x%d|Y%%x%d|X%%x%d",
2101                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
2102                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
2103                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2104                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
2105                                   0.0, 1.0, 0, 0, "Displace direction");
2106                         sprintf(str, "Texture Coordinates%%t"
2107                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2108                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
2109                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
2110                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2111                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
2112                                   0.0, 1.0, 0, 0,
2113                                   "Texture coordinates used for displacement input");
2114                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
2115                                 char *strtmp;
2116                                 int i;
2117                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2118                                                              : &((Mesh*)ob->data)->fdata;
2119                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
2120                                                         dmd->uvlayer_name);
2121                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2122                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
2123                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2124                                 MEM_freeN(strtmp);
2125                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2126                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
2127                                              &fdata->layers[i]);
2128                         }
2129                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
2130                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2131                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2132                                                &dmd->map_object,
2133                                                "Object to get texture coordinates from");
2134                         }
2135                 } else if (md->type==eModifierType_UVProject) {
2136                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
2137                         int i;
2138                         char *strtmp;
2139                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
2140                                                      : &((Mesh*)ob->data)->fdata;
2141                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
2142                                                 umd->uvlayer_name);
2143                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2144                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
2145                               0.0, 1.0, 0, 0, "Set the UV layer to use");
2146                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
2147                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
2148                         MEM_freeN(strtmp);
2149                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
2150                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
2151                                   1, 1000, 100, 2,
2152                                   "Horizontal Aspect Ratio");
2153                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
2154                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
2155                                   &umd->aspecty,
2156                                   1, 1000, 100, 2,
2157                                   "Vertical Aspect Ratio");
2158                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
2159                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
2160                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
2161                                   "Number of objects to use as projectors");
2162                         for(i = 0; i < umd->num_projectors; ++i) {
2163                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2164                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
2165                                                &umd->projectors[i],
2166                                                "Object to use as projector");
2167                         }
2168                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
2169                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
2170                                        &umd->image,
2171                                        "Image to project (only faces with this image "
2172                                        "will be altered");
2173                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
2174                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
2175                                      B_MODIFIER_RECALC, "Override Image",
2176                                      lx, (cy -= 19), buttonWidth, 19,
2177                                      &umd->flags, 0, 0, 0, 0,
2178                                      "Override faces' current images with the "
2179                                      "given image");
2180                 } else if (md->type==eModifierType_Decimate) {
2181                         DecimateModifierData *dmd = (DecimateModifierData*) md;
2182                         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");
2183                         sprintf(str, "Face Count: %d", dmd->faceCount);
2184                         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");
2185                 } else if (md->type==eModifierType_Smooth) {
2186                         SmoothModifierData *smd = (SmoothModifierData*) md;
2187
2188                         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");
2189                         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");
2190                         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");
2191
2192                         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)");
2193                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
2194                         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");
2195                 } else if (md->type==eModifierType_Cast) {
2196                         CastModifierData *cmd = (CastModifierData*) md;
2197
2198                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
2199                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
2200                         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");
2201                         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");
2202                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
2203                                 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");
2204                         }
2205                         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");
2206                         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)");
2207                         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)");
2208                         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)");
2209                         if (ob->type == OB_MESH) {
2210                                 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");
2211                         }
2212                         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");
2213                         if(cmd->object) {
2214                                 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");
2215                         }
2216                 } else if (md->type==eModifierType_Wave) {
2217                         WaveModifierData *wmd = (WaveModifierData*) md;
2218                         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");
2219                         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");
2220                         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");
2221                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
2222                         if (wmd->flag & MOD_WAVE_NORM){
2223                                 if (ob->type==OB_MESH) {
2224                                         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");
2225                                         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");
2226                                         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");
2227                                 }
2228                                 else
2229                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
2230                         }
2231
2232                         uiBlockBeginAlign(block);
2233                         if(wmd->speed >= 0)
2234                                 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");
2235                         else
2236                                 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");
2237                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
2238                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
2239                         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");
2240
2241                         cy -= 9;
2242                         uiBlockBeginAlign(block);
2243                         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");
2244                         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");
2245                         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)");
2246                         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");
2247                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
2248                         sprintf(str, "Texture Coordinates%%t"
2249                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
2250                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
2251                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
2252                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2253                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
2254                                   0.0, 1.0, 0, 0,
2255                                   "Texture coordinates used for modulation input");
2256                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
2257                                 char *strtmp;
2258                                 int i;
2259                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
2260                                                              : &((Mesh*)ob->data)->fdata;
2261                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
2262                                                         wmd->uvlayer_name);
2263                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
2264                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
2265                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
2266                                 MEM_freeN(strtmp);
2267                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
2268                                 uiButSetFunc(but, set_displace_uvlayer, wmd,
2269                                              &fdata->layers[i]);
2270                         }
2271                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
2272                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2273                                                "Ob: ", lx, (cy -= 19), 220, 19,
2274                                                &wmd->map_object,
2275                                                "Object to get texture coordinates from");
2276                         }
2277                         cy -= 9;
2278                         uiBlockBeginAlign(block);
2279                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
2280                         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");
2281                         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");
2282                         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");
2283                 } else if (md->type==eModifierType_Armature) {
2284                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
2285                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
2286                         
2287                         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");
2288                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2289                         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");
2290                         
2291                         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");
2292                         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");
2293                         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");
2294                         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");
2295                         
2296                         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");
2297
2298                 } else if (md->type==eModifierType_Hook) {
2299                         HookModifierData *hmd = (HookModifierData*) md;
2300                         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");
2301                         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");
2302                         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"); 
2303                         if(hmd->indexar==NULL) {
2304                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
2305                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2306                         }
2307                         uiBlockBeginAlign(block);
2308                         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");
2309                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
2310                         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");
2311                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
2312
2313                         if (editing) {
2314                                 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");
2315                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
2316                                 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");
2317                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
2318                         }
2319                 } else if (md->type==eModifierType_Softbody) {
2320                         uiDefBut(block, LABEL, 1, "See Soft Body panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2321                 } else if (md->type==eModifierType_Cloth) {
2322                         uiDefBut(block, LABEL, 1, "See Cloth panel.",   lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2323                 } else if (md->type==eModifierType_Collision) {
2324                         uiDefBut(block, LABEL, 1, "See Collision panel.",       lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2325                 } else if (md->type==eModifierType_Boolean) {
2326                         BooleanModifierData *bmd = (BooleanModifierData*) md;
2327                         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");
2328                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
2329                 } else if (md->type==eModifierType_Array) {
2330                         ArrayModifierData *amd = (ArrayModifierData*) md;
2331                         float range = 10000;
2332                         int cytop, halfwidth = (width - 5)/2 - 15;
2333                         int halflx = lx + halfwidth + 10;
2334
2335                         uiBlockSetEmboss(block, UI_EMBOSSX);
2336                         uiBlockEndAlign(block);
2337
2338                         /* length parameters */
2339                         uiBlockBeginAlign(block);
2340                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2341                                 "|Fit To Curve Length%%x%d",
2342                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2343                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2344                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2345                                   0.0, 1.0, 0, 0, "Array length calculation method");
2346                         switch(amd->fit_type)
2347                         {
2348                         case MOD_ARR_FIXEDCOUNT:
2349                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2350                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2351                                           1, 1000, 0, 0, "Number of duplicates to make");
2352                                 break;
2353                         case MOD_ARR_FITLENGTH:
2354                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2355                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2356                                           0, range, 10, 2,
2357                                           "Length to fit array within");
2358                                 break;
2359                         case MOD_ARR_FITCURVE:
2360                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2361                                                B_CHANGEDEP, "Ob: ",
2362                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2363                                                "Curve object to fit array length to");
2364                                 break;
2365                         }
2366                         uiBlockEndAlign(block);
2367
2368                         /* offset parameters */
2369                         cy -= 10;
2370                         cytop= cy;
2371                         uiBlockBeginAlign(block);
2372                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2373                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2374                                      &amd->offset_type, 0, 0, 0, 0,
2375                                      "Constant offset between duplicates "
2376                                      "(local coordinates)");
2377                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2378                                   lx, (cy-=19), halfwidth, 19,
2379                                   &amd->offset[0],
2380                                   -range, range, 10, 3,
2381                                   "Constant component for duplicate offsets "
2382                                   "(local coordinates)");
2383                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2384                                   lx, (cy-=19), halfwidth, 19,
2385                                   &amd->offset[1],
2386                                   -range, range, 10, 3,
2387                                   "Constant component for duplicate offsets "
2388                                   "(local coordinates)");
2389                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2390                                   lx, (cy-=19), halfwidth, 19,
2391                                   &amd->offset[2],
2392                                   -range, range, 10, 3,
2393                                   "Constant component for duplicate offsets "
2394                                   "(local coordinates)");
2395                         uiBlockEndAlign(block);
2396
2397                         cy= cytop;
2398                         uiBlockBeginAlign(block);
2399                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2400                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2401                                      &amd->offset_type, 0, 0, 0, 0,
2402                                      "Offset between duplicates relative to object width "
2403                                      "(local coordinates)");
2404                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2405                                   halflx, (cy-=19), halfwidth, 19,
2406                                   &amd->scale[0],
2407                                   -range, range, 10, 3,
2408                                   "Component for duplicate offsets relative to object "
2409                                   "width (local coordinates)");
2410                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2411                                   halflx, (cy-=19), halfwidth, 19,
2412                                   &amd->scale[1],
2413                                   -range, range, 10, 3,
2414                                   "Component for duplicate offsets relative to object "
2415                                   "width (local coordinates)");
2416                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2417                                   halflx, (cy-=19), halfwidth, 19,
2418                                   &amd->scale[2],
2419                                   -range, range, 10, 3,
2420                                   "Component for duplicate offsets relative to object "
2421                                   "width (local coordinates)");
2422                         uiBlockEndAlign(block);
2423
2424                         /* vertex merging parameters */
2425                         cy -= 10;
2426                         cytop= cy;
2427
2428                         uiBlockBeginAlign(block);
2429                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2430                                      "Merge",
2431                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2432                                      0, 0, 0, 0,
2433                                      "Merge vertices in adjacent duplicates");
2434                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2435                                      "First Last",
2436                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2437                                      &amd->flags,
2438                                      0, 0, 0, 0,
2439                                      "Merge vertices in first duplicate with vertices"
2440                                      " in last duplicate");
2441                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2442                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2443                                           0, 1.0f, 1, 4,
2444                                           "Limit below which to merge vertices");
2445
2446                         /* offset ob */
2447                         cy = cytop;
2448                         uiBlockBeginAlign(block);
2449                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2450                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2451                                      &amd->offset_type, 0, 0, 0, 0,
2452                                      "Add an object transformation to the total offset");
2453                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2454                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2455                                        &amd->offset_ob,
2456                                        "Object from which to take offset transformation");
2457                         uiBlockEndAlign(block);
2458
2459                         cy -= 10;
2460                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2461                                              B_CHANGEDEP, "Start cap: ",
2462                                              lx, (cy -= 19), halfwidth, 19,
2463                                              &amd->start_cap,
2464                                              "Mesh object to use as start cap");
2465                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2466                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2467                                              B_CHANGEDEP, "End cap: ",
2468                                              halflx, cy, halfwidth, 19,
2469                                              &amd->end_cap,
2470                                              "Mesh object to use as end cap");
2471                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2472                 } else if (md->type==eModifierType_MeshDeform) {
2473                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2474
2475                         uiBlockBeginAlign(block);
2476                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2477                         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");
2478                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2479                         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");
2480
2481                         uiBlockBeginAlign(block);
2482                         if(mmd->bindcos) {
2483                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2484                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2485                         }
2486                         else {
2487                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2488                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2489                                 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");
2490                                 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!)");
2491                         }
2492                         uiBlockEndAlign(block);
2493                 } else if (md->type==eModifierType_ParticleSystem) {
2494                         uiDefBut(block, LABEL, 1, "See Particle buttons.",      lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
2495                 } else if (md->type==eModifierType_ParticleInstance) {
2496                         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
2497                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy -= 19), buttonWidth, 19, &pimd->ob, "Object that has the particlesystem");
2498                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "PSYS:", lx, (cy -= 19), buttonWidth, 19, &pimd->psys, 1, 10, 10, 3, "Particlesystem number in the object");
2499                         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");
2500                         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");
2501                         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");
2502                         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");
2503                         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");
2504                         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");
2505                 } else if (md->type==eModifierType_Explode) {
2506                         ExplodeModifierData *emd = (ExplodeModifierData*) md;
2507                         uiBut *but;
2508                         char *menustr= get_vertexgroup_menustr(ob);
2509                         int defCount=BLI_countlist(&ob->defbase);
2510                         if(defCount==0) emd->vgroup=0;
2511                         uiBlockBeginAlign(block);
2512                         but=uiDefButS(block, MENU, B_MODIFIER_RECALC, menustr,  lx, (cy-=19), buttonWidth-20,19, &emd->vgroup, 0, defCount, 0, 0, "Protect this vertex group");
2513                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2514                         MEM_freeN(menustr);
2515                         
2516                         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");
2517                         uiButSetFunc(but, modifiers_explodeDelVg, (void *)emd, (void *)NULL);
2518                         
2519
2520                         but=uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "",     lx, (cy-=19), buttonWidth,19, &emd->protect, 0.0f, 1.0f, 0, 0, "Clean vertex group edges");
2521                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2522
2523                         but=uiDefBut(block, BUT, B_MODIFIER_RECALC, "Refresh",  lx, (cy-=19), buttonWidth/2,19, 0, 0, 0, 0, 0, "Recalculate faces assigned to particles");
2524                         uiButSetFunc(but,modifiers_explodeFacepa,emd,0);
2525
2526                         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");
2527                         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");
2528                         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");
2529                         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");
2530                         uiBlockEndAlign(block);
2531                 } else if (md->type==eModifierType_Shrinkwrap) {
2532                         ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
2533
2534                         char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|normal projection %x1|nearest vertex %x2";
2535                         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.");
2536
2537                         if (smd->shrinkType == MOD_SHRINKWRAP_NORMAL){
2538
2539                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_ALLOW_DEFAULT_NORMAL, B_MODIFIER_RECALC, "Default normal",      lx,(cy-=19),buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows vertices to move in the normal direction");
2540                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_ALLOW_INVERTED_NORMAL, B_MODIFIER_RECALC, "Invert normal",      lx + buttonWidth/2,cy,buttonWidth/2,19, &smd->shrinkOpts, 0, 0, 0, 0, "Allows vertices to move in the inverse direction of their normal");
2541
2542                                 uiDefButBitS(block, TOG, MOD_SHRINKWRAP_REMOVE_UNPROJECTED_FACES, B_MODIFIER_RECALC, "Remove faces",    lx,(cy-=19),buttonWidth,19, &smd->shrinkOpts, 0, 0, 0, 0, "Remove faces where all vertices haven't been projected");
2543
2544                                 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");
2545                                 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");
2546
2547                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Dist:", lx,(cy-=19),buttonWidth,19, &smd->mergeDist, 0.0f, 0.01f, 0.01f, 0.01f, "Specify merge distance");
2548                                 uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Cut: ",        lx, (cy-=19), buttonWidth,19, &smd->cutPlane, "Target to project points that didn't got projected over target");
2549                         }
2550
2551                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2552                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2553
2554                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &smd->target, "Target to shrink to");
2555                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Offset:",     lx,(cy-=19),buttonWidth,19, &smd->keptDist, 0.0f, 100.0f, 1.0f, 0, "Specify distance to kept from the target");
2556                         uiBlockEndAlign(block);
2557                 } else if (md->type==eModifierType_SimpleDeform) {
2558                         SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md;
2559
2560 /*
2561                         char simpledeform_typemenu[]="Deform type%t|Twist %x1|Bend %x2|Taper %x3|TaperXY %x4|Strech %x5|Squash %x6";
2562                         uiDefButC(block, MENU, B_MODIFIER_RECALC, simpledeform_typemenu, lx,(cy-=19),buttonWidth,19, &smd->mode, 0, 0, 0, 0, "Selects type of deform");
2563 */
2564
2565                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name");
2566                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2567
2568                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth-17,19, &smd->origin, "Origin of modifier space coordinates");
2569
2570                         if(smd->origin)
2571                         {
2572                                 uiDefIconButBitS(block, ICONTOG, OB_RESTRICT_VIEW, REDRAWALL, ICON_RESTRICT_VIEW_OFF,
2573                                                                 lx + buttonWidth-17, cy, 17, 19,
2574                                                                 &(smd->origin->restrictflag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View");
2575                         }
2576                         else
2577                         {
2578                                 uiBut *bt;
2579                                 bt= uiDefIconBut(block, BUT, B_CHANGEDEP, ICON_ZOOMIN, lx+buttonWidth-17, cy, 17, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Creates a new empty");
2580                                 uiButSetFunc(bt, modifier_link_new_empty, &smd->origin, ob);
2581                         }
2582                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth,19, &smd->factor[0], -3000.0f, 3000.0f, 1.0f, 0, "Deform Factor");
2583
2584                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Upper Limit:",        lx,(cy-=19),buttonWidth,19, &smd->factor[2], -3000.0f, 3000.0f, 1.0f, 0, "Upper Limit Bend on X");
2585                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lower Limit:",        lx,(cy-=19),buttonWidth,19, &smd->factor[1], -3000.0f, 3000.0f, 1.0f, 0, "Lower Limit Bend on X");
2586                 }
2587
2588
2589                 uiBlockEndAlign(block);
2590
2591                 y-=height;
2592         }
2593
2594         if (md->error) {
2595                 y -= 6;
2596
2597                 uiBlockSetCol(block, color);
2598                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2599                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2600                 uiBlockSetCol(block, TH_AUTO);
2601
2602                 uiDefIconBut(block,LABEL,B_NOP,ICON_ERROR, x-9, y,19,19, 0,0,0,0,0, "");
2603                 uiDefBut(block, LABEL, B_NOP, md->error, x+5, y, width-15, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2604
2605                 y -= 18;
2606         }
2607
2608         uiClearButLock();
2609
2610         y -= 3+6;
2611
2612         *xco = x;
2613         *yco = y;
2614 }
2615
2616 static void editing_panel_modifiers(Object *ob)
2617 {
2618         ModifierData *md;
2619         uiBlock *block;
2620         char str[64];
2621         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2622
2623         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2624         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2625         
2626         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2627         uiNewPanelHeight(block, 204);
2628
2629         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2630
2631         sprintf(str, "To: %s", ob->id.name+2);
2632         uiDefBut(block, LABEL, 1, str,  140, 190, 160, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2633
2634         xco = 0;
2635         yco = 160;
2636
2637         md = modifiers_getVirtualModifierList(ob);
2638
2639         for (i=0; md; i++, md=md->next) {
2640                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2641                 if (md->mode&eModifierMode_Virtual) i--;
2642         }
2643         
2644         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2645 }
2646
2647 static char *make_key_menu(Key *key, int startindex)
2648 {
2649         KeyBlock *kb;
2650         int index= 1;
2651         char *str, item[64];
2652
2653         for (kb = key->block.first; kb; kb=kb->next, index++);
2654         str= MEM_mallocN(index*40, "key string");
2655         str[0]= 0;
2656         
2657         index= startindex;
2658         for (kb = key->block.first; kb; kb=kb->next, index++) {
2659                 sprintf (item,  "|%s%%x%d", kb->name, index);
2660                 strcat(str, item);
2661         }
2662         
2663         return str;
2664 }
2665
2666 static void editing_panel_shapes(Object *ob)
2667 {
2668         uiBlock *block;
2669         Key *key= NULL;
2670         KeyBlock *kb;
2671         int icon;
2672         char *strp;
2673         
2674         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2675         uiNewPanelTabbed("Modifiers", "Editing");
2676         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2677         
2678         /* Todo check data is library here */
2679         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2680         
2681         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2682         
2683         key= ob_get_key(ob);
2684         if(key==NULL) {
2685                 /* label aligns add button */
2686                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2687                 return;
2688         }
2689         
2690         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2691
2692         kb= BLI_findlink(&key->block, ob->shapenr-1);
2693         if(kb==NULL) {
2694                 ob->shapenr= 1;
2695                 kb= key->block.first;
2696         }
2697
2698         uiBlockBeginAlign(block);
2699         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2700         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");
2701         if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF;
2702         uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape");
2703         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2704         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2705         strp= make_key_menu(key, 1);
2706         uiDefButS(block, MENU, B_SETKEY, strp,                                  75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices");
2707         MEM_freeN(strp);
2708         
2709         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2710         uiClearButLock();
2711         uiDefBut(block, TEX, B_NAMEKEY, "",                                             115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2712         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2713         uiBlockEndAlign(block);
2714
2715         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2716                 uiBlockBeginAlign(block);
2717                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2718                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2719                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2720                 uiBlockEndAlign(block);
2721         }
2722         if(key->type && ob->shapenr!=1) {
2723                 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");
2724
2725                 strp= make_key_menu(key, 0);
2726                 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");
2727                 MEM_freeN(strp);
2728         }
2729         
2730         if(key->type==0)
2731                 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");
2732         
2733 }
2734
2735 /* *************************** FONT ******************************** */
2736
2737 static short give_vfontnr(VFont *vfont)
2738 {
2739         VFont *vf;
2740         short nr= 1;
2741
2742         vf= G.main->vfont.first;
2743         while(vf) {
2744                 if(vf==vfont) return nr;
2745                 nr++;
2746                 vf= vf->id.next;
2747         }
2748         return -1;
2749 }
2750
2751 static VFont *give_vfontpointer(int nr) /* nr= button */
2752 {
2753         VFont *vf;
2754         short tel= 1;
2755
2756         vf= G.main->vfont.first;
2757         while(vf) {
2758                 if(tel==nr) return vf;
2759                 tel++;
2760                 vf= vf->id.next;
2761         }
2762         return G.main->vfont.first;
2763 }
2764
2765 VFont *exist_vfont(char *str)
2766 {
2767         VFont *vf;
2768
2769         vf= G.main->vfont.first;
2770         while(vf) {
2771                 if(strcmp(vf->name, str)==0) return vf;
2772                 vf= vf->id.next;
2773         }
2774         return 0;
2775 }
2776
2777 static char *give_vfontbutstr(void)
2778 {
2779         VFont *vf;
2780         int len= 0;
2781         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2782
2783         vf= G.main->vfont.first;
2784         while(vf) {
2785                 strcpy(di, vf->name);
2786                 BLI_splitdirstring(di, fi);
2787                 len+= strlen(fi)+4;
2788                 vf= vf->id.next;
2789         }
2790
2791         str= MEM_callocN(len+21, "vfontbutstr");
2792         strcpy(str, "FONTS %t");
2793         vf= G.main->vfont.first;
2794         while(vf) {
2795
2796                 if(vf->id.us==0) strcat(str, "|0 ");
2797                 else strcat(str, "|   ");
2798
2799                 strcpy(di, vf->name);
2800                 BLI_splitdirstring(di, fi);
2801
2802                 strcat(str, fi);
2803                 vf= vf->id.next;
2804         }
2805         return str;
2806 }
2807
2808 static void load_buts_vfont(char *name)
2809 {
2810         VFont *vf;
2811         Curve *cu;
2812
2813         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2814         else return;
2815
2816         vf= exist_vfont(name);
2817         if(vf==0) {
2818                 vf= load_vfont(name);
2819                 if(vf==0) return;
2820         }
2821         else id_us_plus((ID *)vf);
2822         
2823         switch(cu->curinfo.flag & CU_STYLE) {
2824                 case CU_BOLD:
2825                         if(cu->vfontb) cu->vfontb->id.us--;
2826                         cu->vfontb= vf;
2827                         break;
2828                 case CU_ITALIC:
2829                         if(cu->vfonti) cu->vfonti->id.us--;             
2830                         cu->vfonti= vf;
2831                         break;                                          
2832                 case (CU_BOLD|CU_ITALIC):
2833                         if(cu->vfontbi) cu->vfontbi->id.us--;
2834                         cu->vfontbi= vf;
2835                         break;
2836                 default:
2837                         if(cu->vfont) cu->vfont->id.us--;
2838                         cu->vfont= vf;
2839                         break;                                          
2840         }       
2841
2842         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2843         BIF_undo_push("Load vector font");
2844         allqueue(REDRAWVIEW3D, 0);
2845         allqueue(REDRAWBUTSEDIT, 0);
2846 }
2847
2848 static void set_unicode_text_fs(char *file)
2849 {
2850         if (file) paste_unicodeText(file); 
2851 }
2852
2853 void do_fontbuts(unsigned short event)
2854 {
2855         Curve *cu;
2856         VFont *vf;
2857         Object *ob;
2858         ScrArea *sa;
2859         char str[80];
2860         int ctevt;
2861         char *ctmenu;
2862         DynStr *ds;
2863         int i, style=0;
2864
2865         ob= OBACT;
2866
2867         switch(event) {
2868         case B_MAKEFONT:
2869                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2870                 allqueue(REDRAWVIEW3D, 0);
2871                 break;
2872
2873         case B_STYLETOSELU:     
2874         case B_STYLETOSELB:
2875         case B_STYLETOSELI:
2876                 switch (event) {
2877                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2878                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2879                         case B_STYLETOSELI: style = CU_ITALIC; break;
2880                 }
2881                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2882                         text_to_curve(ob, 0);
2883                         makeDispListCurveTypes(ob, 0);
2884                         allqueue(REDRAWVIEW3D, 0);
2885                 }
2886                 allqueue(REDRAWBUTSEDIT, 0);
2887                 break;          
2888                 
2889         case B_FASTFONT:
2890                 if (G.obedit) {
2891                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2892                         allqueue(REDRAWVIEW3D, 0);
2893                 }
2894                 break;
2895         case B_INSTB:
2896                 cu= ob->data;
2897                 if (cu->totbox < 256) {
2898                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2899                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2900                         cu->actbox++;
2901                         cu->totbox++;
2902                         allqueue(REDRAWBUTSEDIT, 0);
2903                         allqueue(REDRAWVIEW3D, 0);
2904                         text_to_curve(ob, 0);
2905                         makeDispListCurveTypes(ob, 0);