Changes to "Face Select" mode
[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(FACESEL_PAINT_TEST) 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         }
723
724         /*reconstruct active layer*/
725         if (actlayerdata != layerdata) {
726                 /*find index. . .*/
727                 actindex = CustomData_get_layer_index(data, type);
728                 for (i=actindex; i<data->totlayer; i++) {
729                         if (data->layers[i].data == actlayerdata) {
730                                 actindex = i - actindex;
731                                 break;
732                         }
733                 }
734                 
735                 /*set index. . .*/
736                 CustomData_set_layer_active(data, type, actindex);
737         }
738         
739         if (rndlayerdata != layerdata) {
740                 /*find index. . .*/
741                 rndindex = CustomData_get_layer_index(data, type);
742                 for (i=rndindex; i<data->totlayer; i++) {
743                         if (data->layers[i].data == rndlayerdata) {
744                                 rndindex = i - rndindex;
745                                 break;
746                         }
747                 }
748                 
749                 /*set index. . .*/
750                 CustomData_set_layer_render(data, type, rndindex);
751         }
752         
753         
754         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
755         
756         if(type == CD_MTFACE)
757                 BIF_undo_push("Delete UV Texture");
758         else if(type == CD_MCOL)
759                 BIF_undo_push("Delete Vertex Color");
760
761         allqueue(REDRAWVIEW3D, 0);
762         allqueue(REDRAWIMAGE, 0);
763         allqueue(REDRAWBUTSEDIT, 0);
764 }
765
766 static int customdata_buttons(
767         uiBlock *block, Mesh *me, CustomData *data,
768         int type, int *activep, int *renderp,
769         int setevt, int setevt_rnd, int newevt,
770         char *label, char *shortlabel, char *browsetip, char *browsetip_rnd,
771         char *newtip, char *deltip, int x, int y)
772 {
773         CustomDataLayer *layer;
774         uiBut *but;
775         int i, count= CustomData_number_of_layers(data, type);
776
777         if(count >= MAX_MTFACE) {
778                 uiDefBut(block, LABEL, 0, label, x,y,220,19, 0, 0.0, 0, 0, 0, "");
779         }
780         else {
781                 uiDefBut(block, LABEL, 0, label, x,y,140,19, 0, 0.0, 0, 0, 0, "");
782                 uiBlockBeginAlign(block);
783                 uiDefBut(block, BUT, newevt, "New", x+140,y,80,19, 0,0,0,0,0, newtip);
784                 uiBlockEndAlign(block);
785         }
786
787         y -= (count)? 24: 19;
788
789         uiBlockBeginAlign(block);
790         for (count=1, i=0; i<data->totlayer; i++) {
791                 layer= &data->layers[i];
792
793                 if(layer->type == type) {
794                         *activep= layer->active + 1;
795                         *renderp= layer->active_rnd + 1;
796                         
797                         uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip);
798                         uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd);
799                         but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label);
800                         uiButSetFunc(but, verify_customdata_name_func, data, layer);
801                         but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip);
802                         uiButSetFunc(but, delete_customdata_layer, me, layer);
803
804
805                         count++;
806                         y -= 19;
807                 }
808         }
809         uiBlockEndAlign(block);
810
811         return y;
812 }
813
814 static void editing_panel_mesh_type(Object *ob, Mesh *me)
815 {
816         uiBlock *block;
817         uiBut *but;
818         float val;
819         CustomData *fdata;
820         int yco;
821
822         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_type", UI_EMBOSS, UI_HELV, curarea->win);
823         if( uiNewPanel(curarea, block, "Mesh", "Editing", 320, 0, 318, 204)==0) return;
824         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
825
826         uiBlockBeginAlign(block);
827         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");
828         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");
829         uiBlockEndAlign(block);
830
831         /* Retopo */
832         if(G.obedit) {
833                 uiBlockBeginAlign(block);
834                 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");
835                 uiButSetFunc(but,retopo_toggle,ob,me);
836                 if(G.scene->toolsettings->retopo_mode) {
837                         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.");
838                         uiButSetFunc(but,retopo_paint_toggle,ob,me);
839                         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");
840                         uiButSetFunc(but,retopo_do_all_cb,ob,me);
841                 }
842                 uiBlockEndAlign(block);
843         }
844
845         uiBlockBeginAlign(block);
846         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");
847         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");
848         uiDefBut(block, BUT,B_DOCENTERCURSOR, "Center Cursor",          10, 60, 170, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
849         uiBlockEndAlign(block);
850
851         uiBlockBeginAlign(block);
852         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");
853         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");
854         uiBlockEndAlign(block);
855
856         uiDefIDPoinBut(block, test_meshpoin_but, ID_ME, B_REDR, "TexMesh: ",    190,180,220,19, &me->texcomesh, "Derive texture coordinates from another mesh.");
857
858         if(me->msticky) val= 1.0; else val= 0.0;
859         uiDefBut(block, LABEL, 0, "Sticky",                             190,155,140,19, 0, val, 0, 0, 0, "");
860         uiBlockBeginAlign(block);
861         if(me->msticky==NULL) {
862                 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");
863         }
864         else uiDefBut(block, BUT, B_DELSTICKY, "Delete",        330,155, 80,19, 0, 0, 0, 0, 0, "Deletes Sticky texture coordinates");
865         uiBlockEndAlign(block);
866
867         fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata;
868         yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd,
869                 B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:",
870                 "Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer",
871                 "Removes the current UV texture layer", 190, 130);
872
873         yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd,
874                 B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:",
875                 "Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer",
876                 "Removes the current vertex color layer", 190, yco-5);
877
878         if(yco < 0)
879                 uiNewPanelHeight(block, 204 - yco);
880 }
881
882 /* *************************** MODIFIERS ******************************** */
883
884 void do_modifier_panels(unsigned short event)
885 {
886         Object *ob = OBACT;
887
888         switch(event) {
889         case B_MODIFIER_REDRAW:
890                 allqueue(REDRAWBUTSEDIT, 0);
891                 allqueue(REDRAWOOPS, 0);
892                 break;
893
894         case B_MODIFIER_RECALC:
895                 ob->softflag |= OB_SB_RESET;
896                 allqueue(REDRAWBUTSEDIT, 0);
897                 allqueue(REDRAWVIEW3D, 0);
898                 allqueue(REDRAWIMAGE, 0);
899                 allqueue(REDRAWOOPS, 0);
900                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
901                 object_handle_update(ob);
902                 countall();
903                 break;
904         }
905 }
906
907 static void modifiers_add(void *ob_v, int type)
908 {
909         Object *ob = ob_v;
910         ModifierTypeInfo *mti = modifierType_getInfo(type);
911         
912         if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
913                 ModifierData *md = ob->modifiers.first;
914
915                 while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
916                         md = md->next;
917                 }
918
919                 BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(type));
920         } else {
921                 BLI_addtail(&ob->modifiers, modifier_new(type));
922         }
923         BIF_undo_push("Add modifier");
924 }
925
926 typedef struct MenuEntry {
927         char *name;
928         int ID;
929 } MenuEntry;
930
931 static int menuEntry_compare_names(const void *entry1, const void *entry2)
932 {
933         return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
934 }
935
936 static uiBlock *modifiers_add_menu(void *ob_v)
937 {
938         Object *ob = ob_v;
939         uiBlock *block;
940         int i, yco=0;
941         int numEntries = 0;
942         MenuEntry entries[NUM_MODIFIER_TYPES];
943         
944         block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
945                           UI_EMBOSSP, UI_HELV, curarea->win);
946         uiBlockSetButmFunc(block, modifiers_add, ob);
947
948         for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
949                 ModifierTypeInfo *mti = modifierType_getInfo(i);
950
951                 /* Only allow adding through appropriate other interfaces */
952                 if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
953
954                 if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
955                    (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
956                         entries[numEntries].name = mti->name;
957                         entries[numEntries].ID = i;
958
959                         ++numEntries;
960                 }
961         }
962
963         qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
964
965
966         for(i = 0; i < numEntries; ++i)
967                 uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
968                          0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
969
970         uiTextBoundsBlock(block, 50);
971         uiBlockSetDirection(block, UI_DOWN);
972
973         return block;
974 }
975
976 static void modifiers_del(void *ob_v, void *md_v)
977 {
978         Object *ob = ob_v;
979         ModifierData *md;
980
981                 /* It seems on rapid delete it is possible to
982                  * get called twice on same modifier, so make
983                  * sure it is in list.
984                  */
985         for (md=ob->modifiers.first; md; md=md->next)
986                 if (md==md_v)
987                         break;
988         
989         if (!md)
990                 return;
991
992         BLI_remlink(&ob->modifiers, md_v);
993
994         modifier_free(md_v);
995
996         BIF_undo_push("Del modifier");
997 }
998
999 int mod_moveUp(void *ob_v, void *md_v)
1000 {
1001         Object *ob = ob_v;
1002         ModifierData *md = md_v;
1003
1004         if (md->prev) {
1005                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1006
1007                 if (mti->type!=eModifierTypeType_OnlyDeform) {
1008                         ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type);
1009
1010                         if (nmti->flags&eModifierTypeFlag_RequiresOriginalData)
1011                                 return -1;
1012                 }
1013
1014                 BLI_remlink(&ob->modifiers, md);
1015                 BLI_insertlink(&ob->modifiers, md->prev->prev, md);
1016         }
1017
1018         return 0;
1019 }
1020
1021 static void modifiers_moveUp(void *ob_v, void *md_v)
1022 {
1023         if( mod_moveUp( ob_v, md_v ) )
1024                 error("Cannot move above a modifier requiring original data.");
1025         else
1026                 BIF_undo_push("Move modifier");
1027 }
1028
1029 int mod_moveDown(void *ob_v, void *md_v)
1030 {
1031         Object *ob = ob_v;
1032         ModifierData *md = md_v;
1033
1034         if (md->next) {
1035                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1036
1037                 if (mti->flags&eModifierTypeFlag_RequiresOriginalData) {
1038                         ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type);
1039
1040                         if (nmti->type!=eModifierTypeType_OnlyDeform)
1041                                 return -1;
1042                 }
1043
1044                 BLI_remlink(&ob->modifiers, md);
1045                 BLI_insertlink(&ob->modifiers, md->next, md);
1046         }
1047
1048         return 0;
1049 }
1050
1051 static void modifiers_moveDown(void *ob_v, void *md_v)
1052 {
1053         if( mod_moveDown( ob_v, md_v ) )
1054                 error("Cannot move beyond a non-deforming modifier.");
1055         else
1056                 BIF_undo_push("Move modifier");
1057 }
1058
1059 static void modifier_testLatticeObj(char *name, ID **idpp)
1060 {
1061         ID *id;
1062
1063         for (id= G.main->object.first; id; id= id->next) {
1064                 if( strcmp(name, id->name+2)==0 ) {
1065                         if (((Object *)id)->type != OB_LATTICE) {
1066                                 error ("Lattice deform object must be a lattice");
1067                                 break;
1068                         } 
1069                         *idpp= id;
1070                         return;
1071                 }
1072         }
1073         *idpp= 0;
1074 }
1075
1076 static void modifier_testCurveObj(char *name, ID **idpp)
1077 {
1078         ID *id;
1079
1080         for (id= G.main->object.first; id; id= id->next) {
1081                 if( strcmp(name, id->name+2)==0 ) {
1082                         if (((Object *)id)->type != OB_CURVE) {
1083                                 error ("Curve deform object must be a curve");
1084                                 break;
1085                         } 
1086                         *idpp= id;
1087                         return;
1088                 }
1089         }
1090         *idpp= 0;
1091 }
1092
1093 static void modifier_testMeshObj(char *name, ID **idpp)
1094 {
1095         ID *id;
1096
1097         for (id= G.main->object.first; id; id= id->next) {
1098                 /* no boolean on its own object */
1099                 if(id != (ID *)OBACT) {
1100                         if( strcmp(name, id->name+2)==0 ) {
1101                                 if (((Object *)id)->type != OB_MESH) {
1102                                         error ("Boolean modifier object must be a mesh");
1103                                         break;
1104                                 } 
1105                                 *idpp= id;
1106                                 return;
1107                         }
1108                 }
1109         }
1110         *idpp= NULL;
1111 }
1112
1113 static void modifier_testArmatureObj(char *name, ID **idpp)
1114 {
1115         ID *id;
1116
1117         for (id= G.main->object.first; id; id= id->next) {
1118                 if( strcmp(name, id->name+2)==0 ) {
1119                         if (((Object *)id)->type != OB_ARMATURE) {
1120                                 error ("Armature deform object must be an armature");
1121                                 break;
1122                         } 
1123                         *idpp= id;
1124                         return;
1125                 }
1126         }
1127         *idpp= 0;
1128 }
1129
1130 static void modifier_testTexture(char *name, ID **idpp)
1131 {
1132         ID *id;
1133
1134         for(id = G.main->tex.first; id; id = id->next) {
1135                 if(strcmp(name, id->name + 2) == 0) {
1136                         *idpp = id;
1137                         /* texture gets user, objects not: delete object = clear modifier */
1138                         id_us_plus(id);
1139                         return;
1140                 }
1141         }
1142         *idpp = 0;
1143 }
1144
1145 #if 0 /* this is currently unused, but could be useful in the future */
1146 static void modifier_testMaterial(char *name, ID **idpp)
1147 {
1148         ID *id;
1149
1150         for(id = G.main->mat.first; id; id = id->next) {
1151                 if(strcmp(name, id->name + 2) == 0) {
1152                         *idpp = id;
1153                         return;
1154                 }
1155         }
1156         *idpp = 0;
1157 }
1158 #endif
1159
1160 static void modifier_testImage(char *name, ID **idpp)
1161 {
1162         ID *id;
1163
1164         for(id = G.main->image.first; id; id = id->next) {
1165                 if(strcmp(name, id->name + 2) == 0) {
1166                         *idpp = id;
1167                         return;
1168                 }
1169         }
1170         *idpp = 0;
1171 }
1172
1173 /* autocomplete callback for ID buttons */
1174 void autocomplete_image(char *str, void *arg_v)
1175 {
1176         /* search if str matches the beginning of an ID struct */
1177         if(str[0]) {
1178                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1179                 ID *id;
1180
1181                 for(id = G.main->image.first; id; id = id->next)
1182                         autocomplete_do_name(autocpl, id->name+2);
1183
1184                 autocomplete_end(autocpl, str);
1185         }
1186 }
1187
1188 /* autocomplete callback for ID buttons */
1189 void autocomplete_meshob(char *str, void *arg_v)
1190 {
1191         /* search if str matches the beginning of an ID struct */
1192         if(str[0]) {
1193                 AutoComplete *autocpl = autocomplete_begin(str, 22);
1194                 ID *id;
1195
1196                 for(id = G.main->object.first; id; id = id->next)
1197                         if(((Object *)id)->type == OB_MESH)
1198                                 autocomplete_do_name(autocpl, id->name+2);
1199
1200                 autocomplete_end(autocpl, str);
1201         }
1202 }
1203
1204 static void modifiers_applyModifier(void *obv, void *mdv)
1205 {
1206         Object *ob = obv;
1207         ModifierData *md = mdv;
1208         DerivedMesh *dm;
1209         Mesh *me = ob->data;
1210         int converted = 0;
1211
1212         if (G.obedit) {
1213                 error("Modifiers cannot be applied in editmode");
1214                 return;
1215         } else if (((ID*) ob->data)->us>1) {
1216                 error("Modifiers cannot be applied to multi-user data");
1217                 return;
1218         }
1219
1220         if (md!=ob->modifiers.first) {
1221                 if (!okee("Modifier is not first"))
1222                         return;
1223         }
1224
1225         if (ob->type==OB_MESH) {
1226                 if(me->mr && multires_modifier_warning()) {
1227                         error("Modifier changes topology; cannot apply with multires active");
1228                         return;
1229                 }
1230                 if(me->key) {
1231                         error("Modifier cannot be applied to Mesh with Shape Keys");
1232                         return;
1233                 }
1234         
1235                 sculptmode_pmv_off(me);
1236         
1237                 dm = mesh_create_derived_for_modifier(ob, md);
1238                 if (!dm) {
1239                         error("Modifier is disabled or returned error, skipping apply");
1240                         return;
1241                 }
1242
1243                 DM_to_mesh(dm, me);
1244                 converted = 1;
1245
1246                 dm->release(dm);
1247         } 
1248         else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
1249                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1250                 Curve *cu = ob->data;
1251                 int numVerts;
1252                 float (*vertexCos)[3];
1253
1254                 if (!okee("Apply will only change CV points, not tesselated/bevel vertices"))
1255                         return;
1256
1257                 if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md))) {
1258                         error("Modifier is disabled, skipping apply");
1259                         return;
1260                 }
1261
1262                 vertexCos = curve_getVertexCos(cu, &cu->nurb, &numVerts);
1263                 mti->deformVerts(md, ob, NULL, vertexCos, numVerts);
1264                 curve_applyVertexCos(cu, &cu->nurb, vertexCos);
1265
1266                 converted = 1;
1267
1268                 MEM_freeN(vertexCos);
1269
1270                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1271         }
1272         else {
1273                 error("Cannot apply modifier for this object type");
1274                 return;
1275         }
1276
1277         if (converted) {
1278                 BLI_remlink(&ob->modifiers, md);
1279                 modifier_free(md);
1280
1281                 BIF_undo_push("Apply modifier");
1282         }
1283 }
1284
1285 static void modifiers_copyModifier(void *ob_v, void *md_v)
1286 {
1287         Object *ob = ob_v;
1288         ModifierData *md = md_v;
1289         ModifierData *nmd = modifier_new(md->type);
1290
1291         modifier_copyData(md, nmd);
1292
1293         BLI_insertlink(&ob->modifiers, md, nmd);
1294
1295         BIF_undo_push("Copy modifier");
1296 }
1297
1298 static void modifiers_setOnCage(void *ob_v, void *md_v)
1299 {
1300         Object *ob = ob_v;
1301         ModifierData *md;
1302         
1303         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1304
1305         for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1306                 if( md == md_v ) {
1307                         if( i >= cageIndex )
1308                                 md->mode ^= eModifierMode_OnCage;
1309                         break;
1310                 }
1311 }
1312
1313 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
1314 {
1315         Object *ob = ob_v;
1316         ModifierData *md = md_v;
1317         HookModifierData *hmd = (HookModifierData*) md;
1318         
1319         if (hmd->object) {
1320                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
1321                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
1322                 BIF_undo_push("Clear hook offset");
1323         }
1324 }
1325
1326 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
1327 {
1328         Object *ob = ob_v;
1329         ModifierData *md = md_v;
1330         HookModifierData *hmd = (HookModifierData*) md;
1331
1332         if (G.vd) {
1333                 float *curs = give_cursor();
1334                 float bmat[3][3], imat[3][3];
1335
1336                 where_is_object(ob);
1337         
1338                 Mat3CpyMat4(bmat, ob->obmat);
1339                 Mat3Inv(imat, bmat);
1340
1341                 curs= give_cursor();
1342                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
1343                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
1344                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
1345                 Mat3MulVecfl(imat, hmd->cent);
1346
1347                 BIF_undo_push("Hook cursor center");
1348         }
1349 }
1350
1351 static void modifiers_selectHook(void *ob_v, void *md_v)
1352 {
1353         ModifierData *md = md_v;
1354         HookModifierData *hmd = (HookModifierData*) md;
1355
1356         hook_select(hmd);
1357 }
1358
1359 static void modifiers_reassignHook(void *ob_v, void *md_v)
1360 {
1361         ModifierData *md = md_v;
1362         HookModifierData *hmd = (HookModifierData*) md;
1363         float cent[3];
1364         int *indexar, tot, ok;
1365         char name[32];
1366                 
1367         ok= hook_getIndexArray(&tot, &indexar, name, cent);
1368
1369         if (!ok) {
1370                 error("Requires selected vertices or active Vertex Group");
1371         } else {
1372                 if (hmd->indexar) {
1373                         MEM_freeN(hmd->indexar);
1374                 }
1375
1376                 VECCOPY(hmd->cent, cent);
1377                 hmd->indexar = indexar;
1378                 hmd->totindex = tot;
1379         }
1380 }
1381
1382 static void modifiers_convertToReal(void *ob_v, void *md_v)
1383 {
1384         Object *ob = ob_v;
1385         ModifierData *md = md_v;
1386         ModifierData *nmd = modifier_new(md->type);
1387
1388         modifier_copyData(md, nmd);
1389         nmd->mode &= ~eModifierMode_Virtual;
1390
1391         BLI_addhead(&ob->modifiers, nmd);
1392
1393         ob->partype = PAROBJECT;
1394
1395         BIF_undo_push("Modifier convert to real");
1396 }
1397
1398 static void build_uvlayer_menu_vars(CustomData *data, char **menu_string,
1399                                     int *uvlayer_tmp, char *uvlayer_name)
1400 {
1401         char strtmp[38];
1402         int totuv, i;
1403         CustomDataLayer *layer
1404                     = &data->layers[CustomData_get_layer_index(data, CD_MTFACE)];
1405
1406         *uvlayer_tmp = -1;
1407
1408         totuv = CustomData_number_of_layers(data, CD_MTFACE);
1409
1410         *menu_string = MEM_callocN(sizeof(**menu_string) * (totuv * 38 + 10),
1411                                    "menu_string");
1412         sprintf(*menu_string, "UV Layer%%t");
1413         for(i = 0; i < totuv; i++) {
1414                 /* assign first layer as uvlayer_name if uvlayer_name is null. */
1415                 if(strcmp(layer->name, uvlayer_name) == 0) *uvlayer_tmp = i + 1;
1416                 sprintf(strtmp, "|%s%%x%d", layer->name, i + 1);
1417                 strcat(*menu_string, strtmp);
1418                 layer++;
1419         }
1420
1421         /* there is no uvlayer defined, or else it was deleted. Assign active
1422          * layer, then recalc modifiers.
1423          */
1424         if(*uvlayer_tmp == -1) {
1425                 if(CustomData_get_active_layer_index(data, CD_MTFACE) != -1) {
1426                         *uvlayer_tmp = 1;
1427                         layer = data->layers;
1428                         for(i = 0; i < CustomData_get_active_layer_index(data, CD_MTFACE);
1429                             i++, layer++) {
1430                                 if(layer->type == CD_MTFACE) (*uvlayer_tmp)++;
1431                         }
1432                         strcpy(uvlayer_name, layer->name);
1433
1434                         /* update the modifiers */
1435                         do_modifier_panels(B_MODIFIER_RECALC);
1436                 } else {
1437                         /* ok we have no uv layers, so make sure menu button knows that.*/
1438                         *uvlayer_tmp = 0;
1439                 }
1440         }
1441 }
1442
1443 void set_displace_uvlayer(void *arg1, void *arg2)
1444 {
1445         DisplaceModifierData *dmd=arg1;
1446         CustomDataLayer *layer = arg2;
1447
1448         /*check we have UV layers*/
1449         if (dmd->uvlayer_tmp < 1) return;
1450         layer = layer + (dmd->uvlayer_tmp-1);
1451         
1452         strcpy(dmd->uvlayer_name, layer->name);
1453 }
1454
1455 void set_uvproject_uvlayer(void *arg1, void *arg2)
1456 {
1457         UVProjectModifierData *umd=arg1;
1458         CustomDataLayer *layer = arg2;
1459
1460         /*check we have UV layers*/
1461         if (umd->uvlayer_tmp < 1) return;
1462         layer = layer + (umd->uvlayer_tmp-1);
1463         
1464         strcpy(umd->uvlayer_name, layer->name);
1465 }
1466
1467 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1468 {
1469         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1470         uiBut *but;
1471         int isVirtual = md->mode&eModifierMode_Virtual;
1472         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1473         int editing = (G.obedit==ob);
1474         short height=26, width = 295, buttonWidth = width-120-10;
1475         char str[128];
1476
1477         /* rounded header */
1478         uiBlockSetCol(block, color);
1479                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1480         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1481                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1482         uiBlockSetCol(block, TH_AUTO);
1483         
1484         /* open/close icon */
1485         if (!isVirtual) {
1486                 uiBlockSetEmboss(block, UI_EMBOSSN);
1487                 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");
1488         }
1489
1490         uiBlockSetEmboss(block, UI_EMBOSS);
1491         
1492         if (isVirtual) {
1493                 sprintf(str, "%s parent deform", md->name);
1494                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1495
1496                 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");
1497                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1498         } else {
1499                 uiBlockBeginAlign(block);
1500                 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"); 
1501
1502                         /* Softbody not allowed in this situation, enforce! */
1503                 if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
1504                         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");
1505                         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");
1506                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1507                                 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)");
1508                         }
1509                 }
1510                 uiBlockEndAlign(block);
1511
1512                 uiBlockSetEmboss(block, UI_EMBOSSR);
1513
1514                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1515                         int icon, color;
1516
1517                         if (index==cageIndex) {
1518                                 color = TH_BUT_SETTING;
1519                                 icon = VICON_EDITMODE_HLT;
1520                         } else if (index<cageIndex) {
1521                                 color = TH_BUT_NEUTRAL;
1522                                 icon = VICON_EDITMODE_DEHLT;
1523                         } else {
1524                                 color = TH_BUT_NEUTRAL;
1525                                 icon = ICON_BLANK1;
1526                         }
1527                         uiBlockSetCol(block, color);
1528                         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");
1529                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1530                         uiBlockSetCol(block, TH_AUTO);
1531                 }
1532
1533                 uiBlockSetCol(block, TH_BUT_ACTION);
1534
1535                 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");
1536                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1537
1538                 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");
1539                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1540                 
1541                 uiBlockSetEmboss(block, UI_EMBOSSN);
1542
1543                 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");
1544                 uiButSetFunc(but, modifiers_del, ob, md);
1545                 uiBlockSetCol(block, TH_AUTO);
1546         }
1547
1548         uiBlockSetEmboss(block, UI_EMBOSS);
1549
1550         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1551                 y -= 18;
1552         } else {
1553                 int cy = y - 8;
1554                 int lx = x + width - 60 - 15;
1555
1556                 if (md->type==eModifierType_Subsurf) {
1557                         height = 105;
1558                 } else if (md->type==eModifierType_Lattice) {
1559                         height = 48;
1560                 } else if (md->type==eModifierType_Curve) {
1561                         height = 72;
1562                 } else if (md->type==eModifierType_Build) {
1563                         height = 86;
1564                 } else if (md->type==eModifierType_Mirror) {
1565                         height = 67;
1566                 } else if (md->type==eModifierType_EdgeSplit) {
1567                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1568                         height = 48;
1569                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1570                 } else if (md->type==eModifierType_Displace) {
1571                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1572                         height = 124;
1573                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1574                            dmd->texmapping == MOD_DISP_MAP_UV)
1575                                 height += 19;
1576                 } else if (md->type==eModifierType_UVProject) {
1577                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1578                 } else if (md->type==eModifierType_Decimate) {
1579                         height = 48;
1580                 } else if (md->type==eModifierType_Smooth) {
1581                         height = 86;
1582                 } else if (md->type==eModifierType_Cast) {
1583                         height = 143;
1584                 } else if (md->type==eModifierType_Wave) {
1585                         WaveModifierData *wmd = (WaveModifierData *)md;
1586                         height = 294;
1587                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1588                            wmd->texmapping == MOD_WAV_MAP_UV)
1589                                 height += 19;
1590                         if(wmd->flag & MOD_WAVE_NORM)
1591                                 height += 19;
1592                 } else if (md->type==eModifierType_Armature) {
1593                         height = 86;
1594                 } else if (md->type==eModifierType_Hook) {
1595                         HookModifierData *hmd = (HookModifierData*) md;
1596                         height = 86;
1597                         if (editing)
1598                                 height += 20;
1599                         if(hmd->indexar==NULL)
1600                                 height += 20;
1601                 } else if (md->type==eModifierType_Softbody) {
1602                         height = 26;
1603                 } else if (md->type==eModifierType_Boolean) {
1604                         height = 48;
1605                 } else if (md->type==eModifierType_Array) {
1606                         height = 211;
1607                 } 
1608                 
1609                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1610                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1611
1612                 y -= 18;
1613
1614                 if (!isVirtual) {
1615                         uiBlockBeginAlign(block);
1616                         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");
1617                         uiButSetFunc(but, modifiers_applyModifier, ob, md);
1618                         if (md->type!=eModifierType_Softbody) {
1619                                 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");
1620                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1621                         }
1622                         uiBlockEndAlign(block);
1623                 }
1624
1625                 lx = x + 10;
1626                 cy = y + 10 - 1;
1627                 uiBlockBeginAlign(block);
1628                 if (md->type==eModifierType_Subsurf) {
1629                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1630                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1631                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1632                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1633                         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");
1634
1635                         /* Disabled until non-EM DerivedMesh implementation is complete */
1636
1637                         /*
1638                         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");
1639                         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");
1640                         */
1641
1642                         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");
1643                         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");
1644                 } else if (md->type==eModifierType_Lattice) {
1645                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1646                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1647                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1648                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1649                 } else if (md->type==eModifierType_Curve) {
1650                         CurveModifierData *cmd = (CurveModifierData*) md;
1651                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1652                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1653                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1654                         
1655                         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");
1656                         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");
1657                         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");
1658                         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");
1659                         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");
1660                         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");
1661                 } else if (md->type==eModifierType_Build) {
1662                         BuildModifierData *bmd = (BuildModifierData*) md;
1663                         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");
1664                         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");
1665                         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.");
1666                         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.");
1667                 } else if (md->type==eModifierType_Mirror) {
1668                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1669                         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");
1670                         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");
1671                         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");
1672                         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");
1673                         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");
1674                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1675                                      "Mirror U",
1676                                      lx, (cy-=19), buttonWidth/2, 19,
1677                                      &mmd->flag, 0, 0, 0, 0,
1678                                      "Mirror the U texture coordinate around "
1679                                      "the 0.5 point");
1680                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1681                                      "Mirror V",
1682                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1683                                      &mmd->flag, 0, 0, 0, 0,
1684                                      "Mirror the V texture coordinate around "
1685                                      "the 0.5 point");
1686                 } else if (md->type==eModifierType_EdgeSplit) {
1687                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1688                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1689                                      B_MODIFIER_RECALC, "From Edge Angle",
1690                                      lx, (cy -= 19), buttonWidth, 19,
1691                                      &emd->flags, 0, 0, 0, 0,
1692                                      "Split edges with high angle between faces");
1693                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1694                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1695                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1696                                           0.0, 180.0, 100, 2,
1697                                           "Angle above which to split edges");
1698                         }
1699                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1700                                      B_MODIFIER_RECALC, "From Marked As Sharp",
1701                                      lx, (cy -= 19), buttonWidth, 19,
1702                                      &emd->flags, 0, 0, 0, 0,
1703                                      "Split edges that are marked as sharp");
1704                 } else if (md->type==eModifierType_Displace) {
1705                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1706                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1707                                        lx, (cy -= 19), buttonWidth, 19,
1708                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1709                                        "Name of vertex group to displace"
1710                                        " (displace whole mesh if blank)");
1711                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1712                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
1713                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
1714                                        &dmd->texture,
1715                                        "Texture to use as displacement input");
1716                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
1717                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
1718                                   0, 1, 10, 3,
1719                                   "Material value that gives no displacement");
1720                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
1721                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
1722                                   -1000, 1000, 10, 10,
1723                                   "Strength of displacement");
1724                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
1725                                 "Z%%x%d|Y%%x%d|X%%x%d",
1726                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
1727                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
1728                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1729                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
1730                                   0.0, 1.0, 0, 0, "Displace direction");
1731                         sprintf(str, "Texture Coordinates%%t"
1732                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1733                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
1734                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
1735                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1736                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
1737                                   0.0, 1.0, 0, 0,
1738                                   "Texture coordinates used for displacement input");
1739                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
1740                                 char *strtmp;
1741                                 int i;
1742                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1743                                                              : &((Mesh*)ob->data)->fdata;
1744                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
1745                                                         dmd->uvlayer_name);
1746                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1747                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
1748                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1749                                 MEM_freeN(strtmp);
1750                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1751                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
1752                                              &fdata->layers[i]);
1753                         }
1754                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
1755                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1756                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1757                                                &dmd->map_object,
1758                                                "Object to get texture coordinates from");
1759                         }
1760                 } else if (md->type==eModifierType_UVProject) {
1761                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
1762                         int i;
1763                         char *strtmp;
1764                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
1765                                                      : &((Mesh*)ob->data)->fdata;
1766                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
1767                                                 umd->uvlayer_name);
1768                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1769                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
1770                               0.0, 1.0, 0, 0, "Set the UV layer to use");
1771                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
1772                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
1773                         MEM_freeN(strtmp);
1774                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
1775                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
1776                                   1, 1000, 100, 2,
1777                                   "Horizontal Aspect Ratio");
1778                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
1779                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
1780                                   &umd->aspecty,
1781                                   1, 1000, 100, 2,
1782                                   "Vertical Aspect Ratio");
1783                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
1784                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
1785                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
1786                                   "Number of objects to use as projectors");
1787                         for(i = 0; i < umd->num_projectors; ++i) {
1788                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1789                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1790                                                &umd->projectors[i],
1791                                                "Object to use as projector");
1792                         }
1793                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
1794                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
1795                                        &umd->image,
1796                                        "Image to project (only faces with this image "
1797                                        "will be altered");
1798                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
1799                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
1800                                      B_MODIFIER_RECALC, "Override Image",
1801                                      lx, (cy -= 19), buttonWidth, 19,
1802                                      &umd->flags, 0, 0, 0, 0,
1803                                      "Override faces' current images with the "
1804                                      "given image");
1805                 } else if (md->type==eModifierType_Decimate) {
1806                         DecimateModifierData *dmd = (DecimateModifierData*) md;
1807                         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");
1808                         sprintf(str, "Face Count: %d", dmd->faceCount);
1809                         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");
1810                 } else if (md->type==eModifierType_Smooth) {
1811                         SmoothModifierData *smd = (SmoothModifierData*) md;
1812
1813                         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");
1814                         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");
1815                         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");
1816
1817                         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)");
1818                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
1819                         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");
1820                 } else if (md->type==eModifierType_Cast) {
1821                         CastModifierData *cmd = (CastModifierData*) md;
1822
1823                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
1824                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
1825                         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");
1826                         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");
1827                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
1828                                 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");
1829                         }
1830                         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");
1831                         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)");
1832                         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)");
1833                         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)");
1834                         if (ob->type == OB_MESH) {
1835                                 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");
1836                         }
1837                         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");
1838                         if(cmd->object) {
1839                                 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");
1840                         }
1841                 } else if (md->type==eModifierType_Wave) {
1842                         WaveModifierData *wmd = (WaveModifierData*) md;
1843                         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");
1844                         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");
1845                         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");
1846                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
1847                         if (wmd->flag & MOD_WAVE_NORM){
1848                                 if (ob->type==OB_MESH) {
1849                                         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");
1850                                         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");
1851                                         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");
1852                                 }
1853                                 else
1854                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
1855                         }
1856
1857                         uiBlockBeginAlign(block);
1858                         if(wmd->speed >= 0)
1859                                 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");
1860                         else
1861                                 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");
1862                         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");
1863                         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");
1864                         cy -= 9;
1865                         uiBlockBeginAlign(block);
1866                         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");
1867                         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");
1868                         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)");
1869                         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");
1870                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
1871                         sprintf(str, "Texture Coordinates%%t"
1872                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1873                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
1874                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
1875                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1876                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
1877                                   0.0, 1.0, 0, 0,
1878                                   "Texture coordinates used for modulation input");
1879                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
1880                                 char *strtmp;
1881                                 int i;
1882                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1883                                                              : &((Mesh*)ob->data)->fdata;
1884                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
1885                                                         wmd->uvlayer_name);
1886                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1887                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
1888                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1889                                 MEM_freeN(strtmp);
1890                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1891                                 uiButSetFunc(but, set_displace_uvlayer, wmd,
1892                                              &fdata->layers[i]);
1893                         }
1894                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
1895                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1896                                                "Ob: ", lx, (cy -= 19), 220, 19,
1897                                                &wmd->map_object,
1898                                                "Object to get texture coordinates from");
1899                         }
1900             cy -= 9;
1901                         uiBlockBeginAlign(block);
1902                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
1903                         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");
1904                         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");
1905                         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");
1906                 } else if (md->type==eModifierType_Armature) {
1907                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
1908                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
1909                         
1910                         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");
1911                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1912                         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");
1913                         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");
1914                         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");
1915
1916                         
1917                 } else if (md->type==eModifierType_Hook) {
1918                         HookModifierData *hmd = (HookModifierData*) md;
1919                         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");
1920                         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");
1921                         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"); 
1922                         if(hmd->indexar==NULL) {
1923                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1924                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1925                         }
1926                         uiBlockBeginAlign(block);
1927                         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");
1928                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
1929                         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");
1930                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
1931
1932                         if (editing) {
1933                                 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");
1934                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
1935                                 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");
1936                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
1937                         }
1938                 } else if (md->type==eModifierType_Softbody) {
1939                         uiDefBut(block, LABEL, 1, "See Softbody panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1940                 } else if (md->type==eModifierType_Boolean) {
1941                         BooleanModifierData *bmd = (BooleanModifierData*) md;
1942                         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");
1943                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
1944                 } else if (md->type==eModifierType_Array) {
1945                         ArrayModifierData *amd = (ArrayModifierData*) md;
1946                         float range = 10000;
1947                         int cytop, halfwidth = (width - 5)/2 - 15;
1948                         int halflx = lx + halfwidth + 10;
1949
1950                         uiBlockSetEmboss(block, UI_EMBOSSX);
1951                         uiBlockEndAlign(block);
1952
1953                         /* length parameters */
1954                         uiBlockBeginAlign(block);
1955                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
1956                                 "|Fit To Curve Length%%x%d",
1957                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
1958                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1959                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
1960                                   0.0, 1.0, 0, 0, "Array length calculation method");
1961                         switch(amd->fit_type)
1962                         {
1963                         case MOD_ARR_FIXEDCOUNT:
1964                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
1965                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
1966                                           1, 1000, 0, 0, "Number of duplicates to make");
1967                                 break;
1968                         case MOD_ARR_FITLENGTH:
1969                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
1970                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
1971                                           0, range, 10, 2,
1972                                           "Length to fit array within");
1973                                 break;
1974                         case MOD_ARR_FITCURVE:
1975                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
1976                                                B_CHANGEDEP, "Ob: ",
1977                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
1978                                                "Curve object to fit array length to");
1979                                 break;
1980                         }
1981                         uiBlockEndAlign(block);
1982
1983                         /* offset parameters */
1984                         cy -= 10;
1985                         cytop= cy;
1986                         uiBlockBeginAlign(block);
1987                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
1988                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
1989                                      &amd->offset_type, 0, 0, 0, 0,
1990                                      "Constant offset between duplicates "
1991                                      "(local coordinates)");
1992                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
1993                                   lx, (cy-=19), halfwidth, 19,
1994                                   &amd->offset[0],
1995                                   -range, range, 10, 3,
1996                                   "Constant component for duplicate offsets "
1997                                   "(local coordinates)");
1998                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
1999                                   lx, (cy-=19), halfwidth, 19,
2000                                   &amd->offset[1],
2001                                   -range, range, 10, 3,
2002                                   "Constant component for duplicate offsets "
2003                                   "(local coordinates)");
2004                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2005                                   lx, (cy-=19), halfwidth, 19,
2006                                   &amd->offset[2],
2007                                   -range, range, 10, 3,
2008                                   "Constant component for duplicate offsets "
2009                                   "(local coordinates)");
2010                         uiBlockEndAlign(block);
2011
2012                         cy= cytop;
2013                         uiBlockBeginAlign(block);
2014                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2015                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2016                                      &amd->offset_type, 0, 0, 0, 0,
2017                                      "Offset between duplicates relative to object width "
2018                                      "(local coordinates)");
2019                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2020                                   halflx, (cy-=19), halfwidth, 19,
2021                                   &amd->scale[0],
2022                                   -range, range, 10, 3,
2023                                   "Component for duplicate offsets relative to object "
2024                                   "width (local coordinates)");
2025                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2026                                   halflx, (cy-=19), halfwidth, 19,
2027                                   &amd->scale[1],
2028                                   -range, range, 10, 3,
2029                                   "Component for duplicate offsets relative to object "
2030                                   "width (local coordinates)");
2031                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2032                                   halflx, (cy-=19), halfwidth, 19,
2033                                   &amd->scale[2],
2034                                   -range, range, 10, 3,
2035                                   "Component for duplicate offsets relative to object "
2036                                   "width (local coordinates)");
2037                         uiBlockEndAlign(block);
2038
2039                         /* vertex merging parameters */
2040                         cy -= 10;
2041                         cytop= cy;
2042
2043                         uiBlockBeginAlign(block);
2044                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2045                                      "Merge",
2046                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2047                                      0, 0, 0, 0,
2048                                      "Merge vertices in adjacent duplicates");
2049                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2050                                      "First Last",
2051                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2052                                      &amd->flags,
2053                                      0, 0, 0, 0,
2054                                      "Merge vertices in first duplicate with vertices"
2055                                      " in last duplicate");
2056                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2057                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2058                                           0, 1.0f, 1, 4,
2059                                           "Limit below which to merge vertices");
2060
2061                         /* offset ob */
2062                         cy = cytop;
2063                         uiBlockBeginAlign(block);
2064                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2065                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2066                                      &amd->offset_type, 0, 0, 0, 0,
2067                                      "Add an object transformation to the total offset");
2068                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2069                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2070                                        &amd->offset_ob,
2071                                        "Object from which to take offset transformation");
2072                         uiBlockEndAlign(block);
2073
2074                         cy -= 10;
2075                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2076                                              B_CHANGEDEP, "Start cap: ",
2077                                              lx, (cy -= 19), halfwidth, 19,
2078                                              &amd->start_cap,
2079                                              "Mesh object to use as start cap");
2080                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2081                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2082                                              B_CHANGEDEP, "End cap: ",
2083                                              halflx, cy, halfwidth, 19,
2084                                              &amd->end_cap,
2085                                              "Mesh object to use as end cap");
2086                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2087                 }
2088                 uiBlockEndAlign(block);
2089
2090                 y-=height;
2091         }
2092
2093         if (md->error) {
2094                 char str[512];
2095
2096                 y -= 20;
2097
2098                 uiBlockSetCol(block, color);
2099                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2100                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2101                 uiBlockSetCol(block, TH_AUTO);
2102
2103                 sprintf(str, "Modifier Error: %s", md->error);
2104                 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2105         }
2106
2107         y -= 3+6;
2108
2109         *xco = x;
2110         *yco = y;
2111 }
2112
2113 static void editing_panel_modifiers(Object *ob)
2114 {
2115         ModifierData *md;
2116         uiBlock *block;
2117         char str[64];
2118         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2119
2120         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2121         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2122         
2123         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2124         uiNewPanelHeight(block, 204);
2125
2126         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2127
2128         sprintf(str, "To: %s", ob->id.name+2);
2129         uiDefBut(block, LABEL, 1, str,  140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2130
2131         xco = 0;
2132         yco = 160;
2133
2134         md = modifiers_getVirtualModifierList(ob);
2135
2136         for (i=0; md; i++, md=md->next) {
2137                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2138                 if (md->mode&eModifierMode_Virtual) i--;
2139         }
2140         
2141         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2142 }
2143
2144 static char *make_key_menu(Key *key)
2145 {
2146         KeyBlock *kb;
2147         int index= 1;
2148         char *str, item[64];
2149
2150         for (kb = key->block.first; kb; kb=kb->next, index++);
2151         str= MEM_mallocN(index*40, "key string");
2152         str[0]= 0;
2153         
2154         index= 1;
2155         for (kb = key->block.first; kb; kb=kb->next, index++) {
2156                 sprintf (item,  "|%s%%x%d", kb->name, index);
2157                 strcat(str, item);
2158         }
2159         
2160         return str;
2161 }
2162
2163 static void editing_panel_shapes(Object *ob)
2164 {
2165         uiBlock *block;
2166         Key *key= NULL;
2167         KeyBlock *kb;
2168         int icon;
2169         char *strp;
2170         
2171         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2172         uiNewPanelTabbed("Modifiers", "Editing");
2173         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2174         
2175         /* Todo check data is library here */
2176         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2177         
2178         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2179         
2180         key= ob_get_key(ob);
2181         if(key==NULL) {
2182                 /* label aligns add button */
2183                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2184                 return;
2185         }
2186         
2187         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2188
2189         kb= BLI_findlink(&key->block, ob->shapenr-1);
2190         if(kb==NULL) {
2191                 ob->shapenr= 1;
2192                 kb= key->block.first;
2193         }
2194
2195         uiBlockBeginAlign(block);
2196         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2197         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");
2198         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2199         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2200         strp= make_key_menu(key);
2201         uiDefButS(block, MENU, B_SETKEY, strp,                                  55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
2202         MEM_freeN(strp);
2203         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2204         uiClearButLock();
2205         uiDefBut(block, TEX, B_NAMEKEY, "",                                             95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2206         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2207         uiBlockEndAlign(block);
2208
2209         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2210                 uiBlockBeginAlign(block);
2211                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2212                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2213                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2214                 uiBlockEndAlign(block);
2215         }
2216         if(key->type && ob->shapenr!=1)
2217                 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");
2218
2219         if(key->type==0)
2220                 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");
2221         
2222 }
2223
2224 /* *************************** FONT ******************************** */
2225
2226 static short give_vfontnr(VFont *vfont)
2227 {
2228         VFont *vf;
2229         short nr= 1;
2230
2231         vf= G.main->vfont.first;
2232         while(vf) {
2233                 if(vf==vfont) return nr;
2234                 nr++;
2235                 vf= vf->id.next;
2236         }
2237         return -1;
2238 }
2239
2240 static VFont *give_vfontpointer(int nr) /* nr= button */
2241 {
2242         VFont *vf;
2243         short tel= 1;
2244
2245         vf= G.main->vfont.first;
2246         while(vf) {
2247                 if(tel==nr) return vf;
2248                 tel++;
2249                 vf= vf->id.next;
2250         }
2251         return G.main->vfont.first;
2252 }
2253
2254 VFont *exist_vfont(char *str)
2255 {
2256         VFont *vf;
2257
2258         vf= G.main->vfont.first;
2259         while(vf) {
2260                 if(strcmp(vf->name, str)==0) return vf;
2261                 vf= vf->id.next;
2262         }
2263         return 0;
2264 }
2265
2266 static char *give_vfontbutstr(void)
2267 {
2268         VFont *vf;
2269         int len= 0;
2270         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2271
2272         vf= G.main->vfont.first;
2273         while(vf) {
2274                 strcpy(di, vf->name);
2275                 BLI_splitdirstring(di, fi);
2276                 len+= strlen(fi)+4;
2277                 vf= vf->id.next;
2278         }
2279
2280         str= MEM_callocN(len+21, "vfontbutstr");
2281         strcpy(str, "FONTS %t");
2282         vf= G.main->vfont.first;
2283         while(vf) {
2284
2285                 if(vf->id.us==0) strcat(str, "|0 ");
2286                 else strcat(str, "|   ");
2287
2288                 strcpy(di, vf->name);
2289                 BLI_splitdirstring(di, fi);
2290
2291                 strcat(str, fi);
2292                 vf= vf->id.next;
2293         }
2294         return str;
2295 }
2296
2297 static void load_buts_vfont(char *name)
2298 {
2299         VFont *vf;
2300         Curve *cu;
2301
2302         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2303         else return;
2304
2305         vf= exist_vfont(name);
2306         if(vf==0) {
2307                 vf= load_vfont(name);
2308                 if(vf==0) return;
2309         }
2310         else id_us_plus((ID *)vf);
2311         
2312         switch(cu->curinfo.flag & CU_STYLE) {
2313                 case CU_BOLD:
2314                         if(cu->vfontb) cu->vfontb->id.us--;
2315                         cu->vfontb= vf;
2316                         break;
2317                 case CU_ITALIC:
2318                         if(cu->vfonti) cu->vfonti->id.us--;             
2319                         cu->vfonti= vf;
2320                         break;                                          
2321                 case (CU_BOLD|CU_ITALIC):
2322                         if(cu->vfontbi) cu->vfontbi->id.us--;
2323                         cu->vfontbi= vf;
2324                         break;
2325                 default:
2326                         if(cu->vfont) cu->vfont->id.us--;
2327                         cu->vfont= vf;
2328                         break;                                          
2329         }       
2330
2331         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2332         BIF_undo_push("Load vector font");
2333         allqueue(REDRAWVIEW3D, 0);
2334         allqueue(REDRAWBUTSEDIT, 0);
2335 }
2336
2337 static void set_unicode_text_fs(char *file)
2338 {
2339         if (file > 0) paste_unicodeText(file); 
2340 }
2341
2342 void do_fontbuts(unsigned short event)
2343 {
2344         Curve *cu;
2345         VFont *vf;
2346         Object *ob;
2347         ScrArea *sa;
2348         char str[80];
2349         int ctevt;
2350         char *ctmenu;
2351         DynStr *ds;
2352         int i, style=0;
2353
2354         ob= OBACT;
2355
2356         switch(event) {
2357         case B_MAKEFONT:
2358                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2359                 allqueue(REDRAWVIEW3D, 0);
2360                 break;
2361
2362         case B_STYLETOSELU:     
2363         case B_STYLETOSELB:
2364         case B_STYLETOSELI:
2365                 switch (event) {
2366                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2367                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2368                         case B_STYLETOSELI: style = CU_ITALIC; break;
2369                 }
2370                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2371                         text_to_curve(ob, 0);
2372                         makeDispListCurveTypes(ob, 0);
2373                         allqueue(REDRAWVIEW3D, 0);
2374                 }
2375                 allqueue(REDRAWBUTSEDIT, 0);
2376                 break;          
2377                 
2378         case B_FASTFONT:
2379                 if (G.obedit) {
2380                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2381                         allqueue(REDRAWVIEW3D, 0);
2382                 }
2383                 break;
2384         case B_INSTB:
2385                 cu= ob->data;
2386                 if (cu->totbox < 256) {
2387                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2388                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2389                         cu->actbox++;
2390                         cu->totbox++;
2391                         allqueue(REDRAWBUTSEDIT, 0);
2392                         allqueue(REDRAWVIEW3D, 0);
2393                         text_to_curve(ob, 0);
2394                         makeDispListCurveTypes(ob, 0);
2395                 }
2396                 else {
2397                         error("Do you really need that many text frames?");
2398                 }
2399                 break;
2400         case B_DELTB:
2401                 cu= ob->data;
2402                 if (cu->totbox > 1) {
2403                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2404                         cu->totbox--;
2405                         cu->actbox--;
2406                         allqueue(REDRAWBUTSEDIT, 0);
2407                         allqueue(REDRAWVIEW3D, 0);
2408                         text_to_curve(ob, 0);
2409                         makeDispListCurveTypes(ob, 0);
2410                 }
2411                 break;
2412         case B_TOUPPER:
2413                 to_upper();
2414                 break;
2415         case B_LOADFONT:
2416                 vf= give_vfontpointer(G.buts->texnr);
2417                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2418                 else strcpy(str, U.fontdir);
2419
2420                 sa= closest_bigger_area();
2421                 areawinset(sa->win);
2422
2423                 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2424
2425                 break;
2426         case B_PACKFONT:
2427                 if (ob) {
2428                         cu= ob->data;
2429                         if(cu && cu->vfont) {
2430                                 if (cu->vfont->packedfile) {
2431                                         if (G.fileflags & G_AUTOPACK) {
2432                                                 if (okee("Disable AutoPack ?")) {
2433                                                         G.fileflags &= ~G_AUTOPACK;
2434                                                 }
2435                                         }
2436
2437                                         if ((G.fileflags & G_AUTOPACK) == 0) {
2438                                                 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2439                                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2440                                                         allqueue(REDRAWVIEW3D, 0);
2441                                                 }
2442                                         }
2443                                 } else {
2444                                         cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2445                                 }
2446                         }
2447                 }
2448                 allqueue(REDRAWHEADERS, 0);
2449                 allqueue(REDRAWBUTSEDIT, 0);
2450                 break;
2451
2452         case B_LOAD3DTEXT:
2453                 if (!G.obedit) { error("Only in editmode!"); return; }
2454                 if (G.obedit->type != OB_FONT) return;  
2455                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2456                 break;
2457                 
2458         case B_LOREM:
2459                 if (!G.obedit) { error("Only in editmode!"); return; }
2460                 if (G.obedit->type != OB_FONT) return;  
2461                 add_lorem();
2462                 
2463                 break;          
2464
2465         case B_SETFONT:
2466                 if(ob) {
2467                         cu= ob->data;
2468
2469                         vf= give_vfontpointer(G.buts->texnr);
2470                         if(vf) {
2471                                 id_us_plus((ID *)vf);
2472
2473                                 switch(cu->curinfo.flag & CU_STYLE) {
2474                                         case CU_BOLD:
2475                                                 cu->vfontb->id.us--;
2476                                                 cu->vfontb= vf;
2477                                                 break;
2478                                         case CU_ITALIC:
2479                                                 cu->vfonti->id.us--;
2480                                                 cu->vfonti= vf;
2481                                                 break;                                          
2482                                         case (CU_BOLD|CU_ITALIC):
2483                                                 cu->vfontbi->id.us--;
2484                                                 cu->vfontbi= vf;
2485                                                 break;
2486                                         default:
2487                                                 cu->vfont->id.us--;
2488                                                 cu->vfont= vf;
2489                                                 break;                                          
2490                                 }
2491                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2492
2493                                 BIF_undo_push("Set vector font");
2494                                 allqueue(REDRAWVIEW3D, 0);
2495                                 allqueue(REDRAWBUTSEDIT, 0);
2496                         }
2497                 }
2498                 break;
2499                 
2500         case B_SETCHAR:
2501                 G.charmin = 0x0000;
2502                 G.charmax = 0xffff;
2503                 if(G.charstart < 0)
2504                         G.charstart = 0;        
2505                 if(G.charstart > (0xffff - 12*6))
2506                         G.charstart = 0xffff - (12*6);
2507                 allqueue(REDRAWBUTSEDIT, 0);
2508                 break;
2509                 
2510         case B_SETUPCHAR:
2511                 G.charstart = G.charstart - (12*6);
2512                 if(G.charstart < 0)
2513                         G.charstart = 0;        
2514                 if(G.charstart < G.charmin)
2515                         G.charstart = G.charmin;
2516                 allqueue(REDRAWBUTSEDIT, 0);
2517                 break;
2518                 
2519         case B_SETCAT:
2520                 // Create new dynamic string
2521                 ds = BLI_dynstr_new();
2522                 
2523                 // Fill the dynamic string with entries
2524                 for(i=0;i<104;i++)
2525                 {
2526                         BLI_dynstr_append(ds, "|");
2527                         BLI_dynstr_append(ds, uctabname[i].name);
2528                 }
2529                 
2530                 // Create the menu string from dyn string
2531                 ctmenu = BLI_dynstr_get_cstring(ds);
2532                 
2533                 // Call the popup menu
2534                 ctevt = pupmenu_col(ctmenu, 40);
2535                 G.charstart = uctabname[ctevt-1].start;
2536                 G.charmin = uctabname[ctevt-1].start;
2537                 G.charmax = uctabname[ctevt-1].end;
2538
2539                 // Free all data
2540                 BLI_dynstr_free(ds);
2541                 MEM_freeN(ctmenu);
2542
2543                 // And refresh
2544                 allqueue(REDRAWVIEW3D, 0);
2545                 allqueue(REDRAWBUTSEDIT, 0);
2546                 
2547                 break;  
2548                 
2549         case B_SETDOWNCHAR:
2550                 G.charstart = G.charstart + (12*6);
2551                 if(G.charstart > (0xffff - 12*6))
2552                         G.charstart = 0xffff - (12*6);
2553                 if(G.charstart > G.charmax - 12*6)
2554                         G.charstart = G.charmax - 12*6;
2555                 allqueue(REDRAWBUTSEDIT, 0);
2556                 break;
2557                 
2558         case B_SETUNITEXT:
2559                 sa= closest_bigger_area();
2560                 areawinset(sa->win);
2561
2562                 if(ob==G.obedit) {
2563                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
2564                 }
2565                 break;          
2566                 
2567         case B_TEXTONCURVE:
2568                 if(ob) {
2569                         cu= ob->data;
2570                         if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
2571                                 error("Only Curve Objects");
2572                                 cu->textoncurve= 0;
2573                                 allqueue(REDRAWBUTSEDIT, 0);
2574                         }
2575                         DAG_scene_sort(G.scene); // makes new dag
2576                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2577                         allqueue(REDRAWVIEW3D, 0);
2578                 }
2579         }
2580 }
2581
2582 static void editing_panel_char_type(Object *ob, Curve *cu)
2583 {
2584         uiBlock *block;
2585
2586         block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
2587         uiNewPanelTabbed("Font", "Editing");
2588         if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0) 
2589                 return;
2590
2591         // Set the selected font
2592         G.selfont = cu->vfont;
2593         
2594         uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT,       0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
2595
2596         // Unicode categorization selection button
2597         uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
2598         uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
2599
2600         // Character selection button
2601         uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
2602
2603         // Buttons to change the max, min
2604         uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
2605         uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
2606 }
2607
2608 static void editing_panel_font_type(Object *ob, Curve *cu)
2609 {
2610         uiBlock *block;
2611         char *strp;
2612         static int packdummy = 0;
2613         char str[32];
2614
2615         block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
2616         if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
2617
2618         switch(cu->curinfo.flag & CU_STYLE) {
2619                 case CU_BOLD:
2620                         G.buts->texnr= give_vfontnr(cu->vfontb);
2621                         break;
2622                 case CU_ITALIC:
2623                         G.buts->texnr= give_vfontnr(cu->vfonti);
2624                         break;                                          
2625                 case (CU_BOLD|CU_ITALIC):
2626                         G.buts->texnr= give_vfontnr(cu->vfontbi);
2627                         break;
2628                 default:
2629                         G.buts->texnr= give_vfontnr(cu->vfont);
2630                         break;                                          
2631         }       
2632
2633         strp= give_vfontbutstr();
2634 //      vfd= cu->vfont->data;
2635
2636         uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
2637         uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
2638
2639         if (cu->vfont->packedfile) {
2640                 packdummy = 1;
2641         } else {
2642                 packdummy = 0;
2643         }
2644         uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE,       772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
2645
2646         /* This doesn't work anyway */
2647 //      uiDefBut(block, LABEL, 0, vfd->name,  480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
2648
2649         uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
2650         uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor"); 
2651         uiDefButC(block, TOG|BIT|2,B_STYLETOSELU, "U",          727,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");     
2652         uiBlockBeginAlign(block);
2653         uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSELB, "B",           752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
2654         uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSELI, "i",         772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");    
2655         uiBlockEndAlign(block);
2656
2657         MEM_freeN(strp);
2658
2659         uiBlockBeginAlign(block);
2660         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");
2661         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");
2662         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");
2663         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");
2664         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");   
2665         uiDefBut(block, BUT, B_TOUPPER, "ToUpper",              715,135,78,20, 0, 0, 0, 0, 0, "Toggle between upper and lower case in editmode");
2666         uiBlockEndAlign(block);
2667         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");     
2668
2669         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_TEXTONCURVE, "TextOnCurve:",    480,105,220,19, &cu->textoncurve, "Apply a deforming curve to the text");
2670         uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 480,84,220,19, cu->family, 0.0, 20.0, 0, 0, "Blender uses font from selfmade objects");
2671
2672         uiBlockBeginAlign(block);
2673         uiDefButF(block, NUM,B_MAKEFONT, "Size:",               480,56,155,20, &cu->fsize, 0.1,10.0, 10, 0, "Size of the text");
2674         uiDefButF(block, NUM,B_MAKEFONT, "Linedist:",   640,56,155,20, &cu->linedist, 0.0,10.0, 10, 0, "Distance between text lines");
2675         uiDefButF(block, NUM,B_MAKEFONT, "Word spacing:",       795,56,155,20, &cu->wordspace, 0.0,10.0, 10, 0, "Distance factor between words");               
2676         uiDefButF(block, NUM,B_MAKEFONT, "Spacing:",    480,34,155,20, &cu->spacing, 0.0,10.0, 10, 0, "Spacing of individual characters");
2677         uiDefButF(block, NUM,B_MAKEFONT, "X offset:",   640,34,155,20, &cu->xof, -50.0,50.0, 10, 0, "Horizontal position from object center");
2678         uiDefButF(block, NUM,B_MAKEFONT, "UL position:",        795,34,155,20, &cu->ulpos, -0.2,0.8, 10, 0, "Vertical position of underline");                  
2679         uiDefButF(block, NUM,B_MAKEFONT, "Shear:",              480,12,155,20, &cu->shear, -1.0,1.0, 10, 0, "Italic angle of the characters");
2680         uiDefButF(block, NUM,B_MAKEFONT, "Y offset:",   640,12,155,20, &cu->yof, -50.0,50.0, 10, 0, "Vertical position from object center");
2681         uiDefButF(block, NUM,B_MAKEFONT, "UL height:",  795,12,155,20, &cu->ulheight, 0.01,0.5, 10, 0, "Thickness of underline");                               
2682         uiBlockEndAlign(block); 
2683         
2684         sprintf(str, "%d TextFrame: ", cu->totbox);
2685         uiBlockBeginAlign(block);
2686         uiDefButI(block, NUM, REDRAWVIEW3D, str, 805, 188, 145, 20, &cu->actbox, 1.0, cu->totbox, 0, 10, "Textbox to show settings for");
2687         uiDefBut(block, BUT,B_INSTB, "Insert", 805, 168, 72, 20, 0, 0, 0, 0, 0, "Insert a new text frame after the current one");
2688         uiDefBut(block, BUT,B_DELTB, "Delete", 877, 168, 73, 20, 0, 0, 0, 0, 0, "Delete current text frame and shift the others up");   
2689         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");
2690         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");     
2691         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");
2692         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");         
2693         uiBlockEndAlign(block);
2694 }
2695
2696
2697 /* *************************** CURVE ******************************** */
2698
2699
2700 void do_curvebuts(unsigned short event)
2701 {
2702         extern Nurb *lastnu;
2703         extern ListBase editNurb;  /* from editcurve */
2704         Object *ob;
2705         Curve *cu;
2706         Nurb *nu;
2707
2708         ob= OBACT;
2709         if(ob==0) return;
2710
2711         switch(event) {
2712
2713         case B_CONVERTPOLY:
2714         case B_CONVERTBEZ:
2715         case B_CONVERTBSPL:
2716         case B_CONVERTCARD:
2717         case B_CONVERTNURB:
2718                 if(G.obedit) {
2719                         setsplinetype(event-B_CONVERTPOLY);
2720                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2721                         allqueue(REDRAWVIEW3D, 0);
2722                 }
2723                 break;
2724         case B_UNIFU:
2725         case B_ENDPU:
2726         case B_BEZU:
2727         case B_UNIFV:
2728         case B_ENDPV:
2729         case B_BEZV:
2730                 if(G.obedit) {
2731                         nu= editNurb.first;
2732                         while(nu) {
2733                                 if(isNurbsel(nu)) {
2734                                         if((nu->type & 7)==CU_NURBS) {
2735                                                 if(event<B_UNIFV) {
2736                                                         nu->flagu &= 1;
2737                                                         nu->flagu += ((event-B_UNIFU)<<1);
2738                                                         makeknots(nu, 1, nu->flagu>>1);
2739                                                 }
2740                                                 else if(nu->pntsv>1) {
2741                                                         nu->flagv &= 1;
2742                                                         nu->flagv += ((event-B_UNIFV)<<1);
2743                                                         makeknots(nu, 2, nu->flagv>>1);
2744                                                 }
2745                                         }
2746                                 }
2747                                 nu= nu->next;
2748                         }
2749                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2750                         allqueue(REDRAWVIEW3D, 0);
2751                 }
2752                 break;
2753         case B_SETWEIGHT:
2754                 if(G.obedit) {
2755                         weightflagNurb(1, editbutweight, 0);
2756                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2757                         allqueue(REDRAWVIEW3D, 0);
2758                 }
2759                 break;
2760         case B_SETW1:
2761                 editbutweight= 1.0;
2762                 scrarea_queue_winredraw(curarea);
2763                 break;
2764         case B_SETW2:
2765                 editbutweight= sqrt(2.0)/4.0;
2766                 scrarea_queue_winredraw(curarea);
2767                 break;
2768         case B_SETW3:
2769                 editbutweight= 0.25;
2770                 scrarea_queue_winredraw(curarea);
2771                 break;
2772         case B_SETW4:
2773                 editbutweight= sqrt(0.5);
2774                 scrarea_queue_winredraw(curarea);
2775                 break;
2776         case B_SETORDER:
2777                 if(G.obedit) {
2778                         nu= lastnu;
2779                         if(nu && (nu->type & 7)==CU_NURBS ) {
2780                                 if(nu->orderu>nu->pntsu) {
2781                                         nu->orderu= nu->pntsu;
2782                                         scrarea_queue_winredraw(curarea);
2783                                 }
2784                                 makeknots(nu, 1, nu->flagu>>1);
2785                                 if(nu->orderv>nu->pntsv) {
2786                                         nu->orderv= nu->pntsv;
2787                                         scrarea_queue_winredraw(curarea);
2788                                 }
2789                                 makeknots(nu, 2, nu->flagv>>1);
2790                         }
2791                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2792                         allqueue(REDRAWVIEW3D, 0);
2793                 }
2794                 break;
2795         case B_TILTINTERP:
2796                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2797                 allqueue(REDRAWVIEW3D, 0);
2798                 break;
2799         case B_SUBSURFTYPE:
2800                 /* fallthrough */
2801         case B_MAKEDISP:
2802                 if(G.vd) {
2803                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2804                         allqueue(REDRAWVIEW3D, 0);
2805                         allqueue(REDRAWBUTSALL, 0);
2806                         allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
2807                 }
2808                 break;
2809
2810         case B_SUBDIVCURVE:
2811                 subdivideNurb();
2812                 break;
2813         case B_SPINNURB:
2814                 if( (G.obedit==NULL) || (G.obedit->type!=OB_SURF) || (G.vd==NULL) ||
2815                         ((G.obedit->lay & G.vd->lay) == 0) ) return;
2816                 spinNurb(0, 0);
2817                 countall();
2818                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2819                 allqueue(REDRAWVIEW3D, 0);
2820                 break;
2821         case B_CU3D:        /* allow 3D curve */
2822                 if(G.obedit) {
2823                         cu= G.obedit->data;
2824                         nu= editNurb.first;
2825                         while(nu) {
2826                                 nu->type &= ~CU_2D;
2827                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2828                                 test2DNurb(nu);
2829                                 nu= nu->next;
2830                         }
2831                 }
2832                 if(ob->type==OB_CURVE) {
2833                         cu= ob->data;
2834                         nu= cu->nurb.first;
2835                         while(nu) {
2836                                 nu->type &= ~CU_2D;
2837                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2838                                 test2DNurb(nu);
2839                                 nu= nu->next;
2840                         }
2841                 }
2842                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2843                 allqueue(REDRAWVIEW3D, 0);
2844                 break;
2845         case B_SETRESOLU:
2846                 if(ob->type==OB_CURVE) {
2847                         cu= ob->data;
2848                         if(ob==G.obedit) nu= editNurb.first;
2849                         else nu= cu->nurb.first;
2850
2851                         while(nu) {
2852                                 nu->resolu= cu->resolu;
2853                                 nu= nu->next;
2854                         }
2855                 }
2856
2857                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2858                 allqueue(REDRAWVIEW3D, 0);
2859                 allqueue(REDRAWBUTSALL, 0);
2860                 allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
2861
2862                 break;
2863         }
2864 }
2865
2866 static void editing_panel_curve_tools(Object *ob, Curve *cu)
2867 {
2868         Nurb *nu;
2869         extern ListBase editNurb;  /* from editcurve */
2870         extern Nurb *lastnu;
2871         uiBlock *block;
2872         short *sp;
2873
2874         block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_tools", UI_EMBOSS, UI_HELV, curarea->win);
2875         if(uiNewPanel(curarea, block, "Curve Tools", "Editing", 640, 0, 318, 204)==0) return;
2876
2877         uiDefBut(block, LABEL, 0, "Make Knots",562,173,102, 18, 0, 0, 0, 0, 0, "");
2878
2879         if(ob->type==OB_CURVE) {
2880                 uiDefBut(block, LABEL, 0, "Convert",    463,173,72, 18, 0, 0, 0, 0, 0, "");
2881                 uiBlockBeginAlign(block);
2882                 uiDefBut(block, BUT,B_CONVERTPOLY,"Poly",               467,152,72, 18, 0, 0, 0, 0, 0, "Converts selected into regular Polygon vertices");
2883                 uiDefBut(block, BUT,B_CONVERTBEZ,"Bezier",              467,132,72, 18, 0, 0, 0, 0, 0, "Converts selected to Bezier triples");
2884                 uiDefBut(block, BUT,B_CONVERTNURB,"Nurb",               467,112,72, 18, 0, 0, 0, 0, 0, "Converts selected to Nurbs Points");
2885         }
2886         uiBlockBeginAlign(block);
2887         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");
2888         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");
2889         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");
2890         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");
2891         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");
2892         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");
2893         uiBlockEndAlign(block);
2894
2895         uiDefBut(block, BUT,B_SETWEIGHT,"Set Weight",   465,11,95,49, 0, 0, 0, 0, 0, "Nurbs only; set weight for select points");
2896
2897         uiBlockBeginAlign(block);
2898         uiDefButF(block, NUM,0,"Weight:",               565,36,102,22, &editbutweight, 0.01, 100.0, 10, 0, "The weight you can assign");
2899         uiDefBut(block, BUT,B_SETW1,"1.0",              670,36,50,22, 0, 0, 0, 0, 0, "");
2900         uiDefBut(block, BUT,B_SETW2,"sqrt(2)/4",565,11,55,20, 0, 0, 0, 0, 0, "");
2901         uiDefBut(block, BUT,B_SETW3,"0.25",             620,11,45,20, 0, 0, 0, 0, 0, "");
2902         uiDefBut(block, BUT,B_SETW4,"sqrt(0.5)",665,11,55,20, 0, 0, 0, 0, 0, "");
2903         uiBlockEndAlign(block);
2904
2905         if(ob==G.obedit) {
2906                 nu= lastnu;
2907                 if(nu==NULL) nu= editNurb.first;
2908                 if(nu) {
2909                         if (ob->type==OB_CURVE) {
2910                                 uiDefBut(block, LABEL, 0, "Tilt",
2911                                         467,87,72, 18, 0, 0, 0, 0, 0, "");
2912                                 /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */
2913                                 uiDefButS(block, MENU, B_TILTINTERP, "Tilt Interpolation %t|Linear %x0|Cardinal %x1|BSpline %x2",
2914                                         467,67,72, 18, &(nu->tilt_interp), 0, 0, 0, 0, "Tilt interpolation");
2915                         }
2916                                                 
2917                         uiBlockBeginAlign(block);
2918                         sp= &(nu->orderu);
2919                         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");
2920                         sp= &(nu->orderv);
2921                         uiDefButS(block, NUM, B_SETORDER, "V:",         670,90,50, 19, sp, 2.0, 6.0, 0, 0, "Nurbs only; the amount of control points involved");
2922                         sp= &(nu->resolu);
2923                         uiDefButS(block, NUM, B_MAKEDISP, "Resol U:", 565,70,102, 19, sp, 1.0, 1024.0, 0, 0, "The amount of new points interpolated per control vertex pair");
2924                         sp= &(nu->resolv);
2925              &nb