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