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