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