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