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