2.5
Further simplifying making operators with menus;
now you can add an 'invoke' callback:
WM_menu_invoke
which will automatically generate a menu with choices and assign
it to the property 'type'.
What also helps typing is the new RNA_enum_is_equal() function.
Here's a paste of the now committed 'clear parent'. Note the
undo push will become a flag too.
http://pasteall.org/3660
(Brecht; fixed small bug in RNA_enum_is_equal!)
To evaluate: solving dependencies for multipe scenes... probably
will make a more generic flush call.
This commit is contained in:
@@ -913,48 +913,66 @@ void make_track(Scene *scene, View3D *v3d)
|
||||
BIF_undo_push("Make Track");
|
||||
}
|
||||
|
||||
/* ******************** clear parent operator ******************* */
|
||||
|
||||
void clear_parent(Scene *scene, View3D *v3d)
|
||||
|
||||
static EnumPropertyItem prop_clear_parent_types[] = {
|
||||
{0, "CLEAR", "Clear Parent", ""},
|
||||
{1, "CLEAR_KEEP_TRANSFORM", "Clear and Keep Transformation (Clear Track)", ""},
|
||||
{2, "CLEAR_INVERSE", "Clear Parent Inverse", ""},
|
||||
{0, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* note, poll should check for editable scene */
|
||||
static int clear_parent_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *par;
|
||||
Base *base;
|
||||
int mode;
|
||||
|
||||
if(G.obedit) return;
|
||||
if(scene->id.lib) return;
|
||||
CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
|
||||
|
||||
mode= pupmenu("OK? %t|Clear Parent %x1|Clear and Keep Transformation (Clear Track) %x2|Clear Parent Inverse %x3");
|
||||
|
||||
if(mode<1) return;
|
||||
|
||||
for(base= FIRSTBASE; base; base= base->next) {
|
||||
if(TESTBASELIB(v3d, base)) {
|
||||
par= NULL;
|
||||
if(mode==1 || mode==2) {
|
||||
par= base->object->parent;
|
||||
base->object->parent= NULL;
|
||||
base->object->recalc |= OB_RECALC;
|
||||
|
||||
if(mode==2) {
|
||||
base->object->track= NULL;
|
||||
apply_obmat(base->object);
|
||||
}
|
||||
}
|
||||
else if(mode==3) {
|
||||
Mat4One(base->object->parentinv);
|
||||
base->object->recalc |= OB_RECALC;
|
||||
}
|
||||
if(RNA_enum_is_equal(op->ptr, "type", "CLEAR")) {
|
||||
ob->parent= NULL;
|
||||
}
|
||||
if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_KEEP_TRANSFORM")) {
|
||||
ob->parent= NULL;
|
||||
ob->track= NULL;
|
||||
apply_obmat(ob);
|
||||
}
|
||||
if(RNA_enum_is_equal(op->ptr, "type", "CLEAR_INVERSE")) {
|
||||
Mat4One(ob->parentinv);
|
||||
}
|
||||
ob->recalc |= OB_RECALC;
|
||||
}
|
||||
|
||||
DAG_scene_sort(scene);
|
||||
ED_anim_dag_flush_update(C);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
allqueue(REDRAWOOPS, 0);
|
||||
CTX_DATA_END;
|
||||
|
||||
DAG_scene_sort(CTX_data_scene(C));
|
||||
ED_anim_dag_flush_update(C);
|
||||
|
||||
BIF_undo_push("Clear Parent");
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ED_VIEW3D_OT_clear_parent(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name= "Clear parent";
|
||||
ot->idname= "ED_VIEW3D_OT_clear_parent";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke= WM_menu_invoke;
|
||||
ot->exec= clear_parent_exec;
|
||||
|
||||
ot->poll= ED_operator_areaactive; // XXX solve
|
||||
ot->flag= OPTYPE_REGISTER;
|
||||
|
||||
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_clear_parent_types);
|
||||
}
|
||||
|
||||
/* ***************************** */
|
||||
|
||||
void clear_track(Scene *scene, View3D *v3d)
|
||||
{
|
||||
Base *base;
|
||||
@@ -1346,51 +1364,47 @@ void make_proxy(Scene *scene)
|
||||
oldcode()
|
||||
{
|
||||
else if(mode==4) {
|
||||
bConstraint *con;
|
||||
bFollowPathConstraint *data;
|
||||
|
||||
for(base= FIRSTBASE; base; base= base->next) {
|
||||
if(TESTBASELIB(v3d, base)) {
|
||||
if(base!=BASACT) {
|
||||
float cmat[4][4], vec[3];
|
||||
|
||||
bConstraint *con;
|
||||
bFollowPathConstraint *data;
|
||||
|
||||
for(base= FIRSTBASE; base; base= base->next) {
|
||||
if(TESTBASELIB(v3d, base)) {
|
||||
if(base!=BASACT) {
|
||||
float cmat[4][4], vec[3];
|
||||
|
||||
// XXX con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
|
||||
strcpy (con->name, "AutoPath");
|
||||
|
||||
data = con->data;
|
||||
data->tar = BASACT->object;
|
||||
|
||||
strcpy (con->name, "AutoPath");
|
||||
|
||||
data = con->data;
|
||||
data->tar = BASACT->object;
|
||||
|
||||
// XXX add_constraint_to_object(con, base->object);
|
||||
|
||||
get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(base->object));
|
||||
VecSubf(vec, base->object->obmat[3], cmat[3]);
|
||||
|
||||
base->object->loc[0] = vec[0];
|
||||
base->object->loc[1] = vec[1];
|
||||
base->object->loc[2] = vec[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mode==PARSKEL && base->object->type==OB_MESH && par->type == OB_ARMATURE) {
|
||||
/* Prompt the user as to whether he wants to
|
||||
* add some vertex groups based on the bones
|
||||
* in the parent armature.
|
||||
*/
|
||||
// XXX create_vgroups_from_armature(base->object, par);
|
||||
|
||||
base->object->partype= PAROBJECT;
|
||||
what_does_parent(base->object);
|
||||
Mat4One (base->object->parentinv);
|
||||
base->object->partype= mode;
|
||||
}
|
||||
else
|
||||
what_does_parent(base->object, &workob);
|
||||
Mat4Invert(base->object->parentinv, workob.obmat);
|
||||
}
|
||||
|
||||
get_constraint_target_matrix(con, 0, CONSTRAINT_OBTYPE_OBJECT, NULL, cmat, scene->r.cfra - give_timeoffset(base->object));
|
||||
VecSubf(vec, base->object->obmat[3], cmat[3]);
|
||||
|
||||
base->object->loc[0] = vec[0];
|
||||
base->object->loc[1] = vec[1];
|
||||
base->object->loc[2] = vec[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mode==PARSKEL && base->object->type==OB_MESH && par->type == OB_ARMATURE) {
|
||||
/* Prompt the user as to whether he wants to
|
||||
* add some vertex groups based on the bones
|
||||
* in the parent armature.
|
||||
*/
|
||||
// XXX create_vgroups_from_armature(base->object, par);
|
||||
|
||||
base->object->partype= PAROBJECT;
|
||||
what_does_parent(base->object);
|
||||
Mat4One (base->object->parentinv);
|
||||
base->object->partype= mode;
|
||||
}
|
||||
else
|
||||
what_does_parent(base->object, &workob);
|
||||
Mat4Invert(base->object->parentinv, workob.obmat);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1405,7 +1419,7 @@ oldcode()
|
||||
#define PAR_VERTEX 7
|
||||
#define PAR_TRIA 8
|
||||
|
||||
static EnumPropertyItem prop_make_parent_items[] = {
|
||||
static EnumPropertyItem prop_make_parent_types[] = {
|
||||
{PAR_OBJECT, "OBJECT", "Object", ""},
|
||||
{PAR_ARMATURE, "ARMATURE", "Armature Deform", ""},
|
||||
{PAR_BONE, "BONE", "Bone", ""},
|
||||
@@ -1433,7 +1447,7 @@ static int make_parent_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Object *par= CTX_data_active_object(C);
|
||||
bPoseChannel *pchan= NULL;
|
||||
int partype= RNA_enum_get(op->ptr, "partype");
|
||||
int partype= RNA_enum_get(op->ptr, "type");
|
||||
|
||||
par->recalc |= OB_RECALC_OB;
|
||||
|
||||
@@ -1539,7 +1553,7 @@ static int make_parent_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
else
|
||||
str += sprintf(str, formatstr, "Object", PAR_OBJECT);
|
||||
|
||||
uiPupmenuOperator(C, 0, op, "partype", string);
|
||||
uiPupmenuOperator(C, 0, op, "type", string);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
@@ -1560,8 +1574,8 @@ void ED_VIEW3D_OT_make_parent(wmOperatorType *ot)
|
||||
ot->poll= ED_operator_areaactive; // XXX solve
|
||||
ot->flag= OPTYPE_REGISTER;
|
||||
|
||||
prop = RNA_def_property(ot->srna, "partype", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_make_parent_items);
|
||||
prop = RNA_def_property(ot->srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, prop_make_parent_types);
|
||||
}
|
||||
|
||||
/* ******************* ***************** */
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
/* object_edit.c */
|
||||
void ED_VIEW3D_OT_make_parent(wmOperatorType *ot);
|
||||
|
||||
void ED_VIEW3D_OT_clear_parent(wmOperatorType *ot);
|
||||
|
||||
#endif /* ED_OBJECT_INTERN_H */
|
||||
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
void ED_operatortypes_object(void)
|
||||
{
|
||||
WM_operatortype_append(ED_VIEW3D_OT_make_parent);
|
||||
WM_operatortype_append(ED_VIEW3D_OT_clear_parent);
|
||||
|
||||
}
|
||||
|
||||
/* note object keymap also for other space? */
|
||||
@@ -71,6 +73,7 @@ void ED_keymap_object(wmWindowManager *wm)
|
||||
ListBase *keymap= WM_keymap_listbase(wm, "View3D Object", SPACE_VIEW3D, 0);
|
||||
|
||||
WM_keymap_verify_item(keymap, "ED_VIEW3D_OT_make_parent", PKEY, KM_PRESS, KM_CTRL, 0);
|
||||
WM_keymap_verify_item(keymap, "ED_VIEW3D_OT_clear_parent", PKEY, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
// RNA_int_set(WM_keymap_add_item(keymap, "ED_VIEW3D_OT_viewzoom", PADPLUSKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
|
||||
}
|
||||
|
||||
@@ -1598,8 +1598,8 @@ int RNA_enum_is_equal(PointerRNA *ptr, const char *name, const char *enumname)
|
||||
RNA_property_enum_items(ptr, prop, &item, &totitem);
|
||||
|
||||
for(a=0; a<totitem; a++)
|
||||
if(strcmp(item->identifier, enumname) == 0)
|
||||
return (item->value == RNA_property_enum_get(ptr, prop));
|
||||
if(strcmp(item[a].identifier, enumname) == 0)
|
||||
return (item[a].value == RNA_property_enum_get(ptr, prop));
|
||||
|
||||
printf("RNA_enum_is_equal: %s.%s item %s not found.\n", ptr->type->identifier, name, enumname);
|
||||
return 0;
|
||||
|
||||
@@ -104,16 +104,18 @@ struct wmTimer *WM_event_add_window_timer(wmWindow *win, double timestep);
|
||||
void WM_event_remove_window_timer(wmWindow *win, struct wmTimer *timer);
|
||||
void WM_event_window_timer_sleep(wmWindow *win, struct wmTimer *timer, int dosleep);
|
||||
|
||||
/* operator api, default callbacks */
|
||||
/* confirm menu + exec */
|
||||
/* operator api, default callbacks */
|
||||
/* invoke callback, uses enum property named "type" */
|
||||
int WM_menu_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
|
||||
/* invoke callback, confirm menu + exec */
|
||||
int WM_operator_confirm (struct bContext *C, struct wmOperator *op, struct wmEvent *event);
|
||||
/* context checks */
|
||||
/* poll callback, context checks */
|
||||
int WM_operator_winactive (struct bContext *C);
|
||||
|
||||
/* default error box */
|
||||
void WM_error(struct bContext *C, char *str);
|
||||
|
||||
/* operator api */
|
||||
/* operator api */
|
||||
void WM_operator_free (struct wmOperator *op);
|
||||
wmOperatorType *WM_operatortype_find(const char *idname);
|
||||
wmOperatorType *WM_operatortype_first(void);
|
||||
|
||||
@@ -97,13 +97,33 @@ void WM_operatortype_append(void (*opfunc)(wmOperatorType*))
|
||||
|
||||
/* ************ default op callbacks, exported *********** */
|
||||
|
||||
static void operator_callback(bContext *C, void *arg, int retval)
|
||||
/* invoke callback, uses enum property named "type" */
|
||||
/* only weak thing is the fixed property name... */
|
||||
int WM_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
{
|
||||
wmOperator *op= arg;
|
||||
|
||||
if(op && retval > 0)
|
||||
op->type->exec(C, op);
|
||||
PropertyRNA *prop= RNA_struct_find_property(op->ptr, "type");
|
||||
const EnumPropertyItem *item;
|
||||
int totitem, i, len= strlen(op->type->name) + 5;
|
||||
char *menu, *p;
|
||||
|
||||
if(prop) {
|
||||
RNA_property_enum_items(op->ptr, prop, &item, &totitem);
|
||||
|
||||
for (i=0; i<totitem; i++)
|
||||
len+= strlen(item[i].name) + 5;
|
||||
|
||||
menu= MEM_callocN(len, "string");
|
||||
|
||||
p= menu + sprintf(menu, "%s %%t", op->type->name);
|
||||
for (i=0; i<totitem; i++)
|
||||
p+= sprintf(p, "|%s %%x%d", item[i].name, item[i].value);
|
||||
|
||||
uiPupmenuOperator(C, totitem/30, op, "type", menu);
|
||||
MEM_freeN(menu);
|
||||
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* call anywhere */
|
||||
@@ -113,7 +133,7 @@ void WM_error(bContext *C, char *str)
|
||||
|
||||
BLI_strncpy(testbuf, str, 128);
|
||||
sprintf(buf, "Error %%i%d%%t|%s", ICON_ERROR, testbuf);
|
||||
uiPupmenu(C, 0, operator_callback, NULL, buf);
|
||||
uiPupmenu(C, 0, NULL, NULL, buf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user