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