Blender V2.61 - r43446

object_hook.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * Contributor(s): Blender Foundation, 2002-2008 full recode
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #include "MEM_guardedalloc.h"
00035 
00036 #include "BLI_math.h"
00037 #include "BLI_editVert.h"
00038 #include "BLI_listbase.h"
00039 #include "BLI_string.h"
00040 #include "BLI_utildefines.h"
00041 
00042 #include "DNA_curve_types.h"
00043 #include "DNA_lattice_types.h"
00044 #include "DNA_meshdata_types.h"
00045 #include "DNA_object_types.h"
00046 #include "DNA_scene_types.h"
00047 
00048 #include "BKE_action.h"
00049 #include "BKE_context.h"
00050 #include "BKE_depsgraph.h"
00051 #include "BKE_main.h"
00052 #include "BKE_mesh.h"
00053 #include "BKE_modifier.h"
00054 #include "BKE_object.h"
00055 #include "BKE_report.h"
00056 #include "BKE_scene.h"
00057 #include "BKE_deform.h"
00058 
00059 #include "RNA_define.h"
00060 #include "RNA_access.h"
00061 #include "RNA_enum_types.h"
00062 
00063 #include "ED_curve.h"
00064 #include "ED_mesh.h"
00065 #include "ED_screen.h"
00066 
00067 #include "WM_types.h"
00068 #include "WM_api.h"
00069 
00070 #include "UI_resources.h"
00071 
00072 #include "object_intern.h"
00073 
00074 static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
00075 {
00076     EditVert *eve;
00077     int *index, nr, totvert=0;
00078     
00079     for(eve= em->verts.first; eve; eve= eve->next) {
00080         if(eve->f & SELECT) totvert++;
00081     }
00082     if(totvert==0) return 0;
00083     
00084     *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
00085     *tot= totvert;
00086     nr= 0;
00087     zero_v3(cent);
00088     
00089     for(eve= em->verts.first; eve; eve= eve->next) {
00090         if(eve->f & SELECT) {
00091             *index= nr; index++;
00092             add_v3_v3(cent, eve->co);
00093         }
00094         nr++;
00095     }
00096     
00097     mul_v3_fl(cent, 1.0f/(float)totvert);
00098     
00099     return totvert;
00100 }
00101 
00102 static int return_editmesh_vgroup(Object *obedit, EditMesh *em, char *name, float *cent)
00103 {
00104     zero_v3(cent);
00105 
00106     if(obedit->actdef) {
00107         const int defgrp_index= obedit->actdef-1;
00108         int totvert=0;
00109 
00110         MDeformVert *dvert;
00111         EditVert *eve;
00112 
00113         /* find the vertices */
00114         for(eve= em->verts.first; eve; eve= eve->next) {
00115             dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT);
00116 
00117             if(dvert) {
00118                 if(defvert_find_weight(dvert, defgrp_index) > 0.0f) {
00119                     add_v3_v3(cent, eve->co);
00120                     totvert++;
00121                 }
00122             }
00123         }
00124         if(totvert) {
00125             bDeformGroup *dg = BLI_findlink(&obedit->defbase, defgrp_index);
00126             BLI_strncpy(name, dg->name, sizeof(dg->name));
00127             mul_v3_fl(cent, 1.0f/(float)totvert);
00128             return 1;
00129         }
00130     }
00131     
00132     return 0;
00133 }   
00134 
00135 static void select_editmesh_hook(Object *ob, HookModifierData *hmd)
00136 {
00137     Mesh *me= ob->data;
00138     EditMesh *em= BKE_mesh_get_editmesh(me);
00139     EditVert *eve;
00140     int index=0, nr=0;
00141     
00142     if (hmd->indexar == NULL)
00143         return;
00144     
00145     for(eve= em->verts.first; eve; eve= eve->next, nr++) {
00146         if(nr==hmd->indexar[index]) {
00147             eve->f |= SELECT;
00148             if(index < hmd->totindex-1) index++;
00149         }
00150     }
00151     EM_select_flush(em);
00152 
00153     BKE_mesh_end_editmesh(me, em);
00154 }
00155 
00156 static int return_editlattice_indexar(Lattice *editlatt, int *tot, int **indexar, float *cent)
00157 {
00158     BPoint *bp;
00159     int *index, nr, totvert=0, a;
00160     
00161     /* count */
00162     a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
00163     bp= editlatt->def;
00164     while(a--) {
00165         if(bp->f1 & SELECT) {
00166             if(bp->hide==0) totvert++;
00167         }
00168         bp++;
00169     }
00170 
00171     if(totvert==0) return 0;
00172     
00173     *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
00174     *tot= totvert;
00175     nr= 0;
00176     cent[0]= cent[1]= cent[2]= 0.0;
00177     
00178     a= editlatt->pntsu*editlatt->pntsv*editlatt->pntsw;
00179     bp= editlatt->def;
00180     while(a--) {
00181         if(bp->f1 & SELECT) {
00182             if(bp->hide==0) {
00183                 *index= nr; index++;
00184                 add_v3_v3(cent, bp->vec);
00185             }
00186         }
00187         bp++;
00188         nr++;
00189     }
00190     
00191     mul_v3_fl(cent, 1.0f/(float)totvert);
00192     
00193     return totvert;
00194 }
00195 
00196 static void select_editlattice_hook(Object *obedit, HookModifierData *hmd)
00197 {
00198     Lattice *lt= obedit->data, *editlt;
00199     BPoint *bp;
00200     int index=0, nr=0, a;
00201 
00202     editlt= lt->editlatt->latt;
00203     /* count */
00204     a= editlt->pntsu*editlt->pntsv*editlt->pntsw;
00205     bp= editlt->def;
00206     while(a--) {
00207         if(hmd->indexar[index]==nr) {
00208             bp->f1 |= SELECT;
00209             if(index < hmd->totindex-1) index++;
00210         }
00211         nr++;
00212         bp++;
00213     }
00214 }
00215 
00216 static int return_editcurve_indexar(Object *obedit, int *tot, int **indexar, float *cent)
00217 {
00218     ListBase *editnurb= object_editcurve_get(obedit);
00219     Nurb *nu;
00220     BPoint *bp;
00221     BezTriple *bezt;
00222     int *index, a, nr, totvert=0;
00223     
00224     for(nu= editnurb->first; nu; nu= nu->next) {
00225         if(nu->type == CU_BEZIER) {
00226             bezt= nu->bezt;
00227             a= nu->pntsu;
00228             while(a--) {
00229                 if(bezt->f1 & SELECT) totvert++;
00230                 if(bezt->f2 & SELECT) totvert++;
00231                 if(bezt->f3 & SELECT) totvert++;
00232                 bezt++;
00233             }
00234         }
00235         else {
00236             bp= nu->bp;
00237             a= nu->pntsu*nu->pntsv;
00238             while(a--) {
00239                 if(bp->f1 & SELECT) totvert++;
00240                 bp++;
00241             }
00242         }
00243     }
00244     if(totvert==0) return 0;
00245     
00246     *indexar= index= MEM_mallocN(4*totvert, "hook indexar");
00247     *tot= totvert;
00248     nr= 0;
00249     cent[0]= cent[1]= cent[2]= 0.0;
00250     
00251     for(nu= editnurb->first; nu; nu= nu->next) {
00252         if(nu->type == CU_BEZIER) {
00253             bezt= nu->bezt;
00254             a= nu->pntsu;
00255             while(a--) {
00256                 if(bezt->f1 & SELECT) {
00257                     *index= nr; index++;
00258                     add_v3_v3(cent, bezt->vec[0]);
00259                 }
00260                 nr++;
00261                 if(bezt->f2 & SELECT) {
00262                     *index= nr; index++;
00263                     add_v3_v3(cent, bezt->vec[1]);
00264                 }
00265                 nr++;
00266                 if(bezt->f3 & SELECT) {
00267                     *index= nr; index++;
00268                     add_v3_v3(cent, bezt->vec[2]);
00269                 }
00270                 nr++;
00271                 bezt++;
00272             }
00273         }
00274         else {
00275             bp= nu->bp;
00276             a= nu->pntsu*nu->pntsv;
00277             while(a--) {
00278                 if(bp->f1 & SELECT) {
00279                     *index= nr; index++;
00280                     add_v3_v3(cent, bp->vec);
00281                 }
00282                 nr++;
00283                 bp++;
00284             }
00285         }
00286     }
00287     
00288     mul_v3_fl(cent, 1.0f/(float)totvert);
00289     
00290     return totvert;
00291 }
00292 
00293 static int object_hook_index_array(Scene *scene, Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
00294 {
00295     *indexar= NULL;
00296     *tot= 0;
00297     name[0]= 0;
00298     
00299     switch(obedit->type) {
00300         case OB_MESH:
00301         {
00302             Mesh *me= obedit->data;
00303             EditMesh *em;
00304 
00305             load_editMesh(scene, obedit);
00306             make_editMesh(scene, obedit);
00307 
00308             em = BKE_mesh_get_editmesh(me);
00309 
00310             /* check selected vertices first */
00311             if( return_editmesh_indexar(em, tot, indexar, cent_r)) {
00312                 BKE_mesh_end_editmesh(me, em);
00313                 return 1;
00314             } else {
00315                 int ret = return_editmesh_vgroup(obedit, em, name, cent_r);
00316                 BKE_mesh_end_editmesh(me, em);
00317                 return ret;
00318             }
00319         }
00320         case OB_CURVE:
00321         case OB_SURF:
00322             return return_editcurve_indexar(obedit, tot, indexar, cent_r);
00323         case OB_LATTICE:
00324         {
00325             Lattice *lt= obedit->data;
00326             return return_editlattice_indexar(lt->editlatt->latt, tot, indexar, cent_r);
00327         }
00328         default:
00329             return 0;
00330     }
00331 }
00332 
00333 static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
00334 {
00335     ListBase *editnurb= object_editcurve_get(obedit);
00336     Nurb *nu;
00337     BPoint *bp;
00338     BezTriple *bezt;
00339     int index=0, a, nr=0;
00340     
00341     for(nu= editnurb->first; nu; nu= nu->next) {
00342         if(nu->type == CU_BEZIER) {
00343             bezt= nu->bezt;
00344             a= nu->pntsu;
00345             while(a--) {
00346                 if(nr == hmd->indexar[index]) {
00347                     bezt->f1 |= SELECT;
00348                     if(index<hmd->totindex-1) index++;
00349                 }
00350                 nr++;
00351                 if(nr == hmd->indexar[index]) {
00352                     bezt->f2 |= SELECT;
00353                     if(index<hmd->totindex-1) index++;
00354                 }
00355                 nr++;
00356                 if(nr == hmd->indexar[index]) {
00357                     bezt->f3 |= SELECT;
00358                     if(index<hmd->totindex-1) index++;
00359                 }
00360                 nr++;
00361                 
00362                 bezt++;
00363             }
00364         }
00365         else {
00366             bp= nu->bp;
00367             a= nu->pntsu*nu->pntsv;
00368             while(a--) {
00369                 if(nr == hmd->indexar[index]) {
00370                     bp->f1 |= SELECT;
00371                     if(index<hmd->totindex-1) index++;
00372                 }
00373                 nr++;
00374                 bp++;
00375             }
00376         }
00377     }
00378 }
00379 
00380 static void object_hook_select(Object *ob, HookModifierData *hmd) 
00381 {
00382     if (hmd->indexar == NULL)
00383         return;
00384     
00385     if(ob->type==OB_MESH) select_editmesh_hook(ob, hmd);
00386     else if(ob->type==OB_LATTICE) select_editlattice_hook(ob, hmd);
00387     else if(ob->type==OB_CURVE) select_editcurve_hook(ob, hmd);
00388     else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
00389 }
00390 
00391 /* special poll operators for hook operators */
00392 // TODO: check for properties window modifier context too as alternative?
00393 static int hook_op_edit_poll(bContext *C)
00394 {
00395     Object *obedit= CTX_data_edit_object(C);
00396     
00397     if (obedit) {
00398         if (ED_operator_editmesh(C)) return 1;
00399         if (ED_operator_editsurfcurve(C)) return 1;
00400         if (ED_operator_editlattice(C)) return 1;
00401         //if (ED_operator_editmball(C)) return 1;
00402     }
00403     
00404     return 0;
00405 }
00406 
00407 static Object *add_hook_object_new(Scene *scene, Object *obedit)
00408 {
00409     Base *base, *basedit;
00410     Object *ob;
00411 
00412     ob= add_object(scene, OB_EMPTY);
00413     
00414     basedit = object_in_scene(obedit, scene);
00415     base = object_in_scene(ob, scene);
00416     base->lay = ob->lay = obedit->lay;
00417     
00418     /* icky, add_object sets new base as active.
00419      * so set it back to the original edit object */
00420     scene->basact = basedit;
00421 
00422     return ob;
00423 }
00424 
00425 static void add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode)
00426 {
00427     ModifierData *md=NULL;
00428     HookModifierData *hmd = NULL;
00429     float cent[3];
00430     int tot, ok, *indexar;
00431     char name[MAX_NAME];
00432     
00433     ok = object_hook_index_array(scene, obedit, &tot, &indexar, name, cent);
00434     
00435     if (!ok) return;    // XXX error("Requires selected vertices or active Vertex Group");
00436     
00437     if (mode==OBJECT_ADDHOOK_NEWOB && !ob) {
00438         
00439         ob = add_hook_object_new(scene, obedit);
00440         
00441         /* transform cent to global coords for loc */
00442         mul_v3_m4v3(ob->loc, obedit->obmat, cent);
00443     }
00444     
00445     md = obedit->modifiers.first;
00446     while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
00447         md = md->next;
00448     }
00449     
00450     hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
00451     BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
00452     BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name+2);
00453     modifier_unique_name(&obedit->modifiers, (ModifierData*)hmd);
00454     
00455     hmd->object= ob;
00456     hmd->indexar= indexar;
00457     copy_v3_v3(hmd->cent, cent);
00458     hmd->totindex= tot;
00459     BLI_strncpy(hmd->name, name, sizeof(hmd->name));
00460     
00461     /* matrix calculus */
00462     /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
00463     /*        (parentinv         )                          */
00464     where_is_object(scene, ob);
00465     
00466     invert_m4_m4(ob->imat, ob->obmat);
00467     /* apparently this call goes from right to left... */
00468     mul_serie_m4(hmd->parentinv, ob->imat, obedit->obmat, NULL,
00469                  NULL, NULL, NULL, NULL, NULL);
00470     
00471     DAG_scene_sort(bmain, scene);
00472 }
00473 
00474 static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
00475 {
00476     Main *bmain= CTX_data_main(C);
00477     Scene *scene= CTX_data_scene(C);
00478     Object *obedit = CTX_data_edit_object(C);
00479     Object *obsel=NULL;
00480     
00481     CTX_DATA_BEGIN(C, Object*, ob, selected_objects)
00482     {
00483         if (ob != obedit) {
00484             obsel = ob;
00485             break;
00486         }
00487     }
00488     CTX_DATA_END;
00489     
00490     if (!obsel) {
00491         BKE_report(op->reports, RPT_ERROR, "Can't add hook with no other selected objects");
00492         return OPERATOR_CANCELLED;
00493     }
00494     
00495     add_hook_object(bmain, scene, obedit, obsel, OBJECT_ADDHOOK_SELOB);
00496     
00497     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, obedit);
00498     return OPERATOR_FINISHED;
00499 }
00500 
00501 void OBJECT_OT_hook_add_selobj(wmOperatorType *ot)
00502 {
00503     /* identifiers */
00504     ot->name= "Hook to Selected Object";
00505     ot->description= "Hook selected vertices to the first selected Object";
00506     ot->idname= "OBJECT_OT_hook_add_selob";
00507     
00508     /* api callbacks */
00509     ot->exec= object_add_hook_selob_exec;
00510     ot->poll= hook_op_edit_poll;
00511     
00512     /* flags */
00513     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00514 }
00515 
00516 static int object_add_hook_newob_exec(bContext *C, wmOperator *UNUSED(op))
00517 {
00518     Main *bmain= CTX_data_main(C);
00519     Scene *scene= CTX_data_scene(C);
00520     Object *obedit = CTX_data_edit_object(C);
00521 
00522     add_hook_object(bmain, scene, obedit, NULL, OBJECT_ADDHOOK_NEWOB);
00523     
00524     WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
00525     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, obedit);
00526     return OPERATOR_FINISHED;
00527 }
00528 
00529 void OBJECT_OT_hook_add_newobj(wmOperatorType *ot)
00530 {
00531     /* identifiers */
00532     ot->name= "Hook to New Object";
00533     ot->description= "Hook selected vertices to the first selected Object";
00534     ot->idname= "OBJECT_OT_hook_add_newob";
00535     
00536     /* api callbacks */
00537     ot->exec= object_add_hook_newob_exec;
00538     ot->poll= hook_op_edit_poll;
00539     
00540     /* flags */
00541     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00542 }
00543 
00544 static int object_hook_remove_exec(bContext *C, wmOperator *op)
00545 {
00546     int num= RNA_enum_get(op->ptr, "modifier");
00547     Object *ob=NULL;
00548     HookModifierData *hmd=NULL;
00549 
00550     ob = CTX_data_edit_object(C);
00551     hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
00552 
00553     if (!ob || !hmd) {
00554         BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
00555         return OPERATOR_CANCELLED;
00556     }
00557     
00558     /* remove functionality */
00559     
00560     BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
00561     modifier_free((ModifierData *)hmd);
00562     
00563     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00564     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00565     
00566     return OPERATOR_FINISHED;
00567 }
00568 
00569 static EnumPropertyItem *hook_mod_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
00570 {   
00571     Object *ob = CTX_data_edit_object(C);
00572     EnumPropertyItem tmp = {0, "", 0, "", ""};
00573     EnumPropertyItem *item= NULL;
00574     ModifierData *md = NULL;
00575     int a, totitem= 0;
00576     
00577     if(!ob)
00578         return DummyRNA_NULL_items;
00579     
00580     for(a=0, md=ob->modifiers.first; md; md= md->next, a++) {
00581         if (md->type==eModifierType_Hook) {
00582             tmp.value= a;
00583             tmp.icon = ICON_HOOK;
00584             tmp.identifier= md->name;
00585             tmp.name= md->name;
00586             RNA_enum_item_add(&item, &totitem, &tmp);
00587         }
00588     }
00589     
00590     RNA_enum_item_end(&item, &totitem);
00591     *free= 1;
00592     
00593     return item;
00594 }
00595 
00596 void OBJECT_OT_hook_remove(wmOperatorType *ot)
00597 {
00598     PropertyRNA *prop;
00599     
00600     /* identifiers */
00601     ot->name= "Remove Hook";
00602     ot->idname= "OBJECT_OT_hook_remove";
00603     ot->description= "Remove a hook from the active object";
00604     
00605     /* api callbacks */
00606     ot->exec= object_hook_remove_exec;
00607     ot->invoke= WM_menu_invoke;
00608     ot->poll= hook_op_edit_poll;
00609     
00610     /* flags */
00611     /* this operator removes modifier which isn't stored in local undo stack,
00612        so redoing it from redo panel gives totally weird results  */
00613     ot->flag= /*OPTYPE_REGISTER|*/OPTYPE_UNDO;
00614     
00615     /* properties */
00616     prop= RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
00617     RNA_def_enum_funcs(prop, hook_mod_itemf);
00618     ot->prop= prop;
00619 }
00620 
00621 static int object_hook_reset_exec(bContext *C, wmOperator *op)
00622 {
00623     PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
00624     int num= RNA_enum_get(op->ptr, "modifier");
00625     Object *ob=NULL;
00626     HookModifierData *hmd=NULL;
00627     
00628     if (ptr.data) {     /* if modifier context is available, use that */
00629         ob = ptr.id.data;
00630         hmd= ptr.data;
00631     } 
00632     else {          /* use the provided property */
00633         ob = CTX_data_edit_object(C);
00634         hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
00635     }
00636     if (!ob || !hmd) {
00637         BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
00638         return OPERATOR_CANCELLED;
00639     }
00640     
00641     /* reset functionality */
00642     if(hmd->object) {
00643         bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
00644         
00645         if(hmd->subtarget[0] && pchan) {
00646             float imat[4][4], mat[4][4];
00647             
00648             /* calculate the world-space matrix for the pose-channel target first, then carry on as usual */
00649             mult_m4_m4m4(mat, hmd->object->obmat, pchan->pose_mat);
00650             
00651             invert_m4_m4(imat, mat);
00652             mul_serie_m4(hmd->parentinv, imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
00653         }
00654         else {
00655             invert_m4_m4(hmd->object->imat, hmd->object->obmat);
00656             mul_serie_m4(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
00657         }
00658     }
00659     
00660     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00661     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00662     
00663     return OPERATOR_FINISHED;
00664 }
00665 
00666 void OBJECT_OT_hook_reset(wmOperatorType *ot)
00667 {
00668     PropertyRNA *prop;
00669     
00670     /* identifiers */
00671     ot->name= "Reset Hook";
00672     ot->description= "Recalculate and clear offset transformation";
00673     ot->idname= "OBJECT_OT_hook_reset";
00674     
00675     /* callbacks */
00676     ot->exec= object_hook_reset_exec;
00677     ot->poll= hook_op_edit_poll;
00678     
00679     /* flags */
00680     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00681     
00682     /* properties */
00683     prop= RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
00684     RNA_def_enum_funcs(prop, hook_mod_itemf);
00685 }
00686 
00687 static int object_hook_recenter_exec(bContext *C, wmOperator *op)
00688 {
00689     PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
00690     int num= RNA_enum_get(op->ptr, "modifier");
00691     Object *ob=NULL;
00692     HookModifierData *hmd=NULL;
00693     Scene *scene = CTX_data_scene(C);
00694     float bmat[3][3], imat[3][3];
00695     
00696     if (ptr.data) {     /* if modifier context is available, use that */
00697         ob = ptr.id.data;
00698         hmd= ptr.data;
00699     } 
00700     else {          /* use the provided property */
00701         ob = CTX_data_edit_object(C);
00702         hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
00703     }
00704     if (!ob || !hmd) {
00705         BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
00706         return OPERATOR_CANCELLED;
00707     }
00708     
00709     /* recenter functionality */
00710     copy_m3_m4(bmat, ob->obmat);
00711     invert_m3_m3(imat, bmat);
00712     
00713     sub_v3_v3v3(hmd->cent, scene->cursor, ob->obmat[3]);
00714     mul_m3_v3(imat, hmd->cent);
00715     
00716     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00717     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00718     
00719     return OPERATOR_FINISHED;
00720 }
00721 
00722 void OBJECT_OT_hook_recenter(wmOperatorType *ot)
00723 {
00724     PropertyRNA *prop;
00725     
00726     /* identifiers */
00727     ot->name= "Recenter Hook";
00728     ot->description= "Set hook center to cursor position";
00729     ot->idname= "OBJECT_OT_hook_recenter";
00730     
00731     /* callbacks */
00732     ot->exec= object_hook_recenter_exec;
00733     ot->poll= hook_op_edit_poll;
00734     
00735     /* flags */
00736     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00737     
00738     /* properties */
00739     prop= RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
00740     RNA_def_enum_funcs(prop, hook_mod_itemf);
00741 }
00742 
00743 static int object_hook_assign_exec(bContext *C, wmOperator *op)
00744 {
00745     PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
00746     int num= RNA_enum_get(op->ptr, "modifier");
00747     Object *ob=NULL;
00748     HookModifierData *hmd=NULL;
00749     float cent[3];
00750     char name[MAX_NAME];
00751     int *indexar, tot;
00752     
00753     if (ptr.data) {     /* if modifier context is available, use that */
00754         ob = ptr.id.data;
00755         hmd= ptr.data;
00756     } 
00757     else {          /* use the provided property */
00758         ob = CTX_data_edit_object(C);
00759         hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
00760     }
00761     if (!ob || !hmd) {
00762         BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
00763         return OPERATOR_CANCELLED;
00764     }
00765     
00766     /* assign functionality */
00767     
00768     if(!object_hook_index_array(CTX_data_scene(C), ob, &tot, &indexar, name, cent)) {
00769         BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
00770         return OPERATOR_CANCELLED;
00771     }
00772     if(hmd->indexar)
00773         MEM_freeN(hmd->indexar);
00774     
00775     copy_v3_v3(hmd->cent, cent);
00776     hmd->indexar= indexar;
00777     hmd->totindex= tot;
00778     
00779     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00780     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00781     
00782     return OPERATOR_FINISHED;
00783 }
00784 
00785 void OBJECT_OT_hook_assign(wmOperatorType *ot)
00786 {
00787     PropertyRNA *prop;
00788     
00789     /* identifiers */
00790     ot->name= "Assign to Hook";
00791     ot->description= "Assign the selected vertices to a hook";
00792     ot->idname= "OBJECT_OT_hook_assign";
00793     
00794     /* callbacks */
00795     ot->exec= object_hook_assign_exec;
00796     ot->poll= hook_op_edit_poll;
00797     
00798     /* flags */
00799     /* this operator changes data stored in modifier which doesn't get pushed to undo stack,
00800        so redoing it from redo panel gives totally weird results  */
00801     ot->flag= /*OPTYPE_REGISTER|*/OPTYPE_UNDO;
00802     
00803     /* properties */
00804     prop= RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to assign to");
00805     RNA_def_enum_funcs(prop, hook_mod_itemf);
00806 }
00807 
00808 static int object_hook_select_exec(bContext *C, wmOperator *op)
00809 {
00810     PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
00811     int num= RNA_enum_get(op->ptr, "modifier");
00812     Object *ob=NULL;
00813     HookModifierData *hmd=NULL;
00814     
00815     if (ptr.data) {     /* if modifier context is available, use that */
00816         ob = ptr.id.data;
00817         hmd= ptr.data;
00818     } 
00819     else {          /* use the provided property */
00820         ob = CTX_data_edit_object(C);
00821         hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
00822     }
00823     if (!ob || !hmd) {
00824         BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
00825         return OPERATOR_CANCELLED;
00826     }
00827     
00828     /* select functionality */
00829     object_hook_select(ob, hmd);
00830     
00831     WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
00832     
00833     return OPERATOR_FINISHED;
00834 }
00835 
00836 void OBJECT_OT_hook_select(wmOperatorType *ot)
00837 {
00838     PropertyRNA *prop;
00839     
00840     /* identifiers */
00841     ot->name= "Select Hook";
00842     ot->description= "Select affected vertices on mesh";
00843     ot->idname= "OBJECT_OT_hook_select";
00844     
00845     /* callbacks */
00846     ot->exec= object_hook_select_exec;
00847     ot->poll= hook_op_edit_poll;
00848     
00849     /* flags */
00850     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00851     
00852     /* properties */
00853     prop= RNA_def_enum(ot->srna, "modifier", DummyRNA_NULL_items, 0, "Modifier", "Modifier number to remove");
00854     RNA_def_enum_funcs(prop, hook_mod_itemf);
00855 }
00856