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