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