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