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