From 03b0681fe513c12fda0a377984a1a81afb9fdb8f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 11 Jan 2012 19:33:14 +0000 Subject: [PATCH] running operators now uses last used settings, added reset button to set defaults. details - uses redo stack to get recent settings from. - adds a flag to IDProperties so RNA_property_is_set() can return false even if the property is exists. - PROP_SKIP_SAVE option skips these settings from getting reset (as with presets). --- .../editors/interface/interface_layout.c | 22 ++++++++- source/blender/makesdna/DNA_ID.h | 4 ++ source/blender/makesrna/intern/rna_access.c | 36 ++++++++++++--- source/blender/windowmanager/WM_api.h | 1 + .../windowmanager/intern/wm_event_system.c | 45 +++++++++++++++++++ .../windowmanager/intern/wm_operators.c | 19 ++++++++ 6 files changed, 120 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 5e42b06e1a7..a01efa25d19 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2742,6 +2742,11 @@ const char *uiLayoutIntrospect(uiLayout *layout) return str; } +static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, void *UNUSED(arg_dummy2)) +{ + WM_operator_properties_reset((wmOperator *)op_pt); +} + /* this function does not initialize the layout, functions can be called on the layout before and after */ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,int (*check_prop)(struct PointerRNA *, struct PropertyRNA *), const char label_align, const short flag) { @@ -2803,7 +2808,22 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,in uiItemL(layout, IFACE_("No Properties"), ICON_NONE); } } - + + /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled + * but this is not so important if this button is drawn in those cases + * (which isn't all that likely anyway) - campbell */ + if (op->properties->len) { + uiBlock *block; + uiBut *but; + uiLayout *col; /* needed to avoid alignment errors with previous buttons */ + + col= uiLayoutColumn(layout, 0); + block= uiLayoutGetBlock(col); + but = uiDefIconTextBut(block , BUT, 0, ICON_FILE_REFRESH, "Reset", 0, 0, 18, 20, NULL, 0.0, 0.0, 0.0, 0.0, + "Reset operator defaults"); + uiButSetFunc(but, ui_layout_operator_buts__reset_cb, op, NULL); + } + /* set various special settings for buttons */ { uiBut *but; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index f311d94703f..bfd3bb4b0bf 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -86,6 +86,10 @@ typedef struct IDProperty { /* IDP_STRING */ #define IDP_STRING_SUB_UTF8 0 /* default */ #define IDP_STRING_SUB_BYTE 1 /* arbitrary byte array, _not_ null terminated */ +/*->flag*/ +#define IDP_FLAG_GHOST (1<<7) /* this means the propery is set but RNA will return + * false when checking 'RNA_property_is_set', + * currently this is a runtime flag */ /* add any future new id property types here.*/ diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index ddd0fa1434c..4eebfc52920 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -226,6 +226,12 @@ void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr) /* ID Properties */ +static void rna_idproperty_touch(IDProperty *idprop) +{ + /* so the property is seen as 'set' by rna */ + idprop->flag &= ~IDP_FLAG_GHOST; +} + /* return a UI local ID prop definition for this prop */ IDProperty *rna_idproperty_ui(PropertyRNA *prop) { @@ -1621,8 +1627,10 @@ void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value) /* just incase other values are passed */ if(value) value= 1; - if((idprop=rna_idproperty_check(&prop, ptr))) + if((idprop=rna_idproperty_check(&prop, ptr))) { IDP_Int(idprop)= value; + rna_idproperty_touch(idprop); + } else if(bprop->set) bprop->set(ptr, value); else if(prop->flag & PROP_EDITABLE) { @@ -1698,6 +1706,8 @@ void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const in IDP_Int(idprop)= values[0]; else memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len); + + rna_idproperty_touch(idprop); } else if(prop->arraydimension == 0) RNA_property_boolean_set(ptr, prop, values[0]); @@ -1818,8 +1828,10 @@ void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value) /* useful to check on bad values but set function should clamp */ /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */ - if((idprop=rna_idproperty_check(&prop, ptr))) + if((idprop=rna_idproperty_check(&prop, ptr))) { IDP_Int(idprop)= value; + rna_idproperty_touch(idprop); + } else if(iprop->set) iprop->set(ptr, value); else if(prop->flag & PROP_EDITABLE) { @@ -1931,7 +1943,9 @@ void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *v if(prop->arraydimension == 0) IDP_Int(idprop)= values[0]; else - memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);\ + memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len); + + rna_idproperty_touch(idprop); } else if(prop->arraydimension == 0) RNA_property_int_set(ptr, prop, values[0]); @@ -2054,6 +2068,8 @@ void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value) IDP_Float(idprop)= value; else IDP_Double(idprop)= value; + + rna_idproperty_touch(idprop); } else if(fprop->set) { fprop->set(ptr, value); @@ -2185,6 +2201,8 @@ void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const floa for(i=0; ilen; i++) ((double*)IDP_Array(idprop))[i]= values[i]; } + + rna_idproperty_touch(idprop); } else if(prop->arraydimension == 0) RNA_property_float_set(ptr, prop, values[0]); @@ -2372,9 +2390,11 @@ void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *val BLI_assert(RNA_property_type(prop) == PROP_STRING); - if((idprop=rna_idproperty_check(&prop, ptr))) + if((idprop=rna_idproperty_check(&prop, ptr))) { /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */ IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1); + rna_idproperty_touch(idprop); + } else if(sprop->set) sprop->set(ptr, value); /* set function needs to clamp its self */ else if(prop->flag & PROP_EDITABLE) { @@ -2446,8 +2466,10 @@ void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value) BLI_assert(RNA_property_type(prop) == PROP_ENUM); - if((idprop=rna_idproperty_check(&prop, ptr))) + if((idprop=rna_idproperty_check(&prop, ptr))) { IDP_Int(idprop)= value; + rna_idproperty_touch(idprop); + } else if(eprop->set) { eprop->set(ptr, value); } @@ -2516,6 +2538,7 @@ void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr if((/*idprop=*/ rna_idproperty_check(&prop, ptr))) { /* not supported */ + /* rna_idproperty_touch(idprop); */ } else { PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop; @@ -4415,7 +4438,8 @@ int RNA_collection_length(PointerRNA *ptr, const char *name) int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop) { if(prop->flag & PROP_IDPROPERTY) { - return (rna_idproperty_find(ptr, prop->identifier) != NULL); + IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier); + return ((idprop != NULL) && !(idprop->flag & IDP_FLAG_GHOST)); } else { return 1; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 61c3da36203..11ac56090a3 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -199,6 +199,7 @@ int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, int con void WM_operator_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *opstring); /* used for keymap and macro items */ void WM_operator_properties_sanitize(struct PointerRNA *ptr, const short no_context); /* make props context sensitive or not */ +void WM_operator_properties_reset(struct wmOperator *op); void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring); void WM_operator_properties_create_ptr(struct PointerRNA *ptr, struct wmOperatorType *ot); void WM_operator_properties_free(struct PointerRNA *ptr); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 4107356ca0e..d97f66a69e6 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -729,6 +729,46 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event) } } +static int wm_operator_init_from_last(wmWindowManager *wm, wmOperator *op) +{ + int change= FALSE; + wmOperator *lastop; + + for(lastop= wm->operators.last; lastop; lastop= lastop->prev) { + /* equality check is a bit paranoid but just incase */ + if((op != lastop) && (op->type == (lastop->type))) { + break; + } + } + + if (lastop && op != lastop) { + PropertyRNA *iterprop; + iterprop= RNA_struct_iterator_property(op->type->srna); + + RNA_PROP_BEGIN(op->ptr, itemptr, iterprop) { + PropertyRNA *prop= itemptr.data; + + if((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) { + const char *identifier= RNA_property_identifier(prop); + IDProperty *idp_src= IDP_GetPropertyFromGroup(lastop->properties, identifier); + if(idp_src) { + IDProperty *idp_dst = IDP_CopyProperty(idp_src); + + /* note - in the future this may need to be done recursively, + * but for now RNA doesn't access nested operators */ + idp_dst->flag |= IDP_FLAG_GHOST; + + IDP_ReplaceInGroup(op->properties, idp_dst); + change= TRUE; + } + } + } + RNA_PROP_END; + } + + return change; +} + static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties, ReportList *reports, short poll_only) { wmWindowManager *wm= CTX_wm_manager(C); @@ -741,6 +781,11 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P if(WM_operator_poll(C, ot)) { wmOperator *op= wm_operator_create(wm, ot, properties, reports); /* if reports==NULL, theyll be initialized */ + /* initialize setting from previous run */ + if(wm->op_undo_depth == 0 && (ot->flag & OPTYPE_REGISTER)) { /* not called by py script */ + wm_operator_init_from_last(wm, op); + } + if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE) printf("handle evt %d win %d op %s\n", event?event->type:0, CTX_wm_screen(C)->subwinactive, ot->idname); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index c917031708d..f9a6f0fece3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -638,6 +638,25 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) RNA_STRUCT_END; } +/* remove all props without PROP_SKIP_SAVE */ +void WM_operator_properties_reset(wmOperator *op) +{ + if (op->ptr->data) { + PropertyRNA *iterprop; + iterprop= RNA_struct_iterator_property(op->type->srna); + + RNA_PROP_BEGIN(op->ptr, itemptr, iterprop) { + PropertyRNA *prop= itemptr.data; + + if((RNA_property_flag(prop) & PROP_SKIP_SAVE) == 0) { + const char *identifier = RNA_property_identifier(prop); + RNA_struct_idprops_unset(op->ptr, identifier); + } + } + RNA_PROP_END; + } +} + void WM_operator_properties_free(PointerRNA *ptr) { IDProperty *properties= ptr->data;