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