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