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