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