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