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