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