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