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