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