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