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