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