Blender  V2.59
view3d_buttons.c
Go to the documentation of this file.
00001 /*
00002  * $Id: view3d_buttons.c 38423 2011-07-15 23:55:20Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2009 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Blender Foundation
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <string.h>
00035 #include <stdio.h>
00036 #include <math.h>
00037 #include <float.h>
00038 
00039 #include "DNA_armature_types.h"
00040 #include "DNA_curve_types.h"
00041 #include "DNA_lattice_types.h"
00042 #include "DNA_meta_types.h"
00043 #include "DNA_meshdata_types.h"
00044 #include "DNA_object_types.h"
00045 #include "DNA_scene_types.h"
00046 
00047 #include "MEM_guardedalloc.h"
00048 
00049 #include "BLI_math.h"
00050 #include "BLI_blenlib.h"
00051 #include "BLI_editVert.h"
00052 #include "BLI_rand.h"
00053 #include "BLI_utildefines.h"
00054 
00055 #include "BKE_action.h"
00056 #include "BKE_context.h"
00057 #include "BKE_curve.h"
00058 #include "BKE_customdata.h"
00059 #include "BKE_depsgraph.h"
00060 #include "BKE_main.h"
00061 #include "BKE_mesh.h"
00062 #include "BKE_screen.h"
00063 #include "BKE_deform.h"
00064 
00065 #include "WM_api.h"
00066 #include "WM_types.h"
00067 
00068 #include "RNA_access.h"
00069 
00070 #include "ED_armature.h"
00071 #include "ED_gpencil.h"
00072 #include "ED_mesh.h"
00073 #include "ED_screen.h"
00074 #include "ED_transform.h"
00075 #include "ED_curve.h"
00076 
00077 #include "UI_interface.h"
00078 #include "UI_resources.h"
00079 
00080 #include "view3d_intern.h"      // own include
00081 
00082 
00083 /* ******************* view3d space & buttons ************** */
00084 #define B_NOP           1
00085 #define B_REDR          2
00086 #define B_OBJECTPANELROT        1007
00087 #define B_OBJECTPANELMEDIAN 1008
00088 #define B_ARMATUREPANEL1        1009
00089 #define B_ARMATUREPANEL2        1010
00090 #define B_OBJECTPANELPARENT 1011
00091 #define B_OBJECTPANEL           1012
00092 #define B_ARMATUREPANEL3        1013
00093 #define B_OBJECTPANELSCALE      1014
00094 #define B_OBJECTPANELDIMS       1015
00095 #define B_TRANSFORMSPACEADD     1016
00096 #define B_TRANSFORMSPACECLEAR   1017
00097 #define B_SETPT_AUTO    2125
00098 #define B_SETPT_VECTOR  2126
00099 #define B_SETPT_ALIGN   2127
00100 #define B_SETPT_FREE    2128
00101 #define B_RECALCMBALL   2501
00102 
00103 #define B_WEIGHT0_0             2840
00104 #define B_WEIGHT1_4             2841
00105 #define B_WEIGHT1_2             2842
00106 #define B_WEIGHT3_4             2843
00107 #define B_WEIGHT1_0             2844
00108 
00109 #define B_OPA1_8                2845
00110 #define B_OPA1_4                2846
00111 #define B_OPA1_2                2847
00112 #define B_OPA3_4                2848
00113 #define B_OPA1_0                2849
00114 
00115 #define B_CLR_WPAINT    2850
00116 
00117 #define B_RV3D_LOCKED   2900
00118 #define B_RV3D_BOXVIEW  2901
00119 #define B_RV3D_BOXCLIP  2902
00120 
00121 #define B_IDNAME                3000
00122 
00123 /* temporary struct for storing transform properties */
00124 typedef struct {
00125         float ob_eul[4];        // used for quat too....
00126         float ob_scale[3]; // need temp space due to linked values
00127         float ob_dims[3];
00128         short link_scale;
00129         float ve_median[6];
00130         int curdef;
00131         float *defweightp;
00132 } TransformProperties;
00133 
00134 
00135 /* is used for both read and write... */
00136 static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float lim)
00137 {
00138         uiBlock *block= (layout)? uiLayoutAbsoluteBlock(layout): NULL;
00139         MDeformVert *dvert=NULL;
00140         TransformProperties *tfp;
00141         float median[6], ve_median[6];
00142         int tot, totw, totweight, totedge, totradius;
00143         char defstr[320];
00144         
00145         median[0]= median[1]= median[2]= median[3]= median[4]= median[5]= 0.0;
00146         tot= totw= totweight= totedge= totradius= 0;
00147         defstr[0]= 0;
00148 
00149         /* make sure we got storage */
00150         if(v3d->properties_storage==NULL)
00151                 v3d->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties");
00152         tfp= v3d->properties_storage;
00153         
00154         if(ob->type==OB_MESH) {
00155                 Mesh *me= ob->data;
00156                 EditMesh *em = BKE_mesh_get_editmesh(me);
00157                 EditVert *eve, *evedef=NULL;
00158                 EditEdge *eed;
00159                 
00160                 eve= em->verts.first;
00161                 while(eve) {
00162                         if(eve->f & SELECT) {
00163                                 evedef= eve;
00164                                 tot++;
00165                                 add_v3_v3(median, eve->co);
00166                         }
00167                         eve= eve->next;
00168                 }
00169                 eed= em->edges.first;
00170                 while(eed) {
00171                         if((eed->f & SELECT)) {
00172                                 totedge++;
00173                                 median[3]+= eed->crease;
00174                         }
00175                         eed= eed->next;
00176                 }
00177 
00178                 /* check for defgroups */
00179                 if(evedef)
00180                         dvert= CustomData_em_get(&em->vdata, evedef->data, CD_MDEFORMVERT);
00181                 if(tot==1 && dvert && dvert->totweight) {
00182                         bDeformGroup *dg;
00183                         int i, max=1, init=1;
00184                         char str[320];
00185                         
00186                         for (i=0; i<dvert->totweight; i++){
00187                                 dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
00188                                 if(dg) {
00189                                         max+= BLI_snprintf(str, sizeof(str), "%s %%x%d|", dg->name, dvert->dw[i].def_nr); 
00190                                         if(max<320) strcat(defstr, str);
00191                                 }
00192 
00193                                 if(tfp->curdef==dvert->dw[i].def_nr) {
00194                                         init= 0;
00195                                         tfp->defweightp= &dvert->dw[i].weight;
00196                                 }
00197                         }
00198                         
00199                         if(init) {      // needs new initialized 
00200                                 tfp->curdef= dvert->dw[0].def_nr;
00201                                 tfp->defweightp= &dvert->dw[0].weight;
00202                         }
00203                 }
00204 
00205                 BKE_mesh_end_editmesh(me, em);
00206         }
00207         else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
00208                 Curve *cu= ob->data;
00209                 Nurb *nu;
00210                 BPoint *bp;
00211                 BezTriple *bezt;
00212                 int a;
00213                 ListBase *nurbs= ED_curve_editnurbs(cu);
00214 
00215                 nu= nurbs->first;
00216                 while(nu) {
00217                         if(nu->type == CU_BEZIER) {
00218                                 bezt= nu->bezt;
00219                                 a= nu->pntsu;
00220                                 while(a--) {
00221                                         if(bezt->f2 & SELECT) {
00222                                                 add_v3_v3(median, bezt->vec[1]);
00223                                                 tot++;
00224                                                 median[4]+= bezt->weight;
00225                                                 totweight++;
00226                                                 median[5]+= bezt->radius;
00227                                                 totradius++;
00228                                         }
00229                                         else {
00230                                                 if(bezt->f1 & SELECT) {
00231                                                         add_v3_v3(median, bezt->vec[0]);
00232                                                         tot++;
00233                                                 }
00234                                                 if(bezt->f3 & SELECT) {
00235                                                         add_v3_v3(median, bezt->vec[2]);
00236                                                         tot++;
00237                                                 }
00238                                         }
00239                                         bezt++;
00240                                 }
00241                         }
00242                         else {
00243                                 bp= nu->bp;
00244                                 a= nu->pntsu*nu->pntsv;
00245                                 while(a--) {
00246                                         if(bp->f1 & SELECT) {
00247                                                 add_v3_v3(median, bp->vec);
00248                                                 median[3]+= bp->vec[3];
00249                                                 totw++;
00250                                                 tot++;
00251                                                 median[4]+= bp->weight;
00252                                                 totweight++;
00253                                                 median[5]+= bp->radius;
00254                                                 totradius++;
00255                                         }
00256                                         bp++;
00257                                 }
00258                         }
00259                         nu= nu->next;
00260                 }
00261         }
00262         else if(ob->type==OB_LATTICE) {
00263                 Lattice *lt= ob->data;
00264                 BPoint *bp;
00265                 int a;
00266                 
00267                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
00268                 bp= lt->editlatt->latt->def;
00269                 while(a--) {
00270                         if(bp->f1 & SELECT) {
00271                                 add_v3_v3(median, bp->vec);
00272                                 tot++;
00273                                 median[4]+= bp->weight;
00274                                 totweight++;
00275                         }
00276                         bp++;
00277                 }
00278         }
00279         
00280         if(tot==0) {
00281                 uiDefBut(block, LABEL, 0, "Nothing selected",0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
00282                 return;
00283         }
00284         median[0] /= (float)tot;
00285         median[1] /= (float)tot;
00286         median[2] /= (float)tot;
00287         if(totedge) median[3] /= (float)totedge;
00288         else if(totw) median[3] /= (float)totw;
00289         if(totweight) median[4] /= (float)totweight;
00290         if(totradius) median[5] /= (float)totradius;
00291         
00292         if(v3d->flag & V3D_GLOBAL_STATS)
00293                 mul_m4_v3(ob->obmat, median);
00294         
00295         if(block) {     // buttons
00296                 uiBut *but;
00297 
00298                 memcpy(tfp->ve_median, median, sizeof(tfp->ve_median));
00299                 
00300                 uiBlockBeginAlign(block);
00301                 if(tot==1) {
00302                         uiDefBut(block, LABEL, 0, "Vertex:",                                    0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
00303                         uiBlockBeginAlign(block);
00304 
00305                         but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:",           0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
00306                         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00307                         but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:",           0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
00308                         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00309                         but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:",           0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
00310                         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00311 
00312                         if(totw==1) {
00313                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:",        0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
00314                                 uiBlockBeginAlign(block);
00315                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
00316                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
00317                                 uiBlockEndAlign(block);
00318                                 if(totweight)
00319                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   0, 0, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 1, 3, "");
00320                                 if(totradius)
00321                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
00322                                 }
00323                         else {
00324                                 uiBlockBeginAlign(block);
00325                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
00326                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
00327                                 uiBlockEndAlign(block);
00328                                 if(totweight)
00329                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Weight:",   0, 20, 200, 20, &(tfp->ve_median[4]), 0.0, 1.0, 10, 3, "");
00330                                 if(totradius)
00331                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 20, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
00332                         }
00333                 }
00334                 else {
00335                         uiDefBut(block, LABEL, 0, "Median:",                                    0, 130, 200, 20, NULL, 0, 0, 0, 0, "");
00336                         uiBlockBeginAlign(block);
00337                         but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "X:",           0, 110, 200, 20, &(tfp->ve_median[0]), -lim, lim, 10, 3, "");
00338                         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00339                         but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Y:",           0, 90, 200, 20, &(tfp->ve_median[1]), -lim, lim, 10, 3, "");
00340                         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00341                         but= uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Z:",           0, 70, 200, 20, &(tfp->ve_median[2]), -lim, lim, 10, 3, "");
00342                         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00343                         if(totw==tot) {
00344                                 uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "W:",        0, 50, 200, 20, &(tfp->ve_median[3]), 0.01, 100.0, 1, 3, "");
00345                                 uiBlockEndAlign(block);
00346                                 uiBlockBeginAlign(block);
00347                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
00348                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 25, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
00349                                 uiBlockEndAlign(block);
00350                                 if(totweight)
00351                                         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");
00352                                 if(totradius)
00353                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 10, 3, "Radius of curve CPs");
00354                                 uiBlockEndAlign(block);
00355                         }
00356                         else {
00357                                 uiBlockBeginAlign(block);
00358                                 uiDefButBitS(block, TOG, V3D_GLOBAL_STATS, B_REDR, "Global",            0, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays global values");
00359                                 uiDefButBitS(block, TOGN, V3D_GLOBAL_STATS, B_REDR, "Local",            100, 45, 100, 20, &v3d->flag, 0, 0, 0, 0, "Displays local values");
00360                                 uiBlockEndAlign(block);
00361                                 if(totweight)
00362                                         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");
00363                                 if(totradius)
00364                                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Radius:",   0, 0, 200, 20, &(tfp->ve_median[5]), 0.0, 100.0, 1, 3, "Radius of curve CPs");
00365                                 uiBlockEndAlign(block);
00366                         }
00367                 }
00368                                 
00369                 if(totedge==1)
00370                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Crease:",   0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
00371                 else if(totedge>1)
00372                         uiDefButF(block, NUM, B_OBJECTPANELMEDIAN, "Mean Crease:",      0, 20, 200, 20, &(tfp->ve_median[3]), 0.0, 1.0, 1, 3, "");
00373                 
00374         }
00375         else {  // apply
00376                 memcpy(ve_median, tfp->ve_median, sizeof(tfp->ve_median));
00377                 
00378                 if(v3d->flag & V3D_GLOBAL_STATS) {
00379                         invert_m4_m4(ob->imat, ob->obmat);
00380                         mul_m4_v3(ob->imat, median);
00381                         mul_m4_v3(ob->imat, ve_median);
00382                 }
00383                 sub_v3_v3v3(median, ve_median, median);
00384                 median[3]= ve_median[3]-median[3];
00385                 median[4]= ve_median[4]-median[4];
00386                 median[5]= ve_median[5]-median[5];
00387                 
00388                 if(ob->type==OB_MESH) {
00389                         Mesh *me= ob->data;
00390                         EditMesh *em = BKE_mesh_get_editmesh(me);
00391 
00392                         /* allow for some rounding error becasue of matrix transform */
00393                         if(len_v3(median) > 0.000001f) {
00394                                 EditVert *eve;
00395 
00396                                 for(eve= em->verts.first; eve; eve= eve->next) {
00397                                         if(eve->f & SELECT) {
00398                                                 add_v3_v3(eve->co, median);
00399                                         }
00400                                 }
00401 
00402                                 recalc_editnormals(em);
00403                         }
00404 
00405                         if(median[3] != 0.0f) {
00406                                 EditEdge *eed;
00407                                 const float fixed_crease= (ve_median[3] <= 0.0f ? 0.0f : (ve_median[3] >= 1.0f ? 1.0f : FLT_MAX));
00408                                 
00409                                 if(fixed_crease != FLT_MAX) {
00410                                         /* simple case */
00411 
00412                                         for(eed= em->edges.first; eed; eed= eed->next) {
00413                                                 if(eed->f & SELECT) {
00414                                                         eed->crease= fixed_crease;
00415                                                 }
00416                                         }
00417                                 }
00418                                 else {
00419                                         /* scale crease to target median */
00420                                         float median_new= ve_median[3];
00421                                         float median_orig= ve_median[3] - median[3]; /* previous median value */
00422 
00423                                         /* incase of floating point error */
00424                                         CLAMP(median_orig, 0.0f, 1.0f);
00425                                         CLAMP(median_new, 0.0f, 1.0f);
00426 
00427                                         if(median_new < median_orig) {
00428                                                 /* scale down */
00429                                                 const float sca= median_new / median_orig;
00430                                                 
00431                                                 for(eed= em->edges.first; eed; eed= eed->next) {
00432                                                         if(eed->f & SELECT) {
00433                                                                 eed->crease *= sca;
00434                                                                 CLAMP(eed->crease, 0.0f, 1.0f);
00435                                                         }
00436                                                 }
00437                                         }
00438                                         else {
00439                                                 /* scale up */
00440                                                 const float sca= (1.0f - median_new) / (1.0f - median_orig);
00441 
00442                                                 for(eed= em->edges.first; eed; eed= eed->next) {
00443                                                         if(eed->f & SELECT) {
00444                                                                 eed->crease = 1.0f - ((1.0f - eed->crease) * sca);
00445                                                                 CLAMP(eed->crease, 0.0f, 1.0f);
00446                                                         }
00447                                                 }
00448                                         }
00449                                 }
00450                         }
00451 
00452                         BKE_mesh_end_editmesh(me, em);
00453                 }
00454                 else if(ob->type==OB_CURVE || ob->type==OB_SURF) {
00455                         Curve *cu= ob->data;
00456                         Nurb *nu;
00457                         BPoint *bp;
00458                         BezTriple *bezt;
00459                         int a;
00460                         ListBase *nurbs= ED_curve_editnurbs(cu);
00461 
00462                         nu= nurbs->first;
00463                         while(nu) {
00464                                 if(nu->type == CU_BEZIER) {
00465                                         bezt= nu->bezt;
00466                                         a= nu->pntsu;
00467                                         while(a--) {
00468                                                 if(bezt->f2 & SELECT) {
00469                                                         add_v3_v3(bezt->vec[0], median);
00470                                                         add_v3_v3(bezt->vec[1], median);
00471                                                         add_v3_v3(bezt->vec[2], median);
00472                                                         bezt->weight+= median[4];
00473                                                         bezt->radius+= median[5];
00474                                                 }
00475                                                 else {
00476                                                         if(bezt->f1 & SELECT) {
00477                                                                 add_v3_v3(bezt->vec[0], median);
00478                                                         }
00479                                                         if(bezt->f3 & SELECT) {
00480                                                                 add_v3_v3(bezt->vec[2], median);
00481                                                         }
00482                                                 }
00483                                                 bezt++;
00484                                         }
00485                                 }
00486                                 else {
00487                                         bp= nu->bp;
00488                                         a= nu->pntsu*nu->pntsv;
00489                                         while(a--) {
00490                                                 if(bp->f1 & SELECT) {
00491                                                         add_v3_v3(bp->vec, median);
00492                                                         bp->vec[3]+= median[3];
00493                                                         bp->weight+= median[4];
00494                                                         bp->radius+= median[5];
00495                                                 }
00496                                                 bp++;
00497                                         }
00498                                 }
00499                                 test2DNurb(nu);
00500                                 testhandlesNurb(nu); /* test for bezier too */
00501 
00502                                 nu= nu->next;
00503                         }
00504                 }
00505                 else if(ob->type==OB_LATTICE) {
00506                         Lattice *lt= ob->data;
00507                         BPoint *bp;
00508                         int a;
00509                         
00510                         a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
00511                         bp= lt->editlatt->latt->def;
00512                         while(a--) {
00513                                 if(bp->f1 & SELECT) {
00514                                         add_v3_v3(bp->vec, median);
00515                                         bp->weight+= median[4];
00516                                 }
00517                                 bp++;
00518                         }
00519                 }
00520                 
00521 //              ED_undo_push(C, "Transform properties");
00522         }
00523 }
00524 #define B_VGRP_PNL_COPY 1
00525 #define B_VGRP_PNL_NORMALIZE 2
00526 #define B_VGRP_PNL_EDIT_SINGLE 8 /* or greater */
00527 #define B_VGRP_PNL_COPY_SINGLE 16384 /* or greater */
00528 
00529 static void act_vert_def(Object *ob, EditVert **eve, MDeformVert **dvert)
00530 {
00531         if(ob && ob->mode & OB_MODE_EDIT && ob->type==OB_MESH && ob->defbase.first) {
00532                 Mesh *me= ob->data;
00533                 EditMesh *em = BKE_mesh_get_editmesh(me);
00534                 EditSelection *ese = ((EditSelection*)em->selected.last);
00535 
00536                 if(ese && ese->type == EDITVERT) {
00537                         *eve= (EditVert*)ese->data;
00538                         *dvert= CustomData_em_get(&em->vdata, (*eve)->data, CD_MDEFORMVERT);
00539                         return;
00540                 }
00541 
00542                 BKE_mesh_end_editmesh(me, em);
00543         }
00544 
00545         *eve= NULL;
00546         *dvert= NULL;
00547 }
00548 
00549 static void editvert_mirror_update(Object *ob, EditVert *eve, int def_nr, int index)
00550 {
00551         Mesh *me= ob->data;
00552         EditMesh *em = BKE_mesh_get_editmesh(me);
00553         EditVert *eve_mirr;
00554 
00555         eve_mirr= editmesh_get_x_mirror_vert(ob, em, eve, eve->co, index);
00556 
00557         if(eve_mirr && eve_mirr != eve) {
00558                 MDeformVert *dvert_src= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
00559                 MDeformVert *dvert_dst= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT);
00560                 if(dvert_dst) {
00561                         if(def_nr == -1) {
00562                                 /* all vgroups, add groups where neded  */
00563 
00564                                 int *flip_map= defgroup_flip_map(ob, 1);
00565                                 defvert_sync_mapped(dvert_dst, dvert_src, flip_map, 1);
00566                                 MEM_freeN(flip_map);
00567                         }
00568                         else {
00569                                 /* single vgroup */
00570                                 MDeformWeight *dw= defvert_verify_index(dvert_dst, defgroup_flip_index(ob, def_nr, 1));
00571                                 if(dw) {
00572                                         dw->weight= defvert_find_weight(dvert_src, def_nr);
00573                                 }
00574                         }
00575                 }
00576         }
00577 }
00578 
00579 static void vgroup_adjust_active(Object *ob, int def_nr)
00580 {
00581         EditVert *eve_act;
00582         MDeformVert *dvert_act;
00583 
00584         act_vert_def(ob, &eve_act, &dvert_act);
00585 
00586         if(dvert_act) {
00587                 if(((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X)
00588                         editvert_mirror_update(ob, eve_act, def_nr, -1);
00589         }
00590 }
00591 
00592 static void vgroup_copy_active_to_sel(Object *ob)
00593 {
00594         EditVert *eve_act;
00595         MDeformVert *dvert_act;
00596 
00597         act_vert_def(ob, &eve_act, &dvert_act);
00598 
00599         if(dvert_act==NULL) {
00600                 return;
00601         }
00602         else {
00603                 Mesh *me= ob->data;
00604                 EditMesh *em = BKE_mesh_get_editmesh(me);
00605                 EditVert *eve;
00606                 MDeformVert *dvert;
00607                 int index= 0;
00608 
00609                 for(eve= em->verts.first; eve; eve= eve->next, index++) {
00610                         if(eve->f & SELECT && eve != eve_act) {
00611                                 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
00612                                 if(dvert) {
00613                                         defvert_copy(dvert, dvert_act);
00614 
00615                                         if(me->editflag & ME_EDIT_MIRROR_X)
00616                                                 editvert_mirror_update(ob, eve, -1, index);
00617 
00618                                 }
00619                         }
00620                 }
00621         }
00622 }
00623 
00624 static void vgroup_copy_active_to_sel_single(Object *ob, int def_nr)
00625 {
00626         EditVert *eve_act;
00627         MDeformVert *dvert_act;
00628 
00629         act_vert_def(ob, &eve_act, &dvert_act);
00630 
00631         if(dvert_act==NULL) {
00632                 return;
00633         }
00634         else {
00635                 Mesh *me= ob->data;
00636                 EditMesh *em = BKE_mesh_get_editmesh(me);
00637                 EditVert *eve;
00638                 MDeformVert *dvert;
00639                 MDeformWeight *dw;
00640                 float act_weight = -1.0f;
00641                 int i;
00642                 int index= 0;
00643 
00644                 for(i=0, dw=dvert_act->dw; i < dvert_act->totweight; i++, dw++) {
00645                         if(def_nr == dw->def_nr) {
00646                                 act_weight= dw->weight;
00647                                 break;
00648                         }
00649                 }
00650 
00651                 if(act_weight < -0.5f)
00652                         return;
00653 
00654                 for(eve= em->verts.first; eve; eve= eve->next, index++) {
00655                         if(eve->f & SELECT && eve != eve_act) {
00656                                 dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
00657                                 if(dvert) {
00658                                         for(i=0, dw=dvert->dw; i < dvert->totweight; i++, dw++) {
00659                                                 if(def_nr == dw->def_nr) {
00660                                                         dw->weight= act_weight;
00661 
00662                                                         if(me->editflag & ME_EDIT_MIRROR_X)
00663                                                                 editvert_mirror_update(ob, eve, -1, index);
00664 
00665                                                         break;
00666                                                 }
00667                                         }
00668                                 }
00669                         }
00670                 }
00671 
00672                 if(me->editflag & ME_EDIT_MIRROR_X)
00673                         editvert_mirror_update(ob, eve_act, -1, -1);
00674 
00675         }
00676 }
00677 
00678 static void vgroup_normalize_active(Object *ob)
00679 {
00680         EditVert *eve_act;
00681         MDeformVert *dvert_act;
00682 
00683         act_vert_def(ob, &eve_act, &dvert_act);
00684 
00685         if(dvert_act==NULL)
00686                 return;
00687 
00688         defvert_normalize(dvert_act);
00689 
00690         if(((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X)
00691                 editvert_mirror_update(ob, eve_act, -1, -1);
00692 
00693 
00694 
00695 }
00696 
00697 static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
00698 {
00699         Scene *scene= CTX_data_scene(C);
00700         Object *ob= OBACT;
00701 
00702         if(event==B_VGRP_PNL_NORMALIZE) {
00703                 vgroup_normalize_active(ob);
00704         }
00705         else if(event == B_VGRP_PNL_COPY) {
00706                 vgroup_copy_active_to_sel(ob);
00707         }
00708         else if(event >= B_VGRP_PNL_COPY_SINGLE) {
00709                 vgroup_copy_active_to_sel_single(ob, event - B_VGRP_PNL_COPY_SINGLE);
00710         }
00711         else if(event >= B_VGRP_PNL_EDIT_SINGLE) {
00712                 vgroup_adjust_active(ob, event - B_VGRP_PNL_EDIT_SINGLE);
00713         }
00714 
00715 //  todo
00716 //      if(((Mesh *)ob->data)->editflag & ME_EDIT_MIRROR_X)
00717 //              ED_vgroup_mirror(ob, 1, 1, 0);
00718 
00719         /* default for now */
00720         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00721         WM_event_add_notifier(C, NC_GEOM|ND_DATA, ob->data);
00722 }
00723 
00724 static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
00725 {
00726         Scene *scene= CTX_data_scene(C);
00727         Object *ob= OBACT;
00728         EditVert *eve_act;
00729         MDeformVert *dvert_act;
00730 
00731         act_vert_def(ob, &eve_act, &dvert_act);
00732 
00733         return dvert_act ? dvert_act->totweight : 0;
00734 }
00735 
00736 
00737 static void view3d_panel_vgroup(const bContext *C, Panel *pa)
00738 {
00739         uiBlock *block= uiLayoutAbsoluteBlock(pa->layout);
00740         Scene *scene= CTX_data_scene(C);
00741         Object *ob= OBACT;
00742 
00743         EditVert *eve;
00744         MDeformVert *dvert;
00745 
00746         act_vert_def(ob, &eve, &dvert);
00747 
00748         if(dvert && dvert->totweight) {
00749                 uiLayout *col;
00750                 bDeformGroup *dg;
00751                 int i;
00752                 int yco = 0;
00753 
00754                 uiBlockSetHandleFunc(block, do_view3d_vgroup_buttons, NULL);
00755 
00756                 col= uiLayoutColumn(pa->layout, 0);
00757                 block= uiLayoutAbsoluteBlock(col);
00758 
00759                 uiBlockBeginAlign(block);
00760 
00761                 for (i=0; i<dvert->totweight; i++){
00762                         dg = BLI_findlink (&ob->defbase, dvert->dw[i].def_nr);
00763                         if(dg) {
00764                                 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, "");
00765                                 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");
00766                                 yco -= 20;
00767                         }
00768                 }
00769                 yco-=2;
00770 
00771                 uiBlockEndAlign(block);
00772                 uiBlockBeginAlign(block);
00773                 uiDefBut(block, BUT, B_VGRP_PNL_NORMALIZE, "Normalize", 0, yco,100,20, NULL, 0, 0, 0, 0, "Normalize active vertex weights");
00774                 uiDefBut(block, BUT, B_VGRP_PNL_COPY, "Copy", 100,yco,100,20, NULL, 0, 0, 0, 0, "Copy active vertex to other seleted verts");
00775                 uiBlockEndAlign(block);
00776         }
00777 }
00778 
00779 static void v3d_transform_butsR(uiLayout *layout, PointerRNA *ptr)
00780 {
00781         uiLayout *split, *colsub;
00782         
00783         split = uiLayoutSplit(layout, 0.8, 0);
00784         
00785         if (ptr->type == &RNA_PoseBone) {
00786                 PointerRNA boneptr;
00787                 Bone *bone;
00788                 
00789                 boneptr = RNA_pointer_get(ptr, "bone");
00790                 bone = boneptr.data;
00791                 uiLayoutSetActive(split, !(bone->parent && bone->flag & BONE_CONNECTED));
00792         }
00793         colsub = uiLayoutColumn(split, 1);
00794         uiItemR(colsub, ptr, "location", 0, "Location", ICON_NONE);
00795         colsub = uiLayoutColumn(split, 1);
00796         uiItemL(colsub, "", ICON_NONE);
00797         uiItemR(colsub, ptr, "lock_location", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00798         
00799         split = uiLayoutSplit(layout, 0.8, 0);
00800         
00801         switch(RNA_enum_get(ptr, "rotation_mode")) {
00802                 case ROT_MODE_QUAT: /* quaternion */
00803                         colsub = uiLayoutColumn(split, 1);
00804                         uiItemR(colsub, ptr, "rotation_quaternion", 0, "Rotation", ICON_NONE);
00805                         colsub = uiLayoutColumn(split, 1);
00806                         uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, "4L", ICON_NONE);
00807                         if (RNA_boolean_get(ptr, "lock_rotations_4d"))
00808                                 uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00809                         else
00810                                 uiItemL(colsub, "", ICON_NONE);
00811                         uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00812                         break;
00813                 case ROT_MODE_AXISANGLE: /* axis angle */
00814                         colsub = uiLayoutColumn(split, 1);
00815                         uiItemR(colsub, ptr, "rotation_axis_angle", 0, "Rotation", ICON_NONE);
00816                         colsub = uiLayoutColumn(split, 1);
00817                         uiItemR(colsub, ptr, "lock_rotations_4d", UI_ITEM_R_TOGGLE, "4L", ICON_NONE);
00818                         if (RNA_boolean_get(ptr, "lock_rotations_4d"))
00819                                 uiItemR(colsub, ptr, "lock_rotation_w", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00820                         else
00821                                 uiItemL(colsub, "", ICON_NONE);
00822                         uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00823                         break;
00824                 default: /* euler rotations */
00825                         colsub = uiLayoutColumn(split, 1);
00826                         uiItemR(colsub, ptr, "rotation_euler", 0, "Rotation", ICON_NONE);
00827                         colsub = uiLayoutColumn(split, 1);
00828                         uiItemL(colsub, "", ICON_NONE);
00829                         uiItemR(colsub, ptr, "lock_rotation", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00830                         break;
00831         }
00832         uiItemR(layout, ptr, "rotation_mode", 0, "", ICON_NONE);
00833         
00834         split = uiLayoutSplit(layout, 0.8, 0);
00835         colsub = uiLayoutColumn(split, 1);
00836         uiItemR(colsub, ptr, "scale", 0, "Scale", ICON_NONE);
00837         colsub = uiLayoutColumn(split, 1);
00838         uiItemL(colsub, "", ICON_NONE);
00839         uiItemR(colsub, ptr, "lock_scale", UI_ITEM_R_TOGGLE+UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00840         
00841         if (ptr->type == &RNA_Object) {
00842                 Object *ob = ptr->data;
00843                 if (ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL))
00844                         uiItemR(layout, ptr, "dimensions", 0, "Dimensions", ICON_NONE);
00845         }
00846 }
00847 
00848 static void v3d_posearmature_buts(uiLayout *layout, Object *ob)
00849 {
00850 //      uiBlock *block= uiLayoutGetBlock(layout);
00851 //      bArmature *arm;
00852         bPoseChannel *pchan;
00853 //      TransformProperties *tfp= v3d->properties_storage;
00854         PointerRNA pchanptr;
00855         uiLayout *col;
00856 //      uiLayout *row;
00857 //      uiBut *but;
00858 
00859         pchan= get_active_posechannel(ob);
00860 
00861 //      row= uiLayoutRow(layout, 0);
00862         
00863         if (!pchan)     {
00864                 uiItemL(layout, "No Bone Active", ICON_NONE);
00865                 return; 
00866         }
00867 
00868         RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &pchanptr);
00869 
00870         col= uiLayoutColumn(layout, 0);
00871         
00872         /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.)
00873          * but oldskool UI shows in eulers always. Do we want to be able to still display in Eulers?
00874          * Maybe needs RNA/ui options to display rotations as different types... */
00875         v3d_transform_butsR(col, &pchanptr);
00876 
00877 #if 0
00878         uiLayoutAbsoluteBlock(layout);
00879 
00880         if (pchan->rotmode == ROT_MODE_AXISANGLE) {
00881                 float quat[4];
00882                 /* convert to euler, passing through quats... */
00883                 axis_angle_to_quat(quat, pchan->rotAxis, pchan->rotAngle);
00884                 quat_to_eul( tfp->ob_eul,quat);
00885         }
00886         else if (pchan->rotmode == ROT_MODE_QUAT)
00887                 quat_to_eul( tfp->ob_eul,pchan->quat);
00888         else
00889                 copy_v3_v3(tfp->ob_eul, pchan->eul);
00890         tfp->ob_eul[0]*= 180.0/M_PI;
00891         tfp->ob_eul[1]*= 180.0/M_PI;
00892         tfp->ob_eul[2]*= 180.0/M_PI;
00893         
00894         uiDefBut(block, LABEL, 0, "Location:",                  0, 240, 100, 20, 0, 0, 0, 0, 0, "");
00895         uiBlockBeginAlign(block);
00896         
00897         but= uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:",      0, 220, 120, 19, pchan->loc, -lim, lim, 100, 3, "");
00898         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00899         but= uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:",      0, 200, 120, 19, pchan->loc+1, -lim, lim, 100, 3, "");
00900         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00901         but= uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:",      0, 180, 120, 19, pchan->loc+2, -lim, lim, 100, 3, "");
00902         uiButSetUnitType(but, PROP_UNIT_LENGTH);
00903         uiBlockEndAlign(block);
00904         
00905         uiBlockBeginAlign(block);
00906         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");
00907         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");
00908         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");
00909         uiBlockEndAlign(block);
00910         
00911         uiDefBut(block, LABEL, 0, "Rotation:",                  0, 160, 100, 20, 0, 0, 0, 0, 0, "");
00912         uiBlockBeginAlign(block);
00913         uiDefButF(block, NUM, B_ARMATUREPANEL3, "X:",   0, 140, 120, 19, tfp->ob_eul, -1000.0, 1000.0, 100, 3, "");
00914         uiDefButF(block, NUM, B_ARMATUREPANEL3, "Y:",   0, 120, 120, 19, tfp->ob_eul+1, -1000.0, 1000.0, 100, 3, "");
00915         uiDefButF(block, NUM, B_ARMATUREPANEL3, "Z:",   0, 100, 120, 19, tfp->ob_eul+2, -1000.0, 1000.0, 100, 3, "");
00916         uiBlockEndAlign(block);
00917         
00918         uiBlockBeginAlign(block);
00919         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");
00920         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");
00921         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");
00922         uiBlockEndAlign(block);
00923         
00924         uiDefBut(block, LABEL, 0, "Scale:",                             0, 80, 100, 20, 0, 0, 0, 0, 0, "");
00925         uiBlockBeginAlign(block);
00926         uiDefButF(block, NUM, B_ARMATUREPANEL2, "X:",   0, 60, 120, 19, pchan->size, -lim, lim, 10, 3, "");
00927         uiDefButF(block, NUM, B_ARMATUREPANEL2, "Y:",   0, 40, 120, 19, pchan->size+1, -lim, lim, 10, 3, "");
00928         uiDefButF(block, NUM, B_ARMATUREPANEL2, "Z:",   0, 20, 120, 19, pchan->size+2, -lim, lim, 10, 3, "");
00929         uiBlockEndAlign(block);
00930         
00931         uiBlockBeginAlign(block);
00932         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");
00933         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");
00934         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");
00935         uiBlockEndAlign(block);
00936 #endif
00937 }
00938 
00939 /* assumes armature editmode */
00940 #if 0
00941 static void validate_editbonebutton_cb(bContext *C, void *bonev, void *namev)
00942 {
00943         EditBone *eBone= bonev;
00944         char oldname[sizeof(eBone->name)], newname[sizeof(eBone->name)];
00945 
00946         /* need to be on the stack */
00947         BLI_strncpy(newname, eBone->name, sizeof(eBone->name));
00948         BLI_strncpy(oldname, (char *)namev, sizeof(eBone->name));
00949         /* restore */
00950         BLI_strncpy(eBone->name, oldname, sizeof(eBone->name));
00951 
00952         ED_armature_bone_rename(CTX_data_edit_object(C)->data, oldname, newname); // editarmature.c
00953         WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, CTX_data_edit_object(C)); // XXX fix
00954 }
00955 #endif
00956 
00957 static void v3d_editarmature_buts(uiLayout *layout, Object *ob)
00958 {
00959 //      uiBlock *block= uiLayoutGetBlock(layout);
00960         bArmature *arm= ob->data;
00961         EditBone *ebone;
00962 //      TransformProperties *tfp= v3d->properties_storage;
00963 //      uiLayout *row;
00964         uiLayout *col;
00965         PointerRNA eboneptr;
00966         
00967         ebone= arm->act_edbone;
00968 
00969         if (!ebone || (ebone->layer & arm->layer)==0) {
00970                 uiItemL(layout, "Nothing selected", ICON_NONE);
00971                 return;
00972         }
00973 //      row= uiLayoutRow(layout, 0);
00974         RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &eboneptr);
00975 
00976         col= uiLayoutColumn(layout, 0);
00977         uiItemR(col, &eboneptr, "head", 0, "Head", ICON_NONE);
00978         if (ebone->parent && ebone->flag & BONE_CONNECTED ) {
00979                 PointerRNA parptr = RNA_pointer_get(&eboneptr, "parent");
00980                 uiItemR(col, &parptr, "tail_radius", 0, "Radius (Parent)", ICON_NONE);
00981         } else {
00982                 uiItemR(col, &eboneptr, "head_radius", 0, "Radius", ICON_NONE);
00983         }
00984         
00985         uiItemR(col, &eboneptr, "tail", 0, "Tail", ICON_NONE);
00986         uiItemR(col, &eboneptr, "tail_radius", 0, "Radius", ICON_NONE);
00987         
00988         uiItemR(col, &eboneptr, "roll", 0, "Roll", ICON_NONE);
00989 }
00990 
00991 static void v3d_editmetaball_buts(uiLayout *layout, Object *ob)
00992 {
00993         PointerRNA mbptr, ptr;
00994         MetaBall *mball= ob->data;
00995 //      uiLayout *row;
00996         uiLayout *col;
00997         
00998         if (!mball || !(mball->lastelem)) return;
00999         
01000         RNA_pointer_create(&mball->id, &RNA_MetaBall, mball, &mbptr);
01001         
01002 //      row= uiLayoutRow(layout, 0);
01003 
01004         RNA_pointer_create(&mball->id, &RNA_MetaElement, mball->lastelem, &ptr);
01005         
01006         col= uiLayoutColumn(layout, 0);
01007         uiItemR(col, &ptr, "co", 0, "Location", ICON_NONE);
01008         
01009         uiItemR(col, &ptr, "radius", 0, "Radius", ICON_NONE);
01010         uiItemR(col, &ptr, "stiffness", 0, "Stiffness", ICON_NONE);
01011         
01012         uiItemR(col, &ptr, "type", 0, "Type", ICON_NONE);
01013         
01014         col= uiLayoutColumn(layout, 1);
01015         switch (RNA_enum_get(&ptr, "type")) {
01016                 case MB_BALL:
01017                         break;
01018                 case MB_CUBE:
01019                         uiItemL(col, "Size:", ICON_NONE);
01020                         uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
01021                         uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
01022                         uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE);
01023                         break;
01024                 case MB_TUBE:
01025                         uiItemL(col, "Size:", ICON_NONE);
01026                         uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
01027                         break;
01028                 case MB_PLANE:
01029                         uiItemL(col, "Size:", ICON_NONE);
01030                         uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
01031                         uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
01032                         break;
01033                 case MB_ELIPSOID:
01034                         uiItemL(col, "Size:", ICON_NONE);
01035                         uiItemR(col, &ptr, "size_x", 0, "X", ICON_NONE);
01036                         uiItemR(col, &ptr, "size_y", 0, "Y", ICON_NONE);
01037                         uiItemR(col, &ptr, "size_z", 0, "Z", ICON_NONE);
01038                         break;             
01039         }       
01040 }
01041 
01042 /* test if 'ob' is a parent somewhere in par's parents */
01043 static int test_parent_loop(Object *par, Object *ob)
01044 {
01045         if(par == NULL) return 0;
01046         if(ob == par) return 1;
01047         return test_parent_loop(par->parent, ob);
01048 }
01049 
01050 static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event)
01051 {
01052         Main *bmain= CTX_data_main(C);
01053         Scene *scene= CTX_data_scene(C);
01054 //      Object *obedit= CTX_data_edit_object(C);
01055         View3D *v3d= CTX_wm_view3d(C);
01056 //      BoundBox *bb;
01057         Object *ob= OBACT;
01058         TransformProperties *tfp= v3d->properties_storage;
01059         
01060         switch(event) {
01061         
01062         case B_REDR:
01063                 ED_area_tag_redraw(CTX_wm_area(C));
01064                 return; /* no notifier! */
01065                 
01066         case B_OBJECTPANEL:
01067                 DAG_id_tag_update(&ob->id, OB_RECALC_OB);
01068                 break;
01069 
01070         
01071         case B_OBJECTPANELMEDIAN:
01072                 if(ob) {
01073                         v3d_editvertex_buts(NULL, v3d, ob, 1.0);
01074                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01075                 }
01076                 break;
01077                 
01078                 /* note; this case also used for parbone */
01079         case B_OBJECTPANELPARENT:
01080                 if(ob) {
01081                         if(ob->id.lib || test_parent_loop(ob->parent, ob) ) 
01082                                 ob->parent= NULL;
01083                         else {
01084                                 DAG_scene_sort(bmain, scene);
01085                                 DAG_id_tag_update(&ob->id, OB_RECALC_OB);
01086                         }
01087                 }
01088                 break;
01089                 
01090 
01091         case B_ARMATUREPANEL3:  // rotate button on channel
01092                 {
01093                         bPoseChannel *pchan;
01094                         float eul[3];
01095                         
01096                         pchan= get_active_posechannel(ob);
01097                         if (!pchan) return;
01098                         
01099                         /* make a copy to eul[3], to allow TAB on buttons to work */
01100                         eul[0]= (float)M_PI*tfp->ob_eul[0]/180.0f;
01101                         eul[1]= (float)M_PI*tfp->ob_eul[1]/180.0f;
01102                         eul[2]= (float)M_PI*tfp->ob_eul[2]/180.0f;
01103                         
01104                         if (pchan->rotmode == ROT_MODE_AXISANGLE) {
01105                                 float quat[4];
01106                                 /* convert to axis-angle, passing through quats  */
01107                                 eul_to_quat( quat,eul);
01108                                 quat_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,quat);
01109                         }
01110                         else if (pchan->rotmode == ROT_MODE_QUAT)
01111                                 eul_to_quat( pchan->quat,eul);
01112                         else
01113                                 copy_v3_v3(pchan->eul, eul);
01114                 }
01115                 /* no break, pass on */
01116         case B_ARMATUREPANEL2:
01117                 {
01118                         ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
01119                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01120                 }
01121                 break;
01122         case B_TRANSFORMSPACEADD:
01123         {
01124                 char names[sizeof(((TransformOrientation *)NULL)->name)]= "";
01125                 BIF_createTransformOrientation(C, NULL, names, 1, 0);
01126                 break;
01127         }
01128         case B_TRANSFORMSPACECLEAR:
01129                 BIF_clearTransformOrientation(C);
01130                 break;
01131                 
01132 #if 0 // XXX
01133         case B_WEIGHT0_0:
01134                 wpaint->weight = 0.0f;
01135                 break;
01136                 
01137         case B_WEIGHT1_4:
01138                 wpaint->weight = 0.25f;
01139                 break;
01140         case B_WEIGHT1_2:
01141                 wpaint->weight = 0.5f;
01142                 break;
01143         case B_WEIGHT3_4:
01144                 wpaint->weight = 0.75f;
01145                 break;
01146         case B_WEIGHT1_0:
01147                 wpaint->weight = 1.0f;
01148                 break;
01149                 
01150         case B_OPA1_8:
01151                 wpaint->a = 0.125f;
01152                 break;
01153         case B_OPA1_4:
01154                 wpaint->a = 0.25f;
01155                 break;
01156         case B_OPA1_2:
01157                 wpaint->a = 0.5f;
01158                 break;
01159         case B_OPA3_4:
01160                 wpaint->a = 0.75f;
01161                 break;
01162         case B_OPA1_0:
01163                 wpaint->a = 1.0f;
01164                 break;
01165 #endif
01166         case B_CLR_WPAINT:
01167 //              if(!multires_level1_test()) {
01168                 {
01169                         bDeformGroup *defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
01170                         if(defGroup) {
01171                                 Mesh *me= ob->data;
01172                                 int a;
01173                                 for(a=0; a<me->totvert; a++)
01174                                         ED_vgroup_vert_remove (ob, defGroup, a);
01175                                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01176                         }
01177                 }
01178                 break;
01179         case B_RV3D_LOCKED:
01180         case B_RV3D_BOXVIEW:
01181         case B_RV3D_BOXCLIP:
01182                 {
01183                         ScrArea *sa= CTX_wm_area(C);
01184                         ARegion *ar= sa->regionbase.last;
01185                         RegionView3D *rv3d;
01186                         short viewlock;
01187                         
01188                         ar= ar->prev;
01189                         rv3d= ar->regiondata;
01190                         viewlock= rv3d->viewlock;
01191                         
01192                         if((viewlock & RV3D_LOCKED)==0)
01193                                 viewlock= 0;
01194                         else if((viewlock & RV3D_BOXVIEW)==0)
01195                                 viewlock &= ~RV3D_BOXCLIP;
01196                         
01197                         for(; ar; ar= ar->prev) {
01198                                 if(ar->alignment==RGN_ALIGN_QSPLIT) {
01199                                         rv3d= ar->regiondata;
01200                                         rv3d->viewlock= viewlock;
01201                                 }
01202                         }
01203                         
01204                         if(rv3d->viewlock & RV3D_BOXVIEW)
01205                                 view3d_boxview_copy(sa, sa->regionbase.last);
01206                         
01207                         ED_area_tag_redraw(sa);
01208                 }
01209                 break;
01210         }
01211 
01212         /* default for now */
01213         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, ob);
01214 }
01215 
01216 static void view3d_panel_object(const bContext *C, Panel *pa)
01217 {
01218         uiBlock *block;
01219         Scene *scene= CTX_data_scene(C);
01220         Object *obedit= CTX_data_edit_object(C);
01221         View3D *v3d= CTX_wm_view3d(C);
01222         //uiBut *bt;
01223         Object *ob= OBACT;
01224         // TransformProperties *tfp; // UNUSED
01225         PointerRNA obptr;
01226         uiLayout *col, *row;
01227         float lim;
01228         
01229         if(ob==NULL) return;
01230 
01231         /* make sure we got storage */
01232         /*
01233         if(v3d->properties_storage==NULL)
01234                 v3d->properties_storage= MEM_callocN(sizeof(TransformProperties), "TransformProperties");
01235         tfp= v3d->properties_storage;
01236         
01237 // XXX  uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
01238 
01239         if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)) {
01240         }
01241         else {
01242                 if((ob->mode & OB_MODE_PARTICLE_EDIT)==0) {
01243                         uiBlockEndAlign(block);
01244                 }
01245         }
01246         */
01247 
01248         lim= 10000.0f * MAX2(1.0f, v3d->grid);
01249 
01250         block= uiLayoutGetBlock(pa->layout);
01251         uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
01252 
01253         col= uiLayoutColumn(pa->layout, 0);
01254         row= uiLayoutRow(col, 0);
01255         RNA_id_pointer_create(&ob->id, &obptr);
01256 
01257         if(ob==obedit) {
01258                 if(ob->type==OB_ARMATURE) v3d_editarmature_buts(col, ob);
01259                 else if(ob->type==OB_MBALL) v3d_editmetaball_buts(col, ob);
01260                 else v3d_editvertex_buts(col, v3d, ob, lim);
01261         }
01262         else if(ob->mode & OB_MODE_POSE) {
01263                 v3d_posearmature_buts(col, ob);
01264         }
01265         else {
01266 
01267                 v3d_transform_butsR(col, &obptr);
01268         }
01269 }
01270 
01271 #if 0
01272 static void view3d_panel_preview(bContext *C, ARegion *ar, short cntrl) // VIEW3D_HANDLER_PREVIEW
01273 {
01274         uiBlock *block;
01275         View3D *v3d= sa->spacedata.first;
01276         int ofsx, ofsy;
01277         
01278         block= uiBeginBlock(C, ar, "view3d_panel_preview", UI_EMBOSS);
01279         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | UI_PNL_SCALE | cntrl);
01280         uiSetPanelHandler(VIEW3D_HANDLER_PREVIEW);  // for close and esc
01281         
01282         ofsx= -150+(sa->winx/2)/v3d->blockscale;
01283         ofsy= -100+(sa->winy/2)/v3d->blockscale;
01284         if(uiNewPanel(C, ar, block, "Preview", "View3d", ofsx, ofsy, 300, 200)==0) return;
01285 
01286         uiBlockSetDrawExtraFunc(block, BIF_view3d_previewdraw);
01287         
01288         if(scene->recalc & SCE_PRV_CHANGED) {
01289                 scene->recalc &= ~SCE_PRV_CHANGED;
01290                 //printf("found recalc\n");
01291                 BIF_view3d_previewrender_free(sa->spacedata.first);
01292                 BIF_preview_changed(0);
01293         }
01294 }
01295 #endif
01296 
01297 #if 0 // XXX not used
01298 static void delete_sketch_armature(bContext *C, void *arg1, void *arg2)
01299 {
01300         BIF_deleteSketch(C);
01301 }
01302 
01303 static void convert_sketch_armature(bContext *C, void *arg1, void *arg2)
01304 {
01305         BIF_convertSketch(C);
01306 }
01307 
01308 static void assign_template_sketch_armature(bContext *C, void *arg1, void *arg2)
01309 {
01310         int index = *(int*)arg1;
01311         BIF_setTemplate(C, index);
01312 }
01313 
01314 
01315 static int view3d_panel_bonesketch_spaces_poll(const bContext *C, PanelType *pt)
01316 {
01317         Object *obedit = CTX_data_edit_object(C);
01318 
01319         /* replace with check call to sketching lib */
01320         return (obedit && obedit->type == OB_ARMATURE);
01321 }
01322 static void view3d_panel_bonesketch_spaces(const bContext *C, Panel *pa)
01323 {
01324         Scene *scene = CTX_data_scene(C);
01325         static int template_index;
01326         static char joint_label[128];
01327         uiBlock *block;
01328         uiBut *but;
01329         char *bone_name;
01330         int yco = 130;
01331         int nb_joints;
01332         static char subdiv_tooltip[4][64] = {
01333                 "Subdivide arcs based on a fixed number of bones",
01334                 "Subdivide arcs in bones of equal length",
01335                 "Subdivide arcs based on correlation",
01336                 "Retarget template to stroke"
01337                 };
01338 
01339         
01340         block= uiLayoutAbsoluteBlock(pa->layout);
01341         uiBlockSetHandleFunc(block, do_view3d_region_buttons, NULL);
01342 
01343         uiBlockBeginAlign(block);
01344         
01345         /* use real flag instead of 1 */
01346         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)");
01347         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");
01348         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");
01349         yco -= 20;
01350         
01351         but = uiDefBut(block, BUT, B_REDR, "Convert", 10,yco,100,20, 0, 0, 0, 0, 0, "Convert sketch to armature");
01352         uiButSetFunc(but, convert_sketch_armature, NULL, NULL);
01353 
01354         but = uiDefBut(block, BUT, B_REDR, "Delete", 110,yco,100,20, 0, 0, 0, 0, 0, "Delete sketch");
01355         uiButSetFunc(but, delete_sketch_armature, NULL, NULL);
01356         yco -= 20;
01357         
01358         uiBlockEndAlign(block);
01359 
01360         uiBlockBeginAlign(block);
01361         
01362         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]);
01363 
01364         switch(scene->toolsettings->bone_sketching_convert)
01365         {
01366         case SK_CONVERT_CUT_LENGTH:
01367                 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");
01368                 yco -= 20;
01369                 break;
01370         case SK_CONVERT_CUT_ADAPTATIVE:
01371                 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");
01372                 yco -= 20;
01373                 break;
01374         default:
01375         case SK_CONVERT_CUT_FIXED:
01376                 uiDefButC(block, NUM, B_REDR,                                   "Num:",         70, yco, 140, 19, &scene->toolsettings->skgen_subdivision_number,1, 100, 1, 5,  "Number of subdivided bones");
01377                 yco -= 20;
01378                 break;
01379         case SK_CONVERT_RETARGET:
01380                 uiDefButC(block, ROW, B_NOP, "No",                      70,  yco, 40,19, &scene->toolsettings->skgen_retarget_roll, 0, 0, 0, 0,                                                                 "No special roll treatment");
01381                 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");
01382                 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");
01383                 yco -= 30;
01384 
01385                 uiBlockEndAlign(block);
01386 
01387                 uiBlockBeginAlign(block);
01388                 /* button here to select what to do (copy or not), template, ...*/
01389 
01390                 BIF_makeListTemplates(C);
01391                 template_index = BIF_currentTemplate(C);
01392                 
01393                 but = uiDefButI(block, MENU, B_REDR, BIF_listTemplates(C), 10,yco,200,19, &template_index, 0, 0, 0, 0, "Template");
01394                 uiButSetFunc(but, assign_template_sketch_armature, &template_index, NULL);
01395                 
01396                 yco -= 20;
01397                 
01398                 uiDefButF(block, NUM, B_NOP,                                                    "A:",                   10, yco, 66,19, &scene->toolsettings->skgen_retarget_angle_weight, 0, 10, 1, 0,         "Angle Weight");
01399                 uiDefButF(block, NUM, B_NOP,                                                    "L:",                   76, yco, 67,19, &scene->toolsettings->skgen_retarget_length_weight, 0, 10, 1, 0,                "Length Weight");
01400                 uiDefButF(block, NUM, B_NOP,                                                    "D:",           143,yco, 67,19, &scene->toolsettings->skgen_retarget_distance_weight, 0, 10, 1, 0,              "Distance Weight");
01401                 yco -= 20;
01402                 
01403                 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");
01404                 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");
01405                 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");        
01406                 yco -= 20;
01407 
01408                 /* auto renaming magic */
01409                 uiBlockEndAlign(block);
01410                 
01411                 nb_joints = BIF_nbJointsTemplate(C);
01412 
01413                 if (nb_joints == -1)
01414                 {
01415                         //XXX
01416                         //nb_joints = G.totvertsel;
01417                 }
01418                 
01419                 bone_name = BIF_nameBoneTemplate(C);
01420                 
01421                 BLI_snprintf(joint_label, 32, "%i joints: %s", nb_joints, bone_name);
01422                 
01423                 uiDefBut(block, LABEL, 1, joint_label,                                  10, yco, 200, 20, NULL, 0.0, 0.0, 0, 0, "");
01424                 yco -= 20;
01425                 break;
01426         }
01427 
01428         uiBlockEndAlign(block);
01429 }
01430 
01431 #endif // XXX not used
01432 
01433 void view3d_buttons_register(ARegionType *art)
01434 {
01435         PanelType *pt;
01436 
01437         pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel object");
01438         strcpy(pt->idname, "VIEW3D_PT_object");
01439         strcpy(pt->label, "Transform");
01440         pt->draw= view3d_panel_object;
01441         BLI_addtail(&art->paneltypes, pt);
01442         
01443         pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel gpencil");
01444         strcpy(pt->idname, "VIEW3D_PT_gpencil");
01445         strcpy(pt->label, "Grease Pencil");
01446         pt->draw= gpencil_panel_standard;
01447         BLI_addtail(&art->paneltypes, pt);
01448 
01449         pt= MEM_callocN(sizeof(PanelType), "spacetype view3d panel vgroup");
01450         strcpy(pt->idname, "VIEW3D_PT_vgroup");
01451         strcpy(pt->label, "Vertex Groups");
01452         pt->draw= view3d_panel_vgroup;
01453         pt->poll= view3d_panel_vgroup_poll;
01454         BLI_addtail(&art->paneltypes, pt);
01455 
01456         // XXX view3d_panel_preview(C, ar, 0);
01457 }
01458 
01459 static int view3d_properties(bContext *C, wmOperator *UNUSED(op))
01460 {
01461         ScrArea *sa= CTX_wm_area(C);
01462         ARegion *ar= view3d_has_buttons_region(sa);
01463         
01464         if(ar)
01465                 ED_region_toggle_hidden(C, ar);
01466 
01467         return OPERATOR_FINISHED;
01468 }
01469 
01470 void VIEW3D_OT_properties(wmOperatorType *ot)
01471 {
01472         ot->name= "Properties";
01473         ot->description= "Toggles the properties panel display";
01474         ot->idname= "VIEW3D_OT_properties";
01475         
01476         ot->exec= view3d_properties;
01477         ot->poll= ED_operator_view3d_active;
01478         
01479         /* flags */
01480         ot->flag= 0;
01481 }