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