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