* Re-implemented/refactored 3D View hooks menu.

Now shares the same operators as the modifier buttons, works context-sensitive, and uses Python menu too.

* Cleanups/tweaks in 3D View vertex group menu
This commit is contained in:
Matt Ebb
2009-11-22 06:20:56 +00:00
parent bb43bee5f5
commit 8e76e2d09c
7 changed files with 487 additions and 482 deletions

View File

@@ -746,9 +746,40 @@ class VIEW3D_MT_hook(bpy.types.Menu):
def draw(self, context):
layout = self.layout
layout.operator_context = 'EXEC_AREA'
layout.items_enumO("object.hook_add", "type")
# layout.itemS()
# Other operators still need porting
layout.itemO("object.hook_add_newob")
layout.itemO("object.hook_add_selob")
if [mod.type == 'HOOK' for mod in context.active_object.modifiers]:
layout.itemS()
layout.item_menu_enumO("object.hook_assign", "modifier")
layout.item_menu_enumO("object.hook_remove", "modifier")
layout.itemS()
layout.item_menu_enumO("object.hook_select", "modifier")
layout.item_menu_enumO("object.hook_reset", "modifier")
layout.item_menu_enumO("object.hook_recenter", "modifier")
class VIEW3D_MT_vertex_group(bpy.types.Menu):
bl_label = "Vertex Groups"
def draw(self, context):
layout = self.layout
layout.operator_context = 'EXEC_AREA'
layout.item_booleanO("object.vertex_group_assign", "new", True, text="Assign to New Group")
ob = context.active_object
if ob.mode == 'EDIT':
if ob.vertex_groups and ob.active_vertex_group:
layout.itemS()
layout.itemO("object.vertex_group_assign", text="Assign to Active Group")
layout.itemO("object.vertex_group_remove_from", text="Remove from Active Group")
layout.item_booleanO("object.vertex_group_remove_from", "all", True, text="Remove from All")
layout.itemS()
if ob.vertex_groups and ob.active_vertex_group:
layout.item_menu_enumO("object.vertex_group_set_active", "group", text="Set Active Group")
layout.itemO("object.vertex_group_remove", text="Remove Active Group")
layout.item_booleanO("object.vertex_group_remove", "all", True, text="Remove All Groups")
# ********** Sculpt menu **********
@@ -1062,6 +1093,7 @@ class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
layout.itemS()
layout.itemM("VIEW3D_MT_vertex_group")
layout.itemM("VIEW3D_MT_hook")
@@ -1830,6 +1862,7 @@ bpy.types.register(VIEW3D_MT_make_single_user)
bpy.types.register(VIEW3D_MT_make_links)
bpy.types.register(VIEW3D_MT_hook)
bpy.types.register(VIEW3D_MT_vertex_group)
bpy.types.register(VIEW3D_MT_sculpt) # Sculpt Menu

View File

@@ -297,9 +297,6 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, 0, KKEY);
// TODO: this should probably be made to a menu instead...
WM_keymap_add_item(keymap, "OBJECT_OT_vertex_group_menu", GKEY, KM_PRESS, KM_CTRL, 0);
/* menus */
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_specials", WKEY, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_faces", FKEY, KM_PRESS, KM_CTRL, 0);
@@ -307,7 +304,8 @@ void ED_keymap_mesh(wmKeyConfig *keyconf)
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_vertices", VKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_hook", HKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_uv_map", UKEY, KM_PRESS, 0, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_vertex_group", GKEY, KM_PRESS, KM_CTRL, 0);
ED_object_generic_keymap(keyconf, keymap, TRUE);
}

View File

@@ -35,6 +35,7 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "DNA_action_types.h"
#include "DNA_curve_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
@@ -45,12 +46,15 @@
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_depsgraph.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -59,13 +63,15 @@
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_view3d.h"
#include "ED_screen.h"
#include "WM_types.h"
#include "WM_api.h"
#include "object_intern.h"
#include "UI_interface.h"
#include "UI_resources.h"
/* XXX operators for this are not implemented yet */
#include "object_intern.h"
static int return_editmesh_indexar(EditMesh *em, int *tot, int **indexar, float *cent)
{
@@ -286,7 +292,7 @@ static int return_editcurve_indexar(Object *obedit, int *tot, int **indexar, flo
return totvert;
}
int object_hook_index_array(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
static int object_hook_index_array(Object *obedit, int *tot, int **indexar, char *name, float *cent_r)
{
*indexar= NULL;
*tot= 0;
@@ -368,7 +374,7 @@ static void select_editcurve_hook(Object *obedit, HookModifierData *hmd)
}
}
void object_hook_select(Object *ob, HookModifierData *hmd)
static void object_hook_select(Object *ob, HookModifierData *hmd)
{
if (hmd->indexar == NULL)
return;
@@ -379,281 +385,440 @@ void object_hook_select(Object *ob, HookModifierData *hmd)
else if(ob->type==OB_SURF) select_editcurve_hook(ob, hmd);
}
void add_hook(Scene *scene, View3D *v3d, int mode)
static Object *add_hook_object_new(Scene *scene, Object *obedit)
{
ModifierData *md = NULL;
Base *base, *basedit;
Object *ob;
ob= add_object(scene, OB_EMPTY);
basedit = object_in_scene(obedit, scene);
base = object_in_scene(ob, scene);
base->lay = ob->lay = obedit->lay;
/* icky, add_object sets new base as active.
* so set it back to the original edit object */
scene->basact = basedit;
return ob;
}
static void add_hook_object(Scene *scene, Object *obedit, Object *ob, int mode)
{
ModifierData *md=NULL;
HookModifierData *hmd = NULL;
Object *ob=NULL;
Object *obedit= scene->obedit; // XXX get from context
float cent[3];
int tot, ok, *indexar;
char name[32];
if(obedit==NULL) return;
ok = object_hook_index_array(obedit, &tot, &indexar, name, cent);
/* preconditions */
if(mode==2) { /* selected object */
Base *base;
for(base= FIRSTBASE; base; base= base->next) {
if(TESTBASELIB(v3d, base)) {
if(base!=BASACT) {
ob= base->object;
break;
}
}
}
if(ob==NULL) {
// XXX error("Requires selected Object");
return;
}
if (!ok) return; // XXX error("Requires selected vertices or active Vertex Group");
if (mode==OBJECT_ADDHOOK_NEWOB && !ob) {
ob = add_hook_object_new(scene, obedit);
/* transform cent to global coords for loc */
mul_v3_m4v3(ob->loc, obedit->obmat, cent);
}
else if(mode!=1) {
int maxlen=0, a, nr;
char *cp;
/* make pupmenu with hooks */
for(md=obedit->modifiers.first; md; md= md->next) {
if (md->type==eModifierType_Hook)
maxlen+=32;
}
if(maxlen==0) {
// XXX error("Object has no hooks yet");
return;
}
cp= MEM_callocN(maxlen+32, "temp string");
if(mode==3) strcpy(cp, "Remove %t|");
else if(mode==4) strcpy(cp, "Reassign %t|");
else if(mode==5) strcpy(cp, "Select %t|");
else if(mode==6) strcpy(cp, "Clear Offset %t|");
for(md=obedit->modifiers.first; md; md= md->next) {
if (md->type==eModifierType_Hook) {
strcat(cp, md->name);
strcat(cp, " |");
}
}
nr= 0; // XXX pupmenu(cp);
MEM_freeN(cp);
if(nr<1) return;
a= 1;
for(md=obedit->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Hook) {
if(a==nr) break;
a++;
}
}
hmd = (HookModifierData*) md;
ob= hmd->object;
md = obedit->modifiers.first;
while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
md = md->next;
}
/* do it, new hooks or reassign */
if(mode==1 || mode==2 || mode==4) {
float cent[3];
int tot, ok, *indexar;
char name[32];
ok = object_hook_index_array(obedit, &tot, &indexar, name, cent);
if(ok==0) {
// XXX error("Requires selected vertices or active Vertex Group");
}
else {
if(mode==1) {
Base *base= BASACT, *newbase;
ob= add_object(scene, OB_EMPTY);
/* set layers OK */
newbase= BASACT;
newbase->lay= base->lay;
ob->lay= newbase->lay;
/* transform cent to global coords for loc */
mul_v3_m4v3(ob->loc, obedit->obmat, cent);
/* restore, add_object sets active */
BASACT= base;
}
/* if mode is 2 or 4, ob has been set */
/* new hook */
if(mode==1 || mode==2) {
ModifierData *md = obedit->modifiers.first;
while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) {
md = md->next;
}
hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
modifier_unique_name(&obedit->modifiers, (ModifierData*)hmd);
}
else if (hmd->indexar) MEM_freeN(hmd->indexar); /* reassign, hook was set */
hmd->object= ob;
hmd->indexar= indexar;
copy_v3_v3(hmd->cent, cent);
hmd->totindex= tot;
BLI_strncpy(hmd->name, name, 32);
// TODO: need to take into account bone targets here too now...
if(mode==1 || mode==2) {
/* matrix calculus */
/* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
/* (parentinv ) */
where_is_object(scene, ob);
invert_m4_m4(ob->imat, ob->obmat);
/* apparently this call goes from right to left... */
mul_serie_m4(hmd->parentinv, ob->imat, obedit->obmat, NULL,
NULL, NULL, NULL, NULL, NULL);
}
}
}
else if(mode==3) { /* remove */
BLI_remlink(&obedit->modifiers, md);
modifier_free(md);
}
else if(mode==5) { /* select */
// FIXME: this is now OBJECT_OT_hook_select
object_hook_select(obedit, hmd);
}
else if(mode==6) { /* clear offset */
// FIXME: this is now OBJECT_OT_hook_reset operator
where_is_object(scene, ob); /* ob is hook->parent */
invert_m4_m4(ob->imat, ob->obmat);
/* this call goes from right to left... */
mul_serie_m4(hmd->parentinv, ob->imat, obedit->obmat, NULL,
NULL, NULL, NULL, NULL, NULL);
}
hmd = (HookModifierData*) modifier_new(eModifierType_Hook);
BLI_insertlinkbefore(&obedit->modifiers, md, hmd);
sprintf(hmd->modifier.name, "Hook-%s", ob->id.name+2);
modifier_unique_name(&obedit->modifiers, (ModifierData*)hmd);
hmd->object= ob;
hmd->indexar= indexar;
copy_v3_v3(hmd->cent, cent);
hmd->totindex= tot;
BLI_strncpy(hmd->name, name, 32);
/* matrix calculus */
/* vert x (obmat x hook->imat) x hook->obmat x ob->imat */
/* (parentinv ) */
where_is_object(scene, ob);
invert_m4_m4(ob->imat, ob->obmat);
/* apparently this call goes from right to left... */
mul_serie_m4(hmd->parentinv, ob->imat, obedit->obmat, NULL,
NULL, NULL, NULL, NULL, NULL);
DAG_scene_sort(scene);
}
void add_hook_menu(Scene *scene, View3D *v3d)
{
Object *obedit= scene->obedit; // XXX get from context
int mode;
if(obedit==NULL) return;
if(modifiers_findByType(obedit, eModifierType_Hook))
mode= 0; // XXX pupmenu("Hooks %t|Add, To New Empty %x1|Add, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6");
else
mode= 0; // XXX pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2");
if(mode<1) return;
/* do operations */
add_hook(scene, v3d, mode);
}
void hookmenu(Scene *scene, View3D *v3d)
{
/* only called in object mode */
short event, changed=0;
Object *ob;
Base *base;
ModifierData *md;
HookModifierData *hmd;
event= 0; // XXX pupmenu("Modify Hooks for Selected...%t|Reset Offset%x1|Recenter at Cursor%x2");
if (event==-1) return;
if (event==2 && !(v3d)) {
// XXX error("Cannot perform this operation without a 3d view");
return;
}
for (base= FIRSTBASE; base; base= base->next) {
if(TESTBASELIB(v3d, base)) {
for (md = base->object->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Hook) {
ob = base->object;
hmd = (HookModifierData*) md;
/*
* Copied from modifiers_cursorHookCenter and
* modifiers_clearHookOffset, should consolidate
* */
if (event==1) {
if(hmd->object) {
invert_m4_m4(hmd->object->imat, hmd->object->obmat);
mul_serie_m4(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
changed= 1;
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
}
} else {
float *curs = give_cursor(scene, v3d);
float bmat[3][3], imat[3][3];
where_is_object(scene, ob);
copy_m3_m4(bmat, ob->obmat);
invert_m3_m3(imat, bmat);
curs= give_cursor(scene, v3d);
hmd->cent[0]= curs[0]-ob->obmat[3][0];
hmd->cent[1]= curs[1]-ob->obmat[3][1];
hmd->cent[2]= curs[2]-ob->obmat[3][2];
mul_m3_v3(imat, hmd->cent);
changed= 1;
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
}
}
}
}
}
if (changed) {
}
}
static int object_add_hook_exec(bContext *C, wmOperator *op)
static int object_add_hook_selob_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
int mode= RNA_enum_get(op->ptr, "type");
// XXX - todo, break up this function for different operators
// and detect if this finished correctly or not,
add_hook(scene, v3d, mode);
Object *obedit = CTX_data_edit_object(C);
Object *obsel=NULL;
CTX_DATA_BEGIN(C, Object*, ob, selected_objects)
{
if (ob != obedit) {
obsel = ob;
break;
}
}
CTX_DATA_END;
if (!obsel) {
BKE_report(op->reports, RPT_ERROR, "Can't add hook with no other selected objects.");
return OPERATOR_CANCELLED;
}
add_hook_object(scene, obedit, obsel, OBJECT_ADDHOOK_SELOB);
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_add(wmOperatorType *ot)
void OBJECT_OT_hook_add_selobj(wmOperatorType *ot)
{
static EnumPropertyItem prop_new_hook_types[] = {
{1, "NEW", 0, "New Object", "Create a new object and assign the verts to it."},
{2, "SELECTED", 0, "Selection", "Add the hook to the selected object."},
{0, NULL, 0, NULL, NULL}
};
/* identifiers */
ot->name= "Add Hook";
ot->description= "Add hook to selected verts.";
ot->idname= "OBJECT_OT_hook_add";
ot->name= "Hook to Selected Object";
ot->description= "Hook selected vertices to the first selected Object.";
ot->idname= "OBJECT_OT_hook_add_selob";
/* api callbacks */
ot->invoke= WM_menu_invoke;
ot->exec= object_add_hook_exec;
// ot->poll= ED_operator_editmesh;
ot->exec= object_add_hook_selob_exec;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_enum(ot->srna, "type", prop_new_hook_types, 0, "Type", "");
}
static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
add_hook_object(scene, obedit, NULL, OBJECT_ADDHOOK_NEWOB);
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_add_newobj(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Hook to New Object";
ot->description= "Hook selected vertices to the first selected Object.";
ot->idname= "OBJECT_OT_hook_add_newob";
/* api callbacks */
ot->exec= object_add_hook_newob_exec;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static EnumPropertyItem hook_mod_items[]= {
{0, NULL, 0, NULL, NULL}};
static int object_hook_remove_exec(bContext *C, wmOperator *op)
{
int num= RNA_enum_get(op->ptr, "modifier");
Object *ob=NULL;
HookModifierData *hmd=NULL;
ob = CTX_data_edit_object(C);
hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
if (!ob || !hmd) {
BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
return OPERATOR_CANCELLED;
}
/* remove functionality */
BLI_remlink(&ob->modifiers, (ModifierData *)hmd);
modifier_free((ModifierData *)hmd);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
static EnumPropertyItem *hook_mod_itemf(bContext *C, PointerRNA *ptr, int *free)
{
Object *ob = CTX_data_edit_object(C);
EnumPropertyItem tmp = {0, "", 0, "", ""};
EnumPropertyItem *item= NULL;
ModifierData *md = NULL;
int a, totitem= 0;
if(!ob)
return hook_mod_items;
for(a=0, md=ob->modifiers.first; md; md= md->next, a++) {
if (md->type==eModifierType_Hook) {
tmp.value= a;
tmp.icon = ICON_HOOK;
tmp.identifier= md->name;
tmp.name= md->name;
RNA_enum_item_add(&item, &totitem, &tmp);
}
}
RNA_enum_item_end(&item, &totitem);
*free= 1;
return item;
}
void OBJECT_OT_hook_remove(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name= "Remove Hook";
ot->idname= "OBJECT_OT_hook_remove";
ot->description= "Remove a hook from the active object.";
/* api callbacks */
ot->poll= ED_operator_editmesh;
ot->exec= object_hook_remove_exec;
ot->invoke= WM_menu_invoke;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
prop= RNA_def_enum(ot->srna, "modifier", hook_mod_items, 0, "Modifier", "Modifier number to remove.");
RNA_def_enum_funcs(prop, hook_mod_itemf);
}
static int object_hook_reset_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
int num= RNA_enum_get(op->ptr, "modifier");
Object *ob=NULL;
HookModifierData *hmd=NULL;
if (ptr.data) { /* if modifier context is available, use that */
ob = ptr.id.data;
hmd= ptr.data;
} else { /* use the provided property */
ob = CTX_data_edit_object(C);
hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
}
if (!ob || !hmd) {
BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
return OPERATOR_CANCELLED;
}
/* reset functionality */
if(hmd->object) {
bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
if(hmd->subtarget[0] && pchan) {
float imat[4][4], mat[4][4];
/* calculate the world-space matrix for the pose-channel target first, then carry on as usual */
mul_m4_m4m4(mat, pchan->pose_mat, hmd->object->obmat);
invert_m4_m4(imat, mat);
mul_serie_m4(hmd->parentinv, imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
}
else {
invert_m4_m4(hmd->object->imat, hmd->object->obmat);
mul_serie_m4(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
}
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_reset(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name= "Reset Hook";
ot->description= "Recalculate and and clear offset transformation.";
ot->idname= "OBJECT_OT_hook_reset";
ot->poll= ED_operator_editmesh;
ot->exec= object_hook_reset_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
prop= RNA_def_enum(ot->srna, "modifier", hook_mod_items, 0, "Modifier", "Modifier number to assign to.");
RNA_def_enum_funcs(prop, hook_mod_itemf);
}
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
int num= RNA_enum_get(op->ptr, "modifier");
Object *ob=NULL;
HookModifierData *hmd=NULL;
Scene *scene = CTX_data_scene(C);
float bmat[3][3], imat[3][3];
if (ptr.data) { /* if modifier context is available, use that */
ob = ptr.id.data;
hmd= ptr.data;
} else { /* use the provided property */
ob = CTX_data_edit_object(C);
hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
}
if (!ob || !hmd) {
BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
return OPERATOR_CANCELLED;
}
/* recenter functionality */
copy_m3_m4(bmat, ob->obmat);
invert_m3_m3(imat, bmat);
sub_v3_v3v3(hmd->cent, scene->cursor, ob->obmat[3]);
mul_m3_v3(imat, hmd->cent);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name= "Recenter Hook";
ot->description= "Set hook center to cursor position.";
ot->idname= "OBJECT_OT_hook_recenter";
ot->poll= ED_operator_editmesh;
ot->exec= object_hook_recenter_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
prop= RNA_def_enum(ot->srna, "modifier", hook_mod_items, 0, "Modifier", "Modifier number to assign to.");
RNA_def_enum_funcs(prop, hook_mod_itemf);
}
static int object_hook_assign_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
int num= RNA_enum_get(op->ptr, "modifier");
Object *ob=NULL;
HookModifierData *hmd=NULL;
float cent[3];
char name[32];
int *indexar, tot;
if (ptr.data) { /* if modifier context is available, use that */
ob = ptr.id.data;
hmd= ptr.data;
} else { /* use the provided property */
ob = CTX_data_edit_object(C);
hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
}
if (!ob || !hmd) {
BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
return OPERATOR_CANCELLED;
}
/* assign functionality */
if(!object_hook_index_array(ob, &tot, &indexar, name, cent)) {
BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
return OPERATOR_CANCELLED;
}
if(hmd->indexar)
MEM_freeN(hmd->indexar);
copy_v3_v3(hmd->cent, cent);
hmd->indexar= indexar;
hmd->totindex= tot;
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_assign(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name= "Assign to Hook";
ot->description= "Assign the selected vertices to a hook.";
ot->idname= "OBJECT_OT_hook_assign";
ot->poll= ED_operator_editmesh;
ot->exec= object_hook_assign_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
prop= RNA_def_enum(ot->srna, "modifier", hook_mod_items, 0, "Modifier", "Modifier number to assign to.");
RNA_def_enum_funcs(prop, hook_mod_itemf);
}
static int object_hook_select_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
int num= RNA_enum_get(op->ptr, "modifier");
Object *ob=NULL;
HookModifierData *hmd=NULL;
if (ptr.data) { /* if modifier context is available, use that */
ob = ptr.id.data;
hmd= ptr.data;
} else { /* use the provided property */
ob = CTX_data_edit_object(C);
hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
}
if (!ob || !hmd) {
BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
return OPERATOR_CANCELLED;
}
/* select functionality */
object_hook_select(ob, hmd);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_select(wmOperatorType *ot)
{
PropertyRNA *prop;
ot->name= "Select Hook";
ot->description= "Selects effected vertices on mesh.";
ot->idname= "OBJECT_OT_hook_select";
ot->poll= ED_operator_editmesh;
ot->exec= object_hook_select_exec;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
prop= RNA_def_enum(ot->srna, "modifier", hook_mod_items, 0, "Modifier", "Modifier number to remove.");
RNA_def_enum_funcs(prop, hook_mod_itemf);
}

View File

@@ -36,6 +36,12 @@ struct Object;
struct Mesh;
struct HookModifierData;
/* add hook menu */
enum {
OBJECT_ADDHOOK_NEWOB = 1,
OBJECT_ADDHOOK_SELOB,
} eObject_Hook_Add_Mode;
/* internal exports only */
/* object_transform.c */
@@ -103,10 +109,13 @@ void OBJECT_OT_join(struct wmOperatorType *ot);
void OBJECT_OT_convert(struct wmOperatorType *ot);
/* object_hook.c */
int object_hook_index_array(Object *obedit, int *tot, int **indexar, char *name, float *cent_r);
void object_hook_select(Object *obedit, struct HookModifierData *hmd);
void OBJECT_OT_hook_add(struct wmOperatorType *ot);
void OBJECT_OT_hook_add_selobj(struct wmOperatorType *ot);
void OBJECT_OT_hook_add_newobj(struct wmOperatorType *ot);
void OBJECT_OT_hook_remove(struct wmOperatorType *ot);
void OBJECT_OT_hook_select(struct wmOperatorType *ot);
void OBJECT_OT_hook_assign(struct wmOperatorType *ot);
void OBJECT_OT_hook_reset(struct wmOperatorType *ot);
void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
/* object_lattice.c */
void free_editLatt(Object *ob);
@@ -134,10 +143,6 @@ void OBJECT_OT_modifier_copy(struct wmOperatorType *ot);
void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot);
void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot);
void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot);
void OBJECT_OT_hook_reset(struct wmOperatorType *ot);
void OBJECT_OT_hook_recenter(struct wmOperatorType *ot);
void OBJECT_OT_hook_select(struct wmOperatorType *ot);
void OBJECT_OT_hook_assign(struct wmOperatorType *ot);
void OBJECT_OT_explode_refresh(struct wmOperatorType *ot);
/* object_constraint.c */
@@ -177,7 +182,6 @@ void OBJECT_OT_vertex_group_levels(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_invert(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_blend(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_clean(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_menu(struct wmOperatorType *ot);
void OBJECT_OT_vertex_group_set_active(struct wmOperatorType *ot);
void OBJECT_OT_game_property_new(struct wmOperatorType *ot);

View File

@@ -822,157 +822,6 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/******************** hook operators ************************/
static int hook_poll(bContext *C)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
ID *id= ptr.id.data;
return (ptr.data && id && !id->lib);
}
static int hook_reset_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
Object *ob= ptr.id.data;
HookModifierData *hmd= ptr.data;
if(hmd->object) {
bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
if(hmd->subtarget[0] && pchan) {
float imat[4][4], mat[4][4];
/* calculate the world-space matrix for the pose-channel target first, then carry on as usual */
mul_m4_m4m4(mat, pchan->pose_mat, hmd->object->obmat);
invert_m4_m4(imat, mat);
mul_serie_m4(hmd->parentinv, imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
}
else {
invert_m4_m4(hmd->object->imat, hmd->object->obmat);
mul_serie_m4(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL);
}
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_reset(wmOperatorType *ot)
{
ot->name= "Hook Reset";
ot->description= "Recalculate and and clear offset transformation.";
ot->idname= "OBJECT_OT_hook_reset";
ot->exec= hook_reset_exec;
ot->poll= hook_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int hook_recenter_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
Object *ob= ptr.id.data;
HookModifierData *hmd= ptr.data;
float bmat[3][3], imat[3][3];
copy_m3_m4(bmat, ob->obmat);
invert_m3_m3(imat, bmat);
VECSUB(hmd->cent, scene->cursor, ob->obmat[3]);
mul_m3_v3(imat, hmd->cent);
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_recenter(wmOperatorType *ot)
{
ot->name= "Hook Recenter";
ot->description= "Set hook center to cursor position.";
ot->idname= "OBJECT_OT_hook_recenter";
ot->exec= hook_recenter_exec;
ot->poll= hook_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int hook_select_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
Object *ob= ptr.id.data;
HookModifierData *hmd= ptr.data;
object_hook_select(ob, hmd);
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_select(wmOperatorType *ot)
{
ot->name= "Hook Select";
ot->description= "Selects effected vertices on mesh.";
ot->idname= "OBJECT_OT_hook_select";
ot->exec= hook_select_exec;
ot->poll= hook_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int hook_assign_exec(bContext *C, wmOperator *op)
{
PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
Object *ob= ptr.id.data;
HookModifierData *hmd= ptr.data;
float cent[3];
char name[32];
int *indexar, tot;
if(!object_hook_index_array(ob, &tot, &indexar, name, cent)) {
BKE_report(op->reports, RPT_WARNING, "Requires selected vertices or active vertex group");
return OPERATOR_CANCELLED;
}
if(hmd->indexar)
MEM_freeN(hmd->indexar);
VECCOPY(hmd->cent, cent);
hmd->indexar= indexar;
hmd->totindex= tot;
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
void OBJECT_OT_hook_assign(wmOperatorType *ot)
{
ot->name= "Hook Assign";
ot->description= "Reassigns selected vertices to hook.";
ot->idname= "OBJECT_OT_hook_assign";
ot->exec= hook_assign_exec;
ot->poll= hook_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/****************** explode refresh operator *********************/
static int explode_refresh_poll(bContext *C)

View File

@@ -136,12 +136,8 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_multires_subdivide);
WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete);
WM_operatortype_append(OBJECT_OT_meshdeform_bind);
WM_operatortype_append(OBJECT_OT_hook_reset);
WM_operatortype_append(OBJECT_OT_hook_recenter);
WM_operatortype_append(OBJECT_OT_hook_select);
WM_operatortype_append(OBJECT_OT_hook_assign);
WM_operatortype_append(OBJECT_OT_explode_refresh);
WM_operatortype_append(OBJECT_OT_constraint_add);
WM_operatortype_append(OBJECT_OT_constraint_add_with_targets);
WM_operatortype_append(POSE_OT_constraint_add);
@@ -172,7 +168,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_group_levels);
WM_operatortype_append(OBJECT_OT_vertex_group_blend);
WM_operatortype_append(OBJECT_OT_vertex_group_clean);
WM_operatortype_append(OBJECT_OT_vertex_group_menu);
WM_operatortype_append(OBJECT_OT_vertex_group_set_active);
WM_operatortype_append(OBJECT_OT_game_property_new);
@@ -190,7 +185,13 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_group_add);
WM_operatortype_append(OBJECT_OT_group_remove);
WM_operatortype_append(OBJECT_OT_hook_add);
WM_operatortype_append(OBJECT_OT_hook_add_selobj);
WM_operatortype_append(OBJECT_OT_hook_add_newobj);
WM_operatortype_append(OBJECT_OT_hook_remove);
WM_operatortype_append(OBJECT_OT_hook_select);
WM_operatortype_append(OBJECT_OT_hook_assign);
WM_operatortype_append(OBJECT_OT_hook_reset);
WM_operatortype_append(OBJECT_OT_hook_recenter);
}
void ED_operatormacros_object(void)

View File

@@ -69,6 +69,7 @@
#include "ED_view3d.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "object_intern.h"
@@ -1753,6 +1754,7 @@ static EnumPropertyItem *vgroup_itemf(bContext *C, PointerRNA *ptr, int *free)
for(a=0, def=ob->defbase.first; def; def=def->next, a++) {
tmp.value= a;
tmp.icon= ICON_GROUP_VERTEX;
tmp.identifier= def->name;
tmp.name= def->name;
RNA_enum_item_add(&item, &totitem, &tmp);
@@ -1784,51 +1786,4 @@ void OBJECT_OT_vertex_group_set_active(wmOperatorType *ot)
/* properties */
prop= RNA_def_enum(ot->srna, "group", vgroup_items, 0, "Group", "Vertex group to set as active.");
RNA_def_enum_funcs(prop, vgroup_itemf);
}
static int vertex_group_menu_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
uiPopupMenu *pup;
uiLayout *layout;
pup= uiPupMenuBegin(C, "Vertex Groups", 0);
layout= uiPupMenuLayout(pup);
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
if(vgroup_object_in_edit_mode(ob)) {
uiItemBooleanO(layout, "Assign to New Group", 0, "OBJECT_OT_vertex_group_assign", "new", 1);
if(BLI_countlist(&ob->defbase) && ob->actdef) {
uiItemO(layout, "Assign to Group", 0, "OBJECT_OT_vertex_group_assign");
uiItemO(layout, "Remove from Group", 0, "OBJECT_OT_vertex_group_remove_from");
uiItemBooleanO(layout, "Remove from All", 0, "OBJECT_OT_vertex_group_remove_from", "all", 1);
}
}
if(BLI_countlist(&ob->defbase) && ob->actdef) {
if(vgroup_object_in_edit_mode(ob))
uiItemS(layout);
uiItemMenuEnumO(layout, "Set Active Group", 0, "OBJECT_OT_vertex_group_set_active", "group");
uiItemO(layout, "Remove Group", 0, "OBJECT_OT_vertex_group_remove");
uiItemBooleanO(layout, "Remove All Groups", 0, "OBJECT_OT_vertex_group_remove", "all", 1);
}
uiPupMenuEnd(C, pup);
return OPERATOR_FINISHED;
}
void OBJECT_OT_vertex_group_menu(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Vertex Group Menu";
ot->idname= "OBJECT_OT_vertex_group_menu";
ot->description= "Menu showing the operators available for editing Vertex Groups";
/* api callbacks */
ot->poll= vertex_group_poll;
ot->exec= vertex_group_menu_exec;
}
}