Merge with trunk: svn merge -r 12182:12207 https://svn.blender.org/svnroot/bf-blender...
[blender-staging.git] / source / blender / src / buttons_editing.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <time.h>
34 #include <math.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #ifdef WIN32
39 #ifndef snprintf
40 #define snprintf _snprintf
41 #endif
42 #endif
43
44 #include "MEM_guardedalloc.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_scene_types.h"
48
49 #include "DNA_action_types.h"
50 #include "DNA_armature_types.h"
51 #include "DNA_brush_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_color_types.h"
54 #include "DNA_constraint_types.h"
55 #include "DNA_curve_types.h"
56 #include "DNA_effect_types.h"
57 #include "DNA_group_types.h"
58 #include "DNA_key_types.h"
59 #include "DNA_lamp_types.h"
60 #include "DNA_lattice_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_meta_types.h"
63 #include "DNA_mesh_types.h"
64 #include "DNA_meshdata_types.h"
65 #include "DNA_modifier_types.h"
66 #include "DNA_nla_types.h"
67 #include "DNA_object_types.h"
68 #include "DNA_object_force.h"
69 #include "DNA_radio_types.h"
70 #include "DNA_screen_types.h"
71 #include "DNA_texture_types.h"
72 #include "DNA_userdef_types.h"
73 #include "DNA_vfont_types.h"
74 #include "DNA_view3d_types.h"
75 #include "DNA_world_types.h"
76 #include "DNA_packedFile_types.h"
77
78 #include "BKE_blender.h"
79 #include "BKE_brush.h"
80 #include "BKE_curve.h"
81 #include "BKE_customdata.h"
82 #include "BKE_colortools.h"
83 #include "BKE_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 + 1,20, &amd->deformflag, 0, 0, 0, 0, "Enable deform rotation interpolation with Quaternions");
1918
1919                         
1920                 } else if (md->type==eModifierType_Hook) {
1921                         HookModifierData *hmd = (HookModifierData*) md;
1922                         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");
1923                         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");
1924                         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"); 
1925                         if(hmd->indexar==NULL) {
1926                                 but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",         lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
1927                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
1928                         }
1929                         uiBlockBeginAlign(block);
1930                         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");
1931                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
1932                         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");
1933                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
1934
1935                         if (editing) {
1936                                 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");
1937                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
1938                                 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");
1939                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
1940                         }
1941                 } else if (md->type==eModifierType_Softbody) {
1942                         uiDefBut(block, LABEL, 1, "See Softbody panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1943                 } else if (md->type==eModifierType_Boolean) {
1944                         BooleanModifierData *bmd = (BooleanModifierData*) md;
1945                         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");
1946                         uiDefIDPoinBut(block, modifier_testMeshObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &bmd->object, "Mesh object to use for boolean operation");
1947                 } else if (md->type==eModifierType_Array) {
1948                         ArrayModifierData *amd = (ArrayModifierData*) md;
1949                         float range = 10000;
1950                         int cytop, halfwidth = (width - 5)/2 - 15;
1951                         int halflx = lx + halfwidth + 10;
1952
1953                         uiBlockSetEmboss(block, UI_EMBOSSX);
1954                         uiBlockEndAlign(block);
1955
1956                         /* length parameters */
1957                         uiBlockBeginAlign(block);
1958                         sprintf(str, "Length Fit%%t|Fixed Count%%x%d|Fixed Length%%x%d"
1959                                 "|Fit To Curve Length%%x%d",
1960                                 MOD_ARR_FIXEDCOUNT, MOD_ARR_FITLENGTH, MOD_ARR_FITCURVE);
1961                         uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
1962                                   lx, (cy-=19), buttonWidth, 19, &amd->fit_type,
1963                                   0.0, 1.0, 0, 0, "Array length calculation method");
1964                         switch(amd->fit_type)
1965                         {
1966                         case MOD_ARR_FIXEDCOUNT:
1967                                 uiDefButI(block, NUM, B_MODIFIER_RECALC, "Count:",
1968                                           lx, (cy -= 19), buttonWidth, 19, &amd->count,
1969                                           1, 1000, 0, 0, "Number of duplicates to make");
1970                                 break;
1971                         case MOD_ARR_FITLENGTH:
1972                                 uiDefButF(block, NUM, B_MODIFIER_RECALC, "Length:",
1973                                           lx, (cy -= 19), buttonWidth, 19, &amd->length,
1974                                           0, range, 10, 2,
1975                                           "Length to fit array within");
1976                                 break;
1977                         case MOD_ARR_FITCURVE:
1978                                 uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB,
1979                                                B_CHANGEDEP, "Ob: ",
1980                                                lx, (cy -= 19), buttonWidth, 19, &amd->curve_ob,
1981                                                "Curve object to fit array length to");
1982                                 break;
1983                         }
1984                         uiBlockEndAlign(block);
1985
1986                         /* offset parameters */
1987                         cy -= 10;
1988                         cytop= cy;
1989                         uiBlockBeginAlign(block);
1990                         uiDefButBitI(block, TOG, MOD_ARR_OFF_CONST, B_MODIFIER_RECALC,
1991                                      "Constant Offset", lx, (cy-=19), halfwidth, 19,
1992                                      &amd->offset_type, 0, 0, 0, 0,
1993                                      "Constant offset between duplicates "
1994                                      "(local coordinates)");
1995                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
1996                                   lx, (cy-=19), halfwidth, 19,
1997                                   &amd->offset[0],
1998                                   -range, range, 10, 3,
1999                                   "Constant component for duplicate offsets "
2000                                   "(local coordinates)");
2001                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2002                                   lx, (cy-=19), halfwidth, 19,
2003                                   &amd->offset[1],
2004                                   -range, range, 10, 3,
2005                                   "Constant component for duplicate offsets "
2006                                   "(local coordinates)");
2007                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2008                                   lx, (cy-=19), halfwidth, 19,
2009                                   &amd->offset[2],
2010                                   -range, range, 10, 3,
2011                                   "Constant component for duplicate offsets "
2012                                   "(local coordinates)");
2013                         uiBlockEndAlign(block);
2014
2015                         cy= cytop;
2016                         uiBlockBeginAlign(block);
2017                         uiDefButBitI(block, TOG, MOD_ARR_OFF_RELATIVE, B_MODIFIER_RECALC,
2018                                      "Relative Offset", halflx, (cy-=19), halfwidth, 19,
2019                                      &amd->offset_type, 0, 0, 0, 0,
2020                                      "Offset between duplicates relative to object width "
2021                                      "(local coordinates)");
2022                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "X:",
2023                                   halflx, (cy-=19), halfwidth, 19,
2024                                   &amd->scale[0],
2025                                   -range, range, 10, 3,
2026                                   "Component for duplicate offsets relative to object "
2027                                   "width (local coordinates)");
2028                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Y:",
2029                                   halflx, (cy-=19), halfwidth, 19,
2030                                   &amd->scale[1],
2031                                   -range, range, 10, 3,
2032                                   "Component for duplicate offsets relative to object "
2033                                   "width (local coordinates)");
2034                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Z:",
2035                                   halflx, (cy-=19), halfwidth, 19,
2036                                   &amd->scale[2],
2037                                   -range, range, 10, 3,
2038                                   "Component for duplicate offsets relative to object "
2039                                   "width (local coordinates)");
2040                         uiBlockEndAlign(block);
2041
2042                         /* vertex merging parameters */
2043                         cy -= 10;
2044                         cytop= cy;
2045
2046                         uiBlockBeginAlign(block);
2047                         uiDefButBitI(block, TOG, MOD_ARR_MERGE, B_MODIFIER_RECALC,
2048                                      "Merge",
2049                                      lx, (cy-=19), halfwidth/2, 19, &amd->flags,
2050                                      0, 0, 0, 0,
2051                                      "Merge vertices in adjacent duplicates");
2052                         uiDefButBitI(block, TOG, MOD_ARR_MERGEFINAL, B_MODIFIER_RECALC,
2053                                      "First Last",
2054                                      lx + halfwidth/2, cy, (halfwidth+1)/2, 19,
2055                                      &amd->flags,
2056                                      0, 0, 0, 0,
2057                                      "Merge vertices in first duplicate with vertices"
2058                                      " in last duplicate");
2059                         uiDefButF(block, NUM, B_MODIFIER_RECALC, "Limit:",
2060                                           lx, (cy-=19), halfwidth, 19, &amd->merge_dist,
2061                                           0, 1.0f, 1, 4,
2062                                           "Limit below which to merge vertices");
2063
2064                         /* offset ob */
2065                         cy = cytop;
2066                         uiBlockBeginAlign(block);
2067                         uiDefButBitI(block, TOG, MOD_ARR_OFF_OBJ, B_MODIFIER_RECALC,
2068                                      "Object Offset", halflx, (cy -= 19), halfwidth, 19,
2069                                      &amd->offset_type, 0, 0, 0, 0,
2070                                      "Add an object transformation to the total offset");
2071                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
2072                                        "Ob: ", halflx, (cy -= 19), halfwidth, 19,
2073                                        &amd->offset_ob,
2074                                        "Object from which to take offset transformation");
2075                         uiBlockEndAlign(block);
2076
2077                         cy -= 10;
2078                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2079                                              B_CHANGEDEP, "Start cap: ",
2080                                              lx, (cy -= 19), halfwidth, 19,
2081                                              &amd->start_cap,
2082                                              "Mesh object to use as start cap");
2083                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2084                         but = uiDefIDPoinBut(block, test_meshobpoin_but, ID_OB,
2085                                              B_CHANGEDEP, "End cap: ",
2086                                              halflx, cy, halfwidth, 19,
2087                                              &amd->end_cap,
2088                                              "Mesh object to use as end cap");
2089                         uiButSetCompleteFunc(but, autocomplete_meshob, (void *)ob);
2090                 }
2091                 uiBlockEndAlign(block);
2092
2093                 y-=height;
2094         }
2095
2096         if (md->error) {
2097                 char str[512];
2098
2099                 y -= 20;
2100
2101                 uiBlockSetCol(block, color);
2102                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
2103                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
2104                 uiBlockSetCol(block, TH_AUTO);
2105
2106                 sprintf(str, "Modifier Error: %s", md->error);
2107                 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
2108         }
2109
2110         y -= 3+6;
2111
2112         *xco = x;
2113         *yco = y;
2114 }
2115
2116 static void editing_panel_modifiers(Object *ob)
2117 {
2118         ModifierData *md;
2119         uiBlock *block;
2120         char str[64];
2121         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
2122
2123         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
2124         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
2125         
2126         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2127         uiNewPanelHeight(block, 204);
2128
2129         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
2130
2131         sprintf(str, "To: %s", ob->id.name+2);
2132         uiDefBut(block, LABEL, 1, str,  140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
2133
2134         xco = 0;
2135         yco = 160;
2136
2137         md = modifiers_getVirtualModifierList(ob);
2138
2139         for (i=0; md; i++, md=md->next) {
2140                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
2141                 if (md->mode&eModifierMode_Virtual) i--;
2142         }
2143         
2144         if(yco < 0) uiNewPanelHeight(block, 204-yco);
2145 }
2146
2147 static char *make_key_menu(Key *key)
2148 {
2149         KeyBlock *kb;
2150         int index= 1;
2151         char *str, item[64];
2152
2153         for (kb = key->block.first; kb; kb=kb->next, index++);
2154         str= MEM_mallocN(index*40, "key string");
2155         str[0]= 0;
2156         
2157         index= 1;
2158         for (kb = key->block.first; kb; kb=kb->next, index++) {
2159                 sprintf (item,  "|%s%%x%d", kb->name, index);
2160                 strcat(str, item);
2161         }
2162         
2163         return str;
2164 }
2165
2166 static void editing_panel_shapes(Object *ob)
2167 {
2168         uiBlock *block;
2169         Key *key= NULL;
2170         KeyBlock *kb;
2171         int icon;
2172         char *strp;
2173         
2174         block= uiNewBlock(&curarea->uiblocks, "editing_panel_shapes", UI_EMBOSS, UI_HELV, curarea->win);
2175         uiNewPanelTabbed("Modifiers", "Editing");
2176         if( uiNewPanel(curarea, block, "Shapes", "Editing", 640, 0, 318, 204)==0) return;
2177         
2178         /* Todo check data is library here */
2179         uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
2180         
2181         uiDefBut(block, BUT, B_ADDKEY, "Add Shape Key" ,        10, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "Add new Shape Key");
2182         
2183         key= ob_get_key(ob);
2184         if(key==NULL) {
2185                 /* label aligns add button */
2186                 uiDefBut(block, LABEL, 0, "",           170, 180,140,20, NULL, 0, 0, 0, 0, "");
2187                 return;
2188         }
2189         
2190         uiDefButS(block, TOG, B_RELKEY, "Relative",             170, 180,140,20, &key->type, 0, 0, 0, 0, "Makes Shape Keys relative");
2191
2192         kb= BLI_findlink(&key->block, ob->shapenr-1);
2193         if(kb==NULL) {
2194                 ob->shapenr= 1;
2195                 kb= key->block.first;
2196         }
2197
2198         uiBlockBeginAlign(block);
2199         if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT;
2200         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");
2201         uiSetButLock(G.obedit==ob, "Unable to perform in EditMode");
2202         uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT,             35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key");
2203         strp= make_key_menu(key);
2204         uiDefButS(block, MENU, B_SETKEY, strp,                                  55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
2205         MEM_freeN(strp);
2206         uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT,    75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key");
2207         uiClearButLock();
2208         uiDefBut(block, TEX, B_NAMEKEY, "",                                             95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name");
2209         uiDefIconBut(block, BUT, B_DELKEY, ICON_X,                              285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key");
2210         uiBlockEndAlign(block);
2211
2212         if(key->type && (ob->shapeflag & OB_SHAPE_LOCK)==0 && ob->shapenr!=1) {
2213                 uiBlockBeginAlign(block);
2214                 make_rvk_slider(block, ob, ob->shapenr-1,                       10, 120, 150, 20, "Key value, when used it inserts an animation curve point");
2215                 uiDefButF(block, NUM, B_REDR, "Min ",                           160,120, 75, 20, &kb->slidermin, -10.0, 10.0, 100, 1, "Minumum for slider");
2216                 uiDefButF(block, NUM, B_REDR, "Max ",                           235,120, 75, 20, &kb->slidermax, -10.0, 10.0, 100, 1, "Maximum for slider");
2217                 uiBlockEndAlign(block);
2218         }
2219         if(key->type && ob->shapenr!=1)
2220                 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");
2221
2222         if(key->type==0)
2223                 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");
2224         
2225 }
2226
2227 /* *************************** FONT ******************************** */
2228
2229 static short give_vfontnr(VFont *vfont)
2230 {
2231         VFont *vf;
2232         short nr= 1;
2233
2234         vf= G.main->vfont.first;
2235         while(vf) {
2236                 if(vf==vfont) return nr;
2237                 nr++;
2238                 vf= vf->id.next;
2239         }
2240         return -1;
2241 }
2242
2243 static VFont *give_vfontpointer(int nr) /* nr= button */
2244 {
2245         VFont *vf;
2246         short tel= 1;
2247
2248         vf= G.main->vfont.first;
2249         while(vf) {
2250                 if(tel==nr) return vf;
2251                 tel++;
2252                 vf= vf->id.next;
2253         }
2254         return G.main->vfont.first;
2255 }
2256
2257 VFont *exist_vfont(char *str)
2258 {
2259         VFont *vf;
2260
2261         vf= G.main->vfont.first;
2262         while(vf) {
2263                 if(strcmp(vf->name, str)==0) return vf;
2264                 vf= vf->id.next;
2265         }
2266         return 0;
2267 }
2268
2269 static char *give_vfontbutstr(void)
2270 {
2271         VFont *vf;
2272         int len= 0;
2273         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
2274
2275         vf= G.main->vfont.first;
2276         while(vf) {
2277                 strcpy(di, vf->name);
2278                 BLI_splitdirstring(di, fi);
2279                 len+= strlen(fi)+4;
2280                 vf= vf->id.next;
2281         }
2282
2283         str= MEM_callocN(len+21, "vfontbutstr");
2284         strcpy(str, "FONTS %t");
2285         vf= G.main->vfont.first;
2286         while(vf) {
2287
2288                 if(vf->id.us==0) strcat(str, "|0 ");
2289                 else strcat(str, "|   ");
2290
2291                 strcpy(di, vf->name);
2292                 BLI_splitdirstring(di, fi);
2293
2294                 strcat(str, fi);
2295                 vf= vf->id.next;
2296         }
2297         return str;
2298 }
2299
2300 static void load_buts_vfont(char *name)
2301 {
2302         VFont *vf;
2303         Curve *cu;
2304
2305         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
2306         else return;
2307
2308         vf= exist_vfont(name);
2309         if(vf==0) {
2310                 vf= load_vfont(name);
2311                 if(vf==0) return;
2312         }
2313         else id_us_plus((ID *)vf);
2314         
2315         switch(cu->curinfo.flag & CU_STYLE) {
2316                 case CU_BOLD:
2317                         if(cu->vfontb) cu->vfontb->id.us--;
2318                         cu->vfontb= vf;
2319                         break;
2320                 case CU_ITALIC:
2321                         if(cu->vfonti) cu->vfonti->id.us--;             
2322                         cu->vfonti= vf;
2323                         break;                                          
2324                 case (CU_BOLD|CU_ITALIC):
2325                         if(cu->vfontbi) cu->vfontbi->id.us--;
2326                         cu->vfontbi= vf;
2327                         break;
2328                 default:
2329                         if(cu->vfont) cu->vfont->id.us--;
2330                         cu->vfont= vf;
2331                         break;                                          
2332         }       
2333
2334         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
2335         BIF_undo_push("Load vector font");
2336         allqueue(REDRAWVIEW3D, 0);
2337         allqueue(REDRAWBUTSEDIT, 0);
2338 }
2339
2340 static void set_unicode_text_fs(char *file)
2341 {
2342         if (file > 0) paste_unicodeText(file); 
2343 }
2344
2345 void do_fontbuts(unsigned short event)
2346 {
2347         Curve *cu;
2348         VFont *vf;
2349         Object *ob;
2350         ScrArea *sa;
2351         char str[80];
2352         int ctevt;
2353         char *ctmenu;
2354         DynStr *ds;
2355         int i, style=0;
2356
2357         ob= OBACT;
2358
2359         switch(event) {
2360         case B_MAKEFONT:
2361                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2362                 allqueue(REDRAWVIEW3D, 0);
2363                 break;
2364
2365         case B_STYLETOSELU:     
2366         case B_STYLETOSELB:
2367         case B_STYLETOSELI:
2368                 switch (event) {
2369                         case B_STYLETOSELU: style = CU_UNDERLINE; break;
2370                         case B_STYLETOSELB: style = CU_BOLD; break;                     
2371                         case B_STYLETOSELI: style = CU_ITALIC; break;
2372                 }
2373                 if (style_to_sel(style, ((Curve*)ob->data)->curinfo.flag & style)) {
2374                         text_to_curve(ob, 0);
2375                         makeDispListCurveTypes(ob, 0);
2376                         allqueue(REDRAWVIEW3D, 0);
2377                 }
2378                 allqueue(REDRAWBUTSEDIT, 0);
2379                 break;          
2380                 
2381         case B_FASTFONT:
2382                 if (G.obedit) {
2383                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2384                         allqueue(REDRAWVIEW3D, 0);
2385                 }
2386                 break;
2387         case B_INSTB:
2388                 cu= ob->data;
2389                 if (cu->totbox < 256) {
2390                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
2391                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
2392                         cu->actbox++;
2393                         cu->totbox++;
2394                         allqueue(REDRAWBUTSEDIT, 0);
2395                         allqueue(REDRAWVIEW3D, 0);
2396                         text_to_curve(ob, 0);
2397                         makeDispListCurveTypes(ob, 0);
2398                 }
2399                 else {
2400                         error("Do you really need that many text frames?");
2401                 }
2402                 break;
2403         case B_DELTB:
2404                 cu= ob->data;
2405                 if (cu->totbox > 1) {
2406                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
2407                         cu->totbox--;
2408                         cu->actbox--;
2409                         allqueue(REDRAWBUTSEDIT, 0);
2410                         allqueue(REDRAWVIEW3D, 0);
2411                         text_to_curve(ob, 0);
2412                         makeDispListCurveTypes(ob, 0);
2413                 }
2414                 break;
2415         case B_TOUPPER:
2416                 to_upper();
2417                 break;
2418         case B_LOADFONT:
2419                 vf= give_vfontpointer(G.buts->texnr);
2420                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
2421                 else strcpy(str, U.fontdir);
2422
2423                 sa= closest_bigger_area();
2424                 areawinset(sa->win);
2425
2426                 activate_fileselect(FILE_LOADFONT, "SELECT FONT", str, load_buts_vfont);
2427
2428                 break;
2429         case B_PACKFONT:
2430                 if (ob) {
2431                         cu= ob->data;
2432                         if(cu && cu->vfont) {
2433                                 if (cu->vfont->packedfile) {
2434                                         if (G.fileflags & G_AUTOPACK) {
2435                                                 if (okee("Disable AutoPack ?")) {
2436                                                         G.fileflags &= ~G_AUTOPACK;
2437                                                 }
2438                                         }
2439
2440                                         if ((G.fileflags & G_AUTOPACK) == 0) {
2441                                                 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
2442                                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2443                                                         allqueue(REDRAWVIEW3D, 0);
2444                                                 }
2445                                         }
2446                                 } else {
2447                                         cu->vfont->packedfile = newPackedFile(cu->vfont->name);
2448                                 }
2449                         }
2450                 }
2451                 allqueue(REDRAWHEADERS, 0);
2452                 allqueue(REDRAWBUTSEDIT, 0);
2453                 break;
2454
2455         case B_LOAD3DTEXT:
2456                 if (!G.obedit) { error("Only in editmode!"); return; }
2457                 if (G.obedit->type != OB_FONT) return;  
2458                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
2459                 break;
2460                 
2461         case B_LOREM:
2462                 if (!G.obedit) { error("Only in editmode!"); return; }
2463                 if (G.obedit->type != OB_FONT) return;  
2464                 add_lorem();
2465                 
2466                 break;          
2467
2468         case B_SETFONT:
2469                 if(ob) {
2470                         cu= ob->data;
2471
2472                         vf= give_vfontpointer(G.buts->texnr);
2473                         if(vf) {
2474                                 id_us_plus((ID *)vf);
2475
2476                                 switch(cu->curinfo.flag & CU_STYLE) {
2477                                         case CU_BOLD:
2478                                                 cu->vfontb->id.us--;
2479                                                 cu->vfontb= vf;
2480                                                 break;
2481                                         case CU_ITALIC:
2482                                                 cu->vfonti->id.us--;
2483                                                 cu->vfonti= vf;
2484                                                 break;                                          
2485                                         case (CU_BOLD|CU_ITALIC):
2486                                                 cu->vfontbi->id.us--;
2487                                                 cu->vfontbi= vf;
2488                                                 break;
2489                                         default:
2490                                                 cu->vfont->id.us--;
2491                                                 cu->vfont= vf;
2492                                                 break;                                          
2493                                 }
2494                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2495
2496                                 BIF_undo_push("Set vector font");
2497                                 allqueue(REDRAWVIEW3D, 0);
2498                                 allqueue(REDRAWBUTSEDIT, 0);
2499                         }
2500                 }
2501                 break;
2502                 
2503         case B_SETCHAR:
2504                 G.charmin = 0x0000;
2505                 G.charmax = 0xffff;
2506                 if(G.charstart < 0)
2507                         G.charstart = 0;        
2508                 if(G.charstart > (0xffff - 12*6))
2509                         G.charstart = 0xffff - (12*6);
2510                 allqueue(REDRAWBUTSEDIT, 0);
2511                 break;
2512                 
2513         case B_SETUPCHAR:
2514                 G.charstart = G.charstart - (12*6);
2515                 if(G.charstart < 0)
2516                         G.charstart = 0;        
2517                 if(G.charstart < G.charmin)
2518                         G.charstart = G.charmin;
2519                 allqueue(REDRAWBUTSEDIT, 0);
2520                 break;
2521                 
2522         case B_SETCAT:
2523                 // Create new dynamic string
2524                 ds = BLI_dynstr_new();
2525                 
2526                 // Fill the dynamic string with entries
2527                 for(i=0;i<104;i++)
2528                 {
2529                         BLI_dynstr_append(ds, "|");
2530                         BLI_dynstr_append(ds, uctabname[i].name);
2531                 }
2532                 
2533                 // Create the menu string from dyn string
2534                 ctmenu = BLI_dynstr_get_cstring(ds);
2535                 
2536                 // Call the popup menu
2537                 ctevt = pupmenu_col(ctmenu, 40);
2538                 G.charstart = uctabname[ctevt-1].start;
2539                 G.charmin = uctabname[ctevt-1].start;
2540                 G.charmax = uctabname[ctevt-1].end;
2541
2542                 // Free all data
2543                 BLI_dynstr_free(ds);
2544                 MEM_freeN(ctmenu);
2545
2546                 // And refresh
2547                 allqueue(REDRAWVIEW3D, 0);
2548                 allqueue(REDRAWBUTSEDIT, 0);
2549                 
2550                 break;  
2551                 
2552         case B_SETDOWNCHAR:
2553                 G.charstart = G.charstart + (12*6);
2554                 if(G.charstart > (0xffff - 12*6))
2555                         G.charstart = 0xffff - (12*6);
2556                 if(G.charstart > G.charmax - 12*6)
2557                         G.charstart = G.charmax - 12*6;
2558                 allqueue(REDRAWBUTSEDIT, 0);
2559                 break;
2560                 
2561         case B_SETUNITEXT:
2562                 sa= closest_bigger_area();
2563                 areawinset(sa->win);
2564
2565                 if(ob==G.obedit) {
2566                         activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, set_unicode_text_fs);
2567                 }
2568                 break;          
2569                 
2570         case B_TEXTONCURVE:
2571                 if(ob) {
2572                         cu= ob->data;
2573                         if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
2574                                 error("Only Curve Objects");
2575                                 cu->textoncurve= 0;
2576                                 allqueue(REDRAWBUTSEDIT, 0);
2577                         }
2578                         DAG_scene_sort(G.scene); // makes new dag
2579                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2580                         allqueue(REDRAWVIEW3D, 0);
2581                 }
2582         }
2583 }
2584
2585 #ifdef INTERNATIONAL
2586 static void editing_panel_char_type(Object *ob, Curve *cu)
2587 {
2588         uiBlock *block;
2589
2590         block= uiNewBlock(&curarea->uiblocks, "editing_panel_char_type", UI_EMBOSS, UI_HELV, curarea->win);
2591         uiNewPanelTabbed("Font", "Editing");
2592         if(uiNewPanel(curarea, block, "Char", "Editing", 640, 0, 318, 204)==0) 
2593                 return;
2594
2595         // Set the selected font
2596         G.selfont = cu->vfont;
2597         
2598         uiDefIconBut(block, BUT, B_SETUNITEXT, ICON_TEXT,       0,210,20,20, 0, 0, 0, 0, 0, "Load Unicode Text file");
2599
2600         // Unicode categorization selection button
2601         uiDefBut(block, BUT, B_SETCAT, "Unicode Table", 22,210,226,20, 0, 0, 0, 0, 0, "Select Unicode Table");
2602         uiDefButI(block, NUM, /*B_SETUPCHAR*/ 0, "", 250,210,50,20, &G.charstart, 0, 0xffff, 0, 0, "UT");
2603
2604         // Character selection button
2605         uiDefBut(block, CHARTAB, B_SETCHAR, "", 0, 0, 264, 200, 0, 0, 0, 0, 0, "Select character");
2606
2607         // Buttons to change the max, min
2608         uiDefButI(block, BUT, B_SETUPCHAR, "U", 280, 185, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table up");
2609         uiDefButI(block, BUT, B_SETDOWNCHAR, "D", 280, 0, 15, 15, &G.charstart, 0, 0xffff, 0, 0, "Scroll character table down");
2610 }
2611 #endif
2612
2613 static void editing_panel_font_type(Object *ob, Curve *cu)
2614 {
2615         uiBlock *block;
2616         char *strp;
2617         static int packdummy = 0;
2618         char str[32];
2619
2620         block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
2621         if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
2622
2623         switch(cu->curinfo.flag & CU_STYLE) {
2624                 case CU_BOLD:
2625                         G.buts->texnr= give_vfontnr(cu->vfontb);
2626                         break;
2627                 case CU_ITALIC:
2628                         G.buts->texnr= give_vfontnr(cu->vfonti);
2629                         break;                                          
2630                 case (CU_BOLD|CU_ITALIC):
2631                         G.buts->texnr= give_vfontnr(cu->vfontbi);
2632                         break;
2633                 default:
2634                         G.buts->texnr= give_vfontnr(cu->vfont);
2635                         break;                                          
2636         }       
2637
2638         strp= give_vfontbutstr();
2639 //      vfd= cu->vfont->data;
2640
2641         uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
2642         uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
2643
2644         if (cu->vfont->packedfile) {
2645                 packdummy = 1;
2646         } else {
2647                 packdummy = 0;
2648         }
2649         uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE,       772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
2650
2651         /* This doesn't work anyway */
2652 //      uiDefBut(block, LABEL, 0, vfd->name,  480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
2653
2654         uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
2655         uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor"); 
2656         uiDefButC(block, TOG|BIT|2,B_STYLETOSELU, "U",          727,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");     
2657         uiBlockBeginAlign(block);
2658         uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSELB, "B",           752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
2659         uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSELI, "i",         772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");    
2660         uiBlockEndAlign(block);
2661
2662         MEM_freeN(strp);
2663
2664         uiBlockBeginAlign(block);
2665         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");
2666         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");
2667         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");
2668         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");
2669         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");   
2670         uiDefBut(block, BUT, B_TOUPPER, "ToUpper",              715,135,78,20, 0, 0, 0, 0, 0, "Toggle between upper and lower case in editmode");
2671         uiBlockEndAlign(block);
2672         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");     
2673
2674         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_TEXTONCURVE, "TextOnCurve:",    480,105,220,19, &cu->textoncurve, "Apply a deforming curve to the text");
2675         uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 480,84,220,19, cu->family, 0.0, 20.0, 0, 0, "Blender uses font from selfmade objects");
2676
2677         uiBlockBeginAlign(block);
2678         uiDefButF(block, NUM,B_MAKEFONT, "Size:",               480,56,155,20, &cu->fsize, 0.1,10.0, 10, 0, "Size of the text");
2679         uiDefButF(block, NUM,B_MAKEFONT, "Linedist:",   640,56,155,20, &cu->linedist, 0.0,10.0, 10, 0, "Distance between text lines");
2680         uiDefButF(block, NUM,B_MAKEFONT, "Word spacing:",       795,56,155,20, &cu->wordspace, 0.0,10.0, 10, 0, "Distance factor between words");               
2681         uiDefButF(block, NUM,B_MAKEFONT, "Spacing:",    480,34,155,20, &cu->spacing, 0.0,10.0, 10, 0, "Spacing of individual characters");
2682         uiDefButF(block, NUM,B_MAKEFONT, "X offset:",   640,34,155,20, &cu->xof, -50.0,50.0, 10, 0, "Horizontal position from object center");
2683         uiDefButF(block, NUM,B_MAKEFONT, "UL position:",        795,34,155,20, &cu->ulpos, -0.2,0.8, 10, 0, "Vertical position of underline");                  
2684         uiDefButF(block, NUM,B_MAKEFONT, "Shear:",              480,12,155,20, &cu->shear, -1.0,1.0, 10, 0, "Italic angle of the characters");
2685         uiDefButF(block, NUM,B_MAKEFONT, "Y offset:",   640,12,155,20, &cu->yof, -50.0,50.0, 10, 0, "Vertical position from object center");
2686         uiDefButF(block, NUM,B_MAKEFONT, "UL height:",  795,12,155,20, &cu->ulheight, 0.01,0.5, 10, 0, "Thickness of underline");                               
2687         uiBlockEndAlign(block); 
2688         
2689         sprintf(str, "%d TextFrame: ", cu->totbox);
2690         uiBlockBeginAlign(block);
2691         uiDefButI(block, NUM, REDRAWVIEW3D, str, 805, 188, 145, 20, &cu->actbox, 1.0, cu->totbox, 0, 10, "Textbox to show settings for");
2692         uiDefBut(block, BUT,B_INSTB, "Insert", 805, 168, 72, 20, 0, 0, 0, 0, 0, "Insert a new text frame after the current one");
2693         uiDefBut(block, BUT,B_DELTB, "Delete", 877, 168, 73, 20, 0, 0, 0, 0, 0, "Delete current text frame and shift the others up");   
2694         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");
2695         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");     
2696         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");
2697         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");         
2698         uiBlockEndAlign(block);
2699 }
2700
2701
2702 /* *************************** CURVE ******************************** */
2703
2704
2705 void do_curvebuts(unsigned short event)
2706 {
2707         extern Nurb *lastnu;
2708         extern ListBase editNurb;  /* from editcurve */
2709         Object *ob;
2710         Curve *cu;
2711         Nurb *nu;
2712
2713         ob= OBACT;
2714         if(ob==0) return;
2715
2716         switch(event) {
2717
2718         case B_CONVERTPOLY:
2719         case B_CONVERTBEZ:
2720         case B_CONVERTBSPL:
2721         case B_CONVERTCARD:
2722         case B_CONVERTNURB:
2723                 if(G.obedit) {
2724                         setsplinetype(event-B_CONVERTPOLY);
2725                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2726                         allqueue(REDRAWVIEW3D, 0);
2727                 }
2728                 break;
2729         case B_UNIFU:
2730         case B_ENDPU:
2731         case B_BEZU:
2732         case B_UNIFV:
2733         case B_ENDPV:
2734         case B_BEZV:
2735                 if(G.obedit) {
2736                         nu= editNurb.first;
2737                         while(nu) {
2738                                 if(isNurbsel(nu)) {
2739                                         if((nu->type & 7)==CU_NURBS) {
2740                                                 if(event<B_UNIFV) {
2741                                                         nu->flagu &= 1;
2742                                                         nu->flagu += ((event-B_UNIFU)<<1);
2743                                                         makeknots(nu, 1, nu->flagu>>1);
2744                                                 }
2745                                                 else if(nu->pntsv>1) {
2746                                                         nu->flagv &= 1;
2747                                                         nu->flagv += ((event-B_UNIFV)<<1);
2748                                                         makeknots(nu, 2, nu->flagv>>1);
2749                                                 }
2750                                         }
2751                                 }
2752                                 nu= nu->next;
2753                         }
2754                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2755                         allqueue(REDRAWVIEW3D, 0);
2756                 }
2757                 break;
2758         case B_SETWEIGHT:
2759                 if(G.obedit) {
2760                         weightflagNurb(1, editbutweight, 0);
2761                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2762                         allqueue(REDRAWVIEW3D, 0);
2763                 }
2764                 break;
2765         case B_SETW1:
2766                 editbutweight= 1.0;
2767                 scrarea_queue_winredraw(curarea);
2768                 break;
2769         case B_SETW2:
2770                 editbutweight= sqrt(2.0)/4.0;
2771                 scrarea_queue_winredraw(curarea);
2772                 break;
2773         case B_SETW3:
2774                 editbutweight= 0.25;
2775                 scrarea_queue_winredraw(curarea);
2776                 break;
2777         case B_SETW4:
2778                 editbutweight= sqrt(0.5);
2779                 scrarea_queue_winredraw(curarea);
2780                 break;
2781         case B_SETORDER:
2782                 if(G.obedit) {
2783                         nu= lastnu;
2784                         if(nu && (nu->type & 7)==CU_NURBS ) {
2785                                 if(nu->orderu>nu->pntsu) {
2786                                         nu->orderu= nu->pntsu;
2787                                         scrarea_queue_winredraw(curarea);
2788                                 }
2789                                 makeknots(nu, 1, nu->flagu>>1);
2790                                 if(nu->orderv>nu->pntsv) {
2791                                         nu->orderv= nu->pntsv;
2792                                         scrarea_queue_winredraw(curarea);
2793                                 }
2794                                 makeknots(nu, 2, nu->flagv>>1);
2795                         }
2796                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2797                         allqueue(REDRAWVIEW3D, 0);
2798                 }
2799                 break;
2800         case B_TILTINTERP:
2801                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2802                 allqueue(REDRAWVIEW3D, 0);
2803                 break;
2804         case B_SUBSURFTYPE:
2805                 /* fallthrough */
2806         case B_MAKEDISP:
2807                 if(G.vd) {
2808                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2809                         allqueue(REDRAWVIEW3D, 0);
2810                         allqueue(REDRAWBUTSALL, 0);
2811                         allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
2812                 }
2813                 break;
2814
2815         case B_SUBDIVCURVE:
2816                 subdivideNurb();
2817                 break;
2818         case B_SPINNURB:
2819                 if( (G.obedit==NULL) || (G.obedit->type!=OB_SURF) || (G.vd==NULL) ||
2820                         ((G.obedit->lay & G.vd->lay) == 0) ) return;
2821                 spinNurb(0, 0);
2822                 countall();
2823                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
2824                 allqueue(REDRAWVIEW3D, 0);
2825                 break;
2826         case B_CU3D:        /* allow 3D curve */
2827                 if(G.obedit) {
2828                         cu= G.obedit->data;
2829                         nu= editNurb.first;
2830                         while(nu) {
2831                                 nu->type &= ~CU_2D;
2832                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2833                                 test2DNurb(nu);
2834                                 nu= nu->next;
2835                         }
2836                 }
2837                 if(ob->type==OB_CURVE) {
2838                         cu= ob->data;
2839                         nu= cu->nurb.first;
2840                         while(nu) {
2841                                 nu->type &= ~CU_2D;
2842                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
2843                                 test2DNurb(nu);
2844                                 nu= nu->next;
2845                         }
2846                 }
2847                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2848                 allqueue(REDRAWVIEW3D, 0);
2849                 break;
2850         case B_SETRESOLU:
2851                 if(ob->type==OB_CURVE) {
2852                         cu= ob->data;
2853                         if(ob==G.obedit) nu= editNurb.first;
2854                         else nu= cu->nurb.first;
2855
2856                         while(nu) {
2857                                 nu->resolu= cu->resolu;
2858                                 nu= nu->next;
2859                         }
2860                 }
2861
2862                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2863                 allqueue(REDRAWVIEW3D, 0);
2864                 allqueue(REDRAWBUTSALL, 0);
2865                 allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
2866
2867                 break;
2868     &nbs