- added DerivedMesh.drawUVEdges function & implementations
[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 object, 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 object");
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 object");
459         }
460         else uiDefBut(block, BUT, B_DELVERTCOL, "Delete",       80,50,84,19, 0, 0, 0, 0, 0, "Deletes vertex colours on active object");
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 object'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 object'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 object 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         BLI_remlink(&ob->modifiers, md);
766         modifier_free(md);
767
768         BIF_undo_push("Apply modifier");
769 }
770
771 static void modifiers_copyModifier(void *ob_v, void *md_v)
772 {
773         Object *ob = ob_v;
774         ModifierData *md = md_v;
775         ModifierData *nmd = modifier_new(md->type);
776
777         modifier_copyData(md, nmd);
778
779         BLI_insertlink(&ob->modifiers, md, nmd);
780
781         BIF_undo_push("Copy modifier");
782 }
783
784 static void modifiers_setOnCage(void *ob_v, void *md_v)
785 {
786         Object *ob = ob_v;
787         ModifierData *md;
788         
789         for (md=ob->modifiers.first; md; md=md->next)
790                 if (md!=md_v)
791                         md->mode &= ~eModifierMode_OnCage;
792
793         md = md_v;
794         md->mode ^= eModifierMode_OnCage;
795 }
796
797 static void modifiers_setSubsurfIncremental(void *ob_v, void *md_v)
798 {
799         Object *ob = ob_v;
800         ModifierData *md = md_v;
801         SubsurfModifierData *smd = (SubsurfModifierData*) md;
802                         
803         if ((smd->flags&eSubsurfModifierFlag_Incremental) && ob->type==OB_MESH) {
804                 Mesh *me = ob->data;
805
806                 if (!me->medge) {
807                         if (okee("Requires mesh edges, create now?")) {
808                                 make_edges(me);
809                         }
810                 }
811         }
812 }
813
814 static void modifiers_clearHookOffset(void *ob_v, void *md_v)
815 {
816         Object *ob = ob_v;
817         ModifierData *md = md_v;
818         HookModifierData *hmd = (HookModifierData*) md;
819         
820         if (hmd->object) {
821                 Mat4Invert(hmd->object->imat, hmd->object->obmat);
822                 Mat4MulSerie(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
823                 BIF_undo_push("Clear hook");
824         }
825 }
826
827 static void modifiers_cursorHookCenter(void *ob_v, void *md_v)
828 {
829         Object *ob = ob_v;
830         ModifierData *md = md_v;
831         HookModifierData *hmd = (HookModifierData*) md;
832
833         if (G.vd) {
834                 float *curs = give_cursor();
835                 float bmat[3][3], imat[3][3];
836
837                 where_is_object(ob);
838         
839                 Mat3CpyMat4(bmat, ob->obmat);
840                 Mat3Inv(imat, bmat);
841
842                 curs= give_cursor();
843                 hmd->cent[0]= curs[0]-ob->obmat[3][0];
844                 hmd->cent[1]= curs[1]-ob->obmat[3][1];
845                 hmd->cent[2]= curs[2]-ob->obmat[3][2];
846                 Mat3MulVecfl(imat, hmd->cent);
847
848                 BIF_undo_push("Hook cursor center");
849         }
850 }
851
852 static void modifiers_selectHook(void *ob_v, void *md_v)
853 {
854         ModifierData *md = md_v;
855         HookModifierData *hmd = (HookModifierData*) md;
856
857         hook_select(hmd);
858 }
859
860 static void modifiers_reassignHook(void *ob_v, void *md_v)
861 {
862         ModifierData *md = md_v;
863         HookModifierData *hmd = (HookModifierData*) md;
864         float cent[3];
865         int *indexar, tot = hook_getIndexArray(&indexar, cent);
866
867         if (!tot) {
868                 error("Requires selected vertices");
869         } else {
870                 if (hmd->indexar) {
871                         MEM_freeN(hmd->indexar);
872                 }
873
874                 VECCOPY(hmd->cent, cent);
875                 hmd->indexar = indexar;
876                 hmd->totindex = tot;
877         }
878 }
879
880 static void modifiers_convertToReal(void *ob_v, void *md_v)
881 {
882         Object *ob = ob_v;
883         ModifierData *md = md_v;
884         ModifierData *nmd = modifier_new(md->type);
885
886         modifier_copyData(md, nmd);
887         nmd->mode &= ~eModifierMode_Virtual;
888
889         BLI_addhead(&ob->modifiers, nmd);
890
891         ob->partype = PAROBJECT;
892
893         BIF_undo_push("Modifier convert to real");
894 }
895
896 static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco, int *yco, int index, int cageIndex, int lastCageIndex)
897 {
898         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
899         uiBut *but;
900         int isVirtual = md->mode&eModifierMode_Virtual;
901         int x = *xco, y = *yco, color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
902         int editing = (G.obedit==ob);
903     short height=26, width = 295, buttonWidth = width-120-10;
904         char str[128];
905
906         /* rounded header */
907         uiBlockSetCol(block, color);
908                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
909         uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 26, NULL, 7.0, 0.0, 
910                          md->mode&eModifierMode_Expanded?3:15, -20, ""); 
911         uiBlockSetCol(block, TH_AUTO);
912         
913         /* open/close icon */
914         if (isVirtual) {
915                 uiSetButLock(1, "Modifier is virtual and cannot be edited.");
916                 color = TH_BUT_SETTING1;
917         } else {
918                 uiBlockSetEmboss(block, UI_EMBOSSN);
919                 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");
920         }
921
922         uiBlockSetEmboss(block, UI_EMBOSS);
923         
924         if (isVirtual) {
925                 sprintf(str, "%s (virtual)", md->name);
926                 uiDefBut(block, LABEL, 0, str, x+10, y-1, buttonWidth-60, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
927
928                 uiClearButLock();
929
930                 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");
931                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
932                 uiSetButLock(1, "Modifier is virtual and cannot be edited.");
933         } else {
934                 uiBlockBeginAlign(block);
935                 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"); 
936
937                         /* Softbody not allowed in this situation, enforce! */
938                 if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
939                         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");
940                         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");
941                         if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
942                                 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)");
943                         }
944                 }
945                 uiBlockEndAlign(block);
946
947                 uiBlockSetEmboss(block, UI_EMBOSSR);
948
949                 if (ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
950                         int icon, color;
951
952                         if (index==cageIndex) {
953                                 color = TH_BUT_SETTING;
954                                 icon = VICON_EDITMODE_HLT;
955                         } else if (index<cageIndex) {
956                                 color = TH_BUT_NEUTRAL;
957                                 icon = VICON_EDITMODE_DEHLT;
958                         } else {
959                                 color = TH_BUT_NEUTRAL;
960                                 icon = ICON_BLANK1;
961                         }
962                         uiBlockSetCol(block, color);
963                         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");
964                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
965                         uiBlockSetCol(block, TH_AUTO);
966                 }
967
968                 uiBlockSetCol(block, TH_BUT_ACTION);
969
970                 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");
971                 uiButSetFunc(but, modifiers_moveUp, ob, md);
972
973                 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");
974                 uiButSetFunc(but, modifiers_moveDown, ob, md);
975                 
976                 uiBlockSetEmboss(block, UI_EMBOSSN);
977
978                 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");
979                 uiButSetFunc(but, modifiers_del, ob, md);
980                 uiBlockSetCol(block, TH_AUTO);
981         }
982
983         uiBlockSetEmboss(block, UI_EMBOSS);
984
985         if (!(md->mode&eModifierMode_Expanded)) {
986                 y -= 18;
987         } else {
988                 int cy = y - 8;
989                 int lx = x + width - 60 - 15;
990
991                 if (md->type==eModifierType_Subsurf) {
992                         height = 106;
993                 } else if (md->type==eModifierType_Lattice) {
994                         height = 46;
995                 } else if (md->type==eModifierType_Curve) {
996                         height = 46;
997                 } else if (md->type==eModifierType_Build) {
998                         height = 86;
999                 } else if (md->type==eModifierType_Mirror) {
1000                         height = 46;
1001                 } else if (md->type==eModifierType_Decimate) {
1002                         height = 46;
1003                 } else if (md->type==eModifierType_Wave) {
1004                         height = 200;
1005                 } else if (md->type==eModifierType_Armature) {
1006                         height = 46;
1007                 } else if (md->type==eModifierType_Hook) {
1008                         height = 86;
1009                         if (editing)
1010                                 height += 20;
1011                 } else if (md->type==eModifierType_Softbody) {
1012                         height = 26;
1013                 }
1014
1015                                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1016                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 0, ""); 
1017
1018                 y -= 18;
1019
1020                 if (!isVirtual) {
1021                         uiBlockBeginAlign(block);
1022                         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");
1023                         uiButSetFunc(but, modifiers_applyModifier, ob, md);
1024                         if (md->type!=eModifierType_Softbody) {
1025                                 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");
1026                                 uiButSetFunc(but, modifiers_copyModifier, ob, md);
1027                         }
1028                         uiBlockEndAlign(block);
1029                 }
1030
1031                 lx = x + 10;
1032                 cy = y + 10 - 1;
1033                 uiBlockBeginAlign(block);
1034                 if (md->type==eModifierType_Subsurf) {
1035                         SubsurfModifierData *smd = (SubsurfModifierData*) md;
1036                         char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
1037                         uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu,          lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
1038                         uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:",             lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
1039                         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");
1040
1041                         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");
1042                         uiButSetFunc(but, modifiers_setSubsurfIncremental, ob, md);
1043
1044                         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");
1045
1046                         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");
1047                 } else if (md->type==eModifierType_Lattice) {
1048                         LatticeModifierData *lmd = (LatticeModifierData*) md;
1049                         uiDefIDPoinBut(block, modifier_testLatticeObj, B_CHANGEDEP, "Ob: ",     lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
1050                 } else if (md->type==eModifierType_Curve) {
1051                         CurveModifierData *cmd = (CurveModifierData*) md;
1052                         uiDefIDPoinBut(block, modifier_testCurveObj, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
1053                 } else if (md->type==eModifierType_Build) {
1054                         BuildModifierData *bmd = (BuildModifierData*) md;
1055                         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");
1056                         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");
1057                         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.");
1058                         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.");
1059                 } else if (md->type==eModifierType_Mirror) {
1060                         MirrorModifierData *mmd = (MirrorModifierData*) md;
1061                         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");
1062                         uiDefButI(block, ROW, B_MODIFIER_RECALC, "X",   lx, (cy-=19), 20,19, &mmd->axis, 1, 0, 0, 0, "Specify the axis to mirror about");
1063                         uiDefButI(block, ROW, B_MODIFIER_RECALC, "Y",   lx+20, cy, 20,19, &mmd->axis, 1, 1, 0, 0, "Specify the axis to mirror about");
1064                         uiDefButI(block, ROW, B_MODIFIER_RECALC, "Z",   lx+40, cy, 20,19, &mmd->axis, 1, 2, 0, 0, "Specify the axis to mirror about");
1065                 } else if (md->type==eModifierType_Decimate) {
1066                         DecimateModifierData *dmd = (DecimateModifierData*) md;
1067                         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");
1068                         sprintf(str, "Face Count: %d", dmd->faceCount);
1069                         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");
1070                 } else if (md->type==eModifierType_Wave) {
1071                         WaveModifierData *wmd = (WaveModifierData*) md;
1072                         uiDefButBitS(block, TOG, WAV_X, B_MODIFIER_RECALC, "X",         lx,(cy-=19),45,19, &wmd->flag, 0, 0, 0, 0, "Enable X axis motion");
1073                         uiDefButBitS(block, TOG, WAV_Y, B_MODIFIER_RECALC, "Y",         lx+45,cy,45,19, &wmd->flag, 0, 0, 0, 0, "Enable Y axis motion");
1074                         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");
1075                         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");
1076                         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");
1077                         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");
1078                         cy -= 19;
1079                         uiBlockBeginAlign(block);
1080                         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");
1081                         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");
1082                         uiBlockBeginAlign(block);
1083                         uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Speed:",   lx,(cy-=19),220,19, &wmd->speed, -2.0, 2.0, 0, 0, "Specify the wave speed");
1084                         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");
1085                         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");
1086                         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");
1087                 } else if (md->type==eModifierType_Armature) {
1088                         ArmatureModifierData *amd = (ArmatureModifierData*) md;
1089                         uiDefIDPoinBut(block, modifier_testArmatureObj, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
1090                 } else if (md->type==eModifierType_Hook) {
1091                         HookModifierData *hmd = (HookModifierData*) md;
1092                         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");
1093                         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");
1094                         uiDefIDPoinBut(block, test_obpoin_but, B_CHANGEDEP, "Ob: ",     lx, (cy-=19), buttonWidth,19, &hmd->object, "Parent Object for hook, also recalculates and clears offset"); 
1095                         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");
1096                         uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
1097                         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");
1098                         uiButSetFunc(but, modifiers_cursorHookCenter, ob, md);
1099
1100                         if (editing) {
1101                                 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");
1102                                 uiButSetFunc(but, modifiers_selectHook, ob, md);
1103                                 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");
1104                                 uiButSetFunc(but, modifiers_reassignHook, ob, md);
1105                         }
1106                 } else if (md->type==eModifierType_Softbody) {
1107                         uiDefBut(block, LABEL, 1, "See Softbody panel.",        lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, "");
1108                 }
1109                 uiBlockEndAlign(block);
1110
1111                 y-=height;
1112         }
1113
1114         if (md->error) {
1115                 char str[512];
1116
1117                 y -= 20;
1118
1119                 uiBlockSetCol(block, color);
1120                                         /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
1121                 uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); 
1122                 uiBlockSetCol(block, TH_AUTO);
1123
1124                 sprintf(str, "Modifier Error: %s", md->error);
1125                 uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
1126         }
1127
1128         y -= 3+6;
1129
1130         *xco = x;
1131         *yco = y;
1132
1133         if (isVirtual) {
1134                 uiClearButLock();
1135         }
1136 }
1137
1138 static void editing_panel_modifiers(Object *ob)
1139 {
1140         ModifierData *md;
1141         uiBlock *block;
1142         char str[64];
1143         int xco, yco, i, lastCageIndex, cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
1144
1145         block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win);
1146         if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return;
1147
1148         uiNewPanelHeight(block, 204);
1149
1150         uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier");
1151
1152         sprintf(str, "To: %s", ob->id.name+2);
1153         uiDefBut(block, LABEL, 1, str,  140, 190, 140, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited");
1154
1155         xco = 0;
1156         yco = 160;
1157
1158         md = modifiers_getVirtualModifierList(ob);
1159
1160         for (i=0; md; i++, md=md->next) {
1161                 draw_modifier(block, ob, md, &xco, &yco, i, cageIndex, lastCageIndex);
1162                 if (md->mode&eModifierMode_Virtual) i--;
1163         }
1164         
1165         if(yco < 0) uiNewPanelHeight(block, 204-yco);
1166 }
1167
1168 /* *************************** FONT ******************************** */
1169
1170 static short give_vfontnr(VFont *vfont)
1171 {
1172         VFont *vf;
1173         short nr= 1;
1174
1175         vf= G.main->vfont.first;
1176         while(vf) {
1177                 if(vf==vfont) return nr;
1178                 nr++;
1179                 vf= vf->id.next;
1180         }
1181         return -1;
1182 }
1183
1184 static VFont *give_vfontpointer(int nr) /* nr= button */
1185 {
1186         VFont *vf;
1187         short tel= 1;
1188
1189         vf= G.main->vfont.first;
1190         while(vf) {
1191                 if(tel==nr) return vf;
1192                 tel++;
1193                 vf= vf->id.next;
1194         }
1195         return G.main->vfont.first;
1196 }
1197
1198 VFont *exist_vfont(char *str)
1199 {
1200         VFont *vf;
1201
1202         vf= G.main->vfont.first;
1203         while(vf) {
1204                 if(strcmp(vf->name, str)==0) return vf;
1205                 vf= vf->id.next;
1206         }
1207         return 0;
1208 }
1209
1210 static char *give_vfontbutstr(void)
1211 {
1212         VFont *vf;
1213         int len= 0;
1214         char *str, di[FILE_MAXDIR], fi[FILE_MAXFILE];
1215
1216         vf= G.main->vfont.first;
1217         while(vf) {
1218                 strcpy(di, vf->name);
1219                 BLI_splitdirstring(di, fi);
1220                 len+= strlen(fi)+4;
1221                 vf= vf->id.next;
1222         }
1223
1224         str= MEM_callocN(len+21, "vfontbutstr");
1225         strcpy(str, "FONTS %t");
1226         vf= G.main->vfont.first;
1227         while(vf) {
1228
1229                 if(vf->id.us==0) strcat(str, "|0 ");
1230                 else strcat(str, "|   ");
1231
1232                 strcpy(di, vf->name);
1233                 BLI_splitdirstring(di, fi);
1234
1235                 strcat(str, fi);
1236                 vf= vf->id.next;
1237         }
1238         return str;
1239 }
1240
1241 static void load_buts_vfont(char *name)
1242 {
1243         VFont *vf;
1244         Curve *cu;
1245
1246         if(OBACT && OBACT->type==OB_FONT) cu= OBACT->data;
1247         else return;
1248
1249         vf= exist_vfont(name);
1250         if(vf==0) {
1251                 vf= load_vfont(name);
1252                 if(vf==0) return;
1253         }
1254         else id_us_plus((ID *)vf);
1255         
1256         switch(cu->curinfo.flag & CU_STYLE) {
1257                 case CU_BOLD:
1258                         if(cu->vfontb) cu->vfontb->id.us--;
1259                         cu->vfontb= vf;
1260                         break;
1261                 case CU_ITALIC:
1262                         if(cu->vfonti) cu->vfonti->id.us--;             
1263                         cu->vfonti= vf;
1264                         break;                                          
1265                 case (CU_BOLD|CU_ITALIC):
1266                         if(cu->vfontbi) cu->vfontbi->id.us--;
1267                         cu->vfontbi= vf;
1268                         break;
1269                 default:
1270                         if(cu->vfont) cu->vfont->id.us--;
1271                         cu->vfont= vf;
1272                         break;                                          
1273         }       
1274
1275         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1276         BIF_undo_push("Load vector font");
1277         allqueue(REDRAWVIEW3D, 0);
1278         allqueue(REDRAWBUTSEDIT, 0);
1279 }
1280
1281 void do_fontbuts(unsigned short event)
1282 {
1283         Curve *cu;
1284         VFont *vf;
1285         Object *ob;
1286         ScrArea *sa;
1287         char str[80];
1288         int i;
1289
1290         ob= OBACT;
1291
1292         switch(event) {
1293         case B_MAKEFONT:
1294                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1295                 allqueue(REDRAWVIEW3D, 0);
1296                 break;
1297
1298         case B_STYLETOSEL:
1299                 if (style_to_sel()) {
1300                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1301                         allqueue(REDRAWVIEW3D, 0);
1302                 }
1303                 allqueue(REDRAWBUTSEDIT, 0);
1304                 break;
1305                 
1306         case B_FASTFONT:
1307                 if (G.obedit) {
1308                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1309                         allqueue(REDRAWVIEW3D, 0);
1310                 }
1311                 break;
1312         case B_INSTB:
1313                 cu= ob->data;
1314                 if (cu->totbox < 256) {
1315                         for (i = cu->totbox; i>cu->actbox; i--) cu->tb[i]= cu->tb[i-1];
1316                         cu->tb[cu->actbox]= cu->tb[cu->actbox-1];
1317                         cu->actbox++;
1318                         cu->totbox++;
1319                         allqueue(REDRAWBUTSEDIT, 0);
1320                         allqueue(REDRAWVIEW3D, 0);
1321                         text_to_curve(ob, 0);
1322                         makeDispListCurveTypes(ob, 0);
1323                 }
1324                 else {
1325                         error("Do you really need that many text frames?");
1326                 }
1327                 break;
1328         case B_DELTB:
1329                 cu= ob->data;
1330                 if (cu->totbox > 1) {
1331                         for (i = cu->actbox-1; i < cu->totbox; i++) cu->tb[i]= cu->tb[i+1];
1332                         cu->totbox--;
1333                         cu->actbox--;
1334                         allqueue(REDRAWBUTSEDIT, 0);
1335                         allqueue(REDRAWVIEW3D, 0);
1336                         text_to_curve(ob, 0);
1337                         makeDispListCurveTypes(ob, 0);
1338                 }
1339                 break;
1340         case B_TOUPPER:
1341                 to_upper();
1342                 break;
1343         case B_LOADFONT:
1344                 vf= give_vfontpointer(G.buts->texnr);
1345                 if(vf && vf->id.prev!=vf->id.next) strcpy(str, vf->name);
1346                 else strcpy(str, U.fontdir);
1347
1348                 sa= closest_bigger_area();
1349                 areawinset(sa->win);
1350
1351                 activate_fileselect(FILE_SPECIAL, "SELECT FONT", str, load_buts_vfont);
1352
1353                 break;
1354         case B_PACKFONT:
1355                 if (ob) {
1356                         cu= ob->data;
1357                         if(cu && cu->vfont) {
1358                                 if (cu->vfont->packedfile) {
1359                                         if (G.fileflags & G_AUTOPACK) {
1360                                                 if (okee("Disable AutoPack ?")) {
1361                                                         G.fileflags &= ~G_AUTOPACK;
1362                                                 }
1363                                         }
1364
1365                                         if ((G.fileflags & G_AUTOPACK) == 0) {
1366                                                 if (unpackVFont(cu->vfont, PF_ASK) == RET_OK) {
1367                                                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1368                                                         allqueue(REDRAWVIEW3D, 0);
1369                                                 }
1370                                         }
1371                                 } else {
1372                                         cu->vfont->packedfile = newPackedFile(cu->vfont->name);
1373                                 }
1374                         }
1375                 }
1376                 allqueue(REDRAWHEADERS, 0);
1377                 allqueue(REDRAWBUTSEDIT, 0);
1378                 break;
1379
1380         case B_LOAD3DTEXT:
1381                 if (!G.obedit) { error("Only in editmode!"); return; }
1382                 if (G.obedit->type != OB_FONT) return;  
1383                 activate_fileselect(FILE_SPECIAL, "Open Text File", G.sce, load_3dtext_fs);
1384                 break;
1385                 
1386         case B_LOREM:
1387                 if (!G.obedit) { error("Only in editmode!"); return; }
1388                 if (G.obedit->type != OB_FONT) return;  
1389                 add_lorem();
1390                 
1391                 break;          
1392
1393         case B_SETFONT:
1394                 if(ob) {
1395                         cu= ob->data;
1396
1397                         vf= give_vfontpointer(G.buts->texnr);
1398                         if(vf) {
1399                                 id_us_plus((ID *)vf);
1400
1401                                 switch(cu->curinfo.flag & CU_STYLE) {
1402                                         case CU_BOLD:
1403                                                 cu->vfontb->id.us--;
1404                                                 cu->vfontb= vf;
1405                                                 break;
1406                                         case CU_ITALIC:
1407                                                 cu->vfonti->id.us--;
1408                                                 cu->vfonti= vf;
1409                                                 break;                                          
1410                                         case (CU_BOLD|CU_ITALIC):
1411                                                 cu->vfontbi->id.us--;
1412                                                 cu->vfontbi= vf;
1413                                                 break;
1414                                         default:
1415                                                 cu->vfont->id.us--;
1416                                                 cu->vfont= vf;
1417                                                 break;                                          
1418                                 }
1419                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1420
1421                                 BIF_undo_push("Set vector font");
1422                                 allqueue(REDRAWVIEW3D, 0);
1423                                 allqueue(REDRAWBUTSEDIT, 0);
1424                         }
1425                 }
1426                 break;
1427         case B_TEXTONCURVE:
1428                 if(ob) {
1429                         cu= ob->data;
1430                         if(cu->textoncurve && cu->textoncurve->type!=OB_CURVE) {
1431                                 error("Only Curve Objects");
1432                                 cu->textoncurve= 0;
1433                                 allqueue(REDRAWBUTSEDIT, 0);
1434                         }
1435                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1436                         allqueue(REDRAWVIEW3D, 0);
1437                 }
1438         }
1439 }
1440
1441 static void editing_panel_font_type(Object *ob, Curve *cu)
1442 {
1443         uiBlock *block;
1444         char *strp;
1445         static int packdummy = 0;
1446         char str[32];
1447
1448         block= uiNewBlock(&curarea->uiblocks, "editing_panel_font_type", UI_EMBOSS, UI_HELV, curarea->win);
1449         if(uiNewPanel(curarea, block, "Font", "Editing", 640, 0, 470, 204)==0) return;
1450
1451         switch(cu->curinfo.flag & CU_STYLE) {
1452                 case CU_BOLD:
1453                         G.buts->texnr= give_vfontnr(cu->vfontb);
1454                         break;
1455                 case CU_ITALIC:
1456                         G.buts->texnr= give_vfontnr(cu->vfonti);
1457                         break;                                          
1458                 case (CU_BOLD|CU_ITALIC):
1459                         G.buts->texnr= give_vfontnr(cu->vfontbi);
1460                         break;
1461                 default:
1462                         G.buts->texnr= give_vfontnr(cu->vfont);
1463                         break;                                          
1464         }       
1465
1466         strp= give_vfontbutstr();
1467 //      vfd= cu->vfont->data;
1468
1469         uiDefBut(block, BUT,B_LOADFONT, "Load", 480,188,68,20, 0, 0, 0, 0, 0, "Load a new font");
1470         uiDefButS(block, MENU, B_SETFONT, strp, 550,188,220,20, &G.buts->texnr, 0, 0, 0, 0, "Change font for object");
1471
1472         if (cu->vfont->packedfile) {
1473                 packdummy = 1;
1474         } else {
1475                 packdummy = 0;
1476         }
1477         uiDefIconButI(block, TOG|BIT|0, B_PACKFONT, ICON_PACKAGE,       772,188,20,20, &packdummy, 0, 0, 0, 0, "Pack/Unpack this font");
1478
1479         /* This doesn't work anyway */
1480 //      uiDefBut(block, LABEL, 0, vfd->name,  480, 165,314,20, 0, 0, 0, 0, 0, "Postscript name of the font");
1481
1482         uiDefBut(block, BUT, B_LOAD3DTEXT, "Insert Text", 480, 165, 90, 20, 0, 0, 0, 0, 0, "Insert text file at cursor");
1483         uiDefBut(block, BUT, B_LOREM, "Lorem", 575, 165, 70, 20, 0, 0, 0, 0, 0, "Insert a paragraph of Lorem Ipsum at cursor"); 
1484         uiBlockBeginAlign(block);
1485         uiDefButBitC(block, TOG, CU_BOLD, B_STYLETOSEL, "B",            752,165,20,20, &(cu->curinfo.flag), 0,0, 0, 0, "");
1486         uiDefButBitC(block, TOG, CU_ITALIC, B_STYLETOSEL, "i",          772,165,20,20, &(cu->curinfo.flag), 0, 0, 0, 0, "");    
1487         uiBlockEndAlign(block);
1488
1489         MEM_freeN(strp);
1490
1491         uiBlockBeginAlign(block);
1492         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");
1493         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");
1494         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");
1495         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");
1496         uiDefButS(block, ROW,B_MAKEFONT, "Flush",               668,135,47,20, &cu->spacemode, 0.0,4.0, 0, 0, "Always fill to maximum textframe width");        
1497         uiDefBut(block, BUT, B_TOUPPER, "ToUpper",              715,135,78,20, 0, 0, 0, 0, 0, "Toggle between upper and lower case in editmode");
1498         uiBlockEndAlign(block);
1499         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");     
1500
1501         uiDefIDPoinBut(block, test_obpoin_but, B_TEXTONCURVE, "TextOnCurve:",   480,105,220,19, &cu->textoncurve, "Apply a deforming curve to the text");
1502         uiDefBut(block, TEX,REDRAWVIEW3D, "Ob Family:", 480,84,220,19, cu->family, 0.0, 20.0, 0, 0, "Blender uses font from selfmade objects");
1503
1504         uiBlockBeginAlign(block);
1505         uiDefButF(block, NUM,B_MAKEFONT, "Size:",               480,56,155,20, &cu->fsize, 0.1,10.0, 10, 0, "Size of the text");
1506         uiDefButF(block, NUM,B_MAKEFONT, "Linedist:",   640,56,155,20, &cu->linedist, 0.0,10.0, 10, 0, "Distance between text lines");
1507         uiDefButF(block, NUM,B_MAKEFONT, "Word spacing:",       795,56,155,20, &cu->wordspace, 0.0,10.0, 10, 0, "Distance factor between words");               
1508         uiDefButF(block, NUM,B_MAKEFONT, "Spacing:",    480,34,155,20, &cu->spacing, 0.0,10.0, 10, 0, "Spacing of individual characters");
1509         uiDefButF(block, NUM,B_MAKEFONT, "X offset:",   640,34,155,20, &cu->xof, -50.0,50.0, 10, 0, "Horizontal position from object centre");
1510         uiDefButF(block, NUM,B_MAKEFONT, "Shear:",              480,12,155,20, &cu->shear, -1.0,1.0, 10, 0, "Italic angle of the characters");
1511         uiDefButF(block, NUM,B_MAKEFONT, "Y offset:",   640,12,155,20, &cu->yof, -50.0,50.0, 10, 0, "Vertical position from object centre");
1512         uiBlockEndAlign(block);
1513         
1514         sprintf(str, "%d TextFrame: ", cu->totbox);
1515         uiBlockBeginAlign(block);
1516         uiDefButI(block, NUM, REDRAWVIEW3D, str, 805, 188, 145, 20, &cu->actbox, 1.0, cu->totbox, 0, 10, "Textbox to show settings for");
1517         uiDefBut(block, BUT,B_INSTB, "Insert", 805, 168, 72, 20, 0, 0, 0, 0, 0, "Insert a new text frame after the current one");
1518         uiDefBut(block, BUT,B_DELTB, "Delete", 877, 168, 73, 20, 0, 0, 0, 0, 0, "Delete current text frame and shift the others up");   
1519         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");
1520         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");     
1521         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");
1522         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");         
1523         uiBlockEndAlign(block);
1524 }
1525
1526
1527 /* *************************** CURVE ******************************** */
1528
1529
1530 void do_curvebuts(unsigned short event)
1531 {
1532         extern Nurb *lastnu;
1533         extern ListBase editNurb;  /* from editcurve */
1534         Object *ob;
1535         Curve *cu;
1536         Nurb *nu;
1537
1538         ob= OBACT;
1539         if(ob==0) return;
1540
1541         switch(event) {
1542
1543         case B_CONVERTPOLY:
1544         case B_CONVERTBEZ:
1545         case B_CONVERTBSPL:
1546         case B_CONVERTCARD:
1547         case B_CONVERTNURB:
1548                 if(G.obedit) {
1549                         setsplinetype(event-B_CONVERTPOLY);
1550                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1551                         allqueue(REDRAWVIEW3D, 0);
1552                 }
1553                 break;
1554         case B_UNIFU:
1555         case B_ENDPU:
1556         case B_BEZU:
1557         case B_UNIFV:
1558         case B_ENDPV:
1559         case B_BEZV:
1560                 if(G.obedit) {
1561                         nu= editNurb.first;
1562                         while(nu) {
1563                                 if(isNurbsel(nu)) {
1564                                         if((nu->type & 7)==CU_NURBS) {
1565                                                 if(event<B_UNIFV) {
1566                                                         nu->flagu &= 1;
1567                                                         nu->flagu += ((event-B_UNIFU)<<1);
1568                                                         makeknots(nu, 1, nu->flagu>>1);
1569                                                 }
1570                                                 else if(nu->pntsv>1) {
1571                                                         nu->flagv &= 1;
1572                                                         nu->flagv += ((event-B_UNIFV)<<1);
1573                                                         makeknots(nu, 2, nu->flagv>>1);
1574                                                 }
1575                                         }
1576                                 }
1577                                 nu= nu->next;
1578                         }
1579                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1580                         allqueue(REDRAWVIEW3D, 0);
1581                 }
1582                 break;
1583         case B_SETWEIGHT:
1584                 if(G.obedit) {
1585                         weightflagNurb(1, editbutweight, 0);
1586                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1587                         allqueue(REDRAWVIEW3D, 0);
1588                 }
1589                 break;
1590         case B_SETW1:
1591                 editbutweight= 1.0;
1592                 scrarea_queue_winredraw(curarea);
1593                 break;
1594         case B_SETW2:
1595                 editbutweight= sqrt(2.0)/4.0;
1596                 scrarea_queue_winredraw(curarea);
1597                 break;
1598         case B_SETW3:
1599                 editbutweight= 0.25;
1600                 scrarea_queue_winredraw(curarea);
1601                 break;
1602         case B_SETW4:
1603                 editbutweight= sqrt(0.5);
1604                 scrarea_queue_winredraw(curarea);
1605                 break;
1606         case B_SETORDER:
1607                 if(G.obedit) {
1608                         nu= lastnu;
1609                         if(nu && (nu->type & 7)==CU_NURBS ) {
1610                                 if(nu->orderu>nu->pntsu) {
1611                                         nu->orderu= nu->pntsu;
1612                                         scrarea_queue_winredraw(curarea);
1613                                 }
1614                                 makeknots(nu, 1, nu->flagu>>1);
1615                                 if(nu->orderv>nu->pntsv) {
1616                                         nu->orderv= nu->pntsv;
1617                                         scrarea_queue_winredraw(curarea);
1618                                 }
1619                                 makeknots(nu, 2, nu->flagv>>1);
1620                         }
1621                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1622                         allqueue(REDRAWVIEW3D, 0);
1623                 }
1624                 break;
1625         case B_SUBSURFTYPE:
1626                 /* fallthrough */
1627         case B_MAKEDISP:
1628                 if(G.vd) {
1629                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1630                         allqueue(REDRAWVIEW3D, 0);
1631                         allqueue(REDRAWINFO, 1);        /* 1, because header->win==0! */
1632                 }
1633                 break;
1634
1635         case B_SUBDIVCURVE:
1636                 subdivideNurb();
1637                 break;
1638         case B_SPINNURB:
1639                 if( (G.obedit==NULL) || (G.obedit->type!=OB_SURF) || (G.vd==NULL) ||
1640                         ((G.obedit->lay & G.vd->lay) == 0) ) return;
1641                 spinNurb(0, 0);
1642                 countall();
1643                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
1644                 allqueue(REDRAWVIEW3D, 0);
1645                 break;
1646         case B_CU3D:        /* allow 3D curve */
1647                 if(G.obedit) {
1648                         cu= G.obedit->data;
1649                         nu= editNurb.first;
1650                         while(nu) {
1651                                 nu->type &= ~CU_2D;
1652                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
1653                                 test2DNurb(nu);
1654                                 nu= nu->next;
1655                         }
1656                 }
1657                 if(ob->type==OB_CURVE) {
1658                         cu= ob->data;
1659                         nu= cu->nurb.first;
1660                         while(nu) {
1661                                 nu->type &= ~CU_2D;
1662                                 if((cu->flag & CU_3D)==0) nu->type |= CU_2D;
1663                                 test2DNurb(nu);
1664                                 nu= nu->next;
1665                         }
1666                 }
1667                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1668                 allqueue(REDRAWVIEW3D, 0);
1669                 break;
1670         case B_SETRESOLU:
1671                 if(ob->type==OB_CURVE) {
1672                         cu= ob->data;
1673                         if(ob==G.obedit) nu= editNurb.first;
1674                         else nu= cu->nurb.first;
1675
1676                         while(nu) {
1677                                 nu->resolu= cu->resolu;
1678                                 nu= nu->next;
1679                         }
1680                 }
1681
1682                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1683                 allqueue(REDRAWVIEW3D, 0);
1684
1685                 break;
1686         }
1687 }
1688
1689 static void editing_panel_curve_tools(Object *ob, Curve *cu)
1690 {
1691         Nurb *nu;
1692         extern ListBase editNurb;  /* from editcurve */
1693         extern Nurb *lastnu;
1694         uiBlock *block;
1695         short *sp;
1696
1697         block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_tools", UI_EMBOSS, UI_HELV, curarea->win);
1698         if(uiNewPanel(curarea, block, "Curve Tools", "Editing", 640, 0, 318, 204)==0) return;
1699
1700         uiDefBut(block, LABEL, 0, "Make Knots",562,173,102, 18, 0, 0, 0, 0, 0, "");
1701
1702         if(ob->type==OB_CURVE) {
1703                 uiDefBut(block, LABEL, 0, "Convert",    463,173,72, 18, 0, 0, 0, 0, 0, "");
1704                 uiBlockBeginAlign(block);
1705                 uiDefBut(block, BUT,B_CONVERTPOLY,"Poly",               467,152,72, 18, 0, 0, 0, 0, 0, "Converts selected into regular Polygon vertices");
1706                 uiDefBut(block, BUT,B_CONVERTBEZ,"Bezier",              467,132,72, 18, 0, 0, 0, 0, 0, "Converts selected to Bezier triples");
1707                 uiDefBut(block, BUT,B_CONVERTNURB,"Nurb",               467,112,72, 18, 0, 0, 0, 0, 0, "Converts selected to Nurbs Points");
1708         }
1709         uiBlockBeginAlign(block);
1710         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");
1711         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");
1712         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");
1713         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");
1714         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");
1715         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");
1716         uiBlockEndAlign(block);
1717
1718         uiDefBut(block, BUT,B_SETWEIGHT,"Set Weight",   465,11,95,49, 0, 0, 0, 0, 0, "Nurbs only; set weight for select points");
1719
1720         uiBlockBeginAlign(block);
1721         uiDefButF(block, NUM,0,"Weight:",               565,36,102,22, &editbutweight, 0.01, 100.0, 10, 0, "The weight you can assign");
1722         uiDefBut(block, BUT,B_SETW1,"1.0",              670,36,50,22, 0, 0, 0, 0, 0, "");
1723         uiDefBut(block, BUT,B_SETW2,"sqrt(2)/4",565,11,55,20, 0, 0, 0, 0, 0, "");
1724         uiDefBut(block, BUT,B_SETW3,"0.25",             620,11,45,20, 0, 0, 0, 0, 0, "");
1725         uiDefBut(block, BUT,B_SETW4,"sqrt(0.5)",665,11,55,20, 0, 0, 0, 0, 0, "");
1726         uiBlockEndAlign(block);
1727
1728         if(ob==G.obedit) {
1729                 nu= lastnu;
1730                 if(nu==NULL) nu= editNurb.first;
1731                 if(nu) {
1732                         uiBlockBeginAlign(block);
1733                         sp= &(nu->orderu);
1734                         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");
1735                         sp= &(nu->orderv);
1736                         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");
1737                         sp= &(nu->resolu);
1738                         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");
1739                         sp= &(nu->resolv);
1740                         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");
1741                 }
1742         }
1743
1744
1745 }
1746
1747 static void editing_panel_curve_tools1(Object *ob, Curve *cu)
1748 {
1749         uiBlock *block;
1750
1751         block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_tools1", UI_EMBOSS, UI_HELV, curarea->win);
1752         if(uiNewPanel(curarea, block, "Curve Tools1", "Editing", 960, 0, 318, 204)==0) return;
1753
1754         uiDefBut(block, BUT, B_SUBDIVCURVE, "Subdivide", 400,180,150,20, 0, 0, 0, 0, 0, "Subdivide selected");
1755         if(ob->type==OB_SURF) {
1756                 uiDefBut(block, BUT, B_SPINNURB, "Spin",         400,160,150,20, 0, 0, 0, 0, 0, "Spin selected 360 degrees");
1757         }
1758         uiBlockBeginAlign(block);
1759         uiDefBut(block, BUT,B_HIDE,             "Hide",                 400,120,150,18, 0, 0, 0, 0, 0, "Hides selected faces");
1760         uiDefBut(block, BUT,B_REVEAL,   "Reveal",               400,100,150,18, 0, 0, 0, 0, 0, "Reveals selected faces");
1761         uiDefBut(block, BUT,B_SELSWAP,  "Select Swap",  400,80,150,18, 0, 0, 0, 0, 0, "Selects unselected faces, and deselects selected faces");
1762         uiBlockEndAlign(block);
1763
1764         uiDefButF(block, NUM,   REDRAWVIEW3D, "NSize:", 400, 40, 150, 19, &G.scene->editbutsize, 0.001, 1.0, 10, 0, "Normal size for drawing");
1765 }
1766
1767 /* for curve, surf and font! */
1768 static void editing_panel_curve_type(Object *ob, Curve *cu)
1769 {
1770         uiBlock *block;
1771
1772         block= uiNewBlock(&curarea->uiblocks, "editing_panel_curve_type", UI_EMBOSS, UI_HELV, curarea->win);
1773         if(uiNewPanel(curarea, block, "Curve and Surface", "Editing", 320, 0, 318, 204)==0) return;
1774
1775         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'");
1776         if(ob->type==OB_SURF)
1777                 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");
1778
1779         uiBlockBeginAlign(block);
1780         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");
1781         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");
1782         uiDefBut(block, BUT,B_DOCENTRECURSOR, "Centre Cursor",          600, 75, 150, 19, 0, 0, 0, 0, 0, "Shifts object's origin to cursor location");
1783         uiBlockEndAlign(block);
1784
1785         if(ob->type==OB_SURF) {
1786                 if(cu->key) {
1787                         /* uiDefButS(block, NUM, B_DIFF, "Slurph:",                     600,25,140,19, &(cu->key->slurph), -500.0, 500.0,0,0); ,""*/
1788                         uiDefButS(block, TOG, B_RELKEY, "Relative Keys",        600,45,140,19, &cu->key->type, 0, 0, 0, 0, "");
1789                 }
1790         }
1791
1792         if(ob->type!=OB_SURF) {
1793         
1794                 if(ob->type==OB_CURVE) {
1795                         extern float prlen;             // buttons_object.c, should be moved....
1796                         char str[32];
1797                         
1798                         sprintf(str, "%.4f", prlen);
1799                         uiDefBut(block, BUT, B_PRINTLEN,                "PrintLen",     600,135,75,19, 0, 0, 0, 0, 0, "");
1800                         uiDefBut(block, LABEL, 0, str,                                          675,135,75,19, 0, 1.0, 0, 0, 0, "");
1801                         
1802                         uiBlockBeginAlign(block);
1803                         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");
1804                         uiDefButBitS(block, TOG, CU_PATH, B_RECALCPATH, "CurvePath",    600,30,75,19 , &cu->flag, 0, 0, 0, 0, "Enables curve to become translation path");
1805                         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");
1806                         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");
1807                         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");
1808
1809                         uiBlockEndAlign(block);
1810                 }
1811
1812                 uiBlockBeginAlign(block);
1813                 uiDefButS(block, NUM, B_MAKEDISP, "DefResolU:", 760,160,120,19, &cu->resolu, 1.0, 1024.0, 0, 0, "Default resolution");
1814                 uiDefBut(block, BUT, B_SETRESOLU, "Set",                880,160,30,19, 0, 0, 0, 0, 0, "Set resolution for interpolation");
1815
1816                 uiBlockBeginAlign(block);
1817                 uiDefButF(block, NUM, B_MAKEDISP, "Width:",             760,90,150,19, &cu->width, 0.0, 2.0, 1, 0, "Make interpolated result thinner or fatter");
1818                 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");
1819                 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");
1820                 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");
1821                 uiDefIDPoinBut(block, test_obcurpoin_but, B_CHANGEDEP, "BevOb:",                760,10,150,19, &cu->bevobj, "Curve object name that defines the bevel shape");
1822                 uiDefIDPoinBut(block, test_obcurpoin_but, B_CHANGEDEP, "TaperOb:",              760,-10,150,19, &cu->taperobj, "Curve object name that defines the taper (width)");
1823
1824                 uiBlockBeginAlign(block);
1825                 uiBlockSetCol(block, TH_BUT_SETTING1);
1826                 uiDefButBitS(block, TOG, CU_BACK, B_MAKEDISP, "Back",   760,130,50,19, &cu->flag, 0, 0, 0, 0, "Draw filled back for curves");
1827                 uiDefButBitS(block, TOG, CU_FRONT, B_MAKEDISP, "Front",810,130,50,19, &cu->flag, 0, 0, 0, 0, "Draw filled front for curves");
1828                 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");
1829         }
1830 }
1831
1832
1833 /* *************************** CAMERA ******************************** */
1834
1835
1836 static void editing_panel_camera_type(Object *ob, Camera *cam)
1837 {
1838         uiBlock *block;
1839         float grid=0.0;
1840
1841         if(G.vd) grid= G.vd->grid;
1842         if(grid<1.0) grid= 1.0;
1843
1844         block= uiNewBlock(&curarea->uiblocks, "editing_panel_camera_type", UI_EMBOSS, UI_HELV, curarea->win);
1845         if(uiNewPanel(curarea, block, "Camera", "Editing", 320, 0, 318, 204)==0) return;
1846
1847         if(cam->type==CAM_ORTHO)
1848                 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");
1849         else
1850                 uiDefButF(block, NUM,REDRAWVIEW3D, "Lens:", 470,178,160,20, &cam->lens, 1.0, 250.0, 100, 0, "Specify the lens of the camera");
1851
1852         uiBlockBeginAlign(block);
1853         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");
1854         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");
1855         uiBlockEndAlign(block);
1856
1857         uiDefButF(block, NUM,REDRAWVIEW3D, "DrawSize:", 470,90,160,20, &cam->drawsize, 0.1*grid, 10.0, 10, 0, "Specify the drawsize of the camera");
1858
1859         uiDefButS(block, TOG, REDRAWVIEW3D, "Ortho",            470,29,61,60, &cam->type, 0, 0, 0, 0, "Render orthogonally");
1860         uiBlockBeginAlign(block);
1861         uiDefButBitS(block, TOG, CAM_SHOWLIMITS, REDRAWVIEW3D, "ShowLimits", 533,59,97,30, &cam->flag, 0, 0, 0, 0, "Draw the field of view");
1862         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");
1863         uiBlockEndAlign(block);
1864 }
1865
1866 /* yafray: extra camera panel to set Depth-of-Field parameters */
1867 static void editing_panel_camera_yafraydof(Object *ob, Camera *cam)
1868 {
1869         uiBlock *block;
1870         char *mst1, *mst2;
1871
1872         block= uiNewBlock(&curarea->uiblocks, "editing_panel_camera_yafraydof", UI_EMBOSS, UI_HELV, curarea->win);
1873         uiNewPanelTabbed("Camera", "Editing");
1874         if(uiNewPanel(curarea, block, "Yafray DoF", "Editing", 320, 0, 318, 204)==0) return;
1875
1876         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)");
1877         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)");
1878
1879         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");
1880
1881         uiDefBut(block, LABEL, 0, "Bokeh", 10, 60, 180, 19, 0, 0.0, 0.0, 0, 0, "");
1882         mst1 = "Bokeh Type%t|Disk1%x0|Disk2%x1|Triangle%x2|Square%x3|Pentagon%x4|Hexagon%x5|Ring%x6";
1883         uiDefButS(block, MENU, B_REDR, mst1, 10, 40, 89, 20, &cam->YF_bkhtype, 0.0, 0.0, 0, 0, "Sets Bokeh type");
1884         
1885         if ((cam->YF_bkhtype!=0) && (cam->YF_bkhtype!=6)) {
1886                 mst2 = "Bokeh Bias%t|Uniform%x0|Center%x1|Edge%x2";
1887                 uiDefButS(block, MENU, B_REDR, mst2, 100, 40, 90, 20, &cam->YF_bkhbias, 0.0, 0.0, 0, 0, "Sets Bokeh bias");
1888                 if (cam->YF_bkhtype>1)
1889                         uiDefButF(block, NUM, B_DIFF, "Rotation:", 10, 15, 180, 20, &cam->YF_bkhrot, 0.0, 360.0, 100, 0, "Shape rotation amount in degrees");
1890         }
1891
1892 }
1893
1894 /* **************************** CAMERA *************************** */
1895
1896 void do_cambuts(unsigned short event)
1897 {
1898         Object *ob;
1899         Camera *cam;
1900         
1901         ob= OBACT;
1902         if (ob==0) return;
1903         cam= ob->data;
1904
1905         switch(event) {
1906         case 0:
1907                 ;
1908                 break;
1909         }
1910 }
1911
1912 /* *************************** MBALL ******************************** */
1913
1914 void do_mballbuts(unsigned short event)
1915 {
1916         switch(event) {
1917         case B_RECALCMBALL:
1918                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
1919                 allqueue(REDRAWVIEW3D, 0);
1920                 break;
1921         }
1922 }
1923
1924 static void editing_panel_mball_type(Object *ob, MetaBall *mb)
1925 {
1926         uiBlock *block;
1927
1928         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mball_type", UI_EMBOSS, UI_HELV, curarea->win);
1929         if(uiNewPanel(curarea, block, "MetaBall", "Editing", 320, 0, 318, 204)==0) return;
1930
1931         ob= find_basis_mball(ob);
1932         mb= ob->data;
1933
1934         uiBlockBeginAlign(block);
1935         uiDefButF(block, NUM, B_RECALCMBALL, "Wiresize:", 470,178,250,19, &mb->wiresize, 0.05, 1.0, 1, 0, "Polygonization resolution in 3d window");
1936         uiDefButF(block, NUM, 0, "Rendersize:", 470,158,250,19, &mb->rendersize, 0.05, 1.0, 1, 0, "Polygonization resolution in rendering");
1937         uiDefButF(block, NUM, B_RECALCMBALL, "Threshold:", 470,138,250,19, &mb->thresh, 0.0001, 5.0, 1, 0, "Defines influence of meta elements");
1938
1939         uiBlockBeginAlign(block);
1940         uiBlockSetCol(block, TH_BUT_SETTING1);
1941         uiDefBut(block, LABEL, 0, "Update:", 471,108,120,19, 0, 0, 0, 0, 0, "");
1942         uiDefButS(block, ROW, B_DIFF, "Always", 471, 85, 120, 19, &mb->flag, 0.0, 0.0, 0, 0, "While editing, always updates");
1943         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");
1944         uiDefButS(block, ROW, B_DIFF, "Fast", 471, 45, 120, 19, &mb->flag, 0.0, 2.0, 0, 0, "While editing, updates without polygonization");
1945         uiDefButS(block, ROW, B_DIFF, "Never", 471, 25, 120, 19, &mb->flag, 0.0, 3.0, 0, 0, "While editing, doesn't update");
1946
1947 }
1948
1949 static void editing_panel_mball_tools(Object *ob, MetaBall *mb)
1950 {
1951         extern MetaElem *lastelem;
1952         uiBlock *block;
1953
1954         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mball_tools", UI_EMBOSS, UI_HELV, curarea->win);
1955         if( uiNewPanel(curarea, block, "MetaBall tools", "Editing", 640, 0, 318, 204)==0) return;
1956
1957         if(ob==G.obedit && lastelem) {
1958                 uiBlockBeginAlign(block);
1959                 uiDefButF(block, NUM, B_RECALCMBALL, "Stiffness:", 750,178,250,19, &lastelem->s, 0.0, 10.0, 1, 0, "Stiffness for active meta");
1960                 if(lastelem->type!=MB_BALL)
1961                 uiDefButF(block, NUM, B_RECALCMBALL, "dx:", 750,158,250,19, &lastelem->expx, 0.0, 20.0, 1, 0, "X size for active meta");
1962                 if((lastelem->type!=MB_BALL)&&(lastelem->type!=MB_TUBE))
1963                 uiDefButF(block, NUM, B_RECALCMBALL, "dy:", 750,138,250,19, &lastelem->expy, 0.0, 20.0, 1, 0, "Y size for active meta");
1964
1965                 if((lastelem->type==MB_CUBE)||(lastelem->type==MB_ELIPSOID))
1966                 uiDefButF(block, NUM, B_RECALCMBALL, "dz:", 750,118,250,19, &lastelem->expz, 0.0, 20.0, 1, 0, "Z size for active meta");
1967                 uiBlockEndAlign(block);
1968
1969                 uiDefButS(block, ROW, B_RECALCMBALL, "Ball", 753,83,60,19, &lastelem->type, 1.0, 0.0, 0, 0, "Draw active meta as Ball");
1970                 uiBlockBeginAlign(block);
1971                 uiDefButS(block, ROW, B_RECALCMBALL, "Tube", 753,62,60,19, &lastelem->type, 1.0, 4.0, 0, 0, "Draw active meta as Ball");
1972                 uiDefButS(block, ROW, B_RECALCMBALL, "Plane", 814,62,60,19, &lastelem->type, 1.0, 5.0, 0, 0, "Draw active meta as Plane");
1973                 uiDefButS(block, ROW, B_RECALCMBALL, "Elipsoid", 876,62,60,19, &lastelem->type, 1.0, 6.0, 0, 0, "Draw active meta as Ellipsoid");
1974                 uiDefButS(block, ROW, B_RECALCMBALL, "Cube", 938,62,60,19, &lastelem->type, 1.0, 7.0, 0, 0, "Draw active meta as Cube");
1975                 uiBlockEndAlign(block);
1976
1977                 uiBlockBeginAlign(block);
1978                 uiDefButBitS(block, TOG, MB_NEGATIVE, B_RECALCMBALL, "Negative",753,16,125,19, &lastelem->flag, 0, 0, 0, 0, "Make active meta creating holes");
1979                 uiDefButBitS(block, TOG, MB_HIDE, B_RECALCMBALL, "Hide",878,16,125,19, &lastelem->flag, 0, 0, 0, 0, "Make active meta invisible");
1980                 uiBlockEndAlign(block);
1981
1982         }
1983
1984 }
1985
1986
1987 /* *************************** LATTICE ******************************** */
1988
1989 void do_latticebuts(unsigned short event)
1990 {
1991         Object *ob;
1992         Lattice *lt;
1993
1994         ob= OBACT;
1995         if(ob->type!=OB_LATTICE) return;
1996
1997         switch(event) {
1998         case B_REGULARLAT:
1999                 if(ob) {
2000                         lt = ob->data;
2001                         if(ob==G.obedit) resizelattice(editLatt, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
2002                         else resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
2003                         ob->softflag |= OB_SB_REDO;
2004                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2005                         allqueue(REDRAWVIEW3D, 0);
2006                 }
2007         case B_RESIZELAT:
2008                 if(ob) {
2009                         lt = ob->data;
2010                         resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, ob);
2011                         ob->softflag |= OB_SB_REDO;
2012                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2013                         allqueue(REDRAWVIEW3D, 0);
2014                 }
2015                 break;
2016         case B_DRAWLAT:
2017                 allqueue(REDRAWVIEW3D, 0);
2018                 break;
2019         case B_LATTCHANGED:
2020
2021                 lt= ob->data;
2022                 if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
2023
2024                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2025
2026                 allqueue(REDRAWVIEW3D, 0);
2027
2028                 break;
2029         }
2030 }
2031
2032 static void editing_panel_lattice_type(Object *ob, Lattice *lt)
2033 {
2034         uiBlock *block;
2035
2036         block= uiNewBlock(&curarea->uiblocks, "editing_panel_lattice_type", UI_EMBOSS, UI_HELV, curarea->win);
2037         if(uiNewPanel(curarea, block, "Lattice", "Editing", 320, 0, 318, 204)==0) return;
2038
2039
2040         uiSetButLock(lt->key!=0, "Not with VertexKeys");
2041         uiSetButLock(ob==G.obedit, "Unable to perform function in EditMode");
2042
2043         uiBlockBeginAlign(block);
2044
2045         lt->opntsu = lt->pntsu;
2046         lt->opntsv = lt->pntsv;
2047         lt->opntsw = lt->pntsw;
2048
2049         uiDefButS(block, NUM, B_RESIZELAT,      "U:",                           469, 178,100,19, &lt->opntsu, 1.0, 64.0, 0, 0, "Points in U direction");
2050         uiDefButC(block, ROW, B_LATTCHANGED,            "Lin",          572, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_LINEAR, 0, 0, "Set Linear interpolation");
2051         uiDefButC(block, ROW, B_LATTCHANGED,            "Card",         613, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_CARDINAL, 0, 0, "Set Cardinal interpolation");
2052         uiDefButC(block, ROW, B_LATTCHANGED,            "B",            652, 178, 40, 19, &lt->typeu, 1.0, (float)KEY_BSPLINE, 0, 0, "Set B-spline interpolation");
2053
2054         uiDefButS(block, NUM, B_RESIZELAT,      "V:",                           469, 156,100,19, &lt->opntsv, 1.0, 64.0, 0, 0, "Points in V direction");
2055         uiDefButC(block, ROW, B_LATTCHANGED,            "Lin",          572, 156, 40, 19, &lt->typev, 2.0, (float)KEY_LINEAR, 0, 0, "Set Linear interpolation");
2056         uiDefButC(block, ROW, B_LATTCHANGED,            "Card",         613, 156, 40, 19, &lt->typev, 2.0, (float)KEY_CARDINAL, 0, 0, "Set Cardinal interpolation");
2057         uiDefButC(block, ROW, B_LATTCHANGED,            "B",            652, 156, 40, 19, &lt->typev, 2.0, (float)KEY_BSPLINE, 0, 0, "Set B-spline interpolation");
2058
2059         uiDefButS(block, NUM, B_RESIZELAT,      "W:",                           469, 134,100,19, &lt->opntsw, 1.0, 64.0, 0, 0, "Points in W direction");
2060         uiDefButC(block, ROW, B_LATTCHANGED,            "Lin",          572, 134, 40, 19, &lt->typew, 3.0, (float)KEY_LINEAR, 0, 0, "Set Linear interpolation");
2061         uiDefButC(block, ROW, B_LATTCHANGED,            "Card",         613, 134, 40, 19, &lt->typew, 3.0, (float)KEY_CARDINAL, 0, 0, "Set Cardinal interpolation");
2062         uiDefButC(block, ROW, B_LATTCHANGED,            "B",            652, 134, 40, 19, &lt->typew, 3.0, (float)KEY_BSPLINE, 0, 0, "Set B-spline interpolation");
2063
2064         uiBlockEndAlign(block);
2065
2066         uiDefBut(block, BUT, B_REGULARLAT,      "Make Regular",         469,98,102,31, 0, 0, 0, 0, 0, "Make Lattice regular");
2067
2068         uiClearButLock();
2069         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");
2070
2071         if(lt->key) {
2072                 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");
2073                 uiDefButS(block, TOG, B_RELKEY, "Relative Keys",        469,40,120,19, &lt->key->type, 0, 0, 0, 0, "Use relative keys (instead of absolute)");
2074         }
2075
2076 }
2077
2078 /* *************************** ARMATURE ******************************** */
2079
2080
2081
2082 static int editbone_to_parnr (EditBone *bone)
2083 {
2084         EditBone *ebone;
2085         int     index;
2086
2087         for (ebone=G.edbo.first, index=0; ebone; ebone=ebone->next, index++){
2088                 if (ebone==bone)
2089                         return index;
2090         }
2091
2092         return -1;
2093 }
2094
2095 static void parnr_to_editbone(EditBone *bone)
2096 {
2097         if (bone->parNr == -1){
2098                 bone->parent = NULL;
2099                 bone->flag &= ~BONE_IK_TOPARENT;
2100         }
2101         else{
2102                 bone->parent = BLI_findlink(&G.edbo, bone->parNr);
2103                 attach_bone_to_parent(bone);
2104         }
2105 }
2106
2107 static void parnr_to_editbone_cb(void *bonev, void *arg2_unused)
2108 {
2109         EditBone *curBone= bonev;
2110         parnr_to_editbone(curBone);
2111 }
2112
2113 static void build_bonestring (char *string, EditBone *bone)
2114 {
2115         EditBone *curBone;
2116         EditBone *pBone;
2117         int             skip=0;
2118         int             index, numbones, i;
2119         char (*qsort_ptr)[32] = NULL;
2120
2121         sprintf (string, "Parent%%t| %%x%d", -1);       /* That space is there
2122                                                                                                  * for a reason
2123                                                                                                  */
2124
2125         numbones = BLI_countlist(&G.edbo);
2126
2127         /*
2128          * This will hold the bone names temporarily so we can sort them
2129          */
2130         if (numbones > 0)
2131                 qsort_ptr = MEM_callocN (numbones * sizeof (qsort_ptr[0]),
2132                                                                  "qsort_ptr");
2133
2134         numbones = 0;
2135         for (curBone = G.edbo.first, index=0; curBone;
2136                  curBone=curBone->next, index++){
2137                 /* Make sure this is a valid child */
2138                 if (curBone != bone){
2139                         skip=0;
2140                         for (pBone=curBone->parent; pBone; pBone=pBone->parent){
2141                                 if (pBone==bone){
2142                                         skip=1;
2143                                         break;
2144                                 }
2145                         }
2146
2147                         if (skip)
2148                                 continue;
2149
2150                         sprintf (qsort_ptr[numbones], "|%s%%x%d", curBone->name, index);
2151                         numbones++;
2152                 }
2153         }
2154         qsort (qsort_ptr, numbones, sizeof (qsort_ptr[0]),
2155                    ( int (*)(const void *, const void *) ) strcmp);
2156
2157         for (i=0; i < numbones; ++i) {
2158                 sprintf (string, "%s%s", string, qsort_ptr[i]);
2159         }
2160
2161         if (qsort_ptr)
2162                 MEM_freeN(qsort_ptr);
2163 }
2164
2165 /* assumes armature editmode */
2166 /* exported to drawview.c via BIF_butspace.h */
2167 void validate_editbonebutton_cb(void *bonev, void *namev)
2168 {
2169         EditBone *eBone= bonev;
2170         char oldname[32], newname[32];
2171         
2172         /* need to be on the stack */
2173         BLI_strncpy(newname, eBone->name, 32);
2174         BLI_strncpy(oldname, (char *)namev, 32);
2175         /* restore */
2176         BLI_strncpy(eBone->name, oldname, 32);
2177         
2178         armature_bone_rename(G.obedit->data, oldname, newname); // editarmature.c
2179         allqueue(REDRAWALL, 0);
2180 }
2181
2182 /* assumes armature posemode */
2183 static void validate_posebonebutton_cb(void *bonev, void *namev)
2184 {
2185         Bone *bone= bonev;
2186         Object *ob= OBACT;
2187         char oldname[32], newname[32];
2188         
2189         /* need to be on the stack */
2190         BLI_strncpy(newname, bone->name, 32);
2191         BLI_strncpy(oldname, (char *)namev, 32);
2192         /* restore */
2193         BLI_strncpy(bone->name, oldname, 32);
2194         
2195         armature_bone_rename(ob->data, oldname, newname); // editarmature.c
2196         allqueue(REDRAWALL, 0);
2197 }
2198
2199 static void armature_recalc_func(void *obp, void *pointer2) 
2200 {
2201         Object *ob= obp;
2202
2203         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2204 }
2205
2206 static void editing_panel_armature_type(Object *ob, bArmature *arm)
2207 {
2208         uiBlock         *block;
2209         uiBut       *but;
2210
2211         block= uiNewBlock(&curarea->uiblocks, "editing_panel_armature_type", UI_EMBOSS, UI_HELV, curarea->win);
2212         if(uiNewPanel(curarea, block, "Armature", "Editing", 320, 0, 318, 204)==0) return;
2213
2214         uiBlockBeginAlign(block);
2215         but = uiDefButBitI(block, TOG, ARM_RESTPOS, REDRAWVIEW3D,
2216                                         "Rest Position", 10,180,150,20, &arm->flag, 0, 0, 0, 0, "Disable all animation for this object");
2217         uiButSetFunc(but, armature_recalc_func, ob, NULL);
2218         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");
2219         uiBlockBeginAlign(block);
2220         uiDefButI(block, ROW, REDRAWVIEW3D, "Octahedron", 10, 140,100,20, &arm->drawtype, 0, ARM_OCTA, 0, 0, "Draw bone as octahedra");
2221         uiDefButI(block, ROW, REDRAWVIEW3D, "Sticks",   110, 140,100,20, &arm->drawtype, 0, ARM_LINE, 0, 0, "Draw bone as simple 2d lines with dots");
2222         uiDefButI(block, ROW, REDRAWVIEW3D, "B-Bones",  210, 140,100,20, &arm->drawtype, 0, ARM_B_BONE, 0, 0, "Draw bone as boxes, showing subdivision and b-splines");
2223         
2224         uiBlockBeginAlign(block);
2225         uiDefButBitI(block, TOG, ARM_DRAWAXES, REDRAWVIEW3D, "Draw Axes", 10, 110,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone axes");
2226         uiDefButBitI(block, TOG, ARM_DRAWNAMES, REDRAWVIEW3D, "Draw Names", 110,110,100,20, &arm->flag, 0, 0, 0, 0, "Draw bone names");
2227         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");
2228         
2229         uiBlockBeginAlign(block);
2230         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");
2231 }
2232
2233 static void editing_panel_armature_bones(Object *ob, bArmature *arm)
2234 {
2235         uiBlock         *block;
2236         uiBut           *but;
2237         EditBone        *curBone;
2238         char            *boneString=NULL;
2239         int                     bx=148, by=180;
2240         int                     index;
2241
2242         /* Draw the bone name block */
2243
2244         block= uiNewBlock(&curarea->uiblocks, "editing_panel_armature_bones", UI_EMBOSS, UI_HELV, curarea->win);
2245         if(uiNewPanel(curarea, block, "Armature Bones", "Editing", 640, 0, 318, 204)==0) return;
2246
2247         /* this is a variable height panel, newpanel doesnt force new size on existing panels */
2248         /* so first we make it default height */
2249         uiNewPanelHeight(block, 204);
2250
2251
2252         uiDefBut(block, LABEL, 0, "Selected Bones", bx,by,158,18, 0, 0, 0, 0, 0, "Only show in Armature Editmode");
2253         by-=20;
2254         for (curBone=G.edbo.first, index=0; curBone; curBone=curBone->next, index++){
2255                 if (curBone->flag & (BONE_SELECTED)) {
2256
2257                         /*      Bone naming button */
2258                         but=uiDefBut(block, TEX, REDRAWVIEW3D, "BO:", bx-10,by,117,18, &curBone->name, 0, 24, 0, 0, "Change the bone name");
2259                         uiButSetFunc(but, validate_editbonebutton_cb, curBone, NULL);
2260
2261                         uiDefBut(block, LABEL, 0, "child of", bx+107,by,73,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
2262
2263                         boneString = MEM_mallocN((BLI_countlist(&G.edbo) * 64)+64, "Bone str");
2264                         build_bonestring (boneString, curBone);
2265
2266                         curBone->parNr = editbone_to_parnr(curBone->parent);
2267                         but = uiDefButI(block, MENU,REDRAWVIEW3D, boneString, bx+180,by,120,18, &curBone->parNr, 0.0, 0.0, 0.0, 0.0, "Parent");
2268                         /* last arg NULL means button will put old string there */
2269                         uiButSetFunc(but, parnr_to_editbone_cb, curBone, NULL);
2270
2271                         MEM_freeN(boneString);
2272
2273                         /* IK to parent flag */
2274                         if (curBone->parent){
2275                                 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");
2276                                 uiButSetFunc(but, attach_bone_to_parent_cb, curBone, NULL);
2277                         }
2278
2279                         /* Segment, dist and weight buttons */
2280                         uiBlockBeginAlign(block);
2281                         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");
2282                         uiDefButF(block, NUM,REDRAWVIEW3D, "Dist:", bx+110, by-19, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance");
2283                         uiDefButF(block, NUM,REDRAWVIEW3D, "Weight:", bx+223, by-19,110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
2284                         
2285                         /* bone types */
2286                         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");
2287                         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");
2288                         /* Hide in posemode flag */
2289                         uiDefButBitI(block, TOG, BONE_HIDDEN, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode");
2290                         
2291                         uiBlockEndAlign(block);
2292                         by-=60;
2293                         
2294                         if(by < -200) break;    // for time being... extreme long panels are very slow
2295                 }
2296         }
2297
2298         if(by<0) {
2299                 uiNewPanelHeight(block, 204 - by);
2300         }
2301
2302 }
2303
2304 static void editing_panel_pose_bones(Object *ob, bArmature *arm)
2305 {
2306         uiBlock         *block;
2307         uiBut           *but;
2308         bPoseChannel *pchan;
2309         Bone            *curBone;
2310         int                     bx=148, by=180;
2311         int                     index;
2312         
2313         /* Draw the bone name block */
2314         
2315         block= uiNewBlock(&curarea->uiblocks, "editing_panel_pose_bones", UI_EMBOSS, UI_HELV, curarea->win);
2316         if(uiNewPanel(curarea, block, "Armature Bones", "Editing", 640, 0, 318, 204)==0) return;
2317         
2318         /* this is a variable height panel, newpanel doesnt force new size on existing panels */
2319         /* so first we make it default height */
2320         uiNewPanelHeight(block, 204);
2321         
2322         uiDefBut(block, LABEL, 0, "Selected Bones", bx,by,158,18, 0, 0, 0, 0, 0, "Only show in Armature Editmode/Posemode");
2323         by-=20;
2324         for (pchan=ob->pose->chanbase.first, index=0; pchan; pchan=pchan->next, index++){
2325                 curBone= pchan->bone;
2326                 if (curBone->flag & (BONE_SELECTED)) {
2327
2328                         /*      Bone naming button */
2329                         uiBlockBeginAlign(block);
2330                         but=uiDefBut(block, TEX, REDRAWVIEW3D, "BO:", bx-10,by,117,18, &curBone->name, 0, 24, 0, 0, "Change the bone name");
2331                         uiButSetFunc(but, validate_posebonebutton_cb, curBone, NULL);
2332                         
2333                         /* Dist and weight buttons */
2334                         uiDefButF(block, NUM,REDRAWVIEW3D, "Dist:", bx+107, by, 105, 18, &curBone->dist, 0.0, 1000.0, 10.0, 0.0, "Bone deformation distance");
2335                         uiDefButF(block, NUM,REDRAWVIEW3D, "Weight:", bx+220, by,  110, 18, &curBone->weight, 0.0F, 1000.0F, 10.0F, 0.0F, "Bone deformation weight");
2336                         
2337                         
2338                         /* Segment, ease in/out buttons */
2339                         uiBlockBeginAlign(block);
2340                         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");
2341                         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");
2342                         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");
2343                         
2344                         /* bone types */
2345                         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");
2346                         uiButSetFunc(but, armature_recalc_func, ob, NULL);
2347                         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");
2348                         /* Hide in posemode flag */
2349                         uiDefButBitI(block, TOG, BONE_HIDDEN, REDRAWVIEW3D, "Hide", bx+223,by-38,110,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in posemode");
2350                         uiBlockEndAlign(block);
2351                         
2352                         by-=60;
2353                         if(by < -200) break;    // for time being... extreme long panels are very slow
2354                 }
2355         }
2356         
2357         if(by<0) {
2358                 uiNewPanelHeight(block, 204 - by);
2359         }
2360         
2361 }
2362
2363
2364 /* *************************** MESH ******************************** */
2365
2366 void do_meshbuts(unsigned short event)
2367 {
2368         Object *ob;
2369         Mesh *me;
2370         float fac;
2371         short randfac;
2372
2373         ob= OBACT;
2374         if(ob && ob->type==OB_MESH) {
2375
2376                 me= get_mesh(ob);
2377                 if(me==0) return;
2378
2379                 switch(event) {
2380                 case B_AUTOVGROUP:
2381                         if (!get_armature(ob->parent)){
2382                                 error ("Mesh must be the child of an armature");
2383                                 break;
2384                         }
2385                                 /* Verify that there are vertex groups for bones in armature */
2386                                 /* Remove selected vertices from all defgroups */
2387                                 /* Perform assignment for selected vertices */
2388
2389                         allqueue (REDRAWVIEW3D, 1);
2390                         break;
2391                 case B_NEWVGROUP:
2392                         add_defgroup (G.obedit);
2393                         scrarea_queue_winredraw(curarea);
2394                         break;
2395                 case B_DELVGROUP:
2396                         del_defgroup (G.obedit);
2397                         allqueue (REDRAWVIEW3D, 1);
2398                         BIF_undo_push("Delete vertex group");
2399                         break;
2400                 case B_ASSIGNVGROUP:
2401                         assign_verts_defgroup ();
2402                         allqueue (REDRAWVIEW3D, 1);
2403                         BIF_undo_push("Assign to vertex group");
2404                         break;
2405                 case B_REMOVEVGROUP:
2406                         remove_verts_defgroup (0);
2407                         allqueue (REDRAWVIEW3D, 1);
2408                         BIF_undo_push("Remove from vertex group");
2409                         break;
2410                 case B_SELVGROUP:
2411                         sel_verts_defgroup(1);
2412                         allqueue (REDRAWVIEW3D, 1);
2413                         break;
2414                 case B_DESELVGROUP:
2415                         sel_verts_defgroup(0);
2416                         allqueue (REDRAWVIEW3D, 1);
2417                         break;
2418                 case B_DELSTICKY:
2419
2420                         if(me->msticky) MEM_freeN(me->msticky);
2421                         me->msticky= NULL;
2422                         allqueue(REDRAWBUTSEDIT, 0);
2423                         break;
2424                 case B_MAKESTICKY:
2425                         RE_make_sticky();
2426                         allqueue(REDRAWBUTSEDIT, 0);
2427                         break;
2428                 
2429                 case B_MAKEEDGES:
2430                         /* in editmode we only have to set edge pointer */
2431                         if(ob==G.obedit) {
2432                                 me->medge= MEM_callocN(sizeof(MEdge), "fake mesh edge");
2433                                 me->totedge= 1;
2434                         }
2435                         else make_edges(me);
2436                         allqueue(REDRAWBUTSEDIT, 0);
2437                         break;
2438                 case B_DELEDGES:
2439                         if(me->medge) MEM_freeN(me->medge);
2440                         me->medge= NULL;
2441                         me->totedge= 0;
2442                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2443                         allqueue(REDRAWBUTSEDIT, 0);
2444                         allqueue(REDRAWVIEW3D, 0);
2445                         break;
2446                         
2447                 case B_MAKEVERTCOL:
2448                         make_vertexcol();
2449                         break;
2450                 case B_DELVERTCOL:
2451                         if(me->mcol) MEM_freeN(me->mcol);
2452                         me->mcol= NULL;
2453                         G.f &= ~G_VERTEXPAINT;
2454                         freedisplist(&(ob->disp));
2455                         allqueue(REDRAWBUTSEDIT, 0);
2456                         allqueue(REDRAWVIEW3D, 0);
2457                         break;
2458
2459                 case B_MAKE_TFACES:
2460                         make_tfaces(me);
2461                         allqueue(REDRAWBUTSEDIT, 0);
2462                         break;
2463
2464                 case B_DEL_TFACES:
2465                         if(me->tface) MEM_freeN(me->tface);
2466                         me->tface= 0;
2467                         G.f &= ~G_FACESELECT;
2468                         allqueue(REDRAWBUTSEDIT, 0);
2469                         allqueue(REDRAWVIEW3D, 0);
2470                         allqueue(REDRAWIMAGE, 0);
2471                         break;
2472
2473                 case B_FLIPNORM:
2474                         if(G.obedit) {
2475                                 flip_editnormals();
2476                         }
2477                         else {
2478                                 flipnorm_mesh( get_mesh(ob) );
2479                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2480                         }
2481
2482                         allqueue(REDRAWVIEW3D, 0);
2483                         break;
2484
2485                 case B_SLOWERDRAW:
2486                         slowerdraw();
2487                         break;
2488                 case B_FASTERDRAW:
2489                         fasterdraw();
2490                         break;
2491                 }
2492         }
2493
2494         if(G.obedit==0 || (G.obedit->type!=OB_MESH)) return;
2495
2496         switch(event) {
2497         case B_SPIN:
2498                 if( select_area(SPACE_VIEW3D)) spin_mesh(step, degr, 0, 0);
2499                 break;
2500         case B_SPINDUP:
2501                 if( select_area(SPACE_VIEW3D)) spin_mesh(step, degr, 0, 1);
2502                 break;
2503         case B_EXTR:
2504                 G.f |= G_DISABLE_OK;
2505                 if( select_area(SPACE_VIEW3D)) extrude_mesh();
2506                 G.f -= G_DISABLE_OK;
2507                 break;
2508         case B_SCREW:
2509                 if( select_area(SPACE_VIEW3D)) screw_mesh(step, turn);
2510                 break;
2511         case B_EXTREP:
2512                 if( select_area(SPACE_VIEW3D)) extrude_repeat_mesh(step, extr_offs);
2513                 break;
2514         case B_SPLIT:
2515                 G.f |= G_DISABLE_OK;
2516                 split_mesh();
2517                 G.f -= G_DISABLE_OK;
2518                 break;
2519         case B_REMDOUB:
2520                 notice("Removed: %d", removedoublesflag(1, doublimit));
2521                 allqueue(REDRAWVIEW3D, 0);
2522                 BIF_undo_push("Rem Doubles");
2523                 break;
2524         case B_SUBDIV:
2525                 waitcursor(1);
2526                 esubdivideflag(1, 0.0, editbutflag & B_BEAUTY,1,0);
2527                 countall();
2528                 waitcursor(0);
2529                 allqueue(REDRAWVIEW3D, 0);
2530                 BIF_undo_push("Subdivide");
2531                 break;
2532         case B_FRACSUBDIV:
2533                 randfac= 10;
2534                 if(button(&randfac, 1, 100, "Rand fac:")==0) return;
2535                 waitcursor(1);
2536                 fac= -( (float)randfac )/100;
2537                 esubdivideflag(1, fac, editbutflag & B_BEAUTY,1,0);
2538                 countall();
2539                 waitcursor(0);
2540                 allqueue(REDRAWVIEW3D, 0);
2541                 BIF_undo_push("Fractal Subdivide");
2542                 break;
2543         case B_XSORT:
2544                 if( select_area(SPACE_VIEW3D)) xsortvert_flag(1);
2545                 break;
2546         case B_HASH:
2547                 hashvert_flag(1);
2548                 break;
2549         case B_TOSPHERE:
2550                 vertices_to_sphere();
2551                 break;
2552         case B_VERTEXNOISE:
2553                 vertexnoise();
2554                 break;
2555         case B_VERTEXSMOOTH:
2556                 vertexsmooth();
2557                 break;
2558         case B_DRAWEDGES:
2559                 G.f &= ~G_DRAWCREASES;
2560                 allqueue(REDRAWBUTSEDIT, 0);
2561                 allqueue(REDRAWVIEW3D, 0);
2562                 break;
2563         case B_DRAWCREASES:
2564                 G.f &= ~G_DRAWEDGES;
2565                 allqueue(REDRAWBUTSEDIT, 0);
2566                 allqueue(REDRAWVIEW3D, 0);
2567                 break;
2568         }
2569         /* WATCH IT: previous events only in editmode! */
2570 }
2571
2572 static void editing_panel_mesh_tools(Object *ob, Mesh *me)
2573 {
2574         uiBlock *block;
2575
2576         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_tools", UI_EMBOSS, UI_HELV, curarea->win);
2577         if(uiNewPanel(curarea, block, "Mesh Tools", "Editing", 640, 0, 318, 204)==0) return;
2578
2579         uiBlockBeginAlign(block);
2580         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");
2581         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");
2582
2583         uiDefBut(block, BUT,B_SUBDIV,"Subdivide",               90,195,80,19, 0, 0, 0, 0, 0, "Splits selected faces into halves or quarters");
2584         uiDefBut(block, BUT,B_FRACSUBDIV, "Fract Subd", 170,195,85,19, 0, 0, 0, 0, 0, "Subdivides selected faces with a random factor");
2585
2586         uiDefBut(block, BUT,B_VERTEXNOISE,"Noise",              10,175,80,19, 0, 0, 0, 0, 0, "Use vertex coordinate as texture coordinate");
2587         uiDefBut(block, BUT,B_HASH,"Hash",                              90,175,80,19, 0, 0, 0, 0, 0, "Randomizes selected vertice sequence data");
2588         uiDefBut(block, BUT,B_XSORT,"Xsort",                    170,175,85,19, 0, 0, 0, 0, 0, "Sorts selected vertice data in the X direction");
2589
2590         uiDefBut(block, BUT,B_TOSPHERE,"To Sphere",             10,155,80,19, 0, 0, 0, 0, 0, "Moves selected vertices outwards into a spherical shape");
2591         uiDefBut(block, BUT,B_VERTEXSMOOTH,"Smooth",    90,155,80,19, 0, 0, 0, 0, 0, "Flattens angles of selected faces");
2592         uiDefBut(block, BUT,B_SPLIT,"Split",                    170,155,85,19, 0, 0, 0, 0, 0, "Splits selected verts to separate sub-mesh.");
2593
2594         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");
2595         uiDefBut(block, BUT,B_REMDOUB,"Rem Doubles",    90,135,80,19, 0, 0, 0, 0, 0, "Removes duplicates from selected vertices");
2596         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'");
2597         uiBlockEndAlign(block);
2598
2599         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");
2600
2601         uiBlockBeginAlign(block);
2602         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
2603         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");
2604         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");
2605
2606         uiDefButS(block, NUM, B_DIFF, "Degr:",                  10,55,80,19, &degr,10.0,360.0, 0, 0, "Specifies the number of degrees 'Spin' revolves");
2607         uiDefButS(block, NUM, B_DIFF, "Steps:",                 90,55,80,19, &step,1.0,180.0, 0, 0, "Specifies the total number of 'Spin' slices");
2608         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");
2609         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");
2610         uiDefButBitS(block, TOG, B_CLOCKWISE, B_DIFF, "Clockwise",      170,35,85,19, &editbutflag, 0, 0, 0, 0, "Specifies the direction for 'Screw' and 'Spin'");
2611
2612         uiBlockBeginAlign(block);
2613         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");
2614         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'");
2615         uiBlockEndAlign(block);
2616 }
2617
2618 static void verify_vertexgroup_name_func(void *datav, void *data2_unused)
2619 {
2620         unique_vertexgroup_name((bDeformGroup*)datav, OBACT);
2621 }
2622
2623
2624
2625 static void editing_panel_mesh_tools1(Object *ob, Mesh *me)
2626 {
2627         uiBlock *block;
2628
2629
2630         block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_tools1", UI_EMBOSS, UI_HELV, curarea->win);
2631         if(uiNewPanel(curarea, block, "Mesh Tools 1", "Editing", 960, 0, 318, 204)==0) return;
2632
2633         uiBlockBeginAlign(block);
2634         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");
2635         uiDefBut(block, BUT,B_HIDE,             "Hide",         1115, 200,  160, 19, 0, 0, 0, 0, 0, "Hides selected faces");
2636         uiDefBut(block, BUT,B_SELSWAP,  "Select Swap",  955, 180, 160, 19, 0, 0, 0, 0, 0, "Selects unselected faces, and deselects selected faces");
2637         uiDefBut(block, BUT,B_REVEAL,   "Reveal",               1115, 180,  160, 19, 0, 0, 0, 0, 0, "Reveals selected faces");
2638         uiBlockEndAlign(block);
2639
2640         uiBlockBeginAlign(block);
2641         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");
2642         uiDefButBitI(block, TOG, G_DRAWNORMALS, REDRAWVIEW3D, "Draw Normals",   955,110,150,19, &G.f, 0, 0, 0, 0, "Displays face normals as lines");
2643         uiDefButBitI(block, TOG, G_DRAWFACES, REDRAWVIEW3D, "Draw Faces",               955,88,150,19, &G.f, 0, 0, 0, 0, "Displays all faces as shades");
2644         uiDefButBitI(block, TOG, G_DRAWEDGES, REDRAWVIEW3D, "Draw Edges",       955,66,150,19, &G.f, 0, 0, 0, 0, "Displays selected edges using hilights");
2645         uiDefButBitI(block, TOG, G_DRAWCREASES, REDRAWVIEW3D, "Draw Creases",   955,44,150,19, &G.f, 0, 0, 0, 0, "Displays creases created for subsurf weighting");
2646         uiDefButBitI(block, TOG, G_DRAWSEAMS, REDRAWVIEW3D, "Draw Seams",       955,22,150,19, &G.f, 0, 0, 0, 0, "Displays UV unwrapping seams");
2647         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");
2648         uiBlockEndAlign(block);
2649         
2650         /* Measurement drawing options */
2651         uiBlockBeginAlign(block);
2652         uiDefButBitI(block, TOG, G_DRAW_VNORMALS, REDRAWVIEW3D, "Draw VNormals",1125,110,150,19, &G.f, 0, 0, 0, 0, "Displays vertex normals as lines");
2653         uiDefButBitI(block, TOG, G_DRAW_EDGELEN, REDRAWVIEW3D, "Edge Length",   1125,88,150,19, &G.f, 0, 0, 0, 0, "Displays selected edge lengths");
2654         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");
2655         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");
2656         uiBlockEndAlign(block);
2657
2658 }
2659
2660 char *get_vertexgroup_menustr(Object *ob)
2661 {
2662         bDeformGroup *dg;
2663         int defCount, min, index;
2664         char (*qsort_ptr)[32] = NULL;
2665         char *s, *menustr;
2666         
2667         defCount=BLI_countlist(&ob->defbase);
2668         
2669         if (!defCount) min=0;
2670         else min=1;
2671         
2672         if (defCount > 0) {
2673                 /*
2674                  * This will hold the group names temporarily
2675                  * so we can sort them
2676                  */
2677                 qsort_ptr = MEM_callocN (defCount * sizeof (qsort_ptr[0]),
2678                                                                  "qsort_ptr");
2679                 for (index = 1, dg = ob->defbase.first; dg; index++, dg=dg->next) {
2680                         snprintf (qsort_ptr[index - 1], sizeof (qsort_ptr[0]),
2681                                           "%s%%x%d|", dg->name, index);
2682                 }
2683                 
2684                 qsort (qsort_ptr, defCount, sizeof (qsort_ptr[0]),
2685                            ( int (*)(const void *, const void *) ) strcmp);
2686         }
2687         
2688         s= menustr = MEM_callocN((32 * defCount)+30, "menustr");        // plus 30 for when defCount==0
2689         if(defCount) {
2690                 for (index = 0; index < defCount; index++) {
2691                         int cnt= sprintf (s, "%s", qsort_ptr[index]);
2692                         if (cnt>0) s+= cnt;
2693                 }
2694         }
2695         else strcpy(menustr, "No Vertex Groups in Object");
2696         
2697         if (qsort_ptr)
2698                 MEM_freeN (qsort_ptr);
2699         
2700         return menustr;
2701 }
2702
2703 static void editing_panel_links(Object *ob)
2704 {
2705         uiBlock *block;
2706         ID *id, *idfrom;
2707         int *poin, xco=143;
2708         float min;
2709         Material *ma;
2710         char str[64];
2711         uiBut *but;
2712
2713         block= uiNewBlock(&curarea->uiblocks, "editing_panel_links", UI_EMBOSS, UI_HELV, curarea->win);
2714         if(uiNewPanel(curarea, block, "Link and Materials", "Editing", 0, 0, 318, 204)==0) return;
2715
2716         buttons_active_id(&id, &idfrom);
2717
2718         if(id) {
2719                 int alone= 0;
2720                 int local= 0;
2721                 int browse= B_EDITBROWSE;
2722
2723                 if(ob->type==OB_MESH) {
2724                         browse= B_MESHBROWSE;
2725                         alone= B_MESHALONE;
2726                         local= B_MESHLOCAL;
2727                         uiSetButLock(G.obedit!=0, "Unable to perform function in EditMode");
2728                 }
2729                 else if(ob->type==OB_MBALL) {
2730                         alone= B_MBALLALONE;
2731                         local= B_MBALLLOCAL;
2732                 }
2733                 else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) {
2734                         alone= B_CURVEALONE;
2735                         local= B_CURVELOCAL;
2736                 }
2737                 else if(ob->type==OB_CAMERA) {
2738                         alone= B_CAMERAALONE;
2739                         local= B_CAMERALOCAL;
2740                 }
2741                 else if(ob->type==OB_LAMP) {
2742                         alone= B_LAMPALONE;
2743                         local= B_LAMPLOCAL;
2744                 }
2745                 else if (ob->type==OB_ARMATURE){
2746                         alone = B_ARMALONE;
2747                         local = B_ARMLOCAL;
2748                 }
2749                 else if(ob->type==OB_LATTICE) {
2750                         alone= B_LATTALONE;
2751                         local= B_LATTLOCAL;
2752                 }
2753                 uiBlockSetCol(block, TH_BUT_SETTING2);
2754                 xco= std_libbuttons(block, 143, 180, 0, NULL, browse, id, idfrom, &(G.buts->menunr), alone, local, 0, 0, B_KEEPDATA);
2755                 uiBlockSetCol(block, TH_AUTO);
2756         }
2757         if(ob) {
2758                 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.");
2759                 uiButSetFunc(but, test_idbutton_cb, ob->id.name, NULL);
2760         }
2761
2762
2763
2764         /* to be sure */
2765         if ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL);
2766         else return;
2767
2768
2769         if(ob->type==OB_MESH) poin= &( ((Mesh *)ob->data)->texflag );
2770         else if(ob->type==OB_MBALL) poin= &( ((MetaBall *)ob->data)->texflag );
2771         else poin= &( ((Curve *)ob->data)->texflag );
2772         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");
2773
2774         sprintf(str,"%d Mat ", ob->totcol);
2775         if(ob->totcol) min= 1.0; else min= 0.0;
2776         ma= give_current_material(ob, ob->actcol);
2777
2778         if(ma) uiDefBut(block, LABEL, 0, ma->id.name+2, 318,153, 103, 20, 0, 0, 0, 0, 0, "");
2779
2780         uiBlockBeginAlign(block);
2781         if(ma) uiDefButF(block, COL, B_REDR, "",                        292,123,31,30, &(ma->r), 0, 0, 0, 0, "");
2782         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");
2783         uiDefBut(block, BUT,B_MATWICH,  "?",            424,123,30,30, 0, 0, 0, 0, 0, "In EditMode, sets the active material index from selected faces");
2784
2785         uiBlockBeginAlign(block);
2786         uiDefBut(block, BUT,B_MATNEW,   "New",          292,98,80,20, 0, 0, 0, 0, 0, "Adds a new Material index");
2787         uiDefBut(block, BUT,B_MATDEL,   "Delete",       374,98,80,20, 0, 0, 0, 0, 0, "Deletes this Material index");
2788         uiDefBut(block, BUT,B_MATSEL,   "Select",       292,76,80,20, 0, 0, 0, 0, 0, "In EditMode, selects faces that have the active index");
2789         uiDefBut(block, BUT,B_MATDESEL, "Deselect",     374,76,80,20, 0, 0, 0, 0, 0, "Deselects everything with current indexnumber");
2790         uiDefBut(block, BUT,B_MATASS,   "Assign",       292,47,162,26, 0, 0, 0, 0, 0, "In EditMode, assigns the active index to selected faces");
2791
2792         uiBlockBeginAlign(block);
2793         uiDefBut(block, BUT,B_SETSMOOTH,"Set Smooth",   291,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'smooth' rendering of selected faces");
2794         uiDefBut(block, BUT,B_SETSOLID, "Set Solid",    373,15,80,20, 0, 0, 0, 0, 0, "In EditMode, sets 'solid' rendering of selected faces");
2795         uiBlockEndAlign(block);
2796
2797         /* vertex group... partially editmode... */
2798         if(ob->type==OB_MESH) {
2799                 uiBut *but;
2800                 int     defCount;
2801                 bDeformGroup    *defGroup;
2802         
2803                 uiDefBut(block, LABEL,0,"Vertex Groups",
2804                                  143,153,130,20, 0, 0, 0, 0, 0, "");
2805
2806                 defCount=BLI_countlist(&ob->defbase);
2807
2808                 uiBlockBeginAlign(block);
2809                 if (defCount) {
2810                         char *menustr= get_vertexgroup_menustr(ob);
2811                         
2812                         uiDefButS(block, MENU, REDRAWBUTSEDIT, menustr, 143, 132,18,21, &ob->actdef, 1, defCount, 0, 0, "Browses available vertex groups");
2813                         MEM_freeN (menustr);
2814                 }
2815                 
2816                 if (ob->actdef){
2817                         defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
2818                         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.)");
2819                         uiButSetFunc(but, verify_vertexgroup_name_func, defGroup, NULL);
2820
2821                         uiDefButF(block, NUM, REDRAWVIEW3D, "Weight:",          143, 111, 140, 21, &editbutvweight, 0, 1, 10, 0, "Sets the current vertex group's bone deformation strength");
2822                 }
2823                 uiBlockEndAlign(block);
2824
2825                 if (G.obedit && G.obedit==ob){
2826                         uiBlockBeginAlign(block);
2827         /*              uiDefBut(block, BUT,B_AUTOVGROUP,"Auto Weight",                 740,by-=22,93,18, 0, 0, 0, 0, 0, "Automatically assigns deformation groups"); */
2828                         uiDefBut(block, BUT,B_NEWVGROUP,"New",                  143,90,70,21, 0, 0, 0, 0, 0, "Creates a new vertex group");
2829                         uiDefBut(block, BUT,B_DELVGROUP,"Delete",               213,90,70,21, 0, 0, 0, 0, 0, "Removes the current vertex group");
2830
2831                         uiDefBut(block, BUT,B_ASSIGNVGROUP,"Assign",    143,69,70,21, 0, 0, 0, 0, 0, "Assigns selected vertices to the current vertex group");
2832                         uiDefBut(block, BUT,B_REMOVEVGROUP,"Remove",    213,69,70,21, 0, 0, 0, 0, 0, "Removes selected vertices from the current vertex group");
2833
2834                         uiDefBut(block, BUT,B_SELVGROUP,"Select",               143,48,70,21, 0, 0, 0, 0, 0, "Selects vertices belonging to the current vertex group");
2835                         uiDefBut(block, BUT,B_DESELVGROUP,"Desel.",             213,48,70,21, 0, 0, 0, 0, 0, "Deselects vertices belonging to the current vertex group");
2836                         uiBlockEndAlign(block);
2837                 }
2838         }
2839
2840
2841 }
2842
2843 /* *************************** FACE/PAINT *************************** */
2844
2845 void do_fpaintbuts(unsigned short event)
2846 {
2847         Mesh *me;
2848         Object *ob;
2849         bDeformGroup *defGroup;
2850         extern TFace *lasttface; /* caches info on tface bookkeeping ?*/
2851         extern VPaint Gwp;         /* from vpaint */
2852
2853         ob= OBACT;
2854         if(ob==NULL) return;
2855
2856         switch(event) {
2857
2858         case B_VPGAMMA:
2859                 vpaint_dogamma();
2860                 break;
2861         case B_COPY_TF_MODE:
2862         case B_COPY_TF_UV:
2863         case B_COPY_TF_COL:
2864         case B_COPY_TF_TEX:
2865                 me= get_mesh(ob);
2866                 if(me && me->tface) {
2867 /*                      extern TFace *lasttface; */
2868                         TFace *tface= me->tface;
2869                         int a= me->totface;
2870
2871                         set_lasttface();
2872                         if(lasttface) {
2873
2874                                 while(a--) {
2875                                         if(tface!=lasttface && (tface->flag & TF_SELECT)) {
2876                                                 if(event==B_COPY_TF_MODE) {
2877                                                         tface->mode= lasttface->mode;
2878                                                         tface->transp= lasttface->transp;
2879                                                 }
2880                                                 else if(event==B_COPY_TF_UV) {
2881                                                         memcpy(tface->uv, lasttface->uv, sizeof(tface->uv));
2882                                                         tface->tpage= lasttface->tpage;
2883                                                         tface->tile= lasttface->tile;
2884
2885                                                         if(lasttface->mode & TF_TILES) tface->mode |= TF_TILES;
2886                                                         else tface->mode &= ~TF_TILES;
2887
2888                                                 }
2889                                                 else if(event==B_COPY_TF_TEX) {
2890                                                         tface->tpage= lasttface->tpage;
2891                                                         tface->tile= lasttface->tile;
2892
2893                                                         if(lasttface->mode & TF_TILES) tface->mode |= TF_TILES;
2894                                                         else tface->mode &= ~TF_TILES;
2895                                                 }
2896                                                 else if(event==B_COPY_TF_COL) memcpy(tface->col, lasttface->col, sizeof(tface->col));
2897                                         }
2898                                         tface++;
2899                                 }
2900                         }
2901                         do_shared_vertexcol(me);
2902                         allqueue(REDRAWVIEW3D, 0);
2903                         allqueue(REDRAWIMAGE, 0);
2904                 }
2905                 break;
2906         case B_SET_VCOL:
2907                 if(G.f & G_FACESELECT) 
2908                         clear_vpaint_selectedfaces();
2909                 else
2910                         clear_vpaint();
2911                 break;
2912         case B_REDR_3D_IMA:
2913                 allqueue(REDRAWVIEW3D, 0);
2914                 allqueue(REDRAWIMAGE, 0);
2915                 break;
2916         case B_ASSIGNMESH:
2917
2918                 test_object_materials(ob->data);
2919                 allqueue(REDRAWVIEW3D, 0);
2920                 allqueue(REDRAWBUTSEDIT, 0);
2921                 break;
2922
2923         case B_TFACE_HALO:
2924                 set_lasttface();
2925                 if(lasttface) {
2926                         lasttface->mode &= ~TF_BILLBOARD2;
2927                         allqueue(REDRAWBUTSEDIT, 0);
2928                 }
2929                 break;
2930
2931         case B_TFACE_BILLB:
2932                 set_lasttface();
2933                 if(lasttface) {
2934                         lasttface->mode &= ~TF_BILLBOARD;
2935                         allqueue(REDRAWBUTSEDIT, 0);
2936                 }
2937                 break;
2938         case B_WEIGHT0_0:
2939                 editbutvweight = 0.0f;
2940                 allqueue(REDRAWBUTSEDIT, 0);
2941                 break;
2942
2943         case B_WEIGHT1_4:
2944                 editbutvweight = 0.25f;
2945                 allqueue(REDRAWBUTSEDIT, 0);
2946                 break;
2947         case B_WEIGHT1_2:
2948                 editbutvweight = 0.5f;
2949                 allqueue(REDRAWBUTSEDIT, 0);
2950                 break;
2951         case B_WEIGHT3_4:
2952                 editbutvweight = 0.75f;
2953                 allqueue(REDRAWBUTSEDIT, 0);
2954                 break;
2955         case B_WEIGHT1_0:
2956                 editbutvweight = 1.0f;
2957                 allqueue(REDRAWBUTSEDIT, 0);
2958                 break;
2959                 
2960         case B_OPA1_8:
2961                 Gwp.a = 0.125f;
2962                 allqueue(REDRAWBUTSEDIT, 0);
2963                 break;
2964         case B_OPA1_4:
2965                 Gwp.a = 0.25f;
2966                 allqueue(REDRAWBUTSEDIT, 0);
2967                 break;
2968         case B_OPA1_2:
2969                 Gwp.a = 0.5f;
2970                 allqueue(REDRAWBUTSEDIT, 0);
2971                 break;
2972         case B_OPA3_4:
2973                 Gwp.a = 0.75f;
2974                 allqueue(REDRAWBUTSEDIT, 0);
2975                 break;
2976         case B_OPA1_0:
2977                 Gwp.a = 1.0f;
2978                 allqueue(REDRAWBUTSEDIT, 0);
2979                 break;
2980         case B_CLR_WPAINT:
2981                 defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
2982                 if(defGroup) {
2983                         Mesh *me= ob->data;
2984          &nb