put the revision number in the splash screen (scons and make)
[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->bindcos) {
1474                 if(mmd->bindweights) MEM_freeN(mmd->bindweights);
1475                 if(mmd->bindcos) MEM_freeN(mmd->bindcos);
1476                 if(mmd->dyngrid) MEM_freeN(mmd->dyngrid);
1477                 if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences);
1478                 if(mmd->dynverts) MEM_freeN(mmd->dynverts);
1479                 mmd->bindweights= NULL;
1480                 mmd->bindcos= NULL;
1481                 mmd->dyngrid= NULL;
1482                 mmd->dyninfluences= NULL;
1483                 mmd->dynverts= NULL;
1484                 mmd->totvert= 0;
1485                 mmd->totcagevert= 0;
1486                 mmd->totinfluence= 0;
1487         }
1488         else {
1489                 DerivedMesh *dm;
1490                 int mode= mmd->modifier.mode;
1491
1492                 /* force modifier to run, it will call binding routine */
1493                 mmd->needbind= 1;
1494                 mmd->modifier.mode |= eModifierMode_Realtime;
1495
1496                 if(ob->type == OB_MESH) {
1497                         dm= mesh_create_derived_view(ob, 0);
1498                         dm->release(dm);
1499                 }
1500                 else if(ob->type == OB_LATTICE) {
1501                         lattice_calc_modifiers(ob);
1502                 }
1503
1504                 mmd->needbind= 0;
1505                 mmd->modifier.mode= mode;
1506         }
1507 }
1508
1509 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
1510 {
1511         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1512         uiBut *but;
1513         int isVirtual = md->mode&eModifierMode_Virtual;
1514         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
1515         int editing = (G.obedit==ob);
1516         short height=26, width = 295, buttonWidth = width-120-10;
1517         char str[128];
1518
1519         /* rounded header */
1520         uiBlockSetCol(block, color);
1521                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1522         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
1523                          (!isVirtual && (md->mode&eModifierMode_Expanded))?3:15, 20, ""); 
1524         uiBlockSetCol(block, TH_AUTO);
1525         
1526         /* open/close icon */
1527         if (!isVirtual) {
1528                 uiBlockSetEmboss(block, UI_EMBOSSN);
1529                 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");
1530         }
1531
1532         uiBlockSetEmboss(block, UI_EMBOSS);
1533         
1534         if (isVirtual) {
1535                 sprintf(str, "%s parent deform", md->name);
1536                 uiDefBut(block, LABEL, 0, str, x+10, y-1, width-110, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
1537
1538                 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");
1539                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
1540         } else {
1541                 uiBlockBeginAlign(block);
1542                 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"); 
1543
1544                         /* Softbody not allowed in this situation, enforce! */
1545                 if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
1546                         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");
1547                         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");
1548                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
1549                                 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)");
1550                         }
1551                 }
1552                 uiBlockEndAlign(block);
1553
1554                 uiBlockSetEmboss(block, UI_EMBOSSR);
1555
1556                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
1557                         int icon, color;
1558
1559                         if (index==cageIndex) {
1560                                 color = TH_BUT_SETTING;
1561                                 icon = VICON_EDITMODE_HLT;
1562                         } else if (index<cageIndex) {
1563                                 color = TH_BUT_NEUTRAL;
1564                                 icon = VICON_EDITMODE_DEHLT;
1565                         } else {
1566                                 color = TH_BUT_NEUTRAL;
1567                                 icon = ICON_BLANK1;
1568                         }
1569                         uiBlockSetCol(block, color);
1570                         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");
1571                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
1572                         uiBlockSetCol(block, TH_AUTO);
1573                 }
1574
1575                 uiBlockSetCol(block, TH_BUT_ACTION);
1576
1577                 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");
1578                 uiButSetFunc(but, modifiers_moveUp, ob, md);
1579
1580                 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");
1581                 uiButSetFunc(but, modifiers_moveDown, ob, md);
1582                 
1583                 uiBlockSetEmboss(block, UI_EMBOSSN);
1584
1585                 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");
1586                 uiButSetFunc(but, modifiers_del, ob, md);
1587                 uiBlockSetCol(block, TH_AUTO);
1588         }
1589
1590         uiBlockSetEmboss(block, UI_EMBOSS);
1591
1592         if (isVirtual || !(md->mode&eModifierMode_Expanded)) {
1593                 y -= 18;
1594         } else {
1595                 int cy = y - 8;
1596                 int lx = x + width - 60 - 15;
1597
1598                 if (md->type==eModifierType_Subsurf) {
1599                         height = 105;
1600                 } else if (md->type==eModifierType_Lattice) {
1601                         height = 48;
1602                 } else if (md->type==eModifierType_Curve) {
1603                         height = 72;
1604                 } else if (md->type==eModifierType_Build) {
1605                         height = 86;
1606                 } else if (md->type==eModifierType_Mirror) {
1607                         height = 86;
1608                 } else if (md->type==eModifierType_EdgeSplit) {
1609                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1610                         height = 48;
1611                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) height += 19;
1612                 } else if (md->type==eModifierType_Displace) {
1613                         DisplaceModifierData *dmd = (DisplaceModifierData *)md;
1614                         height = 124;
1615                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT ||
1616                            dmd->texmapping == MOD_DISP_MAP_UV)
1617                                 height += 19;
1618                 } else if (md->type==eModifierType_UVProject) {
1619                         height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
1620                 } else if (md->type==eModifierType_Decimate) {
1621                         height = 48;
1622                 } else if (md->type==eModifierType_Smooth) {
1623                         height = 86;
1624                 } else if (md->type==eModifierType_Cast) {
1625                         height = 143;
1626                 } else if (md->type==eModifierType_Wave) {
1627                         WaveModifierData *wmd = (WaveModifierData *)md;
1628                         height = 294;
1629                         if(wmd->texmapping == MOD_WAV_MAP_OBJECT ||
1630                            wmd->texmapping == MOD_WAV_MAP_UV)
1631                                 height += 19;
1632                         if(wmd->flag & MOD_WAVE_NORM)
1633                                 height += 19;
1634                 } else if (md->type==eModifierType_Armature) {
1635                         height = 86;
1636                 } else if (md->type==eModifierType_Hook) {
1637                         HookModifierData *hmd = (HookModifierData*) md;
1638                         height = 86;
1639                         if (editing)
1640                                 height += 20;
1641                         if(hmd->indexar==NULL)
1642                                 height += 20;
1643                 } else if (md->type==eModifierType_Softbody) {
1644                         height = 26;
1645                 } else if (md->type==eModifierType_Boolean) {
1646                         height = 48;
1647                 } else if (md->type==eModifierType_Array) {
1648                         height = 211;
1649                 } else if (md->type==eModifierType_MeshDeform) {
1650                         MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
1651                         height = (mmd->bindcos)? 73: 93;
1652                 } 
1653                 
1654                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1655                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); 
1656
1657                 y -= 18;
1658
1659                 if (!isVirtual) {
1660                         uiBlockBeginAlign(block);
1661                         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");
1662                         uiButSetFunc(but, modifiers_applyModifier, ob, md);
1663                         if (md->type!=eModifierType_Softbody) {
1664                                 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");
1665                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1666                         }
1667                         uiBlockEndAlign(block);
1668                 }
1669
1670                 lx = x + 10;
1671                 cy = y + 10 - 1;
1672                 uiBlockBeginAlign(block);
1673                 if (md->type==eModifierType_Subsurf) {
1674                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1675                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1676                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1677                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1678                         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");
1679
1680                         /* Disabled until non-EM DerivedMesh implementation is complete */
1681
1682                         /*
1683                         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");
1684                         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");
1685                         */
1686
1687                         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");
1688                         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");
1689                 } else if (md->type==eModifierType_Lattice) {
1690                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1691                         uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ",      lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1692                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1693                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1694                 } else if (md->type==eModifierType_Curve) {
1695                         CurveModifierData *cmd = (CurveModifierData*) md;
1696                         uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1697                         but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",                           lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1698                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1699                         
1700                         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");
1701                         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");
1702                         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");
1703                         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");
1704                         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");
1705                         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");
1706                 } else if (md->type==eModifierType_Build) {
1707                         BuildModifierData *bmd = (BuildModifierData*) md;
1708                         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");
1709                         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");
1710                         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.");
1711                         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.");
1712                 } else if (md->type==eModifierType_Mirror) {
1713                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1714                         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");
1715                         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");
1716                         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");
1717                         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");
1718                         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");
1719                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_U, B_MODIFIER_RECALC,
1720                                      "Mirror U",
1721                                      lx, (cy-=19), buttonWidth/2, 19,
1722                                      &mmd->flag, 0, 0, 0, 0,
1723                                      "Mirror the U texture coordinate around "
1724                                      "the 0.5 point");
1725                         uiDefButBitS(block, TOG, MOD_MIR_MIRROR_V, B_MODIFIER_RECALC,
1726                                      "Mirror V",
1727                                      lx + buttonWidth/2 + 1, cy, buttonWidth/2, 19,
1728                                      &mmd->flag, 0, 0, 0, 0,
1729                                      "Mirror the V texture coordinate around "
1730                                      "the 0.5 point");
1731                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1732                                        "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1733                                        &mmd->mirror_ob,
1734                                        "Object to use as mirror");
1735
1736                 } else if (md->type==eModifierType_EdgeSplit) {
1737                         EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
1738                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
1739                                      B_MODIFIER_RECALC, "From Edge Angle",
1740                                      lx, (cy -= 19), buttonWidth, 19,
1741                                      &emd->flags, 0, 0, 0, 0,
1742                                      "Split edges with high angle between faces");
1743                         if(emd->flags & MOD_EDGESPLIT_FROMANGLE) {
1744                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
1745                                           lx, (cy -= 19), buttonWidth, 19, &emd->split_angle,
1746                                           0.0, 180.0, 100, 2,
1747                                           "Angle above which to split edges");
1748                         }
1749                         uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
1750                                      B_MODIFIER_RECALC, "From Marked As Sharp",
1751                                      lx, (cy -= 19), buttonWidth, 19,
1752                                      &emd->flags, 0, 0, 0, 0,
1753                                      "Split edges that are marked as sharp");
1754                 } else if (md->type==eModifierType_Displace) {
1755                         DisplaceModifierData *dmd = (DisplaceModifierData*) md;
1756                         but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
1757                                        lx, (cy -= 19), buttonWidth, 19,
1758                                        &dmd->defgrp_name, 0.0, 31.0, 0, 0,
1759                                        "Name of vertex group to displace"
1760                                        " (displace whole mesh if blank)");
1761                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1762                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
1763                                        "Texture: ", lx, (cy -= 19), buttonWidth, 19,
1764                                        &dmd->texture,
1765                                        "Texture to use as displacement input");
1766                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
1767                                   lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
1768                                   0, 1, 10, 3,
1769                                   "Material value that gives no displacement");
1770                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
1771                                   lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
1772                                   -1000, 1000, 10, 10,
1773                                   "Strength of displacement");
1774                         sprintf(str, "Direction%%t|Normal%%x%d|RGB -> XYZ%%x%d|"
1775                                 "Z%%x%d|Y%%x%d|X%%x%d",
1776                                 MOD_DISP_DIR_NOR, MOD_DISP_DIR_RGB_XYZ,
1777                                 MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
1778                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1779                                   lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
1780                                   0.0, 1.0, 0, 0, "Displace direction");
1781                         sprintf(str, "Texture Coordinates%%t"
1782                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1783                                 MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
1784                                 MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
1785                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1786                                   lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
1787                                   0.0, 1.0, 0, 0,
1788                                   "Texture coordinates used for displacement input");
1789                         if (dmd->texmapping == MOD_DISP_MAP_UV) {
1790                                 char *strtmp;
1791                                 int i;
1792                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1793                                                              : &((Mesh*)ob->data)->fdata;
1794                                 build_uvlayer_menu_vars(fdata, &strtmp, &dmd->uvlayer_tmp,
1795                                                         dmd->uvlayer_name);
1796                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1797                                       lx, (cy -= 19), buttonWidth, 19, &dmd->uvlayer_tmp,
1798                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1799                                 MEM_freeN(strtmp);
1800                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1801                                 uiButSetFunc(but, set_displace_uvlayer, dmd,
1802                                              &fdata->layers[i]);
1803                         }
1804                         if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
1805                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1806                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1807                                                &dmd->map_object,
1808                                                "Object to get texture coordinates from");
1809                         }
1810                 } else if (md->type==eModifierType_UVProject) {
1811                         UVProjectModifierData *umd = (UVProjectModifierData *) md;
1812                         int i;
1813                         char *strtmp;
1814                         CustomData *fdata = G.obedit ? &G.editMesh->fdata
1815                                                      : &((Mesh*)ob->data)->fdata;
1816                         build_uvlayer_menu_vars(fdata, &strtmp, &umd->uvlayer_tmp,
1817                                                 umd->uvlayer_name);
1818                         but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1819                               lx, (cy -= 19), buttonWidth, 19, &umd->uvlayer_tmp,
1820                               0.0, 1.0, 0, 0, "Set the UV layer to use");
1821                         i = CustomData_get_layer_index(fdata, CD_MTFACE);
1822                         uiButSetFunc(but, set_uvproject_uvlayer, umd, &fdata->layers[i]);
1823                         MEM_freeN(strtmp);
1824                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspX:",
1825                                   lx, (cy -= 19), buttonWidth / 2, 19, &umd->aspectx,
1826                                   1, 1000, 100, 2,
1827                                   "Horizontal Aspect Ratio");
1828                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "AspY:",
1829                                   lx + (buttonWidth / 2) + 1, cy, buttonWidth / 2, 19,
1830                                   &umd->aspecty,
1831                                   1, 1000, 100, 2,
1832                                   "Vertical Aspect Ratio");
1833                         uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
1834                                   lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
1835                                   1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
1836                                   "Number of objects to use as projectors");
1837                         for(i = 0; i < umd->num_projectors; ++i) {
1838                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1839                                                "Ob: ", lx, (cy -= 19), buttonWidth, 19,
1840                                                &umd->projectors[i],
1841                                                "Object to use as projector");
1842                         }
1843                         uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
1844                                        "Image: ", lx, (cy -= 19), buttonWidth, 19,
1845                                        &umd->image,
1846                                        "Image to project (only faces with this image "
1847                                        "will be altered");
1848                         uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
1849                         uiDefButBitI(block, TOG, MOD_UVPROJECT_OVERRIDEIMAGE,
1850                                      B_MODIFIER_RECALC, "Override Image",
1851                                      lx, (cy -= 19), buttonWidth, 19,
1852                                      &umd->flags, 0, 0, 0, 0,
1853                                      "Override faces' current images with the "
1854                                      "given image");
1855                 } else if (md->type==eModifierType_Decimate) {
1856                         DecimateModifierData *dmd = (DecimateModifierData*) md;
1857                         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");
1858                         sprintf(str, "Face Count: %d", dmd->faceCount);
1859                         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");
1860                 } else if (md->type==eModifierType_Smooth) {
1861                         SmoothModifierData *smd = (SmoothModifierData*) md;
1862
1863                         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");
1864                         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");
1865                         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");
1866
1867                         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)");
1868                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:",     lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
1869                         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");
1870                 } else if (md->type==eModifierType_Cast) {
1871                         CastModifierData *cmd = (CastModifierData*) md;
1872
1873                         char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
1874                         uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu,         lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
1875                         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");
1876                         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");
1877                         if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
1878                                 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");
1879                         }
1880                         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");
1881                         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)");
1882                         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)");
1883                         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)");
1884                         if (ob->type == OB_MESH) {
1885                                 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");
1886                         }
1887                         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");
1888                         if(cmd->object) {
1889                                 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");
1890                         }
1891                 } else if (md->type==eModifierType_Wave) {
1892                         WaveModifierData *wmd = (WaveModifierData*) md;
1893                         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");
1894                         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");
1895                         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");
1896                         uiDefButBitS(block, TOG, MOD_WAVE_NORM, B_MODIFIER_RECALC, "Normals",   lx,(cy-=19),buttonWidth,19, &wmd->flag, 0, 0, 0, 0, "Displace along normals");
1897                         if (wmd->flag & MOD_WAVE_NORM){
1898                                 if (ob->type==OB_MESH) {
1899                                         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");
1900                                         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");
1901                                         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");
1902                                 }
1903                                 else
1904                                         uiDefBut(block, LABEL, 1, "Meshes Only",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");                                
1905                         }
1906
1907                         uiBlockBeginAlign(block);
1908                         if(wmd->speed >= 0)
1909                                 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");
1910                         else
1911                                 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");
1912                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lifetime:",   lx,(cy-=19),buttonWidth,19, &wmd->lifetime,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the lifespan of the wave");
1913                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Damptime:",   lx,(cy-=19),buttonWidth,19, &wmd->damp,  -MAXFRAMEF, MAXFRAMEF, 100, 0, "Specify the dampingtime of the wave");
1914                         cy -= 9;
1915                         uiBlockBeginAlign(block);
1916                         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");
1917                         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");
1918                         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)");
1919                         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");
1920                         uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,"Texture: ", lx, (cy -= 19), 220, 19, &wmd->texture,"Texture with which to modulate wave");
1921                         sprintf(str, "Texture Coordinates%%t"
1922                                 "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
1923                                 MOD_WAV_MAP_LOCAL, MOD_WAV_MAP_GLOBAL,
1924                                 MOD_WAV_MAP_OBJECT, MOD_WAV_MAP_UV);
1925                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1926                                   lx, (cy -= 19), 220, 19, &wmd->texmapping,
1927                                   0.0, 1.0, 0, 0,
1928                                   "Texture coordinates used for modulation input");
1929                         if (wmd->texmapping == MOD_WAV_MAP_UV) {
1930                                 char *strtmp;
1931                                 int i;
1932                                 CustomData *fdata = G.obedit ? &G.editMesh->fdata
1933                                                              : &((Mesh*)ob->data)->fdata;
1934                                 build_uvlayer_menu_vars(fdata, &strtmp, &wmd->uvlayer_tmp,
1935                                                         wmd->uvlayer_name);
1936                                 but = uiDefButI(block, MENU, B_MODIFIER_RECALC, strtmp,
1937                                       lx, (cy -= 19), 220, 19, &wmd->uvlayer_tmp,
1938                                       0.0, 1.0, 0, 0, "Set the UV layer to use");
1939                                 MEM_freeN(strtmp);
1940                                 i = CustomData_get_layer_index(fdata, CD_MTFACE);
1941                                 uiButSetFunc(but, set_displace_uvlayer, wmd,
1942                                              &fdata->layers[i]);
1943                         }
1944                         if(wmd->texmapping == MOD_DISP_MAP_OBJECT) {
1945                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
1946                                                "Ob: ", lx, (cy -= 19), 220, 19,
1947                                                &wmd->map_object,
1948                                                "Object to get texture coordinates from");
1949                         }
1950             cy -= 9;
1951                         uiBlockBeginAlign(block);
1952                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
1953                         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");
1954                         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");
1955                         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");
1956                 } else if (md->type==eModifierType_Armature) {
1957                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
1958                         uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
1959                         
1960                         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");
1961                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1962                         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");
1963                         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");
1964                         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");
1965                         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");
1966                 } else if (md->type==eModifierType_Hook) {
1967                         HookModifierData *hmd = (HookModifierData*) md;
1968                         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");
1969                         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");
1970                         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"); 
1971                         if(hmd->indexar==NULL) {
1972                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1973                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1974                         }
1975                         uiBlockBeginAlign(block);
1976                         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");
1977                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
1978                         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");
1979                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
1980
1981                         if (editing) {
1982                                 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");
1983                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
1984                                 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");
1985                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
1986                         }
1987                 } else if (md->type==eModifierType_Softbody) {
1988                         uiDefBut(block, LABEL, 1, "See Softbody panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1989                 } else if (md->type==eModifierType_Boolean) {
1990                         BooleanModifierData *bmd = (BooleanModifierData*) md;
1991                         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");
1992                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
1993                 } else if (md->type==eModifierType_Array) {
1994                         ArrayModifierData *amd = (ArrayModifierData*) md;
1995                         float range = 10000;
1996                         int cytop, halfwidth = (width - 5)/2 - 15;
1997                         int halflx = lx + halfwidth + 10;
1998
1999                         uiBlockSetEmboss(block, UI_EMBOSSX);
2000                         uiBlockEndAlign(block);
2001
2002                         /* length parameters */
2003                         uiBlockBeginAlign(block);
2004                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
2005                                 "|Fit To Curve Length%%x%d",
2006                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
2007                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
2008                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
2009                                   0.0, 1.0, 0, 0, "Array length calculation method");
2010                         switch(amd->fit_type)
2011                         {
2012                         case MOD_ARR_FIXEDCOUNT:
2013                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
2014                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
2015                                           1, 1000, 0, 0, "Number of duplicates to make");
2016                                 break;
2017                         case MOD_ARR_FITLENGTH:
2018                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
2019                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
2020                                           0, range, 10, 2,
2021                                           "Length to fit array within");
2022                                 break;
2023                         case MOD_ARR_FITCURVE:
2024                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
2025                                                B_CHANGEDEP, "Ob: ",
2026                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
2027                                                "Curve object to fit array length to");
2028                                 break;
2029                         }
2030                         uiBlockEndAlign(block);
2031
2032                         /* offset parameters */
2033                         cy -= 10;
2034                         cytop= cy;
2035                         uiBlockBeginAlign(block);
2036                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
2037                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
2038                                      &amd->offset_type, 0, 0, 0, 0,
2039                                      "Constant offset between duplicates "
2040                                      "(local coordinates)");
2041                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2042                                   lx, (cy-=19), halfwidth, 19,
2043                                   &amd->offset[0],
2044                                   -range, range, 10, 3,
2045                                   "Constant component for duplicate offsets "
2046                                   "(local coordinates)");
2047                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2048                                   lx, (cy-=19), halfwidth, 19,
2049                                   &amd->offset[1],
2050                                   -range, range, 10, 3,
2051                                   "Constant component for duplicate offsets "
2052                                   "(local coordinates)");
2053                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2054                                   lx, (cy-=19), halfwidth, 19,
2055                                   &amd->offset[2],
2056                                   -range, range, 10, 3,
2057                                   "Constant component for duplicate offsets "
2058                                   "(local coordinates)");
2059                         uiBlockEndAlign(block);
2060
2061                         cy= cytop;
2062                         uiBlockBeginAlign(block);
2063                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2064                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2065                                      &amd->offset_type, 0, 0, 0, 0,
2066                                      "Offset between duplicates relative to object width "
2067                                      "(local coordinates)");
2068                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2069                                   halflx, (cy-=19), halfwidth, 19,
2070                                   &amd->scale[0],
2071                                   -range, range, 10, 3,
2072                                   "Component for duplicate offsets relative to object "
2073                                   "width (local coordinates)");
2074                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2075                                   halflx, (cy-=19), halfwidth, 19,
2076                                   &amd->scale[1],
2077                                   -range, range, 10, 3,
2078                                   "Component for duplicate offsets relative to object "
2079                                   "width (local coordinates)");
2080                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2081                                   halflx, (cy-=19), halfwidth, 19,
2082                                   &amd->scale[2],
2083                                   -range, range, 10, 3,
2084                                   "Component for duplicate offsets relative to object "
2085                                   "width (local coordinates)");
2086                         uiBlockEndAlign(block);
2087
2088                         /* vertex merging parameters */
2089                         cy -= 10;
2090                         cytop= cy;
2091
2092                         uiBlockBeginAlign(block);
2093                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2094                                      "Merge",
2095                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2096                                      0, 0, 0, 0,
2097                                      "Merge vertices in adjacent duplicates");
2098                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2099                                      "First Last",
2100                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2101                                      &amd->flags,
2102                                      0, 0, 0, 0,
2103                                      "Merge vertices in first duplicate with vertices"
2104                                      " in last duplicate");
2105                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2106                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2107                                           0, 1.0f, 1, 4,
2108                                           "Limit below which to merge vertices");
2109
2110                         /* offset ob */
2111                         cy = cytop;
2112                         uiBlockBeginAlign(block);
2113                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2114                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2115                                      &amd->offset_type, 0, 0, 0, 0,
2116                                      "Add an object transformation to the total offset");
2117                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2118                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2119                                        &amd->offset_ob,
2120                                        "Object from which to take offset transformation");
2121                         uiBlockEndAlign(block);
2122
2123                         cy -= 10;
2124                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2125                                              B_CHANGEDEP, "Start cap: ",
2126                                              lx, (cy -= 19), halfwidth, 19,
2127                                              &amd->start_cap,
2128                                              "Mesh object to use as start cap");
2129                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2130                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2131                                              B_CHANGEDEP, "End cap: ",
2132                                              halflx, cy, halfwidth, 19,
2133                                              &amd->end_cap,
2134                                              "Mesh object to use as end cap");
2135                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2136                 } else if (md->type==eModifierType_MeshDeform) {
2137                         MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
2138
2139                         uiBlockBeginAlign(block);
2140                         uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &mmd->object, "Mesh object to be use as cage"); 
2141                         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");
2142                         uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
2143                         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");
2144
2145                         uiBlockBeginAlign(block);
2146                         if(mmd->bindcos) {
2147                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Unbind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Unbind mesh from cage");
2148                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2149                         }
2150                         else {
2151                                 but= uiDefBut(block, BUT, B_MODIFIER_RECALC, "Bind", lx,(cy-=24), buttonWidth,19, 0, 0, 0, 0, 0, "Bind mesh to cage");
2152                                 uiButSetFunc(but,modifiers_bindMeshDeform,ob,md);
2153                                 uiDefButS(block, NUM, B_NOP, "Precision:", lx,(cy-19), buttonWidth/2 + 20,19, &mmd->gridsize, 2, 10, 0.5, 0, "The grid size for binding");
2154                                 uiDefButBitS(block, TOG, MOD_MDEF_DYNAMIC_BIND, B_MODIFIER_RECALC, "Dynamic", lx+(buttonWidth+1)/2 + 20, (cy-=19), buttonWidth/2 - 20,19, &mmd->flag, 0.0, 31.0, 0, 0, "Invert vertex group influence");
2155                         }
2156                         uiBlockEndAlign(block);
2157                 }
2158
2159                 uiBlockEndAlign(block);
2160
2161                 y-=height;
2162         }
2163
2164         if (md->error) {
2165                 char str[512];
2166
2167                 y -= 20;
2168
2169                 uiBlockSetCol(block, color);
2170                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2171                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2172                 uiBlockSetCol(block, TH_AUTO);
2173
2174                 sprintf(str, "Modifier Error: %s", md->error);
2175                 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2176         }
2177
2178         y -= 3+6;
2179
2180         *xco = x;
2181         *yco = y;
2182 }
2183
2184 static void editing_panel_modifiers(Object *ob)
2185 {
2186         ModifierData *md;
2187         uiBlock *block;
2188         char str[64];
2189         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2190
2191         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2192         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2193         
2194         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2195         uiNewPanelHeight(block, 204);
2196
2197         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2198
2199         sprintf(str, "To: %s", ob->id.name+2);
2200         uiDefBut(block, LABEL, 1, str,  140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2201
2202         xco = 0;
2203         yco = 160;
2204
2205         md = modifiers_getVirtualModifierList(ob);
2206
2207         for (i=0; md; i++, md=md->next) {
2208                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2209                 if (md->mode&eModifierMode_Virtual) i--;
2210         }
2211         
2212         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2213 }
2214
2215 static char *make_key_menu(Key *key)
2216 {
2217         KeyBlock *kb;
2218         int index= 1;
2219         char *str, item[64];
2220
2221         for (kb = key->block.first; kb; kb=kb->next, index++);
2222         str= MEM_mallocN(index*40, "key string");
2223         str[0]= 0;
2224         
2225         index= 1;
2226         for (kb = key->block.first; kb; kb=kb->next, index++) {
2227                 sprintf (item,  "|%s%%x%d", kb->name, index);
2228                 strcat(str, item);
2229         }
2230         
2231         return str;
2232 }
2233
2234 static void editing_panel_shapes(Object *ob)
2235 {
2236         uiBlock *block;
2237         Key *key= NULL;
2238         KeyBlock *kb;
2239         int icon;
2240         char *strp;
2241         
2242         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2243         uiNewPanelTabbed("Modifiers", "Editing");
2244         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2245         
2246         /* Todo check data is library here */
2247         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2248         
2249         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2250         
2251         key= ob_get_key(ob);
2252         if(key==NULL) {
2253                 /* label aligns add button */
2254                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2255                 return;
2256         }
2257         
2258         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2259
2260         kb= BLI_findlink(&key->block, ob->shapenr-1);
2261         if(kb==NULL) {
2262                 ob->shapenr= 1;
2263                 kb= key->block.first;
2264         }
2265
2266         uiBlockBeginAlign(block);
2267         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2268         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");
2269         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2270         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2271         strp= make_key_menu(key);
2272         uiDefButS(block, MENU, B_SETKEY, strp,                                  55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
2273         MEM_freeN(strp);
2274         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2275         uiClearButLock();
2276         uiDefBut(block, TEX, B_NAMEKEY, "",                                             95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2277         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2278         uiBlockEndAlign(block);
2279
2280         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2281                 uiBlockBeginAlign(block);
2282                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2283                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2284                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2285                 uiBlockEndAlign(block);
2286         }
2287         if(key->type && ob->shapenr!=1)
2288                 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");
2289
2290         if(key->type==0)
2291                 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");
2292         
2293 }
2294
2295 /* *************************** FONT ******************************** */
2296
2297 static short give_vfontnr(VFont *vfont)
2298 {
2299         VFont *vf;
2300         short nr= 1;
2301
2302         vf= G.main->vfont.first;
2303         while(vf) {
2304                 if(vf==vfont) return nr;
2305                 nr++;
2306                 vf= vf->id.next;
2307         }
2308         return -1;
2309 }
2310
2311 static VFont *give_vfontpointer(int nr) /* nr= button */
2312 {
2313         VFont *vf;
2314         short tel= 1;
2315
2316         vf= G.main->vfont.first;
2317         while(vf) {
2318                 if(tel==nr) return vf;
2319                 tel++;
2320                 vf= vf->id.next;
2321         }
2322         return G.main->vfont.first;
2323 }
2324
2325 VFont *exist_vfont(char *str)
2326 {
2327         VFont *vf;
2328
2329         vf= G.main->vfont.first;
2330         while(vf) {
2331                 if(strcmp(vf->name, str)==0) return vf;
2332                 vf= vf->id.next;
2333         }
2334         return 0;
2335 }
2336
2337 static char *give_vfontbutstr(void)
2338 {
2339         VFont *vf;
2340         int len= 0;
2341         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2342
2343         vf= G.main->vfont.first;
2344         while(vf) {
2345                 strcpy(di, vf->name);
2346                 BLI_splitdirstring(di, fi);
2347                 len+= strlen(fi)+4;
2348                 vf= vf->id.next;
2349         }
2350
2351         str= MEM_callocN(len+21, "vfontbutstr");
2352         strcpy(str, "FONTS %t");
2353         vf= G.main->vfont.first;
2354         while(vf) {
2355
2356                 if(vf->id.us==0) strcat(str, "|0 ");
2357                 else strcat(str, "|   ");
2358
2359                 strcpy(di, vf->name);
2360                 BLI_splitdirstring(di, fi);
2361
2362                 strcat(str, fi);
2363                 vf= vf->id.next;
2364         }
2365         return str;
2366 }
2367
2368 static void load_buts_vfont(char *name)
2369 {
2370         VFont *vf;
2371         Curve *cu;
2372
2373         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2374         else return;
2375
2376         vf= exist_vfont(name);
2377         if(vf==0) {
2378                 vf= load_vfont(name);
2379                 if(vf==0) return;
2380         }
2381         else id_us_plus((ID *)vf);
2382         
2383         switch(cu->curinfo.flag & CU_STYLE) {
2384                 case CU_BOLD:
2385                         if(cu->vfontb) cu->vfontb->id.us--;
2386                         cu->vfontb= vf;
2387                         break;
2388                 case CU_ITALIC:
2389                         if(cu->vfonti) cu->vfonti->id.us--;             
2390                         cu->vfonti= vf;
2391                         break;                                          
2392                 case (CU_BOLD|CU_ITALIC):
2393                         if(cu->vfontbi) cu->vfontbi->id.us--;
2394                         cu->vfontbi= vf;
2395                         break;
2396                 default:
2397                         if(cu->vfont) cu->vfont->id.us--;
2398                         cu->vfont= vf;
2399                         break;                                          
2400         }       
2401
2402         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2403         BIF_undo_push("Load vector font");
2404         allqueue(REDRAWVIEW3D, 0);
2405         allqueue(REDRAWBUTSEDIT, 0);
2406 }
2407
2408 static void set_unicode_text_fs(char *file)
2409 {
2410         if (file > 0) paste_unicodeText(file); 
2411 }
2412
2413 void do_fontbuts(unsigned short event)
2414 {
2415         Curve *cu;
2416         VFont *vf;
2417         Object *ob;
2418         ScrArea *sa;
2419         char str[80];
2420         int ctevt;
2421         char *ctmenu;
2422         DynStr *ds;
2423         int i, style=0;
2424
2425         ob= OBACT;
2426
2427         switch(event) {
2428         case B_MAKEFONT:
2429                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2430                 allqueue(REDRAWVIEW3D, 0);
2431                 break;
2432
2433         case B_STYLETOSELU:     
2434         case B_STYLETOSELB:
2435         case B_STYLETOSELI:
2436                 switch (event) {
2437                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2438                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2439                         case B_STYLETOSELI: style = CU_ITALIC; break;
2440                 }
2441                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2442                         text_to_curve(ob, 0);
2443                         makeDispListCurveTypes(ob, 0);
2444                         allqueue(REDRAWVIEW3D, 0);
2445                 }
2446                 allqueue(REDRAWBUTSEDIT, 0);
2447                 break;          
2448                 
2449         case B_FASTFONT:
2450                 if (G.obedit) {
2451                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2452                         allqueue(REDRAWVIEW3D, 0);
2453                 }
2454                 break;
2455         case B_INSTB:
2456                 cu= ob->data;
2457                 if (cu->totbox < 256) {
2458                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2459                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2460                         cu->actbox++;
2461                         cu->totbox++;
2462                         allqueue(REDRAWBUTSEDIT, 0);
2463                         allqueue(REDRAWVIEW3D, 0);
2464                         text_to_curve(ob, 0);
2465                         makeDispListCurveTypes(ob, 0);
2466                 }
2467                 else {
2468                         error("Do you really need that many text frames?");
2469                 }
2470                 break;
2471         case B_DELTB:
2472                 cu= ob->data;
2473                 if (cu->totbox > 1) {
2474                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2475                         cu->totbox--;
2476                         cu->actbox--;
2477                         allqueue(REDRAWBUTSEDIT, 0);
2478                         allqueue(REDRAWVIEW3D, 0);
2479                         text_to_curve(ob, 0);
2480                         makeDispListCurveTypes(ob, 0);
2481                 }
2482                 break;
2483         case B_TOUPPER:
2484                 to_upper();
2485                 break;
2486         case B_LOADFONT:
2487                 vf= give_vfontpointer(G.buts->texnr);
2488                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2489                 else strcpy(str, U.fontdir);
2490
2491                 sa= closest_bigger_area();
2492                 areawinset(sa->win);
2493
2494                 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2495
2496                 break;
2497         case B_PACKFONT:
2498                 if (ob) {
2499                         cu= ob->data;
2500                         if(cu && cu->vfont) {
2501                                 if (cu->vfont->packedfile) {
2502                                         if (G.fileflags & G_AUTOPACK) {
2503                                                 if (okee("Disable AutoPack ?")) {
2504                                                         G.fileflags &= ~G_AUTOPACK;
2505                                                 }
2506                                         }
2507
2508                                         if ((G.fileflags & G_AUTOPACK) == 0) {
2509                                                 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2510                                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2511                                                         allqueue(REDRAWVIEW3D, 0);
2512                                                 }
2513                                         }
2514                                 } else {
2515                                         cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2516                                 }
2517                         }
2518                 }
2519                 allqueue(REDRAWHEADERS, 0);
2520                 allqueue(REDRAWBUTSEDIT, 0);
2521                 break;
2522
2523         case B_LOAD3DTEXT:
2524                 if (!G.obedit) { error("Only in editmode!"); return; }
2525                 if (G.obedit->type != OB_FONT) return;  
2526                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2527                 break;
2528                 
2529         case B_LOREM:
2530                 if (!G.obedit) { error("Only in editmode!"); return; }
2531                 if (G.obedit->type != OB_FONT) return;  
2532                 add_lorem();
2533                 
2534                 break;          
2535
2536         case B_SETFONT:
2537                 if(ob) {
2538                         cu= ob->data;
2539
2540                         vf= give_vfontpointer(G.buts->texnr);
2541                         if(vf) {
2542                                 id_us_plus((ID *)vf);
2543
2544                                 switch(cu->curinfo.flag & CU_STYLE) {
2545                                         case CU_BOLD:
2546                                                 cu->vfontb->id.us--;
2547                                                 cu->vfontb= vf;
2548                                                 break;
2549                                         case CU_ITALIC:
2550                                                 cu->vfonti->id.us--;
2551                                                 cu->vfonti= vf;
2552                                                 break;                                          
2553                                         case (CU_BOLD|CU_ITALIC):
2554                                                 cu->vfontbi->id.us--;
2555                                                 cu->vfontbi= vf;
2556                                                 break;
2557                                         default:
2558                                                 cu->vfont->id.us--;
2559                                                 cu->vfont= vf;
2560                                                 break;                                          
2561                                 }
2562                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2563
2564                                 BIF_undo_push("Set vector font");
2565                                 allqueue(REDRAWVIEW3D, 0);
2566                                 allqueue(REDRAWBUTSEDIT, 0);
2567                         }
2568                 }
2569                 break;
2570                 
2571         case B_SETCHAR:
2572                 G.charmin = 0x0000;
2573                 G.charmax = 0xffff;
2574                 if(G.charstart < 0)
2575                         G.charstart = 0;        
2576                 if(G.charstart > (0xffff - 12*6))
2577                         G.charstart = 0xffff - (12*6);
2578                 allqueue(REDRAWBUTSEDIT, 0);
2579                 break;
2580                 
2581         case B_SETUPCHAR:
2582                 G.charstart = G.charstart - (12*6);
2583                 if(G.charstart < 0)
2584                         G.charstart = 0;        
2585                 if(G.charstart < G.charmin)
2586                         G.charstart = G.charmin;
2587                 allqueue(REDRAWBUTSEDIT, 0);
2588                 break;
2589                 
2590         case B_SETCAT:
2591                 // Create new dynamic string
2592                 ds = BLI_dynstr_new();
2593                 
2594                 // Fill the dynamic string with entries
2595                 for(i=0;i<104;i++)
2596                 {
2597                         BLI_dynstr_append(ds, "|");
2598                         BLI_dynstr_append(ds, uctabname[i].name);
2599                 }
2600                 
2601                 // Create the menu string from dyn string
2602                 ctmenu = BLI_dynstr_get_cstring(ds);
2603                 
2604                 // Call the popup menu
2605                 ctevt = pupmenu_col(ctmenu, 40);
2606                 G.charstart = uctabname[ctevt-1].start;
2607                 G.charmin = uctabname[ctevt-1].start;
2608                 G.charmax = uctabname[ctevt-1].end;
2609
2610                 // Free all data
2611                 BLI_dynstr_free(ds);
2612                 MEM_freeN(ctmenu);
2613
2614                 // And refresh
2615                 allqueue(REDRAWVIEW3D, 0);
2616                 allqueue(REDRAWBUTSEDIT, 0);
2617                 
2618                 break;  
2619                 
2620         case B_SETDOWNCHAR:
2621                 G.charstart = G.charstart + (12*6);
2622                 if(G.charstart > (0xffff - 12*6))
2623                         G.charstart = 0xffff - (12*6);
2624                 if(G.charstart > G.charmax - 12*6)
2625                         G.charstart = G.charmax - 12*6;
2626                 allqueue(REDRAWBUTSEDIT, 0);
2627                 break;
2628                 
2629         case B_SETUNITEXT:
2630                 sa= closest_bigger_area();
2631                 areawinset(sa->win);
2632
2633                 if(ob==G.obedit) {
2634                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
2635                 }
2636                 break;          
2637                 
2638         case B_TEXTONCURVE:
2639                 if(ob) {
2640                         cu= ob->data;
2641                         if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
2642                                 error("Only Curve Objects");
2643                                 cu->textoncurve= 0;
2644                                 allqueue(REDRAWBUTSEDIT, 0);
2645                         }
2646                         DAG_scene_sort(G.scene); // makes new dag
2647                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2648                         allqueue(REDRAWVIEW3D, 0);
2649                 }
2650         }
2651 }
2652
2653 #ifdef INTERNATIONAL
2654 static void editing_panel_char_type(Object *ob, Curve *cu)
2655 {
2656         uiBlock *block;
2657
2658         block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
2659         uiNewPanelTabbed("Font", "Editing");
2660         if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0) 
2661                 return;
2662
2663         // Set the selected font
2664         G.selfont = cu->vfont;
2665         
2666         uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT,       0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
2667
2668         // Unicode categorization selection button
2669         uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
2670         uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
2671
2672         // Character selection button
2673         uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
2674
2675         // Buttons to change the max, min
2676         uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
2677         uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
2678 }
2679 #endif
2680
2681 static void editing_panel_font_type(Object *ob, Curve *cu)
2682 {
2683         uiBlock *block;
2684         char *strp;
2685         static int packdummy = 0;
2686         char str[32];
2687
2688         block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
2689         if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
2690
2691         switch(cu->curinfo.flag & CU_STYLE) {
2692                 case CU_BOLD:
2693                         G.buts->texnr= give_vfontnr(cu->vfontb);
2694                         break;
2695                 case CU_ITALIC:
2696                         G.buts->texnr= give_vfontnr(cu->vfonti);
2697                         break;                                          
2698                 case (CU_BOLD|CU_ITALIC):
2699                         G.buts->texnr= give_vfontnr(cu->vfontbi);
2700                         break;
2701                 default:
2702                         G.buts->texnr= give_vfontnr(cu->vfont);
2703                         break;                                          
2704         }       
2705
2706         strp= give_vfontbutstr();
2707 //      vfd= cu->vfont->data;
2708
2709         uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
2710         uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
2711
2712         if (cu->vfont->packedfile) {
2713                 packdummy = 1;
2714         } else {
2715                 packdummy = 0;
2716         }
2717         uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE,       772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
2718
2719         /* This doesn't work anyway */
2720 //      uiDefBut(block, LABEL, 0, vfd->name,  480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
2721
2722         uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
2723         uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor"); 
2724         uiDefButC(block, TOG|BIT|2,B_STYLETOSELU, "U",          727,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");     
2725         uiBlockBeginAlign(block);
2726         uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSELB, "B",           752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
2727         uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSELI, "i",         772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");    
2728         uiBlockEndAlign(block);
2729
2730         MEM_freeN(strp);
2731
2732         uiBlockBeginAlign(block);
2733         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");
2734         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");
2735         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");
2736         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");
2737         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");   
2738         uiDefBut(block, BUT, B_TOUPPER, "ToUpper",              715,135,78,20, 0, 0, 0, 0, 0, "Toggle between upper and lower case in editmode");
2739         uiBlockEndAlign(block);
2740         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");     
2741
2742         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_TEXTONCURVE, "TextOnCurve:",    480,105,220,19, &cu->textoncurve, "Apply a deforming curve to the text");
2743         uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 480,84,220,19, cu->family, 0.0, 20.0, 0, 0, "Blender uses font from selfmade objects");
2744
2745         uiBlockBeginAlign(block);
2746         uiDefButF(block, NUM,B_MAKEFONT, "Size:",               480,56,155,20, &cu->fsize, 0.1,10.0, 10, 0, "Size of the text");
2747         uiDefButF(block, NUM,B_MAKEFONT, "Linedist:",   640,56,155,20, &cu->linedist, 0.0,10.0, 10, 0, "Distance between text lines");
2748         uiDefButF(block, NUM,B_MAKEFONT, "Word spacing:",       795,56,155,20, &cu->wordspace, 0.0,10.0, 10, 0, "Distance factor between words");               
2749         uiDefButF(block, NUM,B_MAKEFONT, "Spacing:",    480,34,155,20, &cu->spacing, 0.0,10.0, 10, 0, "Spacing of individual characters");
2750         uiDefButF(block, NUM,B_MAKEFONT, "X offset:",   640,34,155,20, &cu->xof, -50.0,50.0, 10, 0, "Horizontal position from object center");
2751         uiDefButF(block, NUM,B_MAKEFONT, "UL position:",        795,34,155,20, &cu->ulpos, -0.2,0.8, 10, 0, "Vertical position of underline");                  
2752         uiDefButF(block, NUM,B_MAKEFONT, "Shear:",              480,12,155,20, &cu->shear, -1.0,1.0, 10, 0, "Italic angle of the characters");
2753         uiDefButF(block, NUM,B_MAKEFONT, "Y offset:",   640,12,155,20, &cu->yof, -50.0,50.0, 10, 0, "Vertical position from object center");
2754         uiDefButF(block, NUM,B_MAKEFONT, "UL height:",  795,12,155,20, &cu->ulheight, 0.01,0.5, 10, 0, "Thickness of underline");                               
2755         uiBlockEndAlign(block); 
2756         
2757         sprintf(str, "%d TextFrame: ", cu->totbox);
2758         uiBlockBeginAlign(block);
2759         uiDefButI(block, NUM, REDRAWVIEW3D, str, 805, 188, 145, 20, &cu->actbox, 1.0, cu->totbox, 0, 10, "Textbox to show settings for");
2760         uiDefBut(block, BUT,B_INSTB, "Insert", 805, 168, 72, 20, 0, 0, 0, 0, 0, "Insert a new text frame after the current one");
2761         uiDefBut(block, BUT,B_DELTB, "Delete", 877, 168, 73, 20, 0, 0, 0, 0, 0, "Delete current text frame and shift the others up");   
2762         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");
2763         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");     
2764         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");
2765         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");         
2766         uiBlockEndAlign(block);
2767 }
2768
2769
2770 /* *************************** CURVE ******************************** */
2771
2772
2773 void do_curvebuts(unsigned short event)
2774 {
2775         extern Nurb *lastnu;
2776         extern ListBase editNurb;  /* from editcurve */
2777         Object *ob;
2778         Curve *cu;
2779         Nurb *nu;
2780
2781         ob= OBACT;
2782         if(ob==0) return;
2783
2784         switch(event) {
2785
2786         case B_CONVERTPOLY:
2787         case B_CONVERTBEZ:
2788         case B_CONVERTBSPL:
2789         case B_CONVERTCARD:
2790         case B_CONVERTNURB:
2791                 if(G.obedit) {
2792                         setsplinetype(event-B_CONVERTPOLY);
2793                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2794                         allqueue(REDRAWVIEW3D, 0);
2795                 }
2796                 break;
2797         case B_UNIFU:
2798         case B_ENDPU:
2799         case B_BEZU:
2800         case B_UNIFV:
2801         case B_ENDPV:
2802         case B_BEZV:
2803                 if(G.obedit) {
2804                         nu= editNurb.first;
2805                         while(nu) {
2806                                 if(isNurbsel(nu)) {
2807                                         if((nu->type & 7)==CU_NURBS) {
2808                                                 if(event<B_UNIFV) {
2809                                                         nu->flagu &= 1;
2810                                                         nu->flagu += ((event-B_UNIFU)<<1);
2811                                                         makeknots(nu, 1, nu->flagu>>1);
2812                                                 }
2813                                                 else if(nu->pntsv>1) {
2814                                                         nu->flagv &= 1;
2815                                                         nu->flagv += ((event-B_UNIFV)<<1);
2816                                                         makeknots(nu, 2, nu->flagv>>1);
2817                                                 }
2818                                         }
2819                                 }
2820                                 nu= nu->next;
2821                         }
2822                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2823                         allqueue(REDRAWVIEW3D, 0);
2824                 }
2825                 break;
2826         case B_SETWEIGHT:
2827                 if(G.obedit) {
2828                         weightflagNurb(1, editbutweight, 0);
2829                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2830                         allqueue(REDRAWVIEW3D, 0);
2831                 }
2832                 break;
2833         case B_SETW1:
2834                 editbutweight= 1.0;
2835                 scrarea_queue_winredraw(curarea);
2836                 break;
2837         case B_SETW2:
2838                 editbutweight= sqrt(2.0)/4.0;
2839                 scrarea_queue_winredraw(curarea);
2840                 break;
2841         case B_SETW3:
2842                 editbutweight= 0.25;
2843                 scrarea_queue_winredraw(curarea);
2844                 break;
2845         case B_SETW4:
2846                 editbutweight= sqrt(0.5);
2847                 scrarea_queue_winredraw(curarea);
2848                 break;
2849         case B_SETORDER:
2850                 if(G.obedit) {
2851                         nu= lastnu;
2852                         if(nu && (nu->type & 7)==CU_NURBS ) {
2853                                 if(nu->orderu>nu->pntsu) {
2854                                         nu->orderu= nu->pntsu;
2855                                         scrarea_queue_winredraw(curarea);
2856                                 }
2857                                 makeknots(nu, 1, nu->flagu>>1);
2858                                 if(nu->orderv>nu->pntsv) {
2859                                         nu->orderv= nu->pntsv;
2860                                         scrarea_queue_winredraw(curarea);
2861                                 }
2862                                 makeknots(nu, 2, nu->flagv>>1);
2863                         }
2864                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2865                         allqueue(REDRAWVIEW3D, 0);
2866                 }
2867                 break;
2868         case B_TILTINTERP:
2869                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2870                 allqueue(REDRAWVIEW3D, 0);
2871                 break;
2872         case B_SUBSURFTYPE:
2873                 /* fallthrough */
2874         case B_MAKEDISP:
2875                 if(G.vd) {
2876                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2877                         allqueue(REDRAWVIEW3D, 0);
2878                         allqueue(REDRAWBUTSALL, 0);
2879                         allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
2880                 }
2881                 break;
2882
2883         case B_SUBDIVCURVE:
2884                 subdivideNurb();
2885                 break;
2886         case B_SPINNURB:
2887                 if( (G.obedit==NULL) || (G.obedit->type!=OB_SURF) || (G.vd==NULL) ||
2888                         ((G.obedit->lay & G.vd->lay) == 0) ) return;
2889                 spinNurb(0, 0);
2890                 countall();
2891                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2892                 allqueue(REDRAWVIEW3D, 0);
2893                 break;
2894         case B_CU3D:        /* allow 3D curve */
2895                 if(G.obedit) {
2896                         cu= G.obedit->data;
2897                         nu= editNurb.first;
2898                         while(nu) {
2899                                 nu->type &= ~CU_2D;
2900                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2901                                 test2DNurb(nu);
2902                                 nu= nu->next;
2903                         }
2904                 }
2905                 if(ob->type==OB_CURVE) {
2906                         cu= ob->data;
2907                         nu= cu->nurb.first;
2908                         while(nu) {
2909                                 nu->type &= ~CU_2D;
2910                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2911                                 test2DNurb(nu);
2912                                 nu= nu->next;
2913                         }
2914                 }
2915                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2916                 allqueue(REDRAWVIEW3D, 0);
2917                 break;
2918         case B_SETRESOLU:
2919                 if(ob->type==OB_CURVE) {
2920                         cu= ob->data;
2921                         if(ob==G.obedit) nu= editNurb.first;
2922                         else nu= cu->nurb.first;
2923
2924                         while(nu) {
2925                                 nu->resolu= cu->resolu;
2926                                 nu= nu->next;
2927                         }
2928