svn merge -r 31145:31210 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / blender / editors / space_view3d / view3d_buttons.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <math.h>
32 #include <float.h>
33
34 #include "DNA_armature_types.h"
35 #include "DNA_curve_types.h"
36 #include "DNA_lattice_types.h"
37 #include "DNA_meta_types.h"
38 #include "DNA_meshdata_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_math.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_editVert.h"
47 #include "BLI_rand.h"
48
49 #include "BKE_action.h"
50 #include "BKE_context.h"
51 #include "BKE_curve.h"
52 #include "BKE_customdata.h"
53 #include "BKE_depsgraph.h"
54 #include "BKE_main.h"
55 #include "BKE_mesh.h"
56 #include "BKE_screen.h"
57 #include "BKE_deform.h"
58
59 #include "BIF_gl.h"
60
61 #include "WM_api.h"
62 #include "WM_types.h"
63
64 #include "RNA_access.h"
65
66 #include "ED_armature.h"
67 #include "ED_gpencil.h"
68 #include "ED_mesh.h"
69 #include "ED_screen.h"
70 #include "ED_transform.h"
71 #include "ED_curve.h"
72
73 #include "UI_interface.h"
74 #include "UI_resources.h"
75
76 #include "view3d_intern.h"      // own include
77
78
79 /* ******************* view3d space & buttons ************** */
80 #define B_NOP           1
81 #define B_REDR          2
82 #define B_OBJECTPANELROT        1007
83 #define B_OBJECTPANELMEDIAN 1008
84 #define B_ARMATUREPANEL1        1009
85 #define B_ARMATUREPANEL2        1010
86 #define B_OBJECTPANELPARENT 1011
87 #define B_OBJECTPANEL           1012
88 #define B_ARMATUREPANEL3        1013
89 #define B_OBJECTPANELSCALE      1014
90 #define B_OBJECTPANELDIMS       1015
91 #define B_TRANSFORMSPACEADD     1016
92 #define B_TRANSFORMSPACECLEAR   1017
93 #define B_SETPT_AUTO    2125
94 #define B_SETPT_VECTOR  2126
95 #define B_SETPT_ALIGN   2127
96 #define B_SETPT_FREE    2128
97 #define B_RECALCMBALL   2501
98
99 #define B_WEIGHT0_0             2840
100 #define B_WEIGHT1_4             2841
101 #define B_WEIGHT1_2             2842
102 #define B_WEIGHT3_4             2843
103 #define B_WEIGHT1_0             2844
104
105 #define B_OPA1_8                2845
106 #define B_OPA1_4                2846
107 #define B_OPA1_2                2847
108 #define B_OPA3_4                2848
109 #define B_OPA1_0                2849
110
111 #define B_CLR_WPAINT    2850
112
113 #define B_RV3D_LOCKED   2900
114 #define B_RV3D_BOXVIEW  2901
115 #define B_RV3D_BOXCLIP  2902
116
117 #define B_IDNAME                3000
118
119 /* temporary struct for storing transform properties */
120 typedef struct {
121         float ob_eul[4];        // used for quat too....
122         float ob_scale[3]; // need temp space due to linked values
123         float ob_dims[3];
124         short link_scale;
125         float ve_median[6];
126         int curdef;
127         float *defweightp;
128 } TransformProperties;
129
130
131 /* is used for both read and write... */
132 static void v3d_editvertex_buts(const bContext *C, uiLayout *layout, View3D *v3d, Object *ob, float lim)
133 {
134         uiBlock *block= (layout)? uiLayoutAbsoluteBlock(layout): NULL;
135         MDeformVert *dvert=NULL;
136         TransformProperties *tfp= v3d->properties_storage;
137         float median[6], ve_median[6];
138         int tot, totw, totweight, totedge, totradius;
139         char defstr[320];
140         
141         median[0]= median[1]= median[2]= median[3]= median[4]= median[5]= 0.0;
142         tot= totw= totweight= totedge= totradius= 0;
143         defstr[0]= 0;
144
145         if(ob->type==OB_MESH) {
146                 Mesh *me= ob->data;
147                 EditMesh *em = BKE_mesh_get_editmesh(me);
148                 EditVert *eve, *evedef=NULL;
149                 EditEdge *eed;
150                 
151                 eve= em->verts.first;
152                 while(eve) {
153                         if(eve->f & SELECT) {
154                                 evedef= eve;
155                                 tot++;
156                                 add_v3_v3(median, eve->co);
157                         }
158                         eve= eve->next;
159                 }
160                 eed= em->edges.first;
161                 while(eed) {
162                         if((eed->f & SELECT)) {
163                                 totedge++;
164                                 median[3]+= eed->crease;
165                         }
166                         eed= eed->next;
167                 }
168
169                 /* check for defgroups */
170                 if(evedef)
171                         dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
172                 if(tot==1 && dvert && dvert->totweight) {
173                         bDeformGroup *dg;
174                         int i, max=1, init=1;
175                         char str[320];
176                         
177                         for (i=0; i<dvert->totweight; i++){
178                                 dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
179                                 if(dg) {
180                                         max+= BLI_snprintf(str, sizeof(str), "%s %%x%d|", dg->name, dvert->dw[i].def_nr); 
181                                         if(max<320) strcat(defstr, str);
182                                 }
183
184                                 if(tfp->curdef==dvert->dw[i].def_nr) {
185                                         init= 0;
186                                         tfp->defweightp= &dvert->dw[i].weight;
187                                 }
188                         }
189                         
190                         if(init) {      // needs new initialized 
191                                 tfp->curdef= dvert->dw[0].def_nr;
192                                 tfp->defweightp= &dvert->dw[0].weight;
193                         }
194                 }
195
196                 BKE_mesh_end_editmesh(me, em);
197         }
198         else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
199                 Curve *cu= ob->data;
200                 Nurb *nu;
201                 BPoint *bp;
202                 BezTriple *bezt;
203                 int a;
204                 ListBase *nurbs= ED_curve_editnurbs(cu);
205
206                 nu= nurbs->first;
207                 while(nu) {
208                         if(nu->type == CU_BEZIER) {
209                                 bezt= nu->bezt;
210                                 a= nu->pntsu;
211                                 while(a--) {
212                                         if(bezt->f2 & SELECT) {
213                                                 add_v3_v3(median, bezt->vec[1]);
214                                                 tot++;
215                                                 median[4]+= bezt->weight;
216                                                 totweight++;
217                                                 median[5]+= bezt->radius;
218                                                 totradius++;
219                                         }
220                                         else {
221                                                 if(bezt->f1 & SELECT) {
222                                                         add_v3_v3(median, bezt->vec[0]);
223                                                         tot++;
224                                                 }
225                                                 if(bezt->f3 & SELECT) {
226                                                         add_v3_v3(median, bezt->vec[2]);
227                                                         tot++;
228                                                 }
229                                         }
230                                         bezt++;
231                                 }
232                         }
233                         else {
234                                 bp= nu->bp;
235                                 a= nu->pntsu*nu->pntsv;
236                                 while(a--) {
237                                         if(bp->f1 & SELECT) {
238                                                 add_v3_v3(median, bp->vec);
239                                                 median[3]+= bp->vec[3];
240                                                 totw++;
241                                                 tot++;
242                                                 median[4]+= bp->weight;
243                                                 totweight++;
244                                                 median[5]+= bp->radius;
245                                                 totradius++;
246                                         }
247                                         bp++;
248                                 }
249                         }
250                         nu= nu->next;
251                 }
252         }
253         else if(ob->type==OB_LATTICE) {
254                 Lattice *lt= ob->data;
255                 BPoint *bp;
256                 int a;
257                 
258                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
259                 bp= lt->editlatt->latt->def;
260                 while(a--) {
261                         if(bp->f1 & SELECT) {
262                                 add_v3_v3(median, bp->vec);
263                                 tot++;
264                                 median[4]+= bp->weight;
265                                 totweight++;
266                         }
267                         bp++;
268                 }
269         }
270         
271         if(tot==0) return;
272
273         median[0] /= (float)tot;
274         median[1] /= (float)tot;
275         median[2] /= (float)tot;
276         if(totedge) median[3] /= (float)totedge;
277         else if(totw) median[3] /= (float)totw;
278         if(totweight) median[4] /= (float)totweight;
279         if(totradius) median[5] /= (float)totradius;
280         
281         if(v3d->flag & V3D_GLOBAL_STATS)
282                 mul_m4_v3(ob->obmat, median);
283         
284         if(block) {     // buttons
285                 int but_y;
286                 if((ob->parent) && (ob->partype == PARBONE))    but_y = 135;
287                 else                                                                                    but_y = 150;
288                 
289                 
290                 
291                 memcpy(tfp->ve_median, median, sizeof(tfp->ve_median));
292                 
293                 uiBlockBeginAlign(block);
294                 if(tot==1) {
295                         uiDefBut(block, LABEL, 0, "Vertex:",                                    0, 130, 200, 20, 0, 0, 0, 0, 0, "");
296                         uiBlockBeginAlign(block);
297                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:",                0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
298                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:",                0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
299                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:",                0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
300                         
301                         if(totw==1) {
302                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:",        0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
303                                 uiBlockBeginAlign(block);
304                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
305                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
306                                 uiBlockEndAlign(block);
307                                 if(totweight)
308                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
309                                 if(totradius)
310                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
311                                 }
312                         else {
313                                 uiBlockBeginAlign(block);
314                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
315                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
316                                 uiBlockEndAlign(block);
317                                 if(totweight)
318                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
319                                 if(totradius)
320                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 20, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
321                         }
322                 }
323                 else {
324                         uiDefBut(block, LABEL, 0, "Median:",                                    0, 130, 200, 20, 0, 0, 0, 0, 0, "");
325                         uiBlockBeginAlign(block);
326                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:",                0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
327                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:",                0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
328                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:",                0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
329                         if(totw==tot) {
330                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:",        0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 10, 3, "");
331                                 uiBlockEndAlign(block);
332                                 uiBlockBeginAlign(block);
333                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
334                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
335                                 uiBlockEndAlign(block);
336                                 if(totweight)
337                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
338                                 if(totradius)
339                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
340                                 uiBlockEndAlign(block);
341                         }
342                         else {
343                                 uiBlockBeginAlign(block);
344                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
345                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
346                                 uiBlockEndAlign(block);
347                                 if(totweight)
348                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "Weight is used for SoftBody Goal");
349                                 if(totradius)
350                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
351                                 uiBlockEndAlign(block);
352                         }
353                 }
354                                 
355                 if(totedge==1)
356                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease:",   0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
357                 else if(totedge>1)
358                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Median Crease:",    0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 10, 3, "");
359                 
360         }
361         else {  // apply
362                 memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
363                 
364                 if(v3d->flag & V3D_GLOBAL_STATS) {
365                         invert_m4_m4(ob->imat, ob->obmat);
366                         mul_m4_v3(ob->imat, median);
367                         mul_m4_v3(ob->imat, ve_median);
368                 }
369                 sub_v3_v3v3(median, ve_median, median);
370                 median[3]= ve_median[3]-median[3];
371                 median[4]= ve_median[4]-median[4];
372                 median[5]= ve_median[5]-median[5];
373                 
374                 if(ob->type==OB_MESH) {
375                         Mesh *me= ob->data;
376                         EditMesh *em = BKE_mesh_get_editmesh(me);
377                         EditVert *eve;
378                         EditEdge *eed;
379                         
380                         eve= em->verts.first;
381                         while(eve) {
382                                 if(eve->f & SELECT) {
383                                         add_v3_v3(eve->co, median);
384                                 }
385                                 eve= eve->next;
386                         }
387                         
388                         for(eed= em->edges.first; eed; eed= eed->next) {
389                                 if(eed->f & SELECT) {
390                                         /* ensure the median can be set to zero or one */
391                                         if(ve_median[3]==0.0f) eed->crease= 0.0f;
392                                         else if(ve_median[3]==1.0f) eed->crease= 1.0f;
393                                         else {
394                                                 eed->crease+= median[3];
395                                                 CLAMP(eed->crease, 0.0, 1.0);
396                                         }
397                                 }
398                         }
399                         
400                         recalc_editnormals(em);
401
402                         BKE_mesh_end_editmesh(me, em);
403                 }
404                 else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
405                         Curve *cu= ob->data;
406                         Nurb *nu;
407                         BPoint *bp;
408                         BezTriple *bezt;
409                         int a;
410                         ListBase *nurbs= ED_curve_editnurbs(cu);
411
412                         nu= nurbs->first;
413                         while(nu) {
414                                 if(nu->type == CU_BEZIER) {
415                                         bezt= nu->bezt;
416                                         a= nu->pntsu;
417                                         while(a--) {
418                                                 if(bezt->f2 & SELECT) {
419                                                         add_v3_v3(bezt->vec[0], median);
420                                                         add_v3_v3(bezt->vec[1], median);
421                                                         add_v3_v3(bezt->vec[2], median);
422                                                         bezt->weight+= median[4];
423                                                         bezt->radius+= median[5];
424                                                 }
425                                                 else {
426                                                         if(bezt->f1 & SELECT) {
427                                                                 add_v3_v3(bezt->vec[0], median);
428                                                         }
429                                                         if(bezt->f3 & SELECT) {
430                                                                 add_v3_v3(bezt->vec[2], median);
431                                                         }
432                                                 }
433                                                 bezt++;
434                                         }
435                                 }
436                                 else {
437                                         bp= nu->bp;
438                                         a= nu->pntsu*nu->pntsv;
439                                         while(a--) {
440                                                 if(bp->f1 & SELECT) {
441                                                         add_v3_v3(bp->vec, median);
442                                                         bp->vec[3]+= median[3];
443                                                         bp->weight+= median[4];
444                                                         bp->radius+= median[5];
445                                                 }
446                                                 bp++;
447                                         }
448                                 }
449                                 test2DNurb(nu);
450                                 testhandlesNurb(nu); /* test for bezier too */
451
452                                 nu= nu->next;
453                         }
454                 }
455                 else if(ob->type==OB_LATTICE) {
456                         Lattice *lt= ob->data;
457                         BPoint *bp;
458                         int a;
459                         
460                         a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
461                         bp= lt->editlatt->latt->def;
462                         while(a--) {
463                                 if(bp->f1 & SELECT) {
464                                         add_v3_v3(bp->vec, median);
465                                         bp->weight+= median[4];
466                                 }
467                                 bp++;
468                         }
469                 }
470                 
471 //              ED_undo_push(C, "Transform properties");
472         }
473 }
474 #define B_VGRP_PNL_COPY 1
475 #define B_VGRP_PNL_NORMALIZE 2
476 #define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */
477 #define B_VGRP_PNL_COPY_SINGLE 16384 /* or greater */
478
479 static void act_vert_def(Object *ob, EditVert **eve, MDeformVert **dvert)
480 {
481         if(ob && ob->mode & OB_MODE_EDIT && ob->type==OB_MESH && ob->defbase.first) {
482                 Mesh *me= ob->data;
483                 EditMesh *em = BKE_mesh_get_editmesh(me);
484                 EditSelection *ese = ((EditSelection*)em->selected.last);
485
486                 if(ese && ese->type == EDITVERT) {
487                         *eve= (EditVert*)ese->data;
488                         *dvert= CustomData_em_get(&em->vdata, (*eve)->data, CD_MDEFORMVERT);
489                         return;
490                 }
491
492                 BKE_mesh_end_editmesh(me, em);
493         }
494
495         *eve= NULL;
496         *dvert= NULL;
497 }
498
499 static void editvert_mirror_update(Object *ob, EditVert *eve, int def_nr, int index)
500 {
501         Mesh *me= ob->data;
502         EditMesh *em = BKE_mesh_get_editmesh(me);
503         EditVert *eve_mirr;
504
505         eve_mirr= editmesh_get_x_mirror_vert(ob, em, eve, eve->co, index);
506
507         if(eve_mirr && eve_mirr != eve) {
508                 MDeformVert *dvert_src= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
509                 MDeformVert *dvert_dst= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
510                 if(dvert_dst) {
511                         if(def_nr == -1) {
512                                 /* all vgroups, add groups where neded  */
513
514                                 int *flip_map= defgroup_flip_map(ob, 1);
515                                 defvert_sync_mapped(dvert_dst, dvert_src, flip_map, 1);
516                                 MEM_freeN(flip_map);
517                         }
518                         else {
519                                 /* single vgroup */
520                                 MDeformWeight *dw= defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
521                                 if(dw) {
522                                         dw->weight= defvert_find_weight(dvert_src, def_nr);
523                                 }
524                         }
525                 }
526         }
527 }
528
529 static void vgroup_adjust_active(Object *ob, int def_nr)
530 {
531         EditVert *eve_act;
532         MDeformVert *dvert_act;
533
534         act_vert_def(ob, &eve_act, &dvert_act);
535
536         if(dvert_act) {
537                 if(((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X)
538                         editvert_mirror_update(ob, eve_act, def_nr, -1);
539         }
540 }
541
542 static void vgroup_copy_active_to_sel(Object *ob)
543 {
544         EditVert *eve_act;
545         MDeformVert *dvert_act;
546
547         act_vert_def(ob, &eve_act, &dvert_act);
548
549         if(dvert_act==NULL) {
550                 return;
551         }
552         else {
553                 Mesh *me= ob->data;
554                 EditMesh *em = BKE_mesh_get_editmesh(me);
555                 EditVert *eve;
556                 MDeformVert *dvert;
557                 int index= 0;
558
559                 for(eve= em->verts.first; eve; eve= eve->next, index++) {
560                         if(eve->f & SELECT && eve != eve_act) {
561                                 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
562                                 if(dvert) {
563                                         defvert_copy(dvert, dvert_act);
564
565                                         if(me->editflag & ME_EDIT_MIRROR_X)
566                                                 editvert_mirror_update(ob, eve, -1, index);
567
568                                 }
569                         }
570                 }
571         }
572 }
573
574 static void vgroup_copy_active_to_sel_single(Object *ob, int def_nr)
575 {
576         EditVert *eve_act;
577         MDeformVert *dvert_act;
578
579         act_vert_def(ob, &eve_act, &dvert_act);
580
581         if(dvert_act==NULL) {
582                 return;
583         }
584         else {
585                 Mesh *me= ob->data;
586                 EditMesh *em = BKE_mesh_get_editmesh(me);
587                 EditVert *eve;
588                 MDeformVert *dvert;
589                 MDeformWeight *dw;
590                 float act_weight = -1.0f;
591                 int i;
592                 int index= 0;
593
594                 for(i=0, dw=dvert_act->dw; i < dvert_act->totweight; i++, dw++) {
595                         if(def_nr == dw->def_nr) {
596                                 act_weight= dw->weight;
597                                 break;
598                         }
599                 }
600
601                 if(act_weight < -0.5f)
602                         return;
603
604                 for(eve= em->verts.first; eve; eve= eve->next, index++) {
605                         if(eve->f & SELECT && eve != eve_act) {
606                                 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
607                                 if(dvert) {
608                                         for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
609                                                 if(def_nr == dw->def_nr) {
610                                                         dw->weight= act_weight;
611
612                                                         if(me->editflag & ME_EDIT_MIRROR_X)
613                                                                 editvert_mirror_update(ob, eve, -1, index);
614
615                                                         break;
616                                                 }
617                                         }
618                                 }
619                         }
620                 }
621
622                 if(me->editflag & ME_EDIT_MIRROR_X)
623                         editvert_mirror_update(ob, eve_act, -1, -1);
624
625         }
626 }
627
628 static void vgroup_normalize_active(Object *ob)
629 {
630         EditVert *eve_act;
631         MDeformVert *dvert_act;
632
633         act_vert_def(ob, &eve_act, &dvert_act);
634
635         if(dvert_act==NULL)
636                 return;
637
638         defvert_normalize(dvert_act);
639
640         if(((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X)
641                 editvert_mirror_update(ob, eve_act, -1, -1);
642
643
644
645 }
646
647 static void do_view3d_vgroup_buttons(bContext *C, void *arg, int event)
648 {
649         Scene *scene= CTX_data_scene(C);
650         Object *ob= OBACT;
651
652         if(event==B_VGRP_PNL_NORMALIZE) {
653                 vgroup_normalize_active(ob);
654         }
655         else if(event == B_VGRP_PNL_COPY) {
656                 vgroup_copy_active_to_sel(ob);
657         }
658         else if(event >= B_VGRP_PNL_COPY_SINGLE) {
659                 vgroup_copy_active_to_sel_single(ob, event - B_VGRP_PNL_COPY_SINGLE);
660         }
661         else if(event >= B_VGRP_PNL_EDIT_SINGLE) {
662                 vgroup_adjust_active(ob, event - B_VGRP_PNL_EDIT_SINGLE);
663         }
664
665 //  todo
666 //      if(((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X)
667 //              ED_vgroup_mirror(ob, 1, 1, 0);
668
669         /* default for now */
670         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
671         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
672 }
673
674 int view3d_panel_vgroup_poll(const bContext *C, PanelType *pt)
675 {
676         Scene *scene= CTX_data_scene(C);
677         Object *ob= OBACT;
678         EditVert *eve_act;
679         MDeformVert *dvert_act;
680
681         act_vert_def(ob, &eve_act, &dvert_act);
682
683         return dvert_act ? dvert_act->totweight : 0;
684 }
685
686
687 static void view3d_panel_vgroup(const bContext *C, Panel *pa)
688 {
689         uiBlock *block= uiLayoutAbsoluteBlock(pa->layout);
690         Scene *scene= CTX_data_scene(C);
691         Object *ob= OBACT;
692
693         EditVert *eve;
694         MDeformVert *dvert;
695
696         act_vert_def(ob, &eve, &dvert);
697
698         if(dvert && dvert->totweight) {
699                 uiLayout *col;
700                 bDeformGroup *dg;
701                 int i;
702                 int yco = 0;
703
704                 uiBlockSetHandleFunc(block, do_view3d_vgroup_buttons, NULL);
705
706                 col= uiLayoutColumn(pa->layout, 0);
707                 block= uiLayoutAbsoluteBlock(col);
708
709                 uiBlockBeginAlign(block);
710
711                 for (i=0; i<dvert->totweight; i++){
712                         dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
713                         if(dg) {
714                                 uiDefButF(block, NUM, B_VGRP_PNL_EDIT_SINGLE + dvert->dw[i].def_nr, dg->name,   0, yco, 180, 20, &dvert->dw[i].weight, 0.0, 1.0, 1, 3, "");
715                                 uiDefBut(block, BUT, B_VGRP_PNL_COPY_SINGLE + dvert->dw[i].def_nr, "C", 180,yco,20,20, 0, 0, 0, 0, 0, "Copy this groups weight to other selected verts");
716                                 yco -= 20;
717                         }
718                 }
719                 yco-=2;
720
721                 uiBlockEndAlign(block);
722                 uiBlockBeginAlign(block);
723                 uiDefBut(block, BUT, B_VGRP_PNL_NORMALIZE, "Normalize", 0, yco,100,20, 0, 0, 0, 0, 0, "Normalize active vertex weights");
724                 uiDefBut(block, BUT, B_VGRP_PNL_COPY, "Copy", 100,yco,100,20, 0, 0, 0, 0, 0, "Copy active vertex to other seleted verts");
725                 uiBlockEndAlign(block);
726         }
727 }
728
729 static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
730 {
731         uiLayout *split, *colsub;
732         
733         split = uiLayoutSplit(layout, 0.8, 0);
734         
735         if (ptr->type == &RNA_PoseBone) {
736                 PointerRNA boneptr;
737                 Bone *bone;
738                 
739                 boneptr = RNA_pointer_get(ptr, "bone");
740                 bone = boneptr.data;
741                 uiLayoutSetActive(split, !(bone->parent && bone->flag & BONE_CONNECTED));
742         }
743         colsub = uiLayoutColumn(split, 1);
744         uiItemR(colsub, ptr, "location", 0, "Location", 0);
745         colsub = uiLayoutColumn(split, 1);
746         uiItemL(colsub, "", 0);
747         uiItemR(colsub, ptr, "lock_location", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", 0);
748         
749         split = uiLayoutSplit(layout, 0.8, 0);
750         
751         switch(RNA_enum_get(ptr, "rotation_mode")) {
752                 case ROT_MODE_QUAT: /* quaternion */
753                         colsub = uiLayoutColumn(split, 1);
754                         uiItemR(colsub, ptr, "rotation_quaternion", 0, "Rotation", 0);
755                         colsub = uiLayoutColumn(split, 1);
756                         uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, "4L", 0);
757                         if (RNA_boolean_get(ptr, "lock_rotations_4d"))
758                                 uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", 0);
759                         else
760                                 uiItemL(colsub, "", 0);
761                         uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", 0);
762                         break;
763                 case ROT_MODE_AXISANGLE: /* axis angle */
764                         colsub = uiLayoutColumn(split, 1);
765                         uiItemR(colsub, ptr, "rotation_axis_angle", 0, "Rotation", 0);
766                         colsub = uiLayoutColumn(split, 1);
767                         uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, "4L", 0);
768                         if (RNA_boolean_get(ptr, "lock_rotations_4d"))
769                                 uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", 0);
770                         else
771                                 uiItemL(colsub, "", 0);
772                         uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", 0);
773                         break;
774                 default: /* euler rotations */
775                         colsub = uiLayoutColumn(split, 1);
776                         uiItemR(colsub, ptr, "rotation_euler", 0, "Rotation", 0);
777                         colsub = uiLayoutColumn(split, 1);
778                         uiItemL(colsub, "", 0);
779                         uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", 0);
780                         break;
781         }
782         uiItemR(layout, ptr, "rotation_mode", 0, "", 0);
783         
784         split = uiLayoutSplit(layout, 0.8, 0);
785         colsub = uiLayoutColumn(split, 1);
786         uiItemR(colsub, ptr, "scale", 0, "Scale", 0);
787         colsub = uiLayoutColumn(split, 1);
788         uiItemL(colsub, "", 0);
789         uiItemR(colsub, ptr, "lock_scale", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", 0);
790         
791         if (ptr->type == &RNA_Object) {
792                 Object *ob = ptr->data;
793                 if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
794                         uiItemR(layout, ptr, "dimensions", 0, "Dimensions", 0);
795         }
796 }
797
798 static void v3d_posearmature_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim)
799 {
800 //      uiBlock *block= uiLayoutGetBlock(layout);
801 //      bArmature *arm;
802         bPoseChannel *pchan;
803 //      TransformProperties *tfp= v3d->properties_storage;
804         PointerRNA pchanptr;
805         uiLayout *col;
806 //      uiLayout *row;
807
808         pchan= get_active_posechannel(ob);
809
810 //      row= uiLayoutRow(layout, 0);
811         
812         if (!pchan)     {
813                 uiItemL(layout, "No Bone Active", 0);
814                 return; 
815         }
816
817         RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &pchanptr);
818
819         col= uiLayoutColumn(layout, 0);
820         
821         /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.)
822          * but oldskool UI shows in eulers always. Do we want to be able to still display in Eulers?
823          * Maybe needs RNA/ui options to display rotations as different types... */
824         v3d_transform_butsR(col, &pchanptr);
825
826 #if 0
827         uiLayoutAbsoluteBlock(layout);
828
829         if (pchan->rotmode == ROT_MODE_AXISANGLE) {
830                 float quat[4];
831                 /* convert to euler, passing through quats... */
832                 axis_angle_to_quat(quat, pchan->rotAxis, pchan->rotAngle);
833                 quat_to_eul( tfp->ob_eul,quat);
834         }
835         else if (pchan->rotmode == ROT_MODE_QUAT)
836                 quat_to_eul( tfp->ob_eul,pchan->quat);
837         else
838                 copy_v3_v3(tfp->ob_eul, pchan->eul);
839         tfp->ob_eul[0]*= 180.0/M_PI;
840         tfp->ob_eul[1]*= 180.0/M_PI;
841         tfp->ob_eul[2]*= 180.0/M_PI;
842         
843         uiDefBut(block, LABEL, 0, "Location:",                  0, 240, 100, 20, 0, 0, 0, 0, 0, "");
844         uiBlockBeginAlign(block);
845         uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:",   0, 220, 120, 19, pchan->loc, -lim, lim, 100, 3, "");
846         uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:",   0, 200, 120, 19, pchan->loc+1, -lim, lim, 100, 3, "");
847         uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:",   0, 180, 120, 19, pchan->loc+2, -lim, lim, 100, 3, "");
848         uiBlockEndAlign(block);
849         
850         uiBlockBeginAlign(block);
851         uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCX, B_REDR, ICON_UNLOCKED,   125, 220, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Location value from being Transformed");
852         uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCY, B_REDR, ICON_UNLOCKED,   125, 200, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Location value from being Transformed");
853         uiDefIconButBitS(block, ICONTOG, OB_LOCK_LOCZ, B_REDR, ICON_UNLOCKED,   125, 180, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Z Location value from being Transformed");
854         uiBlockEndAlign(block);
855         
856         uiDefBut(block, LABEL, 0, "Rotation:",                  0, 160, 100, 20, 0, 0, 0, 0, 0, "");
857         uiBlockBeginAlign(block);
858         uiDefButF(block, NUM, B_ARMATUREPANEL3, "X:",   0, 140, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, "");
859         uiDefButF(block, NUM, B_ARMATUREPANEL3, "Y:",   0, 120, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, "");
860         uiDefButF(block, NUM, B_ARMATUREPANEL3, "Z:",   0, 100, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, "");
861         uiBlockEndAlign(block);
862         
863         uiBlockBeginAlign(block);
864         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTX, B_REDR, ICON_UNLOCKED,   125, 140, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Rotation value from being Transformed");
865         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTY, B_REDR, ICON_UNLOCKED,   125, 120, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Rotation value from being Transformed");
866         uiDefIconButBitS(block, ICONTOG, OB_LOCK_ROTZ, B_REDR, ICON_UNLOCKED,   125, 100, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Z Rotation value from being Transformed");
867         uiBlockEndAlign(block);
868         
869         uiDefBut(block, LABEL, 0, "Scale:",                             0, 80, 100, 20, 0, 0, 0, 0, 0, "");
870         uiBlockBeginAlign(block);
871         uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:",   0, 60, 120, 19, pchan->size, -lim, lim, 10, 3, "");
872         uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:",   0, 40, 120, 19, pchan->size+1, -lim, lim, 10, 3, "");
873         uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:",   0, 20, 120, 19, pchan->size+2, -lim, lim, 10, 3, "");
874         uiBlockEndAlign(block);
875         
876         uiBlockBeginAlign(block);
877         uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEX, B_REDR, ICON_UNLOCKED, 125, 60, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects X Scale value from being Transformed");
878         uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEY, B_REDR, ICON_UNLOCKED, 125, 40, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects Y Scale value from being Transformed");
879         uiDefIconButBitS(block, ICONTOG, OB_LOCK_SCALEZ, B_REDR, ICON_UNLOCKED, 125, 20, 25, 19, &(pchan->protectflag), 0, 0, 0, 0, "Protects z Scale value from being Transformed");
880         uiBlockEndAlign(block);
881 #endif
882 }
883
884 /* assumes armature editmode */
885 void validate_editbonebutton_cb(bContext *C, void *bonev, void *namev)
886 {
887         EditBone *eBone= bonev;
888         char oldname[32], newname[32];
889         
890         /* need to be on the stack */
891         BLI_strncpy(newname, eBone->name, 32);
892         BLI_strncpy(oldname, (char *)namev, 32);
893         /* restore */
894         BLI_strncpy(eBone->name, oldname, 32);
895         
896         ED_armature_bone_rename(CTX_data_edit_object(C)->data, oldname, newname); // editarmature.c
897         WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, CTX_data_edit_object(C)); // XXX fix
898 }
899
900 static void v3d_editarmature_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim)
901 {
902 //      uiBlock *block= uiLayoutGetBlock(layout);
903         bArmature *arm= ob->data;
904         EditBone *ebone;
905 //      TransformProperties *tfp= v3d->properties_storage;
906 //      uiLayout *row;
907         uiLayout *col;
908         PointerRNA eboneptr;
909         
910         ebone= arm->act_edbone;
911
912         if (!ebone || (ebone->layer & arm->layer)==0)
913                 return;
914         
915 //      row= uiLayoutRow(layout, 0);
916         RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &eboneptr);
917
918
919         col= uiLayoutColumn(layout, 0);
920         uiItemR(col, &eboneptr, "head", 0, "Head", 0);
921         if (ebone->parent && ebone->flag & BONE_CONNECTED ) {
922                 PointerRNA parptr = RNA_pointer_get(&eboneptr, "parent");
923                 uiItemR(col, &parptr, "tail_radius", 0, "Radius", 0);
924         } else {
925                 uiItemR(col, &eboneptr, "head_radius", 0, "Radius", 0);
926         }
927         
928         uiItemR(col, &eboneptr, "tail", 0, "Tail", 0);
929         uiItemR(col, &eboneptr, "tail_radius", 0, "Radius", 0);
930         
931         uiItemR(col, &eboneptr, "roll", 0, "Roll", 0);
932 }
933
934 static void v3d_editmetaball_buts(uiLayout *layout, Object *ob, float lim)
935 {
936         PointerRNA mbptr, ptr;
937         MetaBall *mball= ob->data;
938 //      uiLayout *row;
939         uiLayout *col;
940         
941         if (!mball || !(mball->lastelem)) return;
942         
943         RNA_pointer_create(&mball->id, &RNA_MetaBall, mball, &mbptr);
944         
945 //      row= uiLayoutRow(layout, 0);
946
947         RNA_pointer_create(&mball->id, &RNA_MetaElement, mball->lastelem, &ptr);
948         
949         col= uiLayoutColumn(layout, 0);
950         uiItemR(col, &ptr, "location", 0, "Location", 0);
951         
952         uiItemR(col, &ptr, "radius", 0, "Radius", 0);
953         uiItemR(col, &ptr, "stiffness", 0, "Stiffness", 0);
954         
955         uiItemR(col, &ptr, "type", 0, "Type", 0);
956         
957         col= uiLayoutColumn(layout, 1);
958         switch (RNA_enum_get(&ptr, "type")) {
959                 case MB_BALL:
960                         break;
961                 case MB_CUBE:
962                         uiItemL(col, "Size:", 0);
963                         uiItemR(col, &ptr, "size_x", 0, "X", 0);
964                         uiItemR(col, &ptr, "size_y", 0, "Y", 0);
965                         uiItemR(col, &ptr, "size_z", 0, "Z", 0);
966                         break;
967                 case MB_TUBE:
968                         uiItemL(col, "Size:", 0);
969                         uiItemR(col, &ptr, "size_x", 0, "X", 0);
970                         break;
971                 case MB_PLANE:
972                         uiItemL(col, "Size:", 0);
973                         uiItemR(col, &ptr, "size_x", 0, "X", 0);
974                         uiItemR(col, &ptr, "size_y", 0, "Y", 0);
975                         break;
976                 case MB_ELIPSOID:
977                         uiItemL(col, "Size:", 0);
978                         uiItemR(col, &ptr, "size_x", 0, "X", 0);
979                         uiItemR(col, &ptr, "size_y", 0, "Y", 0);
980                         uiItemR(col, &ptr, "size_z", 0, "Z", 0);
981                         break;             
982         }       
983 }
984
985 /* test if 'ob' is a parent somewhere in par's parents */
986 static int test_parent_loop(Object *par, Object *ob)
987 {
988         if(par == NULL) return 0;
989         if(ob == par) return 1;
990         return test_parent_loop(par->parent, ob);
991 }
992
993 static void do_view3d_region_buttons(bContext *C, void *arg, int event)
994 {
995         Main *bmain= CTX_data_main(C);
996         Scene *scene= CTX_data_scene(C);
997 //      Object *obedit= CTX_data_edit_object(C);
998         View3D *v3d= CTX_wm_view3d(C);
999 //      BoundBox *bb;
1000         Object *ob= OBACT;
1001         TransformProperties *tfp= v3d->properties_storage;
1002         
1003         switch(event) {
1004         
1005         case B_REDR:
1006                 ED_area_tag_redraw(CTX_wm_area(C));
1007                 return; /* no notifier! */
1008                 
1009         case B_OBJECTPANEL:
1010                 DAG_id_flush_update(&ob->id, OB_RECALC_OB);
1011                 break;
1012
1013         
1014         case B_OBJECTPANELMEDIAN:
1015                 if(ob) {
1016                         v3d_editvertex_buts(C, NULL, v3d, ob, 1.0);
1017                         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1018                 }
1019                 break;
1020                 
1021                 /* note; this case also used for parbone */
1022         case B_OBJECTPANELPARENT:
1023                 if(ob) {
1024                         if(ob->id.lib || test_parent_loop(ob->parent, ob) ) 
1025                                 ob->parent= NULL;
1026                         else {
1027                                 DAG_scene_sort(bmain, scene);
1028                                 DAG_id_flush_update(&ob->id, OB_RECALC_OB);
1029                         }
1030                 }
1031                 break;
1032                 
1033
1034         case B_ARMATUREPANEL3:  // rotate button on channel
1035                 {
1036                         bPoseChannel *pchan;
1037                         float eul[3];
1038                         
1039                         pchan= get_active_posechannel(ob);
1040                         if (!pchan) return;
1041                         
1042                         /* make a copy to eul[3], to allow TAB on buttons to work */
1043                         eul[0]= M_PI*tfp->ob_eul[0]/180.0;
1044                         eul[1]= M_PI*tfp->ob_eul[1]/180.0;
1045                         eul[2]= M_PI*tfp->ob_eul[2]/180.0;
1046                         
1047                         if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1048                                 float quat[4];
1049                                 /* convert to axis-angle, passing through quats  */
1050                                 eul_to_quat( quat,eul);
1051                                 quat_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,quat);
1052                         }
1053                         else if (pchan->rotmode == ROT_MODE_QUAT)
1054                                 eul_to_quat( pchan->quat,eul);
1055                         else
1056                                 copy_v3_v3(pchan->eul, eul);
1057                 }
1058                 /* no break, pass on */
1059         case B_ARMATUREPANEL2:
1060                 {
1061                         ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
1062                         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1063                 }
1064                 break;
1065         case B_TRANSFORMSPACEADD:
1066                 BIF_createTransformOrientation(C, NULL, "", 1, 0);
1067                 break;
1068         case B_TRANSFORMSPACECLEAR:
1069                 BIF_clearTransformOrientation(C);
1070                 break;
1071                 
1072 #if 0 // XXX
1073         case B_WEIGHT0_0:
1074                 wpaint->weight = 0.0f;
1075                 break;
1076                 
1077         case B_WEIGHT1_4:
1078                 wpaint->weight = 0.25f;
1079                 break;
1080         case B_WEIGHT1_2:
1081                 wpaint->weight = 0.5f;
1082                 break;
1083         case B_WEIGHT3_4:
1084                 wpaint->weight = 0.75f;
1085                 break;
1086         case B_WEIGHT1_0:
1087                 wpaint->weight = 1.0f;
1088                 break;
1089                 
1090         case B_OPA1_8:
1091                 wpaint->a = 0.125f;
1092                 break;
1093         case B_OPA1_4:
1094                 wpaint->a = 0.25f;
1095                 break;
1096         case B_OPA1_2:
1097                 wpaint->a = 0.5f;
1098                 break;
1099         case B_OPA3_4:
1100                 wpaint->a = 0.75f;
1101                 break;
1102         case B_OPA1_0:
1103                 wpaint->a = 1.0f;
1104                 break;
1105 #endif
1106         case B_CLR_WPAINT:
1107 //              if(!multires_level1_test()) {
1108                 {
1109                         bDeformGroup *defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
1110                         if(defGroup) {
1111                                 Mesh *me= ob->data;
1112                                 int a;
1113                                 for(a=0; a<me->totvert; a++)
1114                                         ED_vgroup_vert_remove (ob, defGroup, a);
1115                                 DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
1116                         }
1117                 }
1118                 break;
1119         case B_RV3D_LOCKED:
1120         case B_RV3D_BOXVIEW:
1121         case B_RV3D_BOXCLIP:
1122                 {
1123                         ScrArea *sa= CTX_wm_area(C);
1124                         ARegion *ar= sa->regionbase.last;
1125                         RegionView3D *rv3d;
1126                         short viewlock;
1127                         
1128                         ar= ar->prev;
1129                         rv3d= ar->regiondata;
1130                         viewlock= rv3d->viewlock;
1131                         
1132                         if((viewlock & RV3D_LOCKED)==0)
1133                                 viewlock= 0;
1134                         else if((viewlock & RV3D_BOXVIEW)==0)
1135                                 viewlock &= ~RV3D_BOXCLIP;
1136                         
1137                         for(; ar; ar= ar->prev) {
1138                                 if(ar->alignment==RGN_ALIGN_QSPLIT) {
1139                                         rv3d= ar->regiondata;
1140                                         rv3d->viewlock= viewlock;
1141                                 }
1142                         }
1143                         
1144                         if(rv3d->viewlock & RV3D_BOXVIEW)
1145                                 view3d_boxview_copy(sa, sa->regionbase.last);
1146                         
1147                         ED_area_tag_redraw(sa);
1148                 }
1149                 break;
1150         }
1151
1152         /* default for now */
1153         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, ob);
1154 }
1155
1156 void removeTransformOrientation_func(bContext *C, void *target, void *unused)
1157 {
1158         BIF_removeTransformOrientation(C, (TransformOrientation *) target);
1159 }
1160
1161 void selectTransformOrientation_func(bContext *C, void *target, void *unused)
1162 {
1163         BIF_selectTransformOrientation(C, (TransformOrientation *) target);
1164 }
1165
1166 static void view3d_panel_object(const bContext *C, Panel *pa)
1167 {
1168         uiBlock *block;
1169         Scene *scene= CTX_data_scene(C);
1170         Object *obedit= CTX_data_edit_object(C);
1171         View3D *v3d= CTX_wm_view3d(C);
1172         //uiBut *bt;
1173         Object *ob= OBACT;
1174         TransformProperties *tfp;
1175         PointerRNA obptr;
1176         uiLayout *col, *row;
1177         float lim;
1178         
1179         if(ob==NULL) return;
1180
1181         /* make sure we got storage */
1182         if(v3d->properties_storage==NULL)
1183                 v3d->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties");
1184         tfp= v3d->properties_storage;
1185         
1186 // XXX  uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
1187         /*
1188         if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)) {
1189         }
1190         else {
1191                 if((ob->mode & OB_MODE_PARTICLE_EDIT)==0) {
1192                         uiBlockEndAlign(block);
1193                 }
1194         }
1195         */
1196
1197         lim= 10000.0f*MAX2(1.0, v3d->grid);
1198
1199         block= uiLayoutGetBlock(pa->layout);
1200         uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
1201
1202         col= uiLayoutColumn(pa->layout, 0);
1203         row= uiLayoutRow(col, 0);
1204         RNA_id_pointer_create(&ob->id, &obptr);
1205
1206         if(ob==obedit) {
1207                 if(ob->type==OB_ARMATURE) v3d_editarmature_buts(col, v3d, ob, lim);
1208                 if(ob->type==OB_MBALL) v3d_editmetaball_buts(col, ob, lim);
1209                 else v3d_editvertex_buts(C, col, v3d, ob, lim);
1210         }
1211         else if(ob->mode & OB_MODE_POSE) {
1212                 v3d_posearmature_buts(col, v3d, ob, lim);
1213         }
1214         else {
1215
1216                 v3d_transform_butsR(col, &obptr);
1217         }
1218 }
1219
1220 #if 0
1221 static void view3d_panel_preview(bContext *C, ARegion *ar, short cntrl) // VIEW3D_HANDLER_PREVIEW
1222 {
1223         uiBlock *block;
1224         View3D *v3d= sa->spacedata.first;
1225         int ofsx, ofsy;
1226         
1227         block= uiBeginBlock(C, ar, "view3d_panel_preview", UI_EMBOSS);
1228         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
1229         uiSetPanelHandler(VIEW3D_HANDLER_PREVIEW);  // for close and esc
1230         
1231         ofsx= -150+(sa->winx/2)/v3d->blockscale;
1232         ofsy= -100+(sa->winy/2)/v3d->blockscale;
1233         if(uiNewPanel(C, ar, block, "Preview", "View3d", ofsx, ofsy, 300, 200)==0) return;
1234
1235         uiBlockSetDrawExtraFunc(block, BIF_view3d_previewdraw);
1236         
1237         if(scene->recalc & SCE_PRV_CHANGED) {
1238                 scene->recalc &= ~SCE_PRV_CHANGED;
1239                 //printf("found recalc\n");
1240                 BIF_view3d_previewrender_free(sa->spacedata.first);
1241                 BIF_preview_changed(0);
1242         }
1243 }
1244 #endif
1245
1246 #if 0 // XXX not used
1247 static void delete_sketch_armature(bContext *C, void *arg1, void *arg2)
1248 {
1249         BIF_deleteSketch(C);
1250 }
1251
1252 static void convert_sketch_armature(bContext *C, void *arg1, void *arg2)
1253 {
1254         BIF_convertSketch(C);
1255 }
1256
1257 static void assign_template_sketch_armature(bContext *C, void *arg1, void *arg2)
1258 {
1259         int index = *(int*)arg1;
1260         BIF_setTemplate(C, index);
1261 }
1262
1263
1264 static int view3d_panel_bonesketch_spaces_poll(const bContext *C, PanelType *pt)
1265 {
1266         Object *obedit = CTX_data_edit_object(C);
1267
1268         /* replace with check call to sketching lib */
1269         return (obedit && obedit->type == OB_ARMATURE);
1270 }
1271 static void view3d_panel_bonesketch_spaces(const bContext *C, Panel *pa)
1272 {
1273         Scene *scene = CTX_data_scene(C);
1274         static int template_index;
1275         static char joint_label[128];
1276         uiBlock *block;
1277         uiBut *but;
1278         char *bone_name;
1279         int yco = 130;
1280         int nb_joints;
1281         static char subdiv_tooltip[4][64] = {
1282                 "Subdivide arcs based on a fixed number of bones",
1283                 "Subdivide arcs in bones of equal length",
1284                 "Subdivide arcs based on correlation",
1285                 "Retarget template to stroke"
1286                 };
1287
1288         
1289         block= uiLayoutAbsoluteBlock(pa->layout);
1290         uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
1291
1292         uiBlockBeginAlign(block);
1293         
1294         /* use real flag instead of 1 */
1295         uiDefButBitC(block, TOG, BONE_SKETCHING, B_REDR, "Use Bone Sketching", 10, yco, 160, 20, &scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Use sketching to create and edit bones, (Ctrl snaps to mesh volume)");
1296         uiDefButBitC(block, TOG, BONE_SKETCHING_ADJUST, B_REDR, "A", 170, yco, 20, 20, &scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Adjust strokes by drawing near them");
1297         uiDefButBitC(block, TOG, BONE_SKETCHING_QUICK, B_REDR, "Q", 190, yco, 20, 20, &scene->toolsettings->bone_sketching, 0, 0, 0, 0, "Automatically convert and delete on stroke end");
1298         yco -= 20;
1299         
1300         but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,100,20, 0, 0, 0, 0, 0, "Convert sketch to armature");
1301         uiButSetFunc(but, convert_sketch_armature, NULL, NULL);
1302
1303         but = uiDefBut(block, BUT, B_REDR, "Delete", 110,yco,100,20, 0, 0, 0, 0, 0, "Delete sketch");
1304         uiButSetFunc(but, delete_sketch_armature, NULL, NULL);
1305         yco -= 20;
1306         
1307         uiBlockEndAlign(block);
1308
1309         uiBlockBeginAlign(block);
1310         
1311         uiDefButC(block, MENU, B_REDR, "Subdivision Method%t|Length%x1|Adaptative%x2|Fixed%x0|Template%x3", 10,yco,60,19, &scene->toolsettings->bone_sketching_convert, 0, 0, 0, 0, subdiv_tooltip[(unsigned char)scene->toolsettings->bone_sketching_convert]);
1312
1313         switch(scene->toolsettings->bone_sketching_convert)
1314         {
1315         case SK_CONVERT_CUT_LENGTH:
1316                 uiDefButF(block, NUM, B_REDR,                                   "Lim:",         70, yco, 140, 19, &scene->toolsettings->skgen_length_limit,0.1,50.0, 10, 0,             "Maximum length of the subdivided bones");
1317                 yco -= 20;
1318                 break;
1319         case SK_CONVERT_CUT_ADAPTATIVE:
1320                 uiDefButF(block, NUM, B_REDR,                                   "Thres:",                       70, yco, 140, 19, &scene->toolsettings->skgen_correlation_limit,0.0, 1.0, 0.01, 0,      "Correlation threshold for subdivision");
1321                 yco -= 20;
1322                 break;
1323         default:
1324         case SK_CONVERT_CUT_FIXED:
1325                 uiDefButC(block, NUM, B_REDR,                                   "Num:",         70, yco, 140, 19, &scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5,  "Number of subdivided bones");
1326                 yco -= 20;
1327                 break;
1328         case SK_CONVERT_RETARGET:
1329                 uiDefButC(block, ROW, B_NOP, "No",                      70,  yco, 40,19, &scene->toolsettings->skgen_retarget_roll, 0, 0, 0, 0,                                                                 "No special roll treatment");
1330                 uiDefButC(block, ROW, B_NOP, "View",            110,  yco, 50,19, &scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_VIEW, 0, 0,                            "Roll bones perpendicular to view");
1331                 uiDefButC(block, ROW, B_NOP, "Joint",           160, yco, 50,19, &scene->toolsettings->skgen_retarget_roll, 0, SK_RETARGET_ROLL_JOINT, 0, 0,                            "Roll bones relative to joint bend");
1332                 yco -= 30;
1333
1334                 uiBlockEndAlign(block);
1335
1336                 uiBlockBeginAlign(block);
1337                 /* button here to select what to do (copy or not), template, ...*/
1338
1339                 BIF_makeListTemplates(C);
1340                 template_index = BIF_currentTemplate(C);
1341                 
1342                 but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(C), 10,yco,200,19, &template_index, 0, 0, 0, 0, "Template");
1343                 uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL);
1344                 
1345                 yco -= 20;
1346                 
1347                 uiDefButF(block, NUM, B_NOP,                                                    "A:",                   10, yco, 66,19, &scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0,         "Angle Weight");
1348                 uiDefButF(block, NUM, B_NOP,                                                    "L:",                   76, yco, 67,19, &scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0,                "Length Weight");
1349                 uiDefButF(block, NUM, B_NOP,                                                    "D:",           143,yco, 67,19, &scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0,              "Distance Weight");
1350                 yco -= 20;
1351                 
1352                 uiDefBut(block, TEX,B_REDR,"S:",                                                        10,  yco, 90, 20, scene->toolsettings->skgen_side_string, 0.0, 8.0, 0, 0, "Text to replace &S with");
1353                 uiDefBut(block, TEX,B_REDR,"N:",                                                        100, yco, 90, 20, scene->toolsettings->skgen_num_string, 0.0, 8.0, 0, 0, "Text to replace &N with");
1354                 uiDefIconButBitC(block, TOG, SK_RETARGET_AUTONAME, B_NOP, ICON_AUTO,190,yco,20,20, &scene->toolsettings->skgen_retarget_options, 0, 0, 0, 0, "Use Auto Naming");        
1355                 yco -= 20;
1356
1357                 /* auto renaming magic */
1358                 uiBlockEndAlign(block);
1359                 
1360                 nb_joints = BIF_nbJointsTemplate(C);
1361
1362                 if (nb_joints == -1)
1363                 {
1364                         //XXX
1365                         //nb_joints = G.totvertsel;
1366                 }
1367                 
1368                 bone_name = BIF_nameBoneTemplate(C);
1369                 
1370                 BLI_snprintf(joint_label, 32, "%i joints: %s", nb_joints, bone_name);
1371                 
1372                 uiDefBut(block, LABEL, 1, joint_label,                                  10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, "");
1373                 yco -= 20;
1374                 break;
1375         }
1376
1377         uiBlockEndAlign(block);
1378 }
1379
1380 /* op->invoke */
1381 static void redo_cb(bContext *C, void *arg_op, void *arg2)
1382 {
1383         wmOperator *lastop= arg_op;
1384         
1385         if(lastop) {
1386                 int retval;
1387                 
1388                 if (G.f & G_DEBUG)
1389                         printf("operator redo %s\n", lastop->type->name);
1390                 ED_undo_pop(C);
1391                 retval= WM_operator_repeat(C, lastop);
1392                 if((retval & OPERATOR_FINISHED)==0) {
1393                         if (G.f & G_DEBUG)
1394                                 printf("operator redo failed %s\n", lastop->type->name);
1395                         ED_undo_redo(C);
1396                 }
1397         }
1398 }
1399
1400 static void view3d_panel_operator_redo(const bContext *C, Panel *pa)
1401 {
1402         wmWindowManager *wm= CTX_wm_manager(C);
1403         wmOperator *op;
1404         PointerRNA ptr;
1405         uiBlock *block;
1406         
1407         block= uiLayoutGetBlock(pa->layout);
1408
1409         /* only for operators that are registered and did an undo push */
1410         for(op= wm->operators.last; op; op= op->prev)
1411                 if((op->type->flag & OPTYPE_REGISTER) && (op->type->flag & OPTYPE_UNDO))
1412                         break;
1413         
1414         if(op==NULL)
1415                 return;
1416         
1417         uiBlockSetFunc(block, redo_cb, op, NULL);
1418         
1419         if(!op->properties) {
1420                 IDPropertyTemplate val = {0};
1421                 op->properties= IDP_New(IDP_GROUP, val, "wmOperatorProperties");
1422         }
1423         
1424         RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
1425         uiDefAutoButsRNA(C, pa->layout, &ptr, 2);
1426 }
1427 #endif // XXX not used
1428
1429 void view3d_buttons_register(ARegionType *art)
1430 {
1431         PanelType *pt;
1432
1433         pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
1434         strcpy(pt->idname, "VIEW3D_PT_object");
1435         strcpy(pt->label, "Transform");
1436         pt->draw= view3d_panel_object;
1437         BLI_addtail(&art->paneltypes, pt);
1438         
1439         pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
1440         strcpy(pt->idname, "VIEW3D_PT_gpencil");
1441         strcpy(pt->label, "Grease Pencil");
1442         pt->draw= gpencil_panel_standard;
1443         BLI_addtail(&art->paneltypes, pt);
1444
1445         pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
1446         strcpy(pt->idname, "VIEW3D_PT_vgroup");
1447         strcpy(pt->label, "Vertex Groups");
1448         pt->draw= view3d_panel_vgroup;
1449         pt->poll= view3d_panel_vgroup_poll;
1450         BLI_addtail(&art->paneltypes, pt);
1451
1452         // XXX view3d_panel_preview(C, ar, 0);
1453 }
1454
1455 static int view3d_properties(bContext *C, wmOperator *op)
1456 {
1457         ScrArea *sa= CTX_wm_area(C);
1458         ARegion *ar= view3d_has_buttons_region(sa);
1459         
1460         if(ar)
1461                 ED_region_toggle_hidden(C, ar);
1462
1463         return OPERATOR_FINISHED;
1464 }
1465
1466 void VIEW3D_OT_properties(wmOperatorType *ot)
1467 {
1468         ot->name= "Properties";
1469         ot->description= "Toggles the properties panel display";
1470         ot->idname= "VIEW3D_OT_properties";
1471         
1472         ot->exec= view3d_properties;
1473         ot->poll= ED_operator_view3d_active;
1474         
1475         /* flags */
1476         ot->flag= 0;
1477 }