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