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