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