From 32a6e14d413b656a02df03c34022d263f0d4cb67 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 15 Jul 2025 01:56:25 +0200 Subject: [PATCH] Fix #54325: Shrink/Fatten "Offset Even" can not be used as default The default keymap item that triggers `Shrink/Fatten` uses the `Alt` modifier, which coincidentally is the same key that toggles `Offset Even`. What is undesirable. The solution is to alternate between Alt Press and Alt Release depending on the `Offset Even` property. Pull Request: https://projects.blender.org/blender/blender/pulls/141904 --- .../transform/transform_mode_shrink_fatten.cc | 73 +++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.cc b/source/blender/editors/transform/transform_mode_shrink_fatten.cc index 7ea3c06d4c8..c3fc9a6df43 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.cc +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.cc @@ -22,6 +22,8 @@ #include "BLT_translation.hh" +#include "RNA_access.hh" + #include "transform.hh" #include "transform_convert.hh" #include "transform_snap.hh" @@ -34,15 +36,31 @@ namespace blender::ed::transform { /** \name Transform (Shrink-Fatten) * \{ */ +enum eShrinkFattenMode { + EVEN_THICKNESS_OFF = 0, + EVEN_THICKNESS_ON = 1, +}; + +/** + * Custom data, stored in #TransInfo.custom.mode.data + */ +struct ShrinkFattenCustomData { + const wmKeyMapItem *kmi; + eShrinkFattenMode mode; + bool use_alt_press_to_disable; +}; + static void transdata_elem_shrink_fatten(const TransInfo *t, const TransDataContainer * /*tc*/, TransData *td, TransDataExtension *td_ext, const float distance) { + ShrinkFattenCustomData *custom_data = static_cast(t->custom.mode.data); + /* Get the final offset. */ float tdistance = distance * td->factor; - if (td_ext && (t->flag & T_ALT_TRANSFORM) != 0) { + if (td_ext && custom_data->mode == EVEN_THICKNESS_ON) { tdistance *= td_ext->iscale[0]; /* Shell factor. */ } @@ -51,16 +69,22 @@ static void transdata_elem_shrink_fatten(const TransInfo *t, static eRedrawFlag shrinkfatten_handleEvent(TransInfo *t, const wmEvent *event) { - if (t->redraw) { - /* Event already handled. */ - return TREDRAW_NOTHING; - } - BLI_assert(t->mode == TFM_SHRINKFATTEN); - const wmKeyMapItem *kmi = static_cast(t->custom.mode.data); - if (kmi && event->type == kmi->type && event->val == kmi->val) { + ShrinkFattenCustomData *custom_data = static_cast(t->custom.mode.data); + const wmKeyMapItem *kmi = custom_data->kmi; + + if (ELEM(event->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY)) { + bool use_even_thickness = custom_data->use_alt_press_to_disable != (event->val == KM_PRESS); + custom_data->mode = use_even_thickness ? EVEN_THICKNESS_ON : EVEN_THICKNESS_OFF; + return TREDRAW_HARD; + } + else if (kmi && event->type == kmi->type && event->val == kmi->val) { /* Allows the "Even Thickness" effect to be enabled as a toggle. */ - t->flag ^= T_ALT_TRANSFORM; + custom_data->mode = custom_data->mode == EVEN_THICKNESS_ON ? EVEN_THICKNESS_OFF : + EVEN_THICKNESS_ON; + + /* Also toggle the Alt press state. */ + custom_data->use_alt_press_to_disable = !custom_data->use_alt_press_to_disable; return TREDRAW_HARD; } return TREDRAW_NOTHING; @@ -71,6 +95,7 @@ static void applyShrinkFatten(TransInfo *t) float distance; fmt::memory_buffer str; const UnitSettings &unit = t->scene->unit; + ShrinkFattenCustomData *custom_data = static_cast(t->custom.mode.data); distance = t->values[0] + t->values_modal_offset[0]; @@ -105,14 +130,14 @@ static void applyShrinkFatten(TransInfo *t) } fmt::format_to(fmt::appender(str), ", ("); - const wmKeyMapItem *kmi = static_cast(t->custom.mode.data); + const wmKeyMapItem *kmi = custom_data->kmi; if (kmi) { str.append(WM_keymap_item_to_string(kmi, false).value_or("")); } fmt::format_to(fmt::appender(str), fmt::runtime(IFACE_(" or Alt) Even Thickness {}")), - WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); + WM_bool_as_string(custom_data->mode == EVEN_THICKNESS_ON)); /* Done with header string. */ FOREACH_TRANS_DATA_CONTAINER (t, tc) { @@ -133,7 +158,7 @@ static void applyShrinkFatten(TransInfo *t) ED_area_status_text(t->area, fmt::to_string(str).c_str()); } -static void initShrinkFatten(TransInfo *t, wmOperator * /*op*/) +static void initShrinkFatten(TransInfo *t, wmOperator *op) { if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) { BKE_report(t->reports, RPT_ERROR, "'Shrink/Fatten' meshes is only supported in edit mode"); @@ -153,9 +178,31 @@ static void initShrinkFatten(TransInfo *t, wmOperator * /*op*/) t->num.unit_sys = t->scene->unit.system; t->num.unit_type[0] = B_UNIT_LENGTH; + ShrinkFattenCustomData *custom_data = static_cast( + MEM_callocN(sizeof(*custom_data), __func__)); + t->custom.mode.data = custom_data; + t->custom.mode.free_cb = [](TransInfo *t, TransDataContainer *, TransCustomData *custom_data) { + ShrinkFattenCustomData *data = static_cast(custom_data->data); + + /* WORKAROUND: Use #T_ALT_TRANSFORM to indicate the value of the "use_even_offset" property in + * `saveTransform`. */ + SET_FLAG_FROM_TEST(t->flag, data->mode == EVEN_THICKNESS_ON, T_ALT_TRANSFORM); + MEM_freeN(data); + custom_data->data = nullptr; + }; + if (t->keymap) { /* Workaround to use the same key as the modal keymap. */ - t->custom.mode.data = (void *)WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + custom_data->kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + } + + if (op) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_even_offset"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { + /* TODO: Check if the Alt button is already pressed. */ + custom_data->mode = EVEN_THICKNESS_ON; + custom_data->use_alt_press_to_disable = true; + } } }