Merge with trunk: svn merge -r 12151:12179 https://svn.blender.org/svnroot/bf-blender...
[blender.git] / source / blender / src / buttons_editing.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <time.h>
34 #include <math.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #ifdef WIN32
39 #ifndef snprintf
40 #define snprintf _snprintf
41 #endif
42 #endif
43
44 #include "MEM_guardedalloc.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_scene_types.h"
48
49 #include "DNA_action_types.h"
50 #include "DNA_armature_types.h"
51 #include "DNA_brush_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_color_types.h"
54 #include "DNA_constraint_types.h"
55 #include "DNA_curve_types.h"
56 #include "DNA_effect_types.h"
57 #include "DNA_group_types.h"
58 #include "DNA_key_types.h"
59 #include "DNA_lamp_types.h"
60 #include "DNA_lattice_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_meta_types.h"
63 #include "DNA_mesh_types.h"
64 #include "DNA_meshdata_types.h"
65 #include "DNA_modifier_types.h"
66 #include "DNA_nla_types.h"
67 #include "DNA_object_types.h"
68 #include "DNA_object_force.h"
69 #include "DNA_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(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_Cloth)) 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_Cloth) {
1604                         height = 26;
1605                 } else if (md->type==eModifierType_Boolean) {
1606                         height = 48;
1607                 } else if (md->type==eModifierType_Array) {
1608                         height = 211;
1609                 } 
1610                 
1611                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1612                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1613
1614                 y -= 18;
1615
1616                 if (!isVirtual) {
1617                         uiBlockBeginAlign(block);
1618                         but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
1619                         uiButSetFunc(but, modifiers_applyModifier, ob, md);
1620                         if ((md->type!=eModifierType_Softbody) && (md->type!=eModifierType_Cloth)) {
1621                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy",   lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
1622                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1623                         }
1624                         uiBlockEndAlign(block);
1625                 }
1626
1627                 lx = x + 10;
1628                 cy = y + 10 - 1;
1629                 uiBlockBeginAlign(block);
1630                 if (md->type==eModifierType_Subsurf) {
1631                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1632                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1633                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1634                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1635                         uiDefButS(block, NUM, B_MODIFIER_REDRAW, "Render Levels:",              lx, (cy-=19), buttonWidth,19, &smd->renderLevels, 1, 6, 0, 0, "Number subdivisions to perform when rendering");
1636
1637                         /* Disabled until non-EM DerivedMesh implementation is complete */
1638
1639                         /*
1640                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_Incremental, B_MODIFIER_RECALC, "Incremental", lx, (cy-=19),90,19,&smd->flags, 0, 0, 0, 0, "Use incremental calculation, even outside of mesh mode");
1641                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_DebugIncr, B_MODIFIER_RECALC, "Debug", lx+90, cy,buttonWidth-90,19,&smd->flags, 0, 0, 0, 0, "Visualize the subsurf incremental calculation, for debugging effect of other modifiers");
1642                         */
1643
1644                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_ControlEdges, B_MODIFIER_RECALC, "Optimal Draw", lx, (cy-=19), buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Skip drawing/rendering of interior subdivided edges");
1645                         uiDefButBitS(block, TOG, eSubsurfModifierFlag_SubsurfUv, B_MODIFIER_RECALC, "Subsurf UV", lx, (cy-=19),buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Use subsurf to subdivide UVs");
1646                 } else if (md->type==eModifierType_Lattice) {
1647                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1648                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1649                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1650                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1651                 } else if (md->type==eModifierType_Curve) {
1652                         CurveModifierData *cmd = (CurveModifierData*) md;
1653                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1654                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1655                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1656                         
1657                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"X",             lx, (cy-=19), 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSX, 0, 0, "The axis that the curve deforms along");
1658                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"Y",             (lx+buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSY, 0, 0, "The axis that the curve deforms along");
1659                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"Z",             (lx+2*buttonWidth/6), cy, 19,19, &cmd->defaxis, 12.0, MOD_CURVE_POSZ, 0, 0, "The axis that the curve deforms along");
1660                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-X",            (lx+3*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGX, 0, 0, "The axis that the curve deforms along");
1661                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Y",            (lx+4*buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGY, 0, 0, "The axis that the curve deforms along");
1662                         uiDefButS(block, ROW,B_MODIFIER_RECALC,"-Z",            (lx+buttonWidth-buttonWidth/6), cy, 24,19, &cmd->defaxis, 12.0, MOD_CURVE_NEGZ, 0, 0, "The axis that the curve deforms along");
1663                 } else if (md->type==eModifierType_Build) {
1664                         BuildModifierData *bmd = (BuildModifierData*) md;
1665                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Start:", lx, (cy-=19), buttonWidth,19, &bmd->start, 1.0, MAXFRAMEF, 100, 0, "Specify the start frame of the effect");
1666                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:", lx, (cy-=19), buttonWidth,19, &bmd->length, 1.0, MAXFRAMEF, 100, 0, "Specify the total time the build effect requires");
1667                         uiDefButI(block, TOG, B_MODIFIER_RECALC, "Randomize", lx, (cy-=19), buttonWidth,19, &bmd->randomize, 0, 0, 1, 0, "Randomize the faces or edges during build.");
1668                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Seed:", lx, (cy-=19), buttonWidth,19, &bmd->seed, 1.0, MAXFRAMEF, 100, 0, "Specify the seed for random if used.");
1669                 } else if (md->type==eModifierType_Mirror) {
1670                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1671                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Merge Limit:", lx, (cy-=19), buttonWidth,19, &mmd->tolerance, 0.0, 1.0, 10, 10, "Distance from axis within which mirrored vertices are merged");
1672                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_X, B_MODIFIER_RECALC, "X",        lx,(cy-=19),20,19, &mmd->flag, 0, 0, 0, 0, "Enable X axis mirror");
1673                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_Y, B_MODIFIER_RECALC, "Y",        lx+20,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Y axis mirror");
1674                         uiDefButBitS(block, TOG, MOD_MIR_AXIS_Z, B_MODIFIER_RECALC, "Z",        lx+40,cy,20,19,    &mmd->flag, 0, 0, 0, 0, "Enable Z axis mirror");
1675                         uiDefButBitS(block, TOG, MOD_MIR_CLIPPING, B_MODIFIER_RECALC, "Do Clipping",    lx+60, cy, buttonWidth-60,19, &mmd->flag, 1, 2, 0, 0, "Prevents during Transform vertices to go through Mirror");
1676                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1677                                      "Mirror U",
1678                                      lx, (cy-=19), buttonWidth/2, 19,
1679                                      &mmd->flag, 0, 0, 0, 0,
1680                                      "Mirror the U texture coordinate around "
1681                                      "the 0.5 point");
1682                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1683                                      "Mirror V",
1684                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1685                                      &mmd->flag, 0, 0, 0, 0,
1686                                      "Mirror the V texture coordinate around "
1687                                      "the 0.5 point");
1688                 } else if (md->type==eModifierType_EdgeSplit) {
1689                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1690                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1691                                      B_MODIFIER_RECALC, "From Edge Angle",
1692                                      lx, (cy -= 19), buttonWidth, 19,
1693                                      &emd->flags, 0, 0, 0, 0,
1694                                      "Split edges with high angle between faces");
1695                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1696                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1697                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1698                                           0.0, 180.0, 100, 2,
1699                                           "Angle above which to split edges");
1700                         }
1701                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1702                                      B_MODIFIER_RECALC, "From Marked As Sharp",
1703                                      lx, (cy -= 19), buttonWidth, 19,
1704                                      &emd->flags, 0, 0, 0, 0,
1705                                      "Split edges that are marked as sharp");
1706                 } else if (md->type==eModifierType_Displace) {
1707                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1708                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1709                                        lx, (cy -= 19), buttonWidth, 19,
1710                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1711                                        "Name of vertex group to displace"
1712                                        " (displace whole mesh if blank)");
1713                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1714                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
1715                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
1716                                        &dmd->texture,
1717                                        "Texture to use as displacement input");
1718                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
1719                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
1720                                   0, 1, 10, 3,
1721                                   "Material value that gives no displacement");
1722                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
1723                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
1724                                   -1000, 1000, 10, 10,
1725                                   "Strength of displacement");
1726                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
1727                                 "Z%%x%d|Y%%x%d|X%%x%d",
1728                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
1729                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
1730                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1731                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
1732                                   0.0, 1.0, 0, 0, "Displace direction");
1733                         sprintf(str, "Texture Coordinates%%t"
1734                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1735                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
1736                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
1737                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1738                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
1739                                   0.0, 1.0, 0, 0,
1740                                   "Texture coordinates used for displacement input");
1741                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
1742                                 char *strtmp;
1743                                 int i;
1744                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1745                                                              : &((Mesh*)ob->data)->fdata;
1746                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
1747                                                         dmd->uvlayer_name);
1748                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1749                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
1750                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1751                                 MEM_freeN(strtmp);
1752                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1753                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
1754                                              &fdata->layers[i]);
1755                         }
1756                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
1757                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1758                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1759                                                &dmd->map_object,
1760                                                "Object to get texture coordinates from");
1761                         }
1762                 } else if (md->type==eModifierType_UVProject) {
1763                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
1764                         int i;
1765                         char *strtmp;
1766                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
1767                                                      : &((Mesh*)ob->data)->fdata;
1768                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
1769                                                 umd->uvlayer_name);
1770                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1771                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
1772                               0.0, 1.0, 0, 0, "Set the UV layer to use");
1773                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
1774                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
1775                         MEM_freeN(strtmp);
1776                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
1777                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
1778                                   1, 1000, 100, 2,
1779                                   "Horizontal Aspect Ratio");
1780                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
1781                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
1782                                   &umd->aspecty,
1783                                   1, 1000, 100, 2,
1784                                   "Vertical Aspect Ratio");
1785                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
1786                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
1787                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
1788                                   "Number of objects to use as projectors");
1789                         for(i = 0; i < umd->num_projectors; ++i) {
1790                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1791                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1792                                                &umd->projectors[i],
1793                                                "Object to use as projector");
1794                         }
1795                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
1796                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
1797                                        &umd->image,
1798                                        "Image to project (only faces with this image "
1799                                        "will be altered");
1800                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
1801                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
1802                                      B_MODIFIER_RECALC, "Override Image",
1803                                      lx, (cy -= 19), buttonWidth, 19,
1804                                      &umd->flags, 0, 0, 0, 0,
1805                                      "Override faces' current images with the "
1806                                      "given image");
1807                 } else if (md->type==eModifierType_Decimate) {
1808                         DecimateModifierData *dmd = (DecimateModifierData*) md;
1809                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Ratio:",      lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to");
1810                         sprintf(str, "Face Count: %d", dmd->faceCount);
1811                         uiDefBut(block, LABEL, 1, str,  lx, (cy-=19), 160,19, NULL, 0.0, 0.0, 0, 0, "Displays the current number of faces in the decimated mesh");
1812                 } else if (md->type==eModifierType_Smooth) {
1813                         SmoothModifierData *smd = (SmoothModifierData*) md;
1814
1815                         uiDefButBitS(block, TOG, MOD_SMOOTH_X, B_MODIFIER_RECALC, "X",          lx,(cy-=19),45,19, &smd->flag, 0, 0, 0, 0, "Enable X axis smoothing");
1816                         uiDefButBitS(block, TOG, MOD_SMOOTH_Y, B_MODIFIER_RECALC, "Y",          lx+45,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Y axis smoothing");
1817                         uiDefButBitS(block, TOG, MOD_SMOOTH_Z, B_MODIFIER_RECALC, "Z",          lx+90,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Z axis smoothing");
1818
1819                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &smd->fac, -10.0, 10.0, 0.5, 0, "Define the amount of smoothing, from 0.0 to 1.0 (lower / higher values can deform the mesh)");
1820                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
1821                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &smd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
1822                 } else if (md->type==eModifierType_Cast) {
1823                         CastModifierData *cmd = (CastModifierData*) md;
1824
1825                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
1826                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
1827                         uiDefButBitS(block, TOG, MOD_CAST_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) X axis deformation");
1828                         uiDefButBitS(block, TOG, MOD_CAST_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Y axis deformation");
1829                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
1830                                 uiDefButBitS(block, TOG, MOD_CAST_Z, B_MODIFIER_RECALC, "Z",            lx+90,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Z axis deformation");
1831                         }
1832                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:",     lx,(cy-=19),buttonWidth, 19, &cmd->fac, -10.0, 10.0, 5, 0, "Define the amount of deformation");
1833                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Radius:",     lx,(cy-=19),buttonWidth, 19, &cmd->radius, 0.0, 100.0, 10.0, 0, "Only deform vertices within this distance from the center of the effect (leave as 0 for infinite)");
1834                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Size:",       lx,(cy-=19),buttonWidth, 19, &cmd->size, 0.0, 100.0, 10.0, 0, "Size of projection shape (leave as 0 for auto)");
1835                         uiDefButBitS(block, TOG, MOD_CAST_SIZE_FROM_RADIUS, B_MODIFIER_RECALC, "From radius",           lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use radius as size of projection shape (0 = auto)");
1836                         if (ob->type == OB_MESH) {
1837                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
1838                         }
1839                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx,(cy-=19), buttonWidth,19, &cmd->object, "Control object: if available, its location determines the center of the effect");
1840                         if(cmd->object) {
1841                                 uiDefButBitS(block, TOG, MOD_CAST_USE_OB_TRANSFORM, B_MODIFIER_RECALC, "Use transform",         lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use object transform to control projection shape");
1842                         }
1843                 } else if (md->type==eModifierType_Wave) {
1844                         WaveModifierData *wmd = (WaveModifierData*) md;
1845                         uiDefButBitS(block, TOG, MOD_WAVE_X, B_MODIFIER_RECALC, "X",            lx,(cy-=19),45,19, &wmd->flag, 0, 0, 0, 0, "Enable X axis motion");
1846                         uiDefButBitS(block, TOG, MOD_WAVE_Y, B_MODIFIER_RECALC, "Y",            lx+45,cy,45,19, &wmd->flag, 0, 0, 0, 0, "Enable Y axis motion");
1847                         uiDefButBitS(block, TOG, MOD_WAVE_CYCL, B_MODIFIER_RECALC, "Cycl",      lx+90,cy,buttonWidth-90,19, &wmd->flag, 0, 0, 0, 0, "Enable cyclic wave effect");
1848                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
1849                         if (wmd->flag & MOD_WAVE_NORM){
1850                                 if (ob->type==OB_MESH) {
1851                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_X, B_MODIFIER_RECALC, "X",       lx,(cy-=19),buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the X normal");
1852                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_Y, B_MODIFIER_RECALC, "Y",       lx+(buttonWidth/3),cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Y normal");
1853                                         uiDefButBitS(block, TOG, MOD_WAVE_NORM_Z, B_MODIFIER_RECALC, "Z",       lx+(buttonWidth/3)*2,cy,buttonWidth/3,19, &wmd->flag, 0, 0, 0, 0, "Enable displacement along the Z normal");
1854                                 }
1855                                 else
1856                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
1857                         }
1858
1859                         uiBlockBeginAlign(block);
1860                         if(wmd->speed >= 0)
1861                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time sta:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify starting frame of the wave");
1862                         else
1863                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Time end:",   lx,(cy-=19),buttonWidth,19, &wmd->timeoffs, -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify ending frame of the wave");
1864                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
1865                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
1866                         cy -= 9;
1867                         uiBlockBeginAlign(block);
1868                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta x:",              lx,(cy-=19),113,19, &wmd->startx, -100.0, 100.0, 100, 0, "Starting position for the X axis");
1869                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Sta y:",              lx+115,cy,105,19, &wmd->starty, -100.0, 100.0, 100, 0, "Starting position for the Y axis");
1870                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_MODIFIER_RECALC, "Ob: ", lx, (cy-=19), 220,19, &wmd->objectcenter, "Object to use as Starting Position (leave blank to disable)");
1871                         uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",lx, (cy -= 19), 220, 19,&wmd->defgrp_name, 0.0, 31.0, 0, 0, "Name of vertex group with which to modulate displacement");
1872                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
1873                         sprintf(str, "Texture Coordinates%%t"
1874                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1875                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
1876                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
1877                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1878                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
1879                                   0.0, 1.0, 0, 0,
1880                                   "Texture coordinates used for modulation input");
1881                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
1882                                 char *strtmp;
1883                                 int i;
1884                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1885                                                              : &((Mesh*)ob->data)->fdata;
1886                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
1887                                                         wmd->uvlayer_name);
1888                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1889                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
1890                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1891                                 MEM_freeN(strtmp);
1892                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1893                                 uiButSetFunc(but, set_displace_uvlayer, wmd,
1894                                              &fdata->layers[i]);
1895                         }
1896                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
1897                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1898                                                "Ob: ", lx, (cy -= 19), 220, 19,
1899                                                &wmd->map_object,
1900                                                "Object to get texture coordinates from");
1901                         }
1902             cy -= 9;
1903                         uiBlockBeginAlign(block);
1904                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
1905                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Height:",  lx,(cy-=19),220,19, &wmd->height, -2.0, 2.0, 0, 0, "Specify the amplitude of the wave");
1906                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Width:",   lx,(cy-=19),220,19, &wmd->width, 0.0, 5.0, 0, 0, "Specify the width of the wave");
1907                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Narrow:",  lx,(cy-=19),220,19, &wmd->narrow, 0.0, 10.0, 0, 0, "Specify how narrow the wave follows");
1908                 } else if (md->type==eModifierType_Armature) {
1909                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
1910                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
1911                         
1912                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &amd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to control overall armature influence");
1913                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1914                         uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups",       lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform");
1915                         uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes",       lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
1916                         uiDefButBitS(block, TOG, ARM_DEF_QUATERNION, B_ARM_RECALCDATA, "Quaternion",    lx,(cy-=19),buttonWidth + 1,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
1917
1918                         
1919                 } else if (md->type==eModifierType_Hook) {
1920                         HookModifierData *hmd = (HookModifierData*) md;
1921                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ",           lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends");
1922                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Force: ",          lx, (cy-=19), buttonWidth,19, &hmd->force, 0.0, 1.0, 100, 0, "Set relative force of hook");
1923                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &hmd->object, "Parent Object for hook, also recalculates and clears offset"); 
1924                         if(hmd->indexar==NULL) {
1925                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1926                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1927                         }
1928                         uiBlockBeginAlign(block);
1929                         but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reset",          lx, (cy-=19), 80,19,                    NULL, 0.0, 0.0, 0, 0, "Recalculate and clear offset (transform) of hook");
1930                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
1931                         but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Recenter",       lx+80, cy, buttonWidth-80,19,   NULL, 0.0, 0.0, 0, 0, "Sets hook center to cursor position");
1932                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
1933
1934                         if (editing) {
1935                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Select",                 lx, (cy-=19), 80,19, NULL, 0.0, 0.0, 0, 0, "Selects effected vertices on mesh");
1936                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
1937                                 but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reassign",               lx+80, cy, buttonWidth-80,19, NULL, 0.0, 0.0, 0, 0, "Reassigns selected vertices to hook");
1938                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
1939                         }
1940                 } else if (md->type==eModifierType_Softbody) {
1941                         uiDefBut(block, LABEL, 1, "See Softbody panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1942                 } else if (md->type==eModifierType_Boolean) {
1943                         BooleanModifierData *bmd = (BooleanModifierData*) md;
1944                         uiDefButI(block, MENU, B_MODIFIER_RECALC, "Operation%t|Intersect%x0|Union%x1|Difference%x2",    lx,(cy-=19),buttonWidth,19, &bmd->operation, 0.0, 1.0, 0, 0, "Boolean operation to perform");
1945                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
1946                 } else if (md->type==eModifierType_Array) {
1947                         ArrayModifierData *amd = (ArrayModifierData*) md;
1948                         float range = 10000;
1949                         int cytop, halfwidth = (width - 5)/2 - 15;
1950                         int halflx = lx + halfwidth + 10;
1951
1952                         uiBlockSetEmboss(block, UI_EMBOSSX);
1953                         uiBlockEndAlign(block);
1954
1955                         /* length parameters */
1956                         uiBlockBeginAlign(block);
1957                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
1958                                 "|Fit To Curve Length%%x%d",
1959                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
1960                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1961                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
1962                                   0.0, 1.0, 0, 0, "Array length calculation method");
1963                         switch(amd->fit_type)
1964                         {
1965                         case MOD_ARR_FIXEDCOUNT:
1966                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
1967                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
1968                                           1, 1000, 0, 0, "Number of duplicates to make");
1969                                 break;
1970                         case MOD_ARR_FITLENGTH:
1971                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
1972                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
1973                                           0, range, 10, 2,
1974                                           "Length to fit array within");
1975                                 break;
1976                         case MOD_ARR_FITCURVE:
1977                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
1978                                                B_CHANGEDEP, "Ob: ",
1979                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
1980                                                "Curve object to fit array length to");
1981                                 break;
1982                         }
1983                         uiBlockEndAlign(block);
1984
1985                         /* offset parameters */
1986                         cy -= 10;
1987                         cytop= cy;
1988                         uiBlockBeginAlign(block);
1989                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
1990                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
1991                                      &amd->offset_type, 0, 0, 0, 0,
1992                                      "Constant offset between duplicates "
1993                                      "(local coordinates)");
1994                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
1995                                   lx, (cy-=19), halfwidth, 19,
1996                                   &amd->offset[0],
1997                                   -range, range, 10, 3,
1998                                   "Constant component for duplicate offsets "
1999                                   "(local coordinates)");
2000                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2001                                   lx, (cy-=19), halfwidth, 19,
2002                                   &amd->offset[1],
2003                                   -range, range, 10, 3,
2004                                   "Constant component for duplicate offsets "
2005                                   "(local coordinates)");
2006                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2007                                   lx, (cy-=19), halfwidth, 19,
2008                                   &amd->offset[2],
2009                                   -range, range, 10, 3,
2010                                   "Constant component for duplicate offsets "
2011                                   "(local coordinates)");
2012                         uiBlockEndAlign(block);
2013
2014                         cy= cytop;
2015                         uiBlockBeginAlign(block);
2016                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2017                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2018                                      &amd->offset_type, 0, 0, 0, 0,
2019                                      "Offset between duplicates relative to object width "
2020                                      "(local coordinates)");
2021                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2022                                   halflx, (cy-=19), halfwidth, 19,
2023                                   &amd->scale[0],
2024                                   -range, range, 10, 3,
2025                                   "Component for duplicate offsets relative to object "
2026                                   "width (local coordinates)");
2027                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2028                                   halflx, (cy-=19), halfwidth, 19,
2029                                   &amd->scale[1],
2030                                   -range, range, 10, 3,
2031                                   "Component for duplicate offsets relative to object "
2032                                   "width (local coordinates)");
2033                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2034                                   halflx, (cy-=19), halfwidth, 19,
2035                                   &amd->scale[2],
2036                                   -range, range, 10, 3,
2037                                   "Component for duplicate offsets relative to object "
2038                                   "width (local coordinates)");
2039                         uiBlockEndAlign(block);
2040
2041                         /* vertex merging parameters */
2042                         cy -= 10;
2043                         cytop= cy;
2044
2045                         uiBlockBeginAlign(block);
2046                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2047                                      "Merge",
2048                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2049                                      0, 0, 0, 0,
2050                                      "Merge vertices in adjacent duplicates");
2051                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2052                                      "First Last",
2053                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2054                                      &amd->flags,
2055                                      0, 0, 0, 0,
2056                                      "Merge vertices in first duplicate with vertices"
2057                                      " in last duplicate");
2058                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2059                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2060                                           0, 1.0f, 1, 4,
2061                                           "Limit below which to merge vertices");
2062
2063                         /* offset ob */
2064                         cy = cytop;
2065                         uiBlockBeginAlign(block);
2066                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2067                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2068                                      &amd->offset_type, 0, 0, 0, 0,
2069                                      "Add an object transformation to the total offset");
2070                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2071                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2072                                        &amd->offset_ob,
2073                                        "Object from which to take offset transformation");
2074                         uiBlockEndAlign(block);
2075
2076                         cy -= 10;
2077                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2078                                              B_CHANGEDEP, "Start cap: ",
2079                                              lx, (cy -= 19), halfwidth, 19,
2080                                              &amd->start_cap,
2081                                              "Mesh object to use as start cap");
2082                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2083                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2084                                              B_CHANGEDEP, "End cap: ",
2085                                              halflx, cy, halfwidth, 19,
2086                                              &amd->end_cap,
2087                                              "Mesh object to use as end cap");
2088                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2089                 }
2090                 uiBlockEndAlign(block);
2091
2092                 y-=height;
2093         }
2094
2095         if (md->error) {
2096                 char str[512];
2097
2098                 y -= 20;
2099
2100                 uiBlockSetCol(block, color);
2101                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2102                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2103                 uiBlockSetCol(block, TH_AUTO);
2104
2105                 sprintf(str, "Modifier Error: %s", md->error);
2106                 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2107         }
2108
2109         y -= 3+6;
2110
2111         *xco = x;
2112         *yco = y;
2113 }
2114
2115 static void editing_panel_modifiers(Object *ob)
2116 {
2117         ModifierData *md;
2118         uiBlock *block;
2119         char str[64];
2120         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2121
2122         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2123         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2124         
2125         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2126         uiNewPanelHeight(block, 204);
2127
2128         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2129
2130         sprintf(str, "To: %s", ob->id.name+2);
2131         uiDefBut(block, LABEL, 1, str,  140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2132
2133         xco = 0;
2134         yco = 160;
2135
2136         md = modifiers_getVirtualModifierList(ob);
2137
2138         for (i=0; md; i++, md=md->next) {
2139                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2140                 if (md->mode&eModifierMode_Virtual) i--;
2141         }
2142         
2143         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2144 }
2145
2146 static char *make_key_menu(Key *key)
2147 {
2148         KeyBlock *kb;
2149         int index= 1;
2150         char *str, item[64];
2151
2152         for (kb = key->block.first; kb; kb=kb->next, index++);
2153         str= MEM_mallocN(index*40, "key string");
2154         str[0]= 0;
2155         
2156         index= 1;
2157         for (kb = key->block.first; kb; kb=kb->next, index++) {
2158                 sprintf (item,  "|%s%%x%d", kb->name, index);
2159                 strcat(str, item);
2160         }
2161         
2162         return str;
2163 }
2164
2165 static void editing_panel_shapes(Object *ob)
2166 {
2167         uiBlock *block;
2168         Key *key= NULL;
2169         KeyBlock *kb;
2170         int icon;
2171         char *strp;
2172         
2173         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2174         uiNewPanelTabbed("Modifiers", "Editing");
2175         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2176         
2177         /* Todo check data is library here */
2178         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2179         
2180         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2181         
2182         key= ob_get_key(ob);
2183         if(key==NULL) {
2184                 /* label aligns add button */
2185                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2186                 return;
2187         }
2188         
2189         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2190
2191         kb= BLI_findlink(&key->block, ob->shapenr-1);
2192         if(kb==NULL) {
2193                 ob->shapenr= 1;
2194                 kb= key->block.first;
2195         }
2196
2197         uiBlockBeginAlign(block);
2198         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2199         uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object");
2200         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2201         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2202         strp= make_key_menu(key);
2203         uiDefButS(block, MENU, B_SETKEY, strp,                                  55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
2204         MEM_freeN(strp);
2205         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2206         uiClearButLock();
2207         uiDefBut(block, TEX, B_NAMEKEY, "",                                             95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2208         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2209         uiBlockEndAlign(block);
2210
2211         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2212                 uiBlockBeginAlign(block);
2213                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2214                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2215                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2216                 uiBlockEndAlign(block);
2217         }
2218         if(key->type && ob->shapenr!=1)
2219                 uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",     10, 90, 150,19, &kb->vgroup, 0.0, 31.0, 0, 0, "Vertex Weight Group name, to blend with Basis Shape");
2220
2221         if(key->type==0)
2222                 uiDefButS(block, NUM, B_DIFF, "Slurph:",                        10, 60, 150, 19, &(key->slurph), -500.0, 500.0, 0, 0, "Creates a delay in amount of frames in applying keypositions, first vertex goes first");
2223         
2224 }
2225
2226 /* *************************** FONT ******************************** */
2227
2228 static short give_vfontnr(VFont *vfont)
2229 {
2230         VFont *vf;
2231         short nr= 1;
2232
2233         vf= G.main->vfont.first;
2234         while(vf) {
2235                 if(vf==vfont) return nr;
2236                 nr++;
2237                 vf= vf->id.next;
2238         }
2239         return -1;
2240 }
2241
2242 static VFont *give_vfontpointer(int nr) /* nr= button */
2243 {
2244         VFont *vf;
2245         short tel= 1;
2246
2247         vf= G.main->vfont.first;
2248         while(vf) {
2249                 if(tel==nr) return vf;
2250                 tel++;
2251                 vf= vf->id.next;
2252         }
2253         return G.main->vfont.first;
2254 }
2255
2256 VFont *exist_vfont(char *str)
2257 {
2258         VFont *vf;
2259
2260         vf= G.main->vfont.first;
2261         while(vf) {
2262                 if(strcmp(vf->name, str)==0) return vf;
2263                 vf= vf->id.next;
2264         }
2265         return 0;
2266 }
2267
2268 static char *give_vfontbutstr(void)
2269 {
2270         VFont *vf;
2271         int len= 0;
2272         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2273
2274         vf= G.main->vfont.first;
2275         while(vf) {
2276                 strcpy(di, vf->name);
2277                 BLI_splitdirstring(di, fi);
2278                 len+= strlen(fi)+4;
2279                 vf= vf->id.next;
2280         }
2281
2282         str= MEM_callocN(len+21, "vfontbutstr");
2283         strcpy(str, "FONTS %t");
2284         vf= G.main->vfont.first;
2285         while(vf) {
2286
2287                 if(vf->id.us==0) strcat(str, "|0 ");
2288                 else strcat(str, "|   ");
2289
2290                 strcpy(di, vf->name);
2291                 BLI_splitdirstring(di, fi);
2292
2293                 strcat(str, fi);
2294                 vf= vf->id.next;
2295         }
2296         return str;
2297 }
2298
2299 static void load_buts_vfont(char *name)
2300 {
2301         VFont *vf;
2302         Curve *cu;
2303
2304         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2305         else return;
2306
2307         vf= exist_vfont(name);
2308         if(vf==0) {
2309                 vf= load_vfont(name);
2310                 if(vf==0) return;
2311         }
2312         else id_us_plus((ID *)vf);
2313         
2314         switch(cu->curinfo.flag & CU_STYLE) {
2315                 case CU_BOLD:
2316                         if(cu->vfontb) cu->vfontb->id.us--;
2317                         cu->vfontb= vf;
2318                         break;
2319                 case CU_ITALIC:
2320                         if(cu->vfonti) cu->vfonti->id.us--;             
2321                         cu->vfonti= vf;
2322                         break;                                          
2323                 case (CU_BOLD|CU_ITALIC):
2324                         if(cu->vfontbi) cu->vfontbi->id.us--;
2325                         cu->vfontbi= vf;
2326                         break;
2327                 default:
2328                         if(cu->vfont) cu->vfont->id.us--;
2329                         cu->vfont= vf;
2330                         break;                                          
2331         }       
2332
2333         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2334         BIF_undo_push("Load vector font");
2335         allqueue(REDRAWVIEW3D, 0);
2336         allqueue(REDRAWBUTSEDIT, 0);
2337 }
2338
2339 static void set_unicode_text_fs(char *file)
2340 {
2341         if (file > 0) paste_unicodeText(file); 
2342 }
2343
2344 void do_fontbuts(unsigned short event)
2345 {
2346         Curve *cu;
2347         VFont *vf;
2348         Object *ob;
2349         ScrArea *sa;
2350         char str[80];
2351         int ctevt;
2352         char *ctmenu;
2353         DynStr *ds;
2354         int i, style=0;
2355
2356         ob= OBACT;
2357
2358         switch(event) {
2359         case B_MAKEFONT:
2360                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2361                 allqueue(REDRAWVIEW3D, 0);
2362                 break;
2363
2364         case B_STYLETOSELU:     
2365         case B_STYLETOSELB:
2366         case B_STYLETOSELI:
2367                 switch (event) {
2368                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2369                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2370                         case B_STYLETOSELI: style = CU_ITALIC; break;
2371                 }
2372                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2373                         text_to_curve(ob, 0);
2374                         makeDispListCurveTypes(ob, 0);
2375                         allqueue(REDRAWVIEW3D, 0);
2376                 }
2377                 allqueue(REDRAWBUTSEDIT, 0);
2378                 break;          
2379                 
2380         case B_FASTFONT:
2381                 if (G.obedit) {
2382                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2383                         allqueue(REDRAWVIEW3D, 0);
2384                 }
2385                 break;
2386         case B_INSTB:
2387                 cu= ob->data;
2388                 if (cu->totbox < 256) {
2389                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2390                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2391                         cu->actbox++;
2392                         cu->totbox++;
2393                         allqueue(REDRAWBUTSEDIT, 0);
2394                         allqueue(REDRAWVIEW3D, 0);
2395                         text_to_curve(ob, 0);
2396                         makeDispListCurveTypes(ob, 0);
2397                 }
2398                 else {
2399                         error("Do you really need that many text frames?");
2400                 }
2401                 break;
2402         case B_DELTB:
2403                 cu= ob->data;
2404                 if (cu->totbox > 1) {
2405                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2406                         cu->totbox--;
2407                         cu->actbox--;
2408                         allqueue(REDRAWBUTSEDIT, 0);
2409                         allqueue(REDRAWVIEW3D, 0);
2410                         text_to_curve(ob, 0);
2411                         makeDispListCurveTypes(ob, 0);
2412                 }
2413                 break;
2414         case B_TOUPPER:
2415                 to_upper();
2416                 break;
2417         case B_LOADFONT:
2418                 vf= give_vfontpointer(G.buts->texnr);
2419                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2420                 else strcpy(str, U.fontdir);
2421
2422                 sa= closest_bigger_area();
2423                 areawinset(sa->win);
2424
2425                 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2426
2427                 break;
2428         case B_PACKFONT:
2429                 if (ob) {
2430                         cu= ob->data;
2431                         if(cu && cu->vfont) {
2432                                 if (cu->vfont->packedfile) {
2433                                         if (G.fileflags & G_AUTOPACK) {
2434                                                 if (okee("Disable AutoPack ?")) {
2435                                                         G.fileflags &= ~G_AUTOPACK;
2436                                                 }
2437                                         }
2438
2439                                         if ((G.fileflags & G_AUTOPACK) == 0) {
2440                                                 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2441                                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2442                                                         allqueue(REDRAWVIEW3D, 0);
2443                                                 }
2444                                         }
2445                                 } else {
2446                                         cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2447                                 }
2448                         }
2449                 }
2450                 allqueue(REDRAWHEADERS, 0);
2451                 allqueue(REDRAWBUTSEDIT, 0);
2452                 break;
2453
2454         case B_LOAD3DTEXT:
2455                 if (!G.obedit) { error("Only in editmode!"); return; }
2456                 if (G.obedit->type != OB_FONT) return;  
2457                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2458                 break;
2459                 
2460         case B_LOREM:
2461                 if (!G.obedit) { error("Only in editmode!"); return; }
2462                 if (G.obedit->type != OB_FONT) return;  
2463                 add_lorem();
2464                 
2465                 break;          
2466
2467         case B_SETFONT:
2468                 if(ob) {
2469                         cu= ob->data;
2470
2471                         vf= give_vfontpointer(G.buts->texnr);
2472                         if(vf) {
2473                                 id_us_plus((ID *)vf);
2474
2475                                 switch(cu->curinfo.flag & CU_STYLE) {
2476                                         case CU_BOLD:
2477                                                 cu->vfontb->id.us--;
2478                                                 cu->vfontb= vf;
2479                                                 break;
2480                                         case CU_ITALIC:
2481                                                 cu->vfonti->id.us--;
2482                                                 cu->vfonti= vf;
2483                                                 break;                                          
2484                                         case (CU_BOLD|CU_ITALIC):
2485                                                 cu->vfontbi->id.us--;
2486                                                 cu->vfontbi= vf;
2487                                                 break;
2488                                         default:
2489                                                 cu->vfont->id.us--;
2490                                                 cu->vfont= vf;
2491                                                 break;                                          
2492                                 }
2493                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2494
2495                                 BIF_undo_push("Set vector font");
2496                                 allqueue(REDRAWVIEW3D, 0);
2497                                 allqueue(REDRAWBUTSEDIT, 0);
2498                         }
2499                 }
2500                 break;
2501                 
2502         case B_SETCHAR:
2503                 G.charmin = 0x0000;
2504                 G.charmax = 0xffff;
2505                 if(G.charstart < 0)
2506                         G.charstart = 0;        
2507                 if(G.charstart > (0xffff - 12*6))
2508                         G.charstart = 0xffff - (12*6);
2509                 allqueue(REDRAWBUTSEDIT, 0);
2510                 break;
2511                 
2512         case B_SETUPCHAR:
2513                 G.charstart = G.charstart - (12*6);
2514                 if(G.charstart < 0)
2515                         G.charstart = 0;        
2516                 if(G.charstart < G.charmin)
2517                         G.charstart = G.charmin;
2518                 allqueue(REDRAWBUTSEDIT, 0);
2519                 break;
2520                 
2521         case B_SETCAT:
2522                 // Create new dynamic string
2523                 ds = BLI_dynstr_new();
2524                 
2525                 // Fill the dynamic string with entries
2526                 for(i=0;i<104;i++)
2527                 {
2528                         BLI_dynstr_append(ds, "|");
2529                         BLI_dynstr_append(ds, uctabname[i].name);
2530                 }
2531                 
2532                 // Create the menu string from dyn string
2533                 ctmenu = BLI_dynstr_get_cstring(ds);
2534                 
2535                 // Call the popup menu
2536                 ctevt = pupmenu_col(ctmenu, 40);
2537                 G.charstart = uctabname[ctevt-1].start;
2538                 G.charmin = uctabname[ctevt-1].start;
2539                 G.charmax = uctabname[ctevt-1].end;
2540
2541                 // Free all data
2542                 BLI_dynstr_free(ds);
2543                 MEM_freeN(ctmenu);
2544
2545                 // And refresh
2546                 allqueue(REDRAWVIEW3D, 0);
2547                 allqueue(REDRAWBUTSEDIT, 0);
2548                 
2549                 break;  
2550                 
2551         case B_SETDOWNCHAR:
2552                 G.charstart = G.charstart + (12*6);
2553                 if(G.charstart > (0xffff - 12*6))
2554                         G.charstart = 0xffff - (12*6);
2555                 if(G.charstart > G.charmax - 12*6)
2556                         G.charstart = G.charmax - 12*6;
2557                 allqueue(REDRAWBUTSEDIT, 0);
2558                 break;
2559                 
2560         case B_SETUNITEXT:
2561                 sa= closest_bigger_area();
2562                 areawinset(sa->win);
2563
2564                 if(ob==G.obedit) {
2565                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
2566                 }
2567                 break;          
2568                 
2569         case B_TEXTONCURVE:
2570                 if(ob) {
2571                         cu= ob->data;
2572                         if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
2573                                 error("Only Curve Objects");
2574                                 cu->textoncurve= 0;
2575                                 allqueue(REDRAWBUTSEDIT, 0);
2576                         }
2577                         DAG_scene_sort(G.scene); // makes new dag
2578                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2579                         allqueue(REDRAWVIEW3D, 0);
2580                 }
2581         }
2582 }
2583
2584 static void editing_panel_char_type(Object *ob, Curve *cu)
2585 {
2586         uiBlock *block;
2587
2588         block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
2589         uiNewPanelTabbed("Font", "Editing");
2590         if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0) 
2591                 return;
2592
2593         // Set the selected font
2594         G.selfont = cu->vfont;
2595         
2596         uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT,       0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
2597
2598         // Unicode categorization selection button
2599         uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
2600         uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
2601
2602         // Character selection button
2603         uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
2604
2605         // Buttons to change the max, min
2606         uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
2607         uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
2608 }
2609
2610 static void editing_panel_font_type(Object *ob, Curve *cu)
2611 {
2612         uiBlock *block;
2613         char *strp;
2614         static int packdummy = 0;
2615         char str[32];
2616
2617         block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
2618         if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
2619
2620         switch(cu->curinfo.flag & CU_STYLE) {
2621                 case CU_BOLD:
2622                         G.buts->texnr= give_vfontnr(cu->vfontb);
2623                         break;
2624                 case CU_ITALIC:
2625                         G.buts->texnr= give_vfontnr(cu->vfonti);
2626                         break;                                          
2627                 case (CU_BOLD|CU_ITALIC):
2628                         G.buts->texnr= give_vfontnr(cu->vfontbi);
2629                         break;
2630                 default:
2631                         G.buts->texnr= give_vfontnr(cu->vfont);
2632                         break;                                          
2633         }       
2634
2635         strp= give_vfontbutstr();
2636 //      vfd= cu->vfont->data;
2637
2638         uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
2639         uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
2640
2641         if (cu->vfont->packedfile) {
2642                 packdummy = 1;
2643         } else {
2644                 packdummy = 0;
2645         }
2646         uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE,       772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
2647
2648         /* This doesn't work anyway */
2649 //      uiDefBut(block, LABEL, 0, vfd->name,  480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
2650
2651         uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
2652         uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor"); 
2653         uiDefButC(block, TOG|BIT|2,B_STYLETOSELU, "U",          727,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");     
2654         uiBlockBeginAlign(block);
2655         uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSELB, "B",           752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
2656         uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSELI, "i",         772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");    
2657         uiBlockEndAlign(block);
2658
2659         MEM_freeN(strp);
2660
2661         uiBlockBeginAlign(block);
2662         uiDefButS(block, ROW,B_MAKEFONT, "Left",                480,135,47,20, &cu->spacemode, 0.0,0.0, 0, 0, "Left align the text from the object center");
2663         uiDefButS(block, ROW,B_MAKEFONT, "Center",              527,135,47,20, &cu->spacemode, 0.0,1.0, 0, 0, "Middle align the text from the object center");
2664         uiDefButS(block, ROW,B_MAKEFONT, "Right",               574,135,47,20, &cu->spacemode, 0.0,2.0, 0, 0, "Right align the text from the object center");
2665         uiDefButS(block, ROW,B_MAKEFONT, "Justify",             621,135,47,20, &cu->spacemode, 0.0,3.0, 0, 0, "Fill completed lines to maximum textframe width by expanding whitespace");
2666         uiDefButS(block, ROW,B_MAKEFONT, "Flush",               668,135,47,20, &cu->spacemode, 0.0,4.0, 0, 0, "Fill every line to maximum textframe width, distributing space among all characters");   
2667         uiDefBut(block, BUT, B_TOUPPER, "ToUpper",              715,135,78,20, 0, 0, 0, 0, 0, "Toggle between upper and lower case in editmode");
2668         uiBlockEndAlign(block);
2669         uiDefButBitS(block, TOG, CU_FAST, B_FASTFONT, "Fast Edit",              715,105,78,20, &cu->flag, 0, 0, 0, 0, "Don't fill polygons while editing");     
2670
2671         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_TEXTONCURVE, "TextOnCurve:",    480,105,220,19, &cu->textoncurve, "Apply a deforming curve to the text");
2672         uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 480,84,220,19, cu->family, 0.0, 20.0, 0, 0, "Blender uses font from selfmade objects");
2673
2674         uiBlockBeginAlign(block);
2675         uiDefButF(block, NUM,B_MAKEFONT, "Size:",               480,56,155,20, &cu->fsize, 0.1,10.0, 10, 0, "Size of the text");
2676         uiDefButF(block, NUM,B_MAKEFONT, "Linedist:",   640,56,155,20, &cu->linedist, 0.0,10.0, 10, 0, "Distance between text lines");
2677         uiDefButF(block, NUM,B_MAKEFONT, "Word spacing:",       795,56,155,20, &cu->wordspace, 0.0,10.0, 10, 0, "Distance factor between words");               
2678         uiDefButF(block, NUM,B_MAKEFONT, "Spacing:",    480,34,155,20, &cu->spacing, 0.0,10.0, 10, 0, "Spacing of individual characters");
2679         uiDefButF(block, NUM,B_MAKEFONT, "X offset:",   640,34,155,20, &cu->xof, -50.0,50.0, 10, 0, "Horizontal position from object center");
2680         uiDefButF(block, NUM,B_MAKEFONT, "UL position:",        795,34,155,20, &cu->ulpos, -0.2,0.8, 10, 0, "Vertical position of underline");                  
2681         uiDefButF(block, NUM,B_MAKEFONT, "Shear:",              480,12,155,20, &cu->shear, -1.0,1.0, 10, 0, "Italic angle of the characters");
2682         uiDefButF(block, NUM,B_MAKEFONT, "Y offset:",   640,12,155,20, &cu->yof, -50.0,50.0, 10, 0, "Vertical position from object center");
2683         uiDefButF(block, NUM,B_MAKEFONT, "UL height:",  795,12,155,20, &cu->ulheight, 0.01,0.5, 10, 0, "Thickness of underline");                               
2684         uiBlockEndAlign(block); 
2685         
2686         sprintf(str, "%d TextFrame: ", cu->totbox);
2687         uiBlockBeginAlign(block);
2688         uiDefButI(block, NUM, REDRAWVIEW3D, str, 805, 188, 145, 20, &cu->actbox, 1.0, cu->totbox, 0, 10, "Textbox to show settings for");
2689         uiDefBut(block, BUT,B_INSTB, "Insert", 805, 168, 72, 20, 0, 0, 0, 0, 0, "Insert a new text frame after the current one");
2690         uiDefBut(block, BUT,B_DELTB, "Delete", 877, 168, 73, 20, 0, 0, 0, 0, 0, "Delete current text frame and shift the others up");   
2691         uiDefButF(block, NUM,B_MAKEFONT, "X:", 805, 148, 72, 20, &(cu->tb[cu->actbox-1].x), -50.0, 50.0, 10, 0, "Horizontal offset of text frame");
2692         uiDefButF(block, NUM,B_MAKEFONT, "Y:", 877, 148, 73, 20, &(cu->tb[cu->actbox-1].y), -50.0, 50.0, 10, 0, "Horizontal offset of text frame");     
2693         uiDefButF(block, NUM,B_MAKEFONT, "Width:", 805, 128, 145, 20, &(cu->tb[cu->actbox-1].w), 0.0, 50.0, 10, 0, "Horizontal offset of text frame");
2694         uiDefButF(block, NUM,B_MAKEFONT, "Height:", 805, 108, 145, 20, &(cu->tb[cu->actbox-1].h), 0.0, 50.0, 10, 0, "Horizontal offset of text frame");         
2695         uiBlockEndAlign(block);
2696 }
2697
2698
2699 /* *************************** CURVE ******************************** */
2700
2701
2702 void do_curvebuts(unsigned short event)
2703 {
2704         extern Nurb *lastnu;
2705         extern ListBase editNurb;  /* from editcurve */
2706         Object *ob;
2707         Curve *cu;
2708         Nurb *nu;
2709
2710         ob= OBACT;
2711         if(ob==0) return;
2712
2713         switch(event) {
2714
2715         case B_CONVERTPOLY:
2716         case B_CONVERTBEZ:
2717         case B_CONVERTBSPL:
2718         case B_CONVERTCARD:
2719         case B_CONVERTNURB:
2720                 if(G.obedit) {
2721                         setsplinetype(event-B_CONVERTPOLY);
2722                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2723                         allqueue(REDRAWVIEW3D, 0);
2724                 }
2725                 break;
2726         case B_UNIFU:
2727         case B_ENDPU:
2728         case B_BEZU:
2729         case B_UNIFV:
2730         case B_ENDPV:
2731         case B_BEZV:
2732                 if(G.obedit) {
2733                         nu= editNurb.first;
2734                         while(nu) {
2735                                 if(isNurbsel(nu)) {
2736                                         if((nu->type & 7)==CU_NURBS) {
2737                                                 if(event<B_UNIFV) {
2738                                                         nu->flagu &= 1;
2739                                                         nu->flagu += ((event-B_UNIFU)<<1);
2740                                                         makeknots(nu, 1, nu->flagu>>1);
2741                                                 }
2742                                                 else if(nu->pntsv>1) {
2743                                                         nu->flagv &= 1;
2744                                                         nu->flagv += ((event-B_UNIFV)<<1);
2745                                                         makeknots(nu, 2, nu->flagv>>1);
2746                                                 }
2747                                         }
2748                                 }
2749                                 nu= nu->next;
2750                         }
2751                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2752                         allqueue(REDRAWVIEW3D, 0);
2753                 }
2754                 break;
2755         case B_SETWEIGHT:
2756                 if(G.obedit) {
2757                         weightflagNurb(1, editbutweight, 0);
2758                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2759                         allqueue(REDRAWVIEW3D, 0);
2760                 }
2761                 break;
2762         case B_SETW1:
2763                 editbutweight= 1.0;
2764                 scrarea_queue_winredraw(curarea);
2765                 break;
2766         case B_SETW2:
2767                 editbutweight= sqrt(2.0)/4.0;
2768                 scrarea_queue_winredraw(curarea);
2769                 break;
2770         case B_SETW3:
2771                 editbutweight= 0.25;
2772                 scrarea_queue_winredraw(curarea);
2773                 break;
2774         case B_SETW4:
2775                 editbutweight= sqrt(0.5);
2776                 scrarea_queue_winredraw(curarea);
2777                 break;
2778         case B_SETORDER:
2779                 if(G.obedit) {
2780                         nu= lastnu;
2781                         if(nu && (nu->type & 7)==CU_NURBS ) {
2782                                 if(nu->orderu>nu->pntsu) {
2783                                         nu->orderu= nu->pntsu;
2784                                         scrarea_queue_winredraw(curarea);
2785                                 }
2786                                 makeknots(nu, 1, nu->flagu>>1);
2787                                 if(nu->orderv>nu->pntsv) {
2788                                         nu->orderv= nu->pntsv;
2789                                         scrarea_queue_winredraw(curarea);
2790                                 }
2791                                 makeknots(nu, 2, nu->flagv>>1);
2792                         }
2793                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2794                         allqueue(REDRAWVIEW3D, 0);
2795                 }
2796                 break;
2797         case B_TILTINTERP:
2798                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2799                 allqueue(REDRAWVIEW3D, 0);
2800                 break;
2801         case B_SUBSURFTYPE:
2802                 /* fallthrough */
2803         case B_MAKEDISP:
2804                 if(G.vd) {
2805                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2806                         allqueue(REDRAWVIEW3D, 0);
2807                         allqueue(REDRAWBUTSALL, 0);
2808                         allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
2809                 }
2810                 break;
2811
2812         case B_SUBDIVCURVE:
2813                 subdivideNurb();
2814                 break;
2815         case B_SPINNURB:
2816                 if( (G.obedit==NULL) || (G.obedit->type!=OB_SURF) || (G.vd==NULL) ||
2817                         ((G.obedit->lay & G.vd->lay) == 0) ) return;
2818                 spinNurb(0, 0);
2819                 countall();
2820                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2821                 allqueue(REDRAWVIEW3D, 0);
2822                 break;
2823         case B_CU3D:        /* allow 3D curve */
2824                 if(G.obedit) {
2825                         cu= G.obedit->data;
2826                         nu= editNurb.first;
2827                         while(nu) {
2828                                 nu->type &= ~CU_2D;
2829                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2830                                 test2DNurb(nu);
2831                                 nu= nu->next;
2832                         }
2833                 }
2834                 if(ob->type==OB_CURVE) {
2835                         cu= ob->data;
2836                         nu= cu->nurb.first;
2837                         while(nu) {
2838                                 nu->type &= ~CU_2D;
2839                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2840                                 test2DNurb(nu);
2841                                 nu= nu->next;
2842                         }
2843                 }
2844                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2845                 allqueue(REDRAWVIEW3D, 0);
2846                 break;
2847         case B_SETRESOLU:
2848                 if(ob->type==OB_CURVE) {
2849                         cu= ob->data;
2850                         if(ob==G.obedit) nu= editNurb.first;
2851                         else nu= cu->nurb.first;
2852
2853                         while(nu) {
2854                                 nu->resolu= cu->resolu;
2855                                 nu= nu->next;
2856                         }
2857                 }
2858
2859                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2860                 allqueue(REDRAWVIEW3D, 0);
2861                 allqueue(REDRAWBUTSALL, 0);
2862                 allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
2863
2864                 break;
2865         }
2866 }
2867
2868 static void editing_panel_curve_tools(Object *ob, Curve *cu)
2869 {
2870         Nurb *nu;
2871         extern ListBase editNurb;  /* from editcurve */
2872         extern Nurb *lastnu;
2873         uiBlock *block;
2874         short *sp;
2875
2876         block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_tools", UI_EMBOSS, UI_HELV, curarea->win);
2877         if(uiNewPanel(curarea, block, "Curve Tools", "Editing", 640, 0, 318, 204)==0) return;
2878
2879         uiDefBut(block, LABEL, 0, "Make Knots",562,173,102, 18, 0, 0, 0, 0, 0, "");
2880
2881         if(ob->type==OB_CURVE) {
2882                 uiDefBut(block, LABEL, 0, "Convert",    463,173,72, 18, 0, 0, 0, 0, 0, "");
2883                 uiBlockBeginAlign(block);
2884                 uiDefBut(block, BUT,B_CONVERTPOLY,"Poly",               467,152,72, 18, 0, 0, 0, 0, 0, "Converts selected into regular Polygon vertices");
2885                 uiDefBut(block, BUT,B_CONVERTBEZ,"Bezier",              467,132,72, 18, 0, 0, 0, 0, 0, "Converts selected to Bezier triples");
2886                 uiDefBut(block, BUT,B_CONVERTNURB,"Nurb",               467,112,72, 18, 0, 0, 0, 0, 0, "Converts selected to Nurbs Points");
2887         }
2888         uiBlockBeginAlign(block);
2889         uiDefBut(block, BUT,B_UNIFU,"Uniform U",        565,152,102, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result doesn't go to end points in U");
2890         uiDefBut(block, BUT,B_UNIFV,"V",                        670,152,50, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result doesn't go to end points in V");
2891         uiDefBut(block, BUT,B_ENDPU,"Endpoint U",       565,132,102, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result is forced to end points in U");
2892         uiDefBut(block, BUT,B_ENDPV,"V",                        670,132,50, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result is forced to end points in V");
2893         uiDefBut(block, BUT,B_BEZU,"Bezier U",          565,112,102, 18, 0, 0, 0, 0, 0, "Nurbs only; make knots array mimic a Bezier in U");
2894         uiDefBut(block, BUT,B_BEZV,"V",                         670,112,50, 18, 0, 0, 0, 0, 0, "Nurbs only; make knots array mimic a Bezier in V");
2895         uiBlockEndAlign(block);
2896
2897         uiDefBut(block, BUT,B_SETWEIGHT,"Set Weight",   465,11,95,49, 0, 0, 0, 0, 0, "Nurbs only; set weight for select points");
2898
2899         uiBlockBeginAlign(block);
2900         uiDefButF(block, NUM,0,"Weight:",               565,36,102,22, &editbutweight, 0.01, 100.0, 10, 0, "The weight you can assign");
2901         uiDefBut(block, BUT,B_SETW1,"1.0",              670,36,50,22, 0, 0, 0, 0, 0, "");
2902         uiDefBut(block, BUT,B_SETW2,"sqrt(2)/4",565,11,55,20, 0, 0, 0, 0, 0, "");
2903         uiDefBut(block, BUT,B_SETW3,"0.25",             620,11,45,20, 0, 0, 0, 0, 0, "");
2904         uiDefBut(block, BUT,B_SETW4,"sqrt(0.5)",665,11,55,20, 0, 0, 0, 0, 0, "");
2905         uiBlockEndAlign(block);
2906
2907         if(ob==G.obedit) {
2908                 nu= lastnu;
2909                 if(nu==NULL) nu= editNurb.first;
2910                 if(nu) {
2911                         if (ob->type==OB_CURVE) {
2912                                 uiDefBut(block, LABEL, 0, "Tilt",
2913                                         467,87,72, 18, 0, 0, 0, 0, 0, "");
2914                                 /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */
2915                                 uiDefButS(block, MENU, B_TILTINTERP, "Tilt Interpolation %t|Linear %x0|Cardinal %x1|BSpline %x2",
2916                                         467,67,72, 18, &(nu->tilt_interp), 0, 0, 0, 0, "Tilt interpolation");
2917                         }
2918                                                 
2919                         uiBlockBeginAlign(block);
2920                         sp= &(nu->orderu);
2921                         uiDefButS(block, NUM, B_SETORDER, "Order U:", 565,90,102, 19, sp, 2.0, 6.0, 0, 0, "Nurbs only; the amount of control points involved");
2922                         sp= &(nu->orderv);
2923                         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");
2924                         sp= &(nu->resolu);
2925                         uiDefButS(block, NUM, B_MAKEDISP,