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