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