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