diff options
Diffstat (limited to 'source/blender/editors')
18 files changed, 811 insertions, 742 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 560b14bfd9a..80976d150c0 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -461,6 +461,115 @@ void ANIM_deselect_anim_channels( /* ---------------------------- Graph Editor ------------------------------------- */ +/* Copy a certain channel setting to parents of the modified channel. */ +static void anim_flush_channel_setting_up(bAnimContext *ac, + const eAnimChannel_Settings setting, + const eAnimChannels_SetFlag mode, + bAnimListElem *const match, + const int matchLevel) +{ + /* flush up? + * + * For Visibility: + * - only flush up if the current state is now enabled (positive 'on' state is default) + * (otherwise, it's too much work to force the parents to be inactive too) + * + * For everything else: + * - only flush up if the current state is now disabled (negative 'off' state is default) + * (otherwise, it's too much work to force the parents to be active too) + */ + if (setting == ACHANNEL_SETTING_VISIBLE) { + if (mode == ACHANNEL_SETFLAG_CLEAR) { + return; + } + } + else { + if (mode != ACHANNEL_SETFLAG_CLEAR) { + return; + } + } + + /* Go backwards in the list, until the highest-ranking element + * (by indention has been covered). */ + int prevLevel = matchLevel; + for (bAnimListElem *ale = match->prev; ale; ale = ale->prev) { + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + + /* if no channel info was found, skip, since this type might not have any useful info */ + if (acf == NULL) { + continue; + } + + /* Get the level of the current channel traversed + * - we define the level as simply being the offset for the start of the channel + */ + const int level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + + if (level == prevLevel) { + /* Don't influence siblings. */ + continue; + } + + if (level > prevLevel) { + /* If previous level was a base-level (i.e. 0 offset / root of one hierarchy), stop here. */ + if (prevLevel == 0) { + return; + } + + /* Otherwise, this level weaves into another sibling hierarchy to the previous one just + * finished, so skip until we get to the parent of this level. */ + continue; + } + + /* The level is 'less than' (i.e. more important) the level we're matching but also 'less + * than' the level just tried (i.e. only the 1st group above grouped F-Curves, when toggling + * visibility of F-Curves, gets flushed, which should happen if we don't let prevLevel get + * updated below once the first 1st group is found). */ + ANIM_channel_setting_set(ac, ale, setting, mode); + + /* store this level as the 'old' level now */ + prevLevel = level; + } +} + +/* Copy a certain channel setting to children of the modified channel. */ +static void anim_flush_channel_setting_down(bAnimContext *ac, + const eAnimChannel_Settings setting, + const eAnimChannels_SetFlag mode, + bAnimListElem *const match, + const int matchLevel) +{ + /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */ + for (bAnimListElem *ale = match->next; ale; ale = ale->next) { + const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); + + /* if no channel info was found, skip, since this type might not have any useful info */ + if (acf == NULL) { + continue; + } + + /* get the level of the current channel traversed + * - we define the level as simply being the offset for the start of the channel + */ + const int level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; + + /* if the level is 'greater than' (i.e. less important) the channel that was changed, + * flush the new status... + */ + if (level > matchLevel) { + ANIM_channel_setting_set(ac, ale, setting, mode); + /* however, if the level is 'less than or equal to' the channel that was changed, + * (i.e. the current channel is as important if not more important than the changed + * channel) then we should stop, since we've found the last one of the children we should + * flush + */ + } + else { + break; + } + } +} + /* Flush visibility (for Graph Editor) changes up/down hierarchy for changes in the given setting * - anim_data: list of the all the anim channels that can be chosen * -> filtered using ANIMFILTER_CHANNELS only, since if we took VISIBLE too, @@ -477,7 +586,7 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, eAnimChannels_SetFlag mode) { bAnimListElem *ale, *match = NULL; - int prevLevel = 0, matchLevel = 0; + int matchLevel = 0; /* sanity check */ if (ELEM(NULL, anim_data, anim_data->first)) { @@ -517,101 +626,10 @@ void ANIM_flush_setting_anim_channels(bAnimContext *ac, * - we define the level as simply being the offset for the start of the channel */ matchLevel = (acf->get_offset) ? acf->get_offset(ac, ale_setting) : 0; - prevLevel = matchLevel; } - /* flush up? - * - * For Visibility: - * - only flush up if the current state is now enabled (positive 'on' state is default) - * (otherwise, it's too much work to force the parents to be inactive too) - * - * For everything else: - * - only flush up if the current state is now disabled (negative 'off' state is default) - * (otherwise, it's too much work to force the parents to be active too) - */ - if (((setting == ACHANNEL_SETTING_VISIBLE) && (mode != ACHANNEL_SETFLAG_CLEAR)) || - ((setting != ACHANNEL_SETTING_VISIBLE) && (mode == ACHANNEL_SETFLAG_CLEAR))) { - /* Go backwards in the list, until the highest-ranking element - * (by indention has been covered). */ - for (ale = match->prev; ale; ale = ale->prev) { - const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); - int level; - - /* if no channel info was found, skip, since this type might not have any useful info */ - if (acf == NULL) { - continue; - } - - /* get the level of the current channel traversed - * - we define the level as simply being the offset for the start of the channel - */ - level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; - - /* if the level is 'less than' (i.e. more important) the level we're matching - * but also 'less than' the level just tried (i.e. only the 1st group above grouped F-Curves, - * when toggling visibility of F-Curves, gets flushed, which should happen if we don't let - * prevLevel get updated below once the first 1st group is found). - */ - if (level < prevLevel) { - /* flush the new status... */ - ANIM_channel_setting_set(ac, ale, setting, mode); - - /* store this level as the 'old' level now */ - prevLevel = level; - } - /* if the level is 'greater than' (i.e. less important) than the previous level... */ - else if (level > prevLevel) { - /* if previous level was a base-level (i.e. 0 offset / root of one hierarchy), - * stop here - */ - if (prevLevel == 0) { - break; - /* otherwise, this level weaves into another sibling hierarchy to the previous one just - * finished, so skip until we get to the parent of this level - */ - } - continue; - } - } - } - - /* flush down (always) */ - { - /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */ - for (ale = match->next; ale; ale = ale->next) { - const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale); - int level; - - /* if no channel info was found, skip, since this type might not have any useful info */ - if (acf == NULL) { - continue; - } - - /* get the level of the current channel traversed - * - we define the level as simply being the offset for the start of the channel - */ - level = (acf->get_offset) ? acf->get_offset(ac, ale) : 0; - - /* if the level is 'greater than' (i.e. less important) the channel that was changed, - * flush the new status... - */ - if (level > matchLevel) { - ANIM_channel_setting_set(ac, ale, setting, mode); - /* however, if the level is 'less than or equal to' the channel that was changed, - * (i.e. the current channel is as important if not more important than the changed - * channel) then we should stop, since we've found the last one of the children we should - * flush - */ - } - else { - break; - } - - /* store this level as the 'old' level now */ - // prevLevel = level; // XXX: prevLevel is unused - } - } + anim_flush_channel_setting_up(ac, setting, mode, match, matchLevel); + anim_flush_channel_setting_down(ac, setting, mode, match, matchLevel); } /* -------------------------- F-Curves ------------------------------------- */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index fb4c0ae0758..3701e9dc91c 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -162,7 +162,7 @@ bAction *ED_id_action_ensure(Main *bmain, ID *id) * so that users can't accidentally break actions by assigning them * to the wrong places */ - adt->action->idroot = GS(id->name); + BKE_animdata_action_ensure_idroot(id, adt->action); /* Tag depsgraph to be rebuilt to include time dependency. */ DEG_relations_tag_update(bmain); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index ac8085f0e53..b7bf1861ff3 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -4434,6 +4434,19 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) } } + /* Remove unused slots. */ + int actcol = ob_dst->actcol; + for (int slot = 1; slot <= ob_dst->totcol; slot++) { + while (slot <= ob_dst->totcol && !BKE_object_material_slot_used(ob_dst->data, slot)) { + ob_dst->actcol = slot; + BKE_object_material_slot_remove(bmain, ob_dst); + if (actcol >= slot) { + actcol--; + } + } + } + ob_dst->actcol = actcol; + DEG_id_tag_update(&gpd_src->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); DEG_id_tag_update(&gpd_dst->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 376dcb6d811..4f656420b06 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1685,6 +1685,7 @@ struct Panel *UI_panel_begin(struct ARegion *region, bool *r_open); void UI_panel_end(const struct ARegion *region, uiBlock *block, int width, int height, bool open); +bool UI_panel_is_active(const struct Panel *panel); void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y); int UI_panel_size_y(const struct Panel *panel); bool UI_panel_is_dragging(const struct Panel *panel); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 433058260f7..a5b7a011e6b 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -129,43 +129,38 @@ static bool ui_but_is_unit_radians(const uiBut *but) /* ************* window matrix ************** */ -void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *x, float *y) +void ui_block_to_window_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y) { - float gx, gy; - int sx, sy, getsizex, getsizey; + int getsizex = BLI_rcti_size_x(®ion->winrct) + 1; + int getsizey = BLI_rcti_size_y(®ion->winrct) + 1; + int sx = region->winrct.xmin; + int sy = region->winrct.ymin; - getsizex = BLI_rcti_size_x(®ion->winrct) + 1; - getsizey = BLI_rcti_size_y(®ion->winrct) + 1; - sx = region->winrct.xmin; - sy = region->winrct.ymin; - - gx = *x; - gy = *y; + float gx = *r_x; + float gy = *r_y; if (block->panel) { gx += block->panel->ofsx; gy += block->panel->ofsy; } - *x = ((float)sx) + - ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] + - block->winmat[3][0])); - *y = ((float)sy) + - ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] + - block->winmat[3][1])); + *r_x = ((float)sx) + + ((float)getsizex) * (0.5f + 0.5f * (gx * block->winmat[0][0] + gy * block->winmat[1][0] + + block->winmat[3][0])); + *r_y = ((float)sy) + + ((float)getsizey) * (0.5f + 0.5f * (gx * block->winmat[0][1] + gy * block->winmat[1][1] + + block->winmat[3][1])); } -void ui_block_to_window(const ARegion *region, uiBlock *block, int *x, int *y) +void ui_block_to_window(const ARegion *region, uiBlock *block, int *r_x, int *r_y) { - float fx, fy; - - fx = *x; - fy = *y; + float fx = *r_x; + float fy = *r_y; ui_block_to_window_fl(region, block, &fx, &fy); - *x = (int)(fx + 0.5f); - *y = (int)(fy + 0.5f); + *r_x = (int)(fx + 0.5f); + *r_y = (int)(fy + 0.5f); } void ui_block_to_window_rctf(const ARegion *region, @@ -181,9 +176,8 @@ void ui_block_to_window_rctf(const ARegion *region, float ui_block_to_window_scale(const ARegion *region, uiBlock *block) { /* We could have function for this to avoid dummy arg. */ - float dummy_x; float min_y = 0, max_y = 1; - dummy_x = 0.0f; + float dummy_x = 0.0f; ui_block_to_window_fl(region, block, &dummy_x, &min_y); dummy_x = 0.0f; ui_block_to_window_fl(region, block, &dummy_x, &max_y); @@ -191,33 +185,30 @@ float ui_block_to_window_scale(const ARegion *region, uiBlock *block) } /* for mouse cursor */ -void ui_window_to_block_fl(const ARegion *region, uiBlock *block, float *x, float *y) +void ui_window_to_block_fl(const ARegion *region, uiBlock *block, float *r_x, float *r_y) { - float a, b, c, d, e, f, px, py; - int sx, sy, getsizex, getsizey; - - getsizex = BLI_rcti_size_x(®ion->winrct) + 1; - getsizey = BLI_rcti_size_y(®ion->winrct) + 1; - sx = region->winrct.xmin; - sy = region->winrct.ymin; + int getsizex = BLI_rcti_size_x(®ion->winrct) + 1; + int getsizey = BLI_rcti_size_y(®ion->winrct) + 1; + int sx = region->winrct.xmin; + int sy = region->winrct.ymin; - a = 0.5f * ((float)getsizex) * block->winmat[0][0]; - b = 0.5f * ((float)getsizex) * block->winmat[1][0]; - c = 0.5f * ((float)getsizex) * (1.0f + block->winmat[3][0]); + float a = 0.5f * ((float)getsizex) * block->winmat[0][0]; + float b = 0.5f * ((float)getsizex) * block->winmat[1][0]; + float c = 0.5f * ((float)getsizex) * (1.0f + block->winmat[3][0]); - d = 0.5f * ((float)getsizey) * block->winmat[0][1]; - e = 0.5f * ((float)getsizey) * block->winmat[1][1]; - f = 0.5f * ((float)getsizey) * (1.0f + block->winmat[3][1]); + float d = 0.5f * ((float)getsizey) * block->winmat[0][1]; + float e = 0.5f * ((float)getsizey) * block->winmat[1][1]; + float f = 0.5f * ((float)getsizey) * (1.0f + block->winmat[3][1]); - px = *x - sx; - py = *y - sy; + float px = *r_x - sx; + float py = *r_y - sy; - *y = (a * (py - f) + d * (c - px)) / (a * e - d * b); - *x = (px - b * (*y) - c) / a; + *r_y = (a * (py - f) + d * (c - px)) / (a * e - d * b); + *r_x = (px - b * (*r_y) - c) / a; if (block->panel) { - *x -= block->panel->ofsx; - *y -= block->panel->ofsy; + *r_x -= block->panel->ofsx; + *r_y -= block->panel->ofsy; } } @@ -231,23 +222,21 @@ void ui_window_to_block_rctf(const struct ARegion *region, ui_window_to_block_fl(region, block, &rct_dst->xmax, &rct_dst->ymax); } -void ui_window_to_block(const ARegion *region, uiBlock *block, int *x, int *y) +void ui_window_to_block(const ARegion *region, uiBlock *block, int *r_x, int *r_y) { - float fx, fy; - - fx = *x; - fy = *y; + float fx = *r_x; + float fy = *r_y; ui_window_to_block_fl(region, block, &fx, &fy); - *x = (int)(fx + 0.5f); - *y = (int)(fy + 0.5f); + *r_x = (int)(fx + 0.5f); + *r_y = (int)(fy + 0.5f); } -void ui_window_to_region(const ARegion *region, int *x, int *y) +void ui_window_to_region(const ARegion *region, int *r_x, int *r_y) { - *x -= region->winrct.xmin; - *y -= region->winrct.ymin; + *r_x -= region->winrct.xmin; + *r_y -= region->winrct.ymin; } void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti *rct_src) @@ -258,10 +247,10 @@ void ui_window_to_region_rcti(const ARegion *region, rcti *rect_dst, const rcti rect_dst->ymax = rct_src->ymax - region->winrct.ymin; } -void ui_region_to_window(const ARegion *region, int *x, int *y) +void ui_region_to_window(const ARegion *region, int *r_x, int *r_y) { - *x += region->winrct.xmin; - *y += region->winrct.ymin; + *r_x += region->winrct.xmin; + *r_y += region->winrct.ymin; } static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block) @@ -448,8 +437,6 @@ static void ui_block_bounds_calc_text(uiBlock *block, float offset) void ui_block_bounds_calc(uiBlock *block) { - int xof; - if (BLI_listbase_is_empty(&block->buttons)) { if (block->panel) { block->rect.xmin = 0.0; @@ -476,12 +463,7 @@ void ui_block_bounds_calc(uiBlock *block) /* hardcoded exception... but that one is annoying with larger safety */ uiBut *bt = block->buttons.first; - if (bt && STREQLEN(bt->str, "ERROR", 5)) { - xof = 10; - } - else { - xof = 40; - } + int xof = (bt && STREQLEN(bt->str, "ERROR", 5)) ? 10 : 40; block->safety.xmin = block->rect.xmin - xof; block->safety.ymin = block->rect.ymin - xof; @@ -491,23 +473,19 @@ void ui_block_bounds_calc(uiBlock *block) static void ui_block_bounds_calc_centered(wmWindow *window, uiBlock *block) { - int xmax, ymax; - int startx, starty; - int width, height; - /* note: this is used for the splash where window bounds event has not been * updated by ghost, get the window bounds from ghost directly */ - xmax = WM_window_pixels_x(window); - ymax = WM_window_pixels_y(window); + int xmax = WM_window_pixels_x(window); + int ymax = WM_window_pixels_y(window); ui_block_bounds_calc(block); - width = BLI_rctf_size_x(&block->rect); - height = BLI_rctf_size_y(&block->rect); + int width = BLI_rctf_size_x(&block->rect); + int height = BLI_rctf_size_y(&block->rect); - startx = (xmax * 0.5f) - (width * 0.5f); - starty = (ymax * 0.5f) - (height * 0.5f); + int startx = (xmax * 0.5f) - (width * 0.5f); + int starty = (ymax * 0.5f) - (height * 0.5f); UI_block_translate(block, startx - block->rect.xmin, starty - block->rect.ymin); @@ -531,22 +509,16 @@ static void ui_block_bounds_calc_centered_pie(uiBlock *block) static void ui_block_bounds_calc_popup( wmWindow *window, uiBlock *block, eBlockBoundsCalc bounds_calc, const int xy[2], int r_xy[2]) { - int width, height, oldwidth, oldheight; - int oldbounds, xmax, ymax, raw_x, raw_y; - const int margin = UI_SCREEN_MARGIN; - rcti rect, rect_bounds; - int ofs_dummy[2]; - - oldbounds = block->bounds; + int oldbounds = block->bounds; /* compute mouse position with user defined offset */ ui_block_bounds_calc(block); - xmax = WM_window_pixels_x(window); - ymax = WM_window_pixels_y(window); + int xmax = WM_window_pixels_x(window); + int ymax = WM_window_pixels_y(window); - oldwidth = BLI_rctf_size_x(&block->rect); - oldheight = BLI_rctf_size_y(&block->rect); + int oldwidth = BLI_rctf_size_x(&block->rect); + int oldheight = BLI_rctf_size_y(&block->rect); /* first we ensure wide enough text bounds */ if (bounds_calc == UI_BLOCK_BOUNDS_POPUP_MENU) { @@ -561,8 +533,8 @@ static void ui_block_bounds_calc_popup( ui_block_bounds_calc(block); /* and we adjust the position to fit within window */ - width = BLI_rctf_size_x(&block->rect); - height = BLI_rctf_size_y(&block->rect); + int width = BLI_rctf_size_x(&block->rect); + int height = BLI_rctf_size_y(&block->rect); /* avoid divide by zero below, caused by calling with no UI, but better not crash */ oldwidth = oldwidth > 0 ? oldwidth : MAX2(1, width); @@ -570,16 +542,21 @@ static void ui_block_bounds_calc_popup( /* offset block based on mouse position, user offset is scaled * along in case we resized the block in ui_block_bounds_calc_text */ - raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->bounds_offset[0] * width) / oldwidth; - raw_y = rect.ymin = xy[1] + block->rect.ymin + (block->bounds_offset[1] * height) / oldheight; + rcti rect; + int raw_x = rect.xmin = xy[0] + block->rect.xmin + (block->bounds_offset[0] * width) / oldwidth; + int raw_y = rect.ymin = xy[1] + block->rect.ymin + + (block->bounds_offset[1] * height) / oldheight; rect.xmax = rect.xmin + width; rect.ymax = rect.ymin + height; + rcti rect_bounds; + const int margin = UI_SCREEN_MARGIN; rect_bounds.xmin = margin; rect_bounds.ymin = margin; rect_bounds.xmax = xmax - margin; rect_bounds.ymax = ymax - UI_POPUP_MENU_TOP; + int ofs_dummy[2]; BLI_rcti_clamp(&rect, &rect_bounds, ofs_dummy); UI_block_translate(block, rect.xmin - block->rect.xmin, rect.ymin - block->rect.ymin); @@ -634,12 +611,10 @@ void UI_block_bounds_set_menu(uiBlock *block, int addval, const int bounds_offse block->bounds = addval; block->bounds_type = UI_BLOCK_BOUNDS_POPUP_MENU; if (bounds_offset != NULL) { - block->bounds_offset[0] = bounds_offset[0]; - block->bounds_offset[1] = bounds_offset[1]; + copy_v2_v2_int(block->bounds_offset, bounds_offset); } else { - block->bounds_offset[0] = 0; - block->bounds_offset[1] = 0; + zero_v2_int(block->bounds_offset); } } @@ -746,25 +721,22 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut) uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new) { - uiBut *but_old = NULL; LISTBASE_FOREACH (uiBut *, but, &block_old->buttons) { if (ui_but_equals_old(but_new, but)) { - but_old = but; - break; + return but; } } - return but_old; + return NULL; } + uiBut *ui_but_find_new(uiBlock *block_new, const uiBut *but_old) { - uiBut *but_new = NULL; LISTBASE_FOREACH (uiBut *, but, &block_new->buttons) { if (ui_but_equals_old(but, but_old)) { - but_new = but; - break; + return but; } } - return but_new; + return NULL; } static bool ui_but_extra_icons_equals_old(const uiButExtraOpIcon *new_extra_icon, @@ -960,16 +932,14 @@ static bool ui_but_update_from_old_block(const bContext *C, bool UI_but_active_only_ex( const bContext *C, ARegion *region, uiBlock *block, uiBut *but, const bool remove_on_failure) { - uiBlock *oldblock; - uiBut *oldbut; bool activate = false, found = false, isactive = false; - oldblock = block->oldblock; + uiBlock *oldblock = block->oldblock; if (!oldblock) { activate = true; } else { - oldbut = ui_but_find_old(oldblock, but); + uiBut *oldbut = ui_but_find_old(oldblock, but); if (oldbut) { found = true; @@ -1077,8 +1047,8 @@ static void ui_menu_block_set_keyaccels(uiBlock *block) } for (int pass = 0; pass < 2; pass++) { - /* 2 Passes, on for first letter only, second for any letter if first fails - * fun first pass on all buttons so first word chars always get first priority */ + /* 2 Passes: One for first letter only, second for any letter if the first pass fails. + * Run first pass on all buttons so first word chars always get first priority. */ LISTBASE_FOREACH (uiBut *, but, &block->buttons) { if (!ELEM(but->type, @@ -1090,48 +1060,53 @@ static void ui_menu_block_set_keyaccels(uiBlock *block) /* For PIE-menus. */ UI_BTYPE_ROW) || (but->flag & UI_HIDDEN)) { - /* pass */ + continue; } - else if (but->menu_key == '\0') { - if (but->str && but->str[0]) { - const char *str_pt = but->str; - uchar menu_key; - do { - menu_key = tolower(*str_pt); - if ((menu_key >= 'a' && menu_key <= 'z') && !(menu_key_mask & 1 << (menu_key - 'a'))) { - menu_key_mask |= 1 << (menu_key - 'a'); - break; - } - if (pass == 0) { - /* Skip to next delimiter on first pass (be picky) */ - while (isalpha(*str_pt)) { - str_pt++; - } + if (but->menu_key != '\0') { + continue; + } - if (*str_pt) { - str_pt++; - } - } - else { - /* just step over every char second pass and find first usable key */ - str_pt++; - } - } while (*str_pt); + if (but->str == NULL || but->str[0] == '\0') { + continue; + } - if (*str_pt) { - but->menu_key = menu_key; - } - else { - /* run second pass */ - tot_missing++; + const char *str_pt = but->str; + uchar menu_key; + do { + menu_key = tolower(*str_pt); + if ((menu_key >= 'a' && menu_key <= 'z') && !(menu_key_mask & 1 << (menu_key - 'a'))) { + menu_key_mask |= 1 << (menu_key - 'a'); + break; + } + + if (pass == 0) { + /* Skip to next delimiter on first pass (be picky) */ + while (isalpha(*str_pt)) { + str_pt++; } - /* if all keys have been used just exit, unlikely */ - if (menu_key_mask == (1 << 26) - 1) { - return; + if (*str_pt) { + str_pt++; } } + else { + /* just step over every char second pass and find first usable key */ + str_pt++; + } + } while (*str_pt); + + if (*str_pt) { + but->menu_key = menu_key; + } + else { + /* run second pass */ + tot_missing++; + } + + /* if all keys have been used just exit, unlikely */ + if (menu_key_mask == (1 << 26) - 1) { + return; } } @@ -1156,23 +1131,24 @@ void ui_but_add_shortcut(uiBut *but, const char *shortcut_str, const bool do_str } /* without this, just allow stripping of the shortcut */ - if (shortcut_str) { - char *butstr_orig; + if (shortcut_str == NULL) { + return; + } - if (but->str != but->strdata) { - butstr_orig = but->str; /* free after using as source buffer */ - } - else { - butstr_orig = BLI_strdup(but->str); - } - BLI_snprintf( - but->strdata, sizeof(but->strdata), "%s" UI_SEP_CHAR_S "%s", butstr_orig, shortcut_str); - MEM_freeN(butstr_orig); - but->str = but->strdata; - but->flag |= UI_BUT_HAS_SEP_CHAR; - but->drawflag |= UI_BUT_HAS_SHORTCUT; - ui_but_update(but); + char *butstr_orig; + if (but->str != but->strdata) { + butstr_orig = but->str; /* free after using as source buffer */ } + else { + butstr_orig = BLI_strdup(but->str); + } + BLI_snprintf( + but->strdata, sizeof(but->strdata), "%s" UI_SEP_CHAR_S "%s", butstr_orig, shortcut_str); + MEM_freeN(butstr_orig); + but->str = but->strdata; + but->flag |= UI_BUT_HAS_SEP_CHAR; + but->drawflag |= UI_BUT_HAS_SHORTCUT; + ui_but_update(but); } /* -------------------------------------------------------------------- */ @@ -1207,11 +1183,10 @@ static bool ui_but_event_operator_string_from_menu(const bContext *C, BLI_assert(mt != NULL); bool found = false; - IDProperty *prop_menu; /* annoying, create a property */ const IDPropertyTemplate val = {0}; - prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */ + IDProperty *prop_menu = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */ IDP_AddToGroup(prop_menu, IDP_NewString(mt->idname, "name", sizeof(mt->idname))); if (WM_key_event_operator_string( @@ -1233,11 +1208,10 @@ static bool ui_but_event_operator_string_from_panel(const bContext *C, BLI_assert(pt != NULL); bool found = false; - IDProperty *prop_panel; /* annoying, create a property */ const IDPropertyTemplate val = {0}; - prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */ + IDProperty *prop_panel = IDP_New(IDP_GROUP, &val, __func__); /* dummy, name is unimportant */ IDP_AddToGroup(prop_panel, IDP_NewString(pt->idname, "name", sizeof(pt->idname))); IDP_AddToGroup(prop_panel, IDP_New(IDP_INT, @@ -1354,72 +1328,75 @@ static bool ui_but_event_property_operator_string(const bContext *C, /* Don't use the button again. */ but = NULL; + if (prop == NULL) { + return NULL; + } + /* this version is only for finding hotkeys for properties * (which get set via context using operators) */ - if (prop) { - /* to avoid massive slowdowns on property panels, for now, we only check the - * hotkeys for Editor / Scene settings... - * - * TODO: userpref settings? - */ - char *data_path = NULL; + /* to avoid massive slowdowns on property panels, for now, we only check the + * hotkeys for Editor / Scene settings... + * + * TODO: userpref settings? + */ + char *data_path = NULL; - if (ptr->owner_id) { - ID *id = ptr->owner_id; + if (ptr->owner_id) { + ID *id = ptr->owner_id; - if (GS(id->name) == ID_SCR) { - /* screen/editor property - * NOTE: in most cases, there is actually no info for backwards tracing - * how to get back to ID from the editor data we may be dealing with - */ - if (RNA_struct_is_a(ptr->type, &RNA_Space)) { - /* data should be directly on here... */ - data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop)); - } - else if (RNA_struct_is_a(ptr->type, &RNA_Area)) { - /* data should be directly on here... */ - const char *prop_id = RNA_property_identifier(prop); - /* Hack since keys access 'type', UI shows 'ui_type'. */ - if (STREQ(prop_id, "ui_type")) { - prop_id = "type"; - prop_enum_value >>= 16; - prop = RNA_struct_find_property(ptr, prop_id); - - opnames = ctx_enum_opnames_for_Area_ui_type; - opnames_len = ARRAY_SIZE(ctx_enum_opnames_for_Area_ui_type); - prop_enum_value_id = "space_type"; - prop_enum_value_is_int = true; - } - else { - data_path = BLI_sprintfN("area.%s", prop_id); - } + if (GS(id->name) == ID_SCR) { + /* screen/editor property + * NOTE: in most cases, there is actually no info for backwards tracing + * how to get back to ID from the editor data we may be dealing with + */ + if (RNA_struct_is_a(ptr->type, &RNA_Space)) { + /* data should be directly on here... */ + data_path = BLI_sprintfN("space_data.%s", RNA_property_identifier(prop)); + } + else if (RNA_struct_is_a(ptr->type, &RNA_Area)) { + /* data should be directly on here... */ + const char *prop_id = RNA_property_identifier(prop); + /* Hack since keys access 'type', UI shows 'ui_type'. */ + if (STREQ(prop_id, "ui_type")) { + prop_id = "type"; + prop_enum_value >>= 16; + prop = RNA_struct_find_property(ptr, prop_id); + + opnames = ctx_enum_opnames_for_Area_ui_type; + opnames_len = ARRAY_SIZE(ctx_enum_opnames_for_Area_ui_type); + prop_enum_value_id = "space_type"; + prop_enum_value_is_int = true; } else { - /* special exceptions for common nested data in editors... */ - if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) { - /* dopesheet filtering options... */ - data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop)); - } - else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) { - /* Filebrowser options... */ - data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop)); - } + data_path = BLI_sprintfN("area.%s", prop_id); } } - else if (GS(id->name) == ID_SCE) { - if (RNA_struct_is_a(ptr->type, &RNA_ToolSettings)) { - /* Tool-settings property: - * NOTE: tool-settings is usually accessed directly (i.e. not through scene). */ - data_path = RNA_path_from_ID_to_property(ptr, prop); + else { + /* special exceptions for common nested data in editors... */ + if (RNA_struct_is_a(ptr->type, &RNA_DopeSheet)) { + /* dopesheet filtering options... */ + data_path = BLI_sprintfN("space_data.dopesheet.%s", RNA_property_identifier(prop)); } - else { - /* scene property */ - char *path = RNA_path_from_ID_to_property(ptr, prop); + else if (RNA_struct_is_a(ptr->type, &RNA_FileSelectParams)) { + /* Filebrowser options... */ + data_path = BLI_sprintfN("space_data.params.%s", RNA_property_identifier(prop)); + } + } + } + else if (GS(id->name) == ID_SCE) { + if (RNA_struct_is_a(ptr->type, &RNA_ToolSettings)) { + /* Tool-settings property: + * NOTE: tool-settings is usually accessed directly (i.e. not through scene). */ + data_path = RNA_path_from_ID_to_property(ptr, prop); + } + else { + /* scene property */ + char *path = RNA_path_from_ID_to_property(ptr, prop); - if (path) { - data_path = BLI_sprintfN("scene.%s", path); - MEM_freeN(path); - } + if (path) { + data_path = BLI_sprintfN("scene.%s", path); + MEM_freeN(path); + } #if 0 else { printf("ERROR in %s(): Couldn't get path for scene property - %s\n", @@ -1427,69 +1404,68 @@ static bool ui_but_event_property_operator_string(const bContext *C, RNA_property_identifier(prop)); } #endif - } } - else { - // puts("other id"); - } - - // printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path); - } - - /* we have a datapath! */ - if (data_path || (prop_enum_value_ok && prop_enum_value_id)) { - /* create a property to host the "datapath" property we're sending to the operators */ - IDProperty *prop_path; - - const IDPropertyTemplate val = {0}; - prop_path = IDP_New(IDP_GROUP, &val, __func__); - if (data_path) { - IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1)); - } - if (prop_enum_value_ok) { - const EnumPropertyItem *item; - bool free; - RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free); - const int index = RNA_enum_from_value(item, prop_enum_value); - if (index != -1) { - IDProperty *prop_value; - if (prop_enum_value_is_int) { - const int value = item[index].value; - prop_value = IDP_New(IDP_INT, - &(IDPropertyTemplate){ - .i = value, - }, - prop_enum_value_id); - } - else { - const char *id = item[index].identifier; - prop_value = IDP_NewString(id, prop_enum_value_id, strlen(id) + 1); - } - IDP_AddToGroup(prop_path, prop_value); + } + else { + // puts("other id"); + } + + // printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path); + } + + /* we have a datapath! */ + if (data_path || (prop_enum_value_ok && prop_enum_value_id)) { + /* create a property to host the "datapath" property we're sending to the operators */ + IDProperty *prop_path; + + const IDPropertyTemplate val = {0}; + prop_path = IDP_New(IDP_GROUP, &val, __func__); + if (data_path) { + IDP_AddToGroup(prop_path, IDP_NewString(data_path, "data_path", strlen(data_path) + 1)); + } + if (prop_enum_value_ok) { + const EnumPropertyItem *item; + bool free; + RNA_property_enum_items((bContext *)C, ptr, prop, &item, NULL, &free); + const int index = RNA_enum_from_value(item, prop_enum_value); + if (index != -1) { + IDProperty *prop_value; + if (prop_enum_value_is_int) { + const int value = item[index].value; + prop_value = IDP_New(IDP_INT, + &(IDPropertyTemplate){ + .i = value, + }, + prop_enum_value_id); } else { - opnames_len = 0; /* Do nothing. */ - } - if (free) { - MEM_freeN((void *)item); + const char *id = item[index].identifier; + prop_value = IDP_NewString(id, prop_enum_value_id, strlen(id) + 1); } + IDP_AddToGroup(prop_path, prop_value); } + else { + opnames_len = 0; /* Do nothing. */ + } + if (free) { + MEM_freeN((void *)item); + } + } - /* check each until one works... */ + /* check each until one works... */ - for (int i = 0; (i < opnames_len) && (opnames[i]); i++) { - if (WM_key_event_operator_string( - C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, buf, buf_len)) { - found = true; - break; - } + for (int i = 0; (i < opnames_len) && (opnames[i]); i++) { + if (WM_key_event_operator_string( + C, opnames[i], WM_OP_INVOKE_REGION_WIN, prop_path, false, buf, buf_len)) { + found = true; + break; } + } - /* cleanup */ - IDP_FreeProperty(prop_path); - if (data_path) { - MEM_freeN(data_path); - } + /* cleanup */ + IDP_FreeProperty(prop_path); + if (data_path) { + MEM_freeN(data_path); } } @@ -1689,17 +1665,14 @@ static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but) static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but) { - StructRNA *type; - short idcode; - BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR)); if (but->rnaprop == NULL) { return false; } - type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); - idcode = RNA_type_to_ID_code(type); + StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); + short idcode = RNA_type_to_ID_code(type); return ((but->editstr == NULL) && (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode))); } @@ -1786,13 +1759,11 @@ static void ui_but_predefined_extra_operator_icons_add(uiBut *but) void UI_block_update_from_old(const bContext *C, uiBlock *block) { - uiBut *but_old; - if (!block->oldblock) { return; } - but_old = block->oldblock->buttons.first; + uiBut *but_old = block->oldblock->buttons.first; if (BLI_listbase_is_empty(&block->oldblock->butstore) == false) { UI_butstore_update(block); @@ -1977,11 +1948,9 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *region, uiBlock *bloc void UI_block_draw(const bContext *C, uiBlock *block) { uiStyle style = *UI_style_get_dpi(); /* XXX pass on as arg */ - ARegion *region; - rcti rect; /* get menu region or area region */ - region = CTX_wm_menu(C); + ARegion *region = CTX_wm_menu(C); if (!region) { region = CTX_wm_region(C); } @@ -2000,6 +1969,7 @@ void UI_block_draw(const bContext *C, uiBlock *block) ui_fontscale(&style.widget.points, block->aspect); /* scale block min/max to rect */ + rcti rect; ui_but_to_pixelrect(&rect, region, block, NULL); /* pixel space for AA widgets */ @@ -2234,15 +2204,12 @@ void UI_block_lock_clear(uiBlock *block) /* for buttons pointing to color for example */ void ui_but_v3_get(uiBut *but, float vec[3]) { - PropertyRNA *prop; - int a; - if (but->editvec) { copy_v3_v3(vec, but->editvec); } if (but->rnaprop) { - prop = but->rnaprop; + PropertyRNA *prop = but->rnaprop; zero_v3(vec); @@ -2254,7 +2221,7 @@ void ui_but_v3_get(uiBut *but, float vec[3]) } else { tot = min_ii(tot, 3); - for (a = 0; a < tot; a++) { + for (int a = 0; a < tot; a++) { vec[a] = RNA_property_float_get_index(&but->rnapoin, prop, a); } } @@ -2286,14 +2253,12 @@ void ui_but_v3_get(uiBut *but, float vec[3]) /* for buttons pointing to color for example */ void ui_but_v3_set(uiBut *but, const float vec[3]) { - PropertyRNA *prop; - if (but->editvec) { copy_v3_v3(but->editvec, vec); } if (but->rnaprop) { - prop = but->rnaprop; + PropertyRNA *prop = but->rnaprop; if (RNA_property_type(prop) == PROP_FLOAT) { int tot; @@ -2440,7 +2405,6 @@ bool ui_but_supports_cycling(const uiBut *but) double ui_but_value_get(uiBut *but) { - PropertyRNA *prop; double value = 0.0; if (but->editval) { @@ -2451,7 +2415,7 @@ double ui_but_value_get(uiBut *but) } if (but->rnaprop) { - prop = but->rnaprop; + PropertyRNA *prop = but->rnaprop; BLI_assert(but->rnaindex != -1); @@ -2506,11 +2470,9 @@ double ui_but_value_get(uiBut *but) void ui_but_value_set(uiBut *but, double value) { - PropertyRNA *prop; - /* value is a hsv value: convert to rgb */ if (but->rnaprop) { - prop = but->rnaprop; + PropertyRNA *prop = but->rnaprop; if (RNA_property_editable(&but->rnapoin, prop)) { switch (RNA_property_type(prop)) { @@ -2642,17 +2604,19 @@ static double ui_get_but_scale_unit(uiBut *but, double value) /* str will be overwritten */ void ui_but_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen) { - if (ui_but_is_unit(but)) { - UnitSettings *unit = but->block->unit; - const int unit_type = UI_but_unit_type_get(but); - char *orig_str; + if (!ui_but_is_unit(but)) { + return; + } - orig_str = BLI_strdup(str); + UnitSettings *unit = but->block->unit; + const int unit_type = UI_but_unit_type_get(but); + char *orig_str; - BKE_unit_name_to_alt(str, maxlen, orig_str, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type)); + orig_str = BLI_strdup(str); - MEM_freeN(orig_str); - } + BKE_unit_name_to_alt(str, maxlen, orig_str, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type)); + + MEM_freeN(orig_str); } /** @@ -2703,29 +2667,30 @@ static float ui_get_but_step_unit(uiBut *but, float step_default) const double step = BKE_unit_closest_scalar(scale_step, but->block->unit->system, unit_type); /* -1 is an error value */ - if (step != -1.0) { - const double scale_unit = ui_get_but_scale_unit(but, 1.0); - const double step_unit = BKE_unit_closest_scalar( - scale_unit, but->block->unit->system, unit_type); - double step_final; - - BLI_assert(step > 0.0); - - step_final = (step / scale_unit) / (double)UI_PRECISION_FLOAT_SCALE; - - if (step == step_unit) { - /* Logic here is to scale by the original 'step_orig' - * only when the unit step matches the scaled step. - * - * This is needed for units that don't have a wide range of scales (degrees for eg.). - * Without this we can't select between a single degree, or a 10th of a degree. - */ - step_final *= step_orig; - } + if (step == -1.0f) { + return step_default; + } + + const double scale_unit = ui_get_but_scale_unit(but, 1.0); + const double step_unit = BKE_unit_closest_scalar( + scale_unit, but->block->unit->system, unit_type); + double step_final; - return (float)step_final; + BLI_assert(step > 0.0); + + step_final = (step / scale_unit) / (double)UI_PRECISION_FLOAT_SCALE; + + if (step == step_unit) { + /* Logic here is to scale by the original 'step_orig' + * only when the unit step matches the scaled step. + * + * This is needed for units that don't have a wide range of scales (degrees for eg.). + * Without this we can't select between a single degree, or a 10th of a degree. + */ + step_final *= step_orig; } - return step_default; + + return (float)step_final; } /** @@ -2746,12 +2711,10 @@ void ui_but_string_get_ex(uiBut *but, } if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU, UI_BTYPE_TAB)) { - PropertyType type; - const char *buf = NULL; - int buf_len; - - type = RNA_property_type(but->rnaprop); + PropertyType type = RNA_property_type(but->rnaprop); + int buf_len; + const char *buf = NULL; if ((but->type == UI_BTYPE_TAB) && (but->custom_data)) { StructRNA *ptr_type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); PointerRNA ptr; @@ -2807,9 +2770,7 @@ void ui_but_string_get_ex(uiBut *but, } else { /* number editing */ - double value; - - value = ui_but_value_get(but); + double value = ui_but_value_get(but); PropertySubType subtype = PROP_NONE; if (but->rnaprop) { @@ -2875,9 +2836,7 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size) *r_str_size = 1; if (but->rnaprop && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { - PropertyType type; - - type = RNA_property_type(but->rnaprop); + PropertyType type = RNA_property_type(but->rnaprop); if (type == PROP_STRING) { /* RNA string */ @@ -3044,9 +3003,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) { if (but->rnaprop && but->rnapoin.data && ELEM(but->type, UI_BTYPE_TEXT, UI_BTYPE_SEARCH_MENU)) { if (RNA_property_editable(&but->rnapoin, but->rnaprop)) { - PropertyType type; - - type = RNA_property_type(but->rnaprop); + PropertyType type = RNA_property_type(but->rnaprop); if (type == PROP_STRING) { /* RNA string */ @@ -3173,8 +3130,7 @@ void ui_but_default_set(bContext *C, const bool all, const bool use_afterfunc) wmOperatorType *ot = WM_operatortype_find("UI_OT_reset_default_button", true); if (use_afterfunc) { - PointerRNA *ptr; - ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true); + PointerRNA *ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true); RNA_boolean_set(ptr, "all", all); } else { @@ -3218,31 +3174,25 @@ static double soft_range_round_down(double value, double max) void ui_but_range_set_hard(uiBut *but) { - if (but->rnaprop) { - const PropertyType type = RNA_property_type(but->rnaprop); - double hardmin, hardmax; - - /* clamp button range to something reasonable in case - * we get -inf/inf from RNA properties */ - if (type == PROP_INT) { - int imin, imax; + if (but->rnaprop == NULL) { + return; + } - RNA_property_int_range(&but->rnapoin, but->rnaprop, &imin, &imax); - hardmin = (imin == INT_MIN) ? -1e4 : imin; - hardmax = (imin == INT_MAX) ? 1e4 : imax; - } - else if (type == PROP_FLOAT) { - float fmin, fmax; + const PropertyType type = RNA_property_type(but->rnaprop); - RNA_property_float_range(&but->rnapoin, but->rnaprop, &fmin, &fmax); - hardmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin; - hardmax = (fmax == FLT_MAX) ? (float)1e4 : fmax; - } - else { - return; - } - but->hardmin = hardmin; - but->hardmax = hardmax; + /* clamp button range to something reasonable in case + * we get -inf/inf from RNA properties */ + if (type == PROP_INT) { + int imin, imax; + RNA_property_int_range(&but->rnapoin, but->rnaprop, &imin, &imax); + but->hardmin = (imin == INT_MIN) ? -1e4 : imin; + but->hardmax = (imin == INT_MAX) ? 1e4 : imax; + } + else if (type == PROP_FLOAT) { + float fmin, fmax; + RNA_property_float_range(&but->rnapoin, but->rnaprop, &fmin, &fmax); + but->hardmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin; + but->hardmax = (fmax == FLT_MAX) ? (float)1e4 : fmax; } } @@ -3424,10 +3374,9 @@ static void ui_but_free(const bContext *C, uiBut *but) /* can be called with C==NULL */ void UI_block_free(const bContext *C, uiBlock *block) { - uiBut *but; - UI_butstore_clear(block); + uiBut *but; while ((but = BLI_pophead(&block->buttons))) { ui_but_free(C, but); } @@ -3473,7 +3422,6 @@ void UI_blocklist_draw(const bContext *C, const ListBase *lb) void UI_blocklist_free(const bContext *C, ListBase *lb) { uiBlock *block; - while ((block = BLI_pophead(lb))) { UI_block_free(C, block); } @@ -3519,29 +3467,25 @@ void UI_block_region_set(uiBlock *block, ARegion *region) uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, char emboss) { - uiBlock *block; - wmWindow *window; - Scene *scn; - - window = CTX_wm_window(C); - scn = CTX_data_scene(C); + wmWindow *window = CTX_wm_window(C); + Scene *scene = CTX_data_scene(C); - block = MEM_callocN(sizeof(uiBlock), "uiBlock"); + uiBlock *block = MEM_callocN(sizeof(uiBlock), "uiBlock"); block->active = 1; block->emboss = emboss; block->evil_C = (void *)C; /* XXX */ - if (scn) { + if (scene) { /* store display device name, don't lookup for transformations yet * block could be used for non-color displays where looking up for transformation * would slow down redraw, so only lookup for actual transform when it's indeed * needed */ - STRNCPY(block->display_device, scn->display_settings.display_device); + STRNCPY(block->display_device, scene->display_settings.display_device); /* copy to avoid crash when scene gets deleted with ui still open */ - block->unit = MEM_mallocN(sizeof(scn->unit), "UI UnitSettings"); - memcpy(block->unit, &scn->unit, sizeof(scn->unit)); + block->unit = MEM_mallocN(sizeof(scene->unit), "UI UnitSettings"); + memcpy(block->unit, &scene->unit, sizeof(scene->unit)); } else { STRNCPY(block->display_device, IMB_colormanagement_display_get_default_name()); @@ -3759,9 +3703,8 @@ static void ui_but_update_ex(uiBut *but, const bool validate) case UI_BTYPE_LABEL: if (ui_but_is_float(but)) { - int prec; UI_GET_BUT_VALUE_INIT(but, value); - prec = ui_but_calc_float_precision(but, value); + int prec = ui_but_calc_float_precision(but, value); BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value); } else { @@ -3952,7 +3895,6 @@ static uiBut *ui_but_alloc(const eButType type) { size_t alloc_size; const char *alloc_str; - ui_but_alloc_info(type, &alloc_size, &alloc_str, NULL); return MEM_callocN(alloc_size, alloc_str); @@ -4037,9 +3979,6 @@ static uiBut *ui_def_but(uiBlock *block, float a2, const char *tip) { - uiBut *but; - int slen; - BLI_assert(width >= 0 && height >= 0); /* we could do some more error checks here */ @@ -4055,7 +3994,7 @@ static uiBut *ui_def_but(uiBlock *block, } } - but = ui_but_alloc(type & BUTTYPE); + uiBut *but = ui_but_alloc(type & BUTTYPE); but->type = type & BUTTYPE; but->pointype = type & UI_BUT_POIN_TYPES; @@ -4066,7 +4005,7 @@ static uiBut *ui_def_but(uiBlock *block, but->retval = retval; - slen = strlen(str); + int slen = strlen(str); ui_but_string_set_internal(but, str, slen); but->rect.xmin = x; @@ -4212,25 +4151,20 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu uiBut *but = (uiBut *)but_p; /* see comment in ui_item_enum_expand, re: uiname */ - const EnumPropertyItem *item, *item_array; - bool free; - - uiLayout *split, *column = NULL; - - int totitems = 0; - int columns, rows, a, b; - int column_end = 0; - int nbr_entries_nosepr = 0; + const EnumPropertyItem *item_array; UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); + bool free; RNA_property_enum_items_gettexted( block->evil_C, &but->rnapoin, but->rnaprop, &item_array, NULL, &free); /* we dont want nested rows, cols in menus */ UI_block_layout_set_current(block, layout); - for (item = item_array; item->identifier; item++, totitems++) { + int totitems = 0; + int nbr_entries_nosepr = 0; + for (const EnumPropertyItem *item = item_array; item->identifier; item++, totitems++) { if (!item->identifier[0]) { /* inconsistent, but menus with categories do not look good flipped */ if (item->name) { @@ -4244,7 +4178,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu } /* Columns and row estimation. Ignore simple separators here. */ - columns = (nbr_entries_nosepr + 20) / 20; + int columns = (nbr_entries_nosepr + 20) / 20; if (columns < 1) { columns = 1; } @@ -4252,7 +4186,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu columns = (nbr_entries_nosepr + 25) / 25; } - rows = totitems / columns; + int rows = totitems / columns; if (rows < 1) { rows = 1; } @@ -4282,16 +4216,18 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu /* note, item_array[...] is reversed on access */ /* create items */ - split = uiLayoutSplit(layout, 0.0f, false); + uiLayout *split = uiLayoutSplit(layout, 0.0f, false); - for (a = 0; a < totitems; a++) { + int column_end = 0; + uiLayout *column = NULL; + for (int a = 0; a < totitems; a++) { if (a == column_end) { /* start new column, and find out where it ends in advance, so we * can flip the order of items properly per column */ column_end = totitems; - for (b = a + 1; b < totitems; b++) { - item = &item_array[b]; + for (int b = a + 1; b < totitems; b++) { + const EnumPropertyItem *item = &item_array[b]; /* new column on N rows or on separation label */ if (((b - a) % rows == 0) || (!item->identifier[0] && item->name)) { @@ -4303,7 +4239,7 @@ static void ui_def_but_rna__menu(bContext *UNUSED(C), uiLayout *layout, void *bu column = uiLayoutColumn(split, false); } - item = &item_array[a]; + const EnumPropertyItem *item = &item_array[a]; if (!item->identifier[0]) { if (item->name) { @@ -4483,7 +4419,6 @@ static uiBut *ui_def_but_rna(uiBlock *block, const char *tip) { const PropertyType proptype = RNA_property_type(prop); - uiBut *but; int icon = 0; uiMenuCreateFunc func = NULL; const bool always_set_a1_a2 = ELEM(type, UI_BTYPE_NUM); @@ -4494,14 +4429,12 @@ static uiBut *ui_def_but_rna(uiBlock *block, /* use rna values if parameters are not specified */ if ((proptype == PROP_ENUM) && ELEM(type, UI_BTYPE_MENU, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { - /* UI_BTYPE_MENU is handled a little differently here */ - const EnumPropertyItem *item; - int value; bool free; - int i; - + const EnumPropertyItem *item; RNA_property_enum_items(block->evil_C, ptr, prop, &item, NULL, &free); + int value; + /* UI_BTYPE_MENU is handled a little differently here */ if (type == UI_BTYPE_MENU) { value = RNA_property_enum_get(ptr, prop); } @@ -4509,7 +4442,7 @@ static uiBut *ui_def_but_rna(uiBlock *block, value = (int)max; } - i = RNA_enum_from_value(item, value); + int i = RNA_enum_from_value(item, value); if (i != -1) { if (!str) { @@ -4594,7 +4527,8 @@ static uiBut *ui_def_but_rna(uiBlock *block, } /* now create button */ - but = ui_def_but(block, type, retval, str, x, y, width, height, NULL, min, max, a1, a2, tip); + uiBut *but = ui_def_but( + block, type, retval, str, x, y, width, height, NULL, min, max, a1, a2, tip); if (but->type == UI_BTYPE_NUM) { /* Set default values, can be overriden later. */ @@ -4674,8 +4608,8 @@ static uiBut *ui_def_but_rna_propname(uiBlock *block, const char *tip) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); - uiBut *but; + uiBut *but; if (prop) { but = ui_def_but_rna( block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip); @@ -4701,8 +4635,6 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block, short height, const char *tip) { - uiBut *but; - if (!str) { if (ot && ot->srna) { str = WM_operatortype_name(ot, NULL); @@ -4716,7 +4648,7 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block, tip = RNA_struct_ui_description(ot->srna); } - but = ui_def_but(block, type, -1, str, x, y, width, height, NULL, 0, 0, 0, 0, tip); + uiBut *but = ui_def_but(block, type, -1, str, x, y, width, height, NULL, 0, 0, 0, 0, tip); but->optype = ot; but->opcontext = opcontext; but->flag &= ~UI_BUT_UNDO; /* no need for ui_but_is_rna_undo(), we never need undo here */ @@ -4856,15 +4788,16 @@ void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name) { char *truncate = autocpl->truncate; const char *startname = autocpl->startname; - int a; - - for (a = 0; a < autocpl->maxlen - 1; a++) { + int match_index = 0; + for (int a = 0; a < autocpl->maxlen - 1; a++) { if (startname[a] == 0 || startname[a] != name[a]) { + match_index = a; break; } } + /* found a match */ - if (startname[a] == 0) { + if (startname[match_index] == 0) { autocpl->matches++; /* first match */ if (truncate[0] == 0) { @@ -4872,7 +4805,7 @@ void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name) } else { /* remove from truncate what is not in bone->name */ - for (a = 0; a < autocpl->maxlen - 1; a++) { + for (int a = 0; a < autocpl->maxlen - 1; a++) { if (name[a] == 0) { truncate[a] = 0; break; @@ -5217,8 +5150,7 @@ uiBut *uiDefButR(uiBlock *block, float a2, const char *tip) { - uiBut *but; - but = ui_def_but_rna_propname( + uiBut *but = ui_def_but_rna_propname( block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip); ui_but_update(but); return but; @@ -5240,8 +5172,7 @@ uiBut *uiDefButR_prop(uiBlock *block, float a2, const char *tip) { - uiBut *but; - but = ui_def_but_rna( + uiBut *but = ui_def_but_rna( block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip); ui_but_update(but); return but; @@ -5258,8 +5189,7 @@ uiBut *uiDefButO_ptr(uiBlock *block, short height, const char *tip) { - uiBut *but; - but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip); + uiBut *but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip); ui_but_update(but); return but; } @@ -5603,8 +5533,7 @@ uiBut *uiDefIconButR(uiBlock *block, float a2, const char *tip) { - uiBut *but; - but = ui_def_but_rna_propname( + uiBut *but = ui_def_but_rna_propname( block, type, retval, "", x, y, width, height, ptr, propname, index, min, max, a1, a2, tip); ui_but_update_and_icon_set(but, icon); return but; @@ -5626,8 +5555,7 @@ uiBut *uiDefIconButR_prop(uiBlock *block, float a2, const char *tip) { - uiBut *but; - but = ui_def_but_rna( + uiBut *but = ui_def_but_rna( block, type, retval, "", x, y, width, height, ptr, prop, index, min, max, a1, a2, tip); ui_but_update_and_icon_set(but, icon); return but; @@ -5644,8 +5572,7 @@ uiBut *uiDefIconButO_ptr(uiBlock *block, short height, const char *tip) { - uiBut *but; - but = ui_def_but_operator_ptr(block, type, ot, opcontext, "", x, y, width, height, tip); + uiBut *but = ui_def_but_operator_ptr(block, type, ot, opcontext, "", x, y, width, height, tip); ui_but_update_and_icon_set(but, icon); return but; } @@ -6007,8 +5934,7 @@ uiBut *uiDefIconTextButR(uiBlock *block, float a2, const char *tip) { - uiBut *but; - but = ui_def_but_rna_propname( + uiBut *but = ui_def_but_rna_propname( block, type, retval, str, x, y, width, height, ptr, propname, index, min, max, a1, a2, tip); ui_but_update_and_icon_set(but, icon); but->drawflag |= UI_BUT_ICON_LEFT; @@ -6032,8 +5958,7 @@ uiBut *uiDefIconTextButR_prop(uiBlock *block, float a2, const char *tip) { - uiBut *but; - but = ui_def_but_rna( + uiBut *but = ui_def_but_rna( block, type, retval, str, x, y, width, height, ptr, prop, index, min, max, a1, a2, tip); ui_but_update_and_icon_set(but, icon); but->drawflag |= UI_BUT_ICON_LEFT; @@ -6051,8 +5976,7 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, short height, const char *tip) { - uiBut *but; - but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip); + uiBut *but = ui_def_but_operator_ptr(block, type, ot, opcontext, str, x, y, width, height, tip); ui_but_update_and_icon_set(but, icon); but->drawflag |= UI_BUT_ICON_LEFT; return but; @@ -6820,9 +6744,7 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, float a2, const char *tip) { - uiBut *but; - - but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip); + uiBut *but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip); UI_but_func_search_set(but, ui_searchbox_create_generic, operator_enum_search_update_fn, @@ -6876,7 +6798,6 @@ void UI_but_number_precision_set(uiBut *but, float precision) void UI_but_focus_on_enter_event(wmWindow *win, uiBut *but) { wmEvent event; - wm_event_init_from_window(win, &event); event.type = EVT_BUT_OPEN; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index b9ed1688e80..65415a750bb 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -877,6 +877,11 @@ void UI_panels_set_expansion_from_seach_filter(const bContext *C, ARegion *regio } } +bool UI_panel_is_active(const Panel *panel) +{ + return panel->runtime_flag & PANEL_ACTIVE; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 2e9f297b705..7b41b1df0ab 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -450,8 +450,25 @@ void ED_area_do_mgs_subscribe_for_tool_ui( struct wmMsgBus *mbus) { BLI_assert(region->regiontype == RGN_TYPE_UI); + const char *panel_category_tool = "Tool"; const char *category = UI_panel_category_active_get(region, false); - if (category && STREQ(category, "Tool")) { + + bool update_region = false; + if (category && STREQ(category, panel_category_tool)) { + update_region = true; + } + else { + /* Check if a tool category panel is pinned and visible in another category. */ + LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { + if (UI_panel_is_active(panel) && panel->flag & PNL_PIN && + STREQ(panel->type->category, panel_category_tool)) { + update_region = true; + break; + } + } + } + + if (update_region) { wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index a1894e1b4c6..175d98ba9aa 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -341,6 +341,7 @@ typedef enum { void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot); void PAINT_OT_mask_lasso_gesture(struct wmOperatorType *ot); void PAINT_OT_mask_box_gesture(struct wmOperatorType *ot); +void PAINT_OT_mask_line_gesture(struct wmOperatorType *ot); /* paint_curve.c */ void PAINTCURVE_OT_new(struct wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index fc17af8d2cb..0f2ebdd28aa 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -234,6 +234,7 @@ void PAINT_OT_mask_flood_fill(struct wmOperatorType *ot) typedef enum eSculptGestureShapeType { SCULPT_GESTURE_SHAPE_BOX, SCULPT_GESTURE_SHAPE_LASSO, + SCULPT_GESTURE_SHAPE_LINE, } eMaskGesturesShapeType; typedef struct LassoGestureData { @@ -246,6 +247,11 @@ typedef struct LassoGestureData { BLI_bitmap *mask_px; } LassoGestureData; +typedef struct LineGestureData { + float true_plane[4]; + float plane[4]; +} LineGestureData; + struct SculptGestureOperation; typedef struct SculptGestureContext { @@ -280,6 +286,9 @@ typedef struct SculptGestureContext { /* Lasso Gesture. */ LassoGestureData lasso; + /* Line Gesture. */ + LineGestureData line; + /* Task Callback Data. */ PBVHNode **nodes; int totnode; @@ -430,6 +439,44 @@ static SculptGestureContext *sculpt_gesture_init_from_box(bContext *C, wmOperato return sgcontext; } +static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperator *op) +{ + SculptGestureContext *sgcontext = MEM_callocN(sizeof(SculptGestureContext), + "sculpt gesture context line"); + sgcontext->shape_type = SCULPT_GESTURE_SHAPE_LINE; + + sculpt_gesture_context_init_common(C, op, sgcontext); + + float line_points[2][2]; + line_points[0][0] = RNA_int_get(op->ptr, "xstart"); + line_points[0][1] = RNA_int_get(op->ptr, "ystart"); + line_points[1][0] = RNA_int_get(op->ptr, "xend"); + line_points[1][1] = RNA_int_get(op->ptr, "yend"); + + float depth_point[3]; + float plane_points[3][3]; + + /* Calculate a triangle in the line's plane. */ + add_v3_v3v3(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[0]); + + madd_v3_v3v3fl(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal, 10.0f); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[1]); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], plane_points[2]); + + /* Calculate final line plane and normal using the triangle. */ + float normal[3]; + normal_tri_v3(normal, plane_points[0], plane_points[1], plane_points[2]); + if (!sgcontext->vc.rv3d->is_persp) { + mul_v3_fl(normal, -1.0f); + } + plane_from_point_normal_v3(sgcontext->line.true_plane, plane_points[0], normal); + return sgcontext; +} + static void sculpt_gesture_context_free(SculptGestureContext *sgcontext) { MEM_SAFE_FREE(sgcontext->lasso.mask_px); @@ -470,12 +517,28 @@ static void sculpt_gesture_flip_for_symmetry_pass(SculptGestureContext *sgcontex for (int j = 0; j < 4; j++) { flip_plane(sgcontext->clip_planes[j], sgcontext->true_clip_planes[j], symmpass); } + negate_m4(sgcontext->clip_planes); + flip_v3_v3(sgcontext->view_normal, sgcontext->true_view_normal, symmpass); flip_v3_v3(sgcontext->view_origin, sgcontext->true_view_origin, symmpass); + flip_plane(sgcontext->line.plane, sgcontext->line.true_plane, symmpass); } -static void sculpt_gesture_update_effected_nodes(SculptGestureContext *sgcontext) +static void sculpt_gesture_update_effected_nodes_by_line_plane(SculptGestureContext *sgcontext) +{ + SculptSession *ss = sgcontext->ss; + float clip_planes[1][4]; + copy_v4_v4(clip_planes[0], sgcontext->line.plane); + PBVHFrustumPlanes frustum = {.planes = clip_planes, .num_planes = 1}; + BKE_pbvh_search_gather(ss->pbvh, + BKE_pbvh_node_frustum_contain_AABB, + &frustum, + &sgcontext->nodes, + &sgcontext->totnode); +} + +static void sculpt_gesture_update_effected_nodes_by_clip_planes(SculptGestureContext *sgcontext) { SculptSession *ss = sgcontext->ss; float clip_planes[4][4]; @@ -489,6 +552,19 @@ static void sculpt_gesture_update_effected_nodes(SculptGestureContext *sgcontext &sgcontext->totnode); } +static void sculpt_gesture_update_effected_nodes(SculptGestureContext *sgcontext) +{ + switch (sgcontext->shape_type) { + case SCULPT_GESTURE_SHAPE_BOX: + case SCULPT_GESTURE_SHAPE_LASSO: + sculpt_gesture_update_effected_nodes_by_clip_planes(sgcontext); + break; + case SCULPT_GESTURE_SHAPE_LINE: + sculpt_gesture_update_effected_nodes_by_line_plane(sgcontext); + break; + } +} + static bool sculpt_gesture_is_effected_lasso(SculptGestureContext *sgcontext, const float co[3]) { float scr_co_f[2]; @@ -532,6 +608,8 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P return isect_point_planes_v3(sgcontext->clip_planes, 4, vd->co); case SCULPT_GESTURE_SHAPE_LASSO: return sculpt_gesture_is_effected_lasso(sgcontext, vd->co); + case SCULPT_GESTURE_SHAPE_LINE: + return plane_point_side_v3(sgcontext->line.plane, vd->co) > 0.0f; } return false; } @@ -1117,6 +1195,18 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op) +{ + SculptGestureContext *sgcontext = sculpt_gesture_init_from_line(C, op); + if (!sgcontext) { + return OPERATOR_CANCELLED; + } + sculpt_gesture_init_mask_properties(sgcontext, op); + sculpt_gesture_apply(C, sgcontext); + sculpt_gesture_context_free(sgcontext); + return OPERATOR_FINISHED; +} + static int face_set_gesture_box_exec(bContext *C, wmOperator *op) { SculptGestureContext *sgcontext = sculpt_gesture_init_from_box(C, op); @@ -1222,6 +1312,27 @@ void PAINT_OT_mask_box_gesture(wmOperatorType *ot) paint_mask_gesture_operator_properties(ot); } +void PAINT_OT_mask_line_gesture(wmOperatorType *ot) +{ + ot->name = "Mask Line Gesture"; + ot->idname = "PAINT_OT_mask_line_gesture"; + ot->description = "Add mask to the right of a line as you move the brush"; + + ot->invoke = WM_gesture_straightline_invoke; + ot->modal = WM_gesture_straightline_oneshot_modal; + ot->exec = paint_mask_gesture_line_exec; + + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER; + + /* Properties. */ + WM_operator_properties_gesture_straightline(ot, WM_CURSOR_EDIT); + sculpt_gesture_operator_properties(ot); + + paint_mask_gesture_operator_properties(ot); +} + void SCULPT_OT_face_set_lasso_gesture(wmOperatorType *ot) { ot->name = "Face Set Lasso Gesture"; @@ -1232,10 +1343,6 @@ void SCULPT_OT_face_set_lasso_gesture(wmOperatorType *ot) ot->modal = WM_gesture_lasso_modal; ot->exec = face_set_gesture_lasso_exec; - ot->poll = SCULPT_mode_poll; - - ot->flag = OPTYPE_REGISTER; - /* Properties. */ WM_operator_properties_gesture_lasso(ot); sculpt_gesture_operator_properties(ot); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 43ff03ea7e2..e239b9619ec 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -1357,6 +1357,7 @@ void ED_operatortypes_paint(void) WM_operatortype_append(PAINT_OT_mask_flood_fill); WM_operatortype_append(PAINT_OT_mask_lasso_gesture); WM_operatortype_append(PAINT_OT_mask_box_gesture); + WM_operatortype_append(PAINT_OT_mask_line_gesture); } void ED_keymap_paint(wmKeyConfig *keyconf) diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 2e10cc94004..410197da5da 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -68,11 +68,8 @@ static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, StructRNA *type) { - PointerRNA *ptr; - int a; - - for (a = 0; a < path->len; a++) { - ptr = &path->ptr[a]; + for (int i = 0; i < path->len; i++) { + PointerRNA *ptr = &path->ptr[i]; if (RNA_struct_is_a(ptr->type, type)) { CTX_data_pointer_set(result, ptr->owner_id, ptr->type, ptr->data); @@ -85,11 +82,8 @@ static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, S static PointerRNA *get_pointer_type(ButsContextPath *path, StructRNA *type) { - PointerRNA *ptr; - int a; - - for (a = 0; a < path->len; a++) { - ptr = &path->ptr[a]; + for (int i = 0; i < path->len; i++) { + PointerRNA *ptr = &path->ptr[i]; if (RNA_struct_is_a(ptr->type, type)) { return ptr; @@ -109,14 +103,14 @@ static bool buttons_context_path_scene(ButsContextPath *path) return RNA_struct_is_a(ptr->type, &RNA_Scene); } -static int buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win) +static bool buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win) { PointerRNA *ptr = &path->ptr[path->len - 1]; /* View Layer may have already been resolved in a previous call * (e.g. in buttons_context_path_linestyle). */ if (RNA_struct_is_a(ptr->type, &RNA_ViewLayer)) { - return 1; + return true; } if (buttons_context_path_scene(path)) { @@ -126,45 +120,42 @@ static int buttons_context_path_view_layer(ButsContextPath *path, wmWindow *win) RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &path->ptr[path->len]); path->len++; - return 1; + return true; } - return 0; + return false; } -/* note: this function can return 1 without adding a world to the path +/* note: this function can return true without adding a world to the path * so the buttons stay visible, but be sure to check the ID type if a ID_WO */ -static int buttons_context_path_world(ButsContextPath *path) +static bool buttons_context_path_world(ButsContextPath *path) { - Scene *scene; - World *world; PointerRNA *ptr = &path->ptr[path->len - 1]; /* if we already have a (pinned) world, we're done */ if (RNA_struct_is_a(ptr->type, &RNA_World)) { - return 1; + return true; } /* if we have a scene, use the scene's world */ if (buttons_context_path_scene(path)) { - scene = path->ptr[path->len - 1].data; - world = scene->world; + Scene *scene = path->ptr[path->len - 1].data; + World *world = scene->world; if (world) { RNA_id_pointer_create(&scene->world->id, &path->ptr[path->len]); path->len++; - return 1; + return true; } - return 1; + return true; } /* no path to a world possible */ - return 0; + return false; } static bool buttons_context_path_linestyle(ButsContextPath *path, wmWindow *window) { - FreestyleLineStyle *linestyle; PointerRNA *ptr = &path->ptr[path->len - 1]; /* if we already have a (pinned) linestyle, we're done */ @@ -174,7 +165,7 @@ static bool buttons_context_path_linestyle(ButsContextPath *path, wmWindow *wind /* if we have a view layer, use the lineset's linestyle */ if (buttons_context_path_view_layer(path, window)) { ViewLayer *view_layer = path->ptr[path->len - 1].data; - linestyle = BKE_linestyle_active_from_view_layer(view_layer); + FreestyleLineStyle *linestyle = BKE_linestyle_active_from_view_layer(view_layer); if (linestyle) { RNA_id_pointer_create(&linestyle->id, &path->ptr[path->len]); path->len++; @@ -214,7 +205,6 @@ static bool buttons_context_path_object(ButsContextPath *path) static bool buttons_context_path_data(ButsContextPath *path, int type) { - Object *ob; PointerRNA *ptr = &path->ptr[path->len - 1]; /* if we already have a data, we're done */ @@ -264,7 +254,7 @@ static bool buttons_context_path_data(ButsContextPath *path, int type) } /* try to get an object in the path, no pinning supported here */ if (buttons_context_path_object(path)) { - ob = path->ptr[path->len - 1].data; + Object *ob = path->ptr[path->len - 1].data; if (ob && (type == -1 || type == ob->type)) { RNA_id_pointer_create(ob->data, &path->ptr[path->len]); @@ -280,10 +270,8 @@ static bool buttons_context_path_data(ButsContextPath *path, int type) static bool buttons_context_path_modifier(ButsContextPath *path) { - Object *ob; - if (buttons_context_path_object(path)) { - ob = path->ptr[path->len - 1].data; + Object *ob = path->ptr[path->len - 1].data; if (ob && ELEM(ob->type, OB_MESH, @@ -304,10 +292,8 @@ static bool buttons_context_path_modifier(ButsContextPath *path) static bool buttons_context_path_shaderfx(ButsContextPath *path) { - Object *ob; - if (buttons_context_path_object(path)) { - ob = path->ptr[path->len - 1].data; + Object *ob = path->ptr[path->len - 1].data; if (ob && ELEM(ob->type, OB_GPENCIL)) { return true; @@ -319,9 +305,7 @@ static bool buttons_context_path_shaderfx(ButsContextPath *path) static bool buttons_context_path_material(ButsContextPath *path) { - Object *ob; PointerRNA *ptr = &path->ptr[path->len - 1]; - Material *ma; /* if we already have a (pinned) material, we're done */ if (RNA_struct_is_a(ptr->type, &RNA_Material)) { @@ -329,10 +313,10 @@ static bool buttons_context_path_material(ButsContextPath *path) } /* if we have an object, use the object material slot */ if (buttons_context_path_object(path)) { - ob = path->ptr[path->len - 1].data; + Object *ob = path->ptr[path->len - 1].data; if (ob && OB_TYPE_SUPPORT_MATERIAL(ob->type)) { - ma = BKE_object_material_get(ob, ob->actcol); + Material *ma = BKE_object_material_get(ob, ob->actcol); if (ma != NULL) { RNA_id_pointer_create(&ma->id, &path->ptr[path->len]); path->len++; @@ -347,16 +331,13 @@ static bool buttons_context_path_material(ButsContextPath *path) static bool buttons_context_path_bone(ButsContextPath *path) { - bArmature *arm; - EditBone *edbo; - /* if we have an armature, get the active bone */ if (buttons_context_path_data(path, OB_ARMATURE)) { - arm = path->ptr[path->len - 1].data; + bArmature *arm = path->ptr[path->len - 1].data; if (arm->edbo) { if (arm->act_edbone) { - edbo = arm->act_edbone; + EditBone *edbo = arm->act_edbone; RNA_pointer_create(&arm->id, &RNA_EditBone, edbo, &path->ptr[path->len]); path->len++; return true; @@ -409,8 +390,6 @@ static bool buttons_context_path_pose_bone(ButsContextPath *path) static bool buttons_context_path_particle(ButsContextPath *path) { - Object *ob; - ParticleSystem *psys; PointerRNA *ptr = &path->ptr[path->len - 1]; /* if we already have (pinned) particle settings, we're done */ @@ -419,10 +398,10 @@ static bool buttons_context_path_particle(ButsContextPath *path) } /* if we have an object, get the active particle system */ if (buttons_context_path_object(path)) { - ob = path->ptr[path->len - 1].data; + Object *ob = path->ptr[path->len - 1].data; if (ob && ob->type == OB_MESH) { - psys = psys_get_current(ob); + ParticleSystem *psys = psys_get_current(ob); RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &path->ptr[path->len]); path->len++; @@ -436,8 +415,6 @@ static bool buttons_context_path_particle(ButsContextPath *path) static bool buttons_context_path_brush(const bContext *C, ButsContextPath *path) { - Scene *scene; - Brush *br = NULL; PointerRNA *ptr = &path->ptr[path->len - 1]; /* if we already have a (pinned) brush, we're done */ @@ -446,8 +423,9 @@ static bool buttons_context_path_brush(const bContext *C, ButsContextPath *path) } /* if we have a scene, use the toolsettings brushes */ if (buttons_context_path_scene(path)) { - scene = path->ptr[path->len - 1].data; + Scene *scene = path->ptr[path->len - 1].data; + Brush *br = NULL; if (scene) { wmWindow *window = CTX_wm_window(C); ViewLayer *view_layer = WM_window_get_active_view_layer(window); @@ -471,7 +449,6 @@ static bool buttons_context_path_texture(const bContext *C, ButsContextTexture *ct) { PointerRNA *ptr = &path->ptr[path->len - 1]; - ID *id; if (!ct) { return false; @@ -486,7 +463,7 @@ static bool buttons_context_path_texture(const bContext *C, return false; } - id = ct->user->id; + ID *id = ct->user->id; if (id) { if (GS(id->name) == ID_BR) { @@ -516,20 +493,18 @@ static bool buttons_context_linestyle_pinnable(const bContext *C, ViewLayer *vie { wmWindow *window = CTX_wm_window(C); Scene *scene = WM_window_get_active_scene(window); - FreestyleConfig *config; - SpaceProperties *sbuts; /* if Freestyle is disabled in the scene */ if ((scene->r.mode & R_EDGE_FRS) == 0) { return false; } /* if Freestyle is not in the Parameter Editor mode */ - config = &view_layer->freestyle_config; + FreestyleConfig *config = &view_layer->freestyle_config; if (config->mode != FREESTYLE_CONTROL_EDITOR_MODE) { return false; } /* if the scene has already been pinned */ - sbuts = CTX_wm_space_properties(C); + SpaceProperties *sbuts = CTX_wm_space_properties(C); if (sbuts->pinid && sbuts->pinid == &scene->id) { return false; } @@ -545,15 +520,13 @@ static bool buttons_context_path(const bContext *C, ButsContextPath *path, int m wmWindow *window = CTX_wm_window(C); Scene *scene = WM_window_get_active_scene(window); ViewLayer *view_layer = WM_window_get_active_view_layer(window); - ID *id; - int found; memset(path, 0, sizeof(*path)); path->flag = flag; /* If some ID datablock is pinned, set the root pointer. */ if (sbuts->pinid) { - id = sbuts->pinid; + ID *id = sbuts->pinid; RNA_id_pointer_create(id, &path->ptr[0]); path->len++; @@ -576,6 +549,7 @@ static bool buttons_context_path(const bContext *C, ButsContextPath *path, int m /* now for each buttons context type, we try to construct a path, * tracing back recursively */ + bool found; switch (mainb) { case BCONTEXT_SCENE: case BCONTEXT_RENDER: @@ -676,15 +650,14 @@ static int buttons_shading_new_context(const bContext *C, int flag) void buttons_context_compute(const bContext *C, SpaceProperties *sbuts) { - ButsContextPath *path; - PointerRNA *ptr; - int a, pflag = 0, flag = 0; - if (!sbuts->path) { sbuts->path = MEM_callocN(sizeof(ButsContextPath), "ButsContextPath"); } - path = sbuts->path; + ButsContextPath *path = sbuts->path; + + int pflag = 0; + int flag = 0; /* Set scene path. */ buttons_context_path(C, path, BCONTEXT_SCENE, pflag); @@ -693,13 +666,13 @@ void buttons_context_compute(const bContext *C, SpaceProperties *sbuts) /* for each context, see if we can compute a valid path to it, if * this is the case, we know we have to display the button */ - for (a = 0; a < BCONTEXT_TOT; a++) { - if (buttons_context_path(C, path, a, pflag)) { - flag |= (1 << a); + for (int i = 0; i < BCONTEXT_TOT; i++) { + if (buttons_context_path(C, path, i, pflag)) { + flag |= (1 << i); /* setting icon for data context */ - if (a == BCONTEXT_DATA) { - ptr = &path->ptr[path->len - 1]; + if (i == BCONTEXT_DATA) { + PointerRNA *ptr = &path->ptr[path->len - 1]; if (ptr->type) { if (RNA_struct_is_a(ptr->type, &RNA_Light)) { @@ -731,9 +704,9 @@ void buttons_context_compute(const bContext *C, SpaceProperties *sbuts) sbuts->mainb = BCONTEXT_OBJECT; } else { - for (a = 0; a < BCONTEXT_TOT; a++) { - if (flag & (1 << a)) { - sbuts->mainb = a; + for (int i = 0; i < BCONTEXT_TOT; i++) { + if (flag & (1 << i)) { + sbuts->mainb = i; break; } } @@ -1123,24 +1096,19 @@ static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt)) static void buttons_panel_context_draw(const bContext *C, Panel *panel) { - uiLayout *layout = panel->layout; SpaceProperties *sbuts = CTX_wm_space_properties(C); ButsContextPath *path = sbuts->path; - uiLayout *row; - PointerRNA *ptr; - char namebuf[128], *name; - int a, icon; - bool first = true; if (!path) { return; } - row = uiLayoutRow(layout, true); + uiLayout *row = uiLayoutRow(panel->layout, true); uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); - for (a = 0; a < path->len; a++) { - ptr = &path->ptr[a]; + bool first = true; + for (int i = 0; i < path->len; i++) { + PointerRNA *ptr = &path->ptr[i]; /* Skip scene and view layer to save space. */ if ((!ELEM(sbuts->mainb, @@ -1166,33 +1134,35 @@ static void buttons_panel_context_draw(const bContext *C, Panel *panel) if (!first) { uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC); } - else { - first = false; + + if (ptr->data == NULL) { + continue; } - /* Add icon + name .*/ - if (ptr->data) { - icon = RNA_struct_ui_icon(ptr->type); - name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL); + /* Add icon and name .*/ + int icon = RNA_struct_ui_icon(ptr->type); + char namebuf[128]; + char *name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL); - if (name) { - uiItemLDrag(row, ptr, name, icon); + if (name) { + uiItemLDrag(row, ptr, name, icon); - if (name != namebuf) { - MEM_freeN(name); - } - } - else { - uiItemL(row, "", icon); + if (name != namebuf) { + MEM_freeN(name); } } + else { + uiItemL(row, "", icon); + } + + first = false; } } void buttons_context_register(ARegionType *art) { PanelType *pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context"); - strcpy(pt->idname, "BUTTONS_PT_context"); + strcpy(pt->idname, "PROPERTIES_PT_context"); strcpy(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA); pt->poll = buttons_panel_context_poll; @@ -1205,32 +1175,32 @@ ID *buttons_context_id_path(const bContext *C) { SpaceProperties *sbuts = CTX_wm_space_properties(C); ButsContextPath *path = sbuts->path; - PointerRNA *ptr; - int a; - - if (path->len) { - for (a = path->len - 1; a >= 0; a--) { - ptr = &path->ptr[a]; - - /* pin particle settings instead of system, since only settings are an idblock*/ - if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) { - if (ptr->type == &RNA_ParticleSystem && ptr->data) { - ParticleSystem *psys = ptr->data; - return &psys->part->id; - } - } - /* There is no valid image ID panel, Image Empty objects need this workaround.*/ - if (sbuts->mainb == BCONTEXT_DATA && sbuts->flag & SB_PIN_CONTEXT) { - if (ptr->type == &RNA_Image && ptr->data) { - continue; - } + if (path->len == 0) { + return NULL; + } + + for (int i = path->len - 1; i >= 0; i--) { + PointerRNA *ptr = &path->ptr[i]; + + /* pin particle settings instead of system, since only settings are an idblock*/ + if (sbuts->mainb == BCONTEXT_PARTICLE && sbuts->flag & SB_PIN_CONTEXT) { + if (ptr->type == &RNA_ParticleSystem && ptr->data) { + ParticleSystem *psys = ptr->data; + return &psys->part->id; } + } - if (ptr->owner_id) { - return ptr->owner_id; + /* There is no valid image ID panel, Image Empty objects need this workaround.*/ + if (sbuts->mainb == BCONTEXT_DATA && sbuts->flag & SB_PIN_CONTEXT) { + if (ptr->type == &RNA_Image && ptr->data) { + continue; } } + + if (ptr->owner_id) { + return ptr->owner_id; + } } return NULL; diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index eb2969aa15d..a4043d426a3 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -1448,7 +1448,7 @@ static const EnumPropertyItem prop_object_op_types[] = { "OBJECT_PROXY_TO_OVERRIDE", 0, "Convert Proxy to Override", - "Convert a Proxy object to a full library override, inclduing all its dependencies"}, + "Convert a Proxy object to a full library override, including all its dependencies"}, {0, NULL, 0, NULL, NULL}, }; @@ -1739,7 +1739,7 @@ static const EnumPropertyItem prop_id_op_types[] = { "OVERRIDE_LIBRARY_PROXY_CONVERT", 0, "Convert Proxy to Override", - "Convert a Proxy object to a full library override, inclduing all its dependencies"}, + "Convert a Proxy object to a full library override, including all its dependencies"}, {OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET, "OVERRIDE_LIBRARY_RESET", 0, diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index bc08cb91c0d..7ed276e45de 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -755,26 +755,26 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is stopConstraint(t); } else { - setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1); + setUserConstraint(t, constraint_axis, msg1); } } else if (!edit_2d) { + short orient_index = 1; if (t->orient_curr == 0 || ELEM(cmode, '\0', axis)) { /* Successive presses on existing axis, cycle orientation modes. */ - t->orient_curr = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient)); - transform_orientations_current_set(t, t->orient_curr); + orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient)); } - if (t->orient_curr == 0) { + transform_orientations_current_set(t, orient_index); + if (orient_index == 0) { stopConstraint(t); } else { - const short orientation = t->orient[t->orient_curr].type; if (is_plane == false) { - setUserConstraint(t, orientation, constraint_axis, msg2); + setUserConstraint(t, constraint_axis, msg2); } else { - setUserConstraint(t, orientation, constraint_plane, msg3); + setUserConstraint(t, constraint_plane, msg3); } } } @@ -1717,10 +1717,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initTransInfo(C, t, op, event); - /* Use the custom orientation when it is set. */ - short orient_index = t->orient[0].type == V3D_ORIENT_CUSTOM_MATRIX ? 0 : t->orient_curr; - transform_orientations_current_set(t, orient_index); - if (t->spacetype == SPACE_VIEW3D) { t->draw_handle_apply = ED_region_draw_cb_activate( t->region->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW); @@ -1868,7 +1864,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* Constraint init from operator */ if (t->con.mode & CON_APPLY) { - setUserConstraint(t, t->orient[t->orient_curr].type, t->con.mode, "%s"); + setUserConstraint(t, t->con.mode, "%s"); } /* Don't write into the values when non-modal because they are already set from operator redo diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 805411ffc20..27ece728276 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -686,9 +686,15 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) * ftext is a format string passed to BLI_snprintf. It will add the name of * the orientation where %s is (logically). */ -void setUserConstraint(TransInfo *t, short orientation, int mode, const char ftext[]) +void setUserConstraint(TransInfo *t, int mode, const char ftext[]) { char text[256]; + short orientation = t->orient[t->orient_curr].type; + if (orientation == V3D_ORIENT_CUSTOM_MATRIX) { + /* Use the real value of the "orient_type". */ + orientation = t->orient[0].type; + } + const char *spacename = transform_orientations_spacename_get(t, orientation); BLI_snprintf(text, sizeof(text), ftext, spacename); @@ -943,12 +949,10 @@ void stopConstraint(TransInfo *t) void initSelectConstraint(TransInfo *t) { if (t->orient_curr == 0) { - t->orient_curr = 1; - transform_orientations_current_set(t, t->orient_curr); + transform_orientations_current_set(t, 1); } - short orientation = t->orient[t->orient_curr].type; - setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "%s"); + setUserConstraint(t, CON_APPLY | CON_SELECT, "%s"); setNearestAxis(t); } diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index 4c901842964..ac62c057f9d 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -35,7 +35,7 @@ void transform_constraint_snap_axis_to_face(const TransInfo *t, void setConstraint(TransInfo *t, int mode, const char text[]); void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]); void setLocalConstraint(TransInfo *t, int mode, const char text[]); -void setUserConstraint(TransInfo *t, short orientation, int mode, const char text[]); +void setUserConstraint(TransInfo *t, int mode, const char text[]); void drawConstraint(TransInfo *t); void drawPropCircle(const struct bContext *C, TransInfo *t); void startConstraint(TransInfo *t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index a2e1c50e375..ba87f0bcc38 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -442,7 +442,10 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } BLI_assert(is_zero_v4(t->values_modal_offset)); + + bool use_orient_axis = false; bool t_values_set_is_array = false; + if (op && (prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ @@ -465,19 +468,28 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } } + if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { + t->orient_axis = RNA_property_enum_get(op->ptr, prop); + use_orient_axis = true; + } + if (op && (prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { bool constraint_axis[3] = {false, false, false}; - if (RNA_property_is_set(op->ptr, prop)) { - RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); - } - - if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) { - /* For operators whose `t->values` is array, set constraint so that the - * orientation is more intuitive in the Redo Panel. */ - for (int i = 3; i--;) { - constraint_axis[i] |= t->values[i] != 0.0f; + if (t->flag & T_INPUT_IS_VALUES_FINAL) { + if (t_values_set_is_array) { + /* For operators whose `t->values` is array, set constraint so that the + * orientation is more intuitive in the Redo Panel. */ + for (int i = 3; i--;) { + constraint_axis[i] |= t->values[i] != 0.0f; + } + } + else if (use_orient_axis) { + constraint_axis[t->orient_axis] = true; } } + else if (RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); + } if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { t->con.mode |= CON_APPLY; @@ -495,9 +507,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } { - short orient_type_set = -1; - short orient_type_matrix_set = -1; + short orient_types[3]; + float custom_matrix[3][3]; + + short orient_type_default = V3D_ORIENT_GLOBAL; short orient_type_scene = V3D_ORIENT_GLOBAL; + short orient_type_set = V3D_ORIENT_GLOBAL; + short orient_type_matrix_set = -1; if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; @@ -508,14 +524,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } } - short orient_types[3]; - float custom_matrix[3][3]; - bool use_orient_axis = false; - - if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { - t->orient_axis = RNA_property_enum_get(op->ptr, prop); - use_orient_axis = true; - } if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); } @@ -530,21 +538,21 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } /* Change the default orientation to be used when redoing. */ - orient_types[0] = orient_type_set; - orient_types[1] = orient_type_set; - orient_types[2] = orient_type_scene; + orient_type_default = orient_type_set; + } + else if (t->con.mode & CON_APPLY) { + orient_type_set = orient_type_default = orient_type_scene; } else { + if (orient_type_set == orient_type_scene) { + BLI_assert(orient_type_set == V3D_ORIENT_GLOBAL); + orient_type_set = V3D_ORIENT_LOCAL; + } + if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode)) && (t->mode != TFM_ALIGN)) { - orient_types[0] = V3D_ORIENT_VIEW; + orient_type_default = V3D_ORIENT_VIEW; } - else { - orient_types[0] = orient_type_scene; - } - orient_types[1] = orient_type_scene; - orient_types[2] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL : - V3D_ORIENT_LOCAL; } if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) && @@ -555,39 +563,39 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve RNA_property_is_set(op->ptr, prop)) { orient_type_matrix_set = RNA_property_enum_get(op->ptr, prop); } - else if (orient_type_set != -1) { - orient_type_matrix_set = orient_type_set; - } else { - orient_type_matrix_set = orient_type_set = V3D_ORIENT_GLOBAL; + orient_type_matrix_set = orient_type_set; } if (orient_type_matrix_set == orient_type_set) { /* Constraints are forced to use the custom matrix when redoing. */ - orient_types[0] = V3D_ORIENT_CUSTOM_MATRIX; + orient_type_set = V3D_ORIENT_CUSTOM_MATRIX; } } - if (t->con.mode & CON_APPLY) { - t->orient_curr = 1; - } + orient_types[0] = orient_type_default; + orient_types[1] = orient_type_scene; + orient_types[2] = orient_type_set; - /* For efficiency, avoid calculating the same orientation twice. */ - for (int i = 1; i < 3; i++) { - t->orient[i].type = transform_orientation_matrix_get( - C, t, orient_types[i], custom_matrix, t->orient[i].matrix); - } - - if (orient_types[0] != orient_types[1]) { - t->orient[0].type = transform_orientation_matrix_get( - C, t, orient_types[0], custom_matrix, t->orient[0].matrix); - } - else { - memcpy(&t->orient[0], &t->orient[1], sizeof(t->orient[0])); + for (int i = 0; i < 3; i++) { + /* For efficiency, avoid calculating the same orientation twice. */ + int j; + for (j = 0; j < i; j++) { + if (orient_types[j] == orient_types[i]) { + memcpy(&t->orient[i], &t->orient[j], sizeof(*t->orient)); + break; + } + } + if (j == i) { + t->orient[i].type = transform_orientation_matrix_get( + C, t, orient_types[i], custom_matrix, t->orient[i].matrix); + } } - const char *spacename = transform_orientations_spacename_get(t, orient_types[0]); - BLI_strncpy(t->spacename, spacename, sizeof(t->spacename)); + /* Set orient_curr to -1 in order to force the update in + * `transform_orientations_current_set`. */ + t->orient_curr = -1; + transform_orientations_current_set(t, (t->con.mode & CON_APPLY) ? 2 : 0); } if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index c0ddd4eb2a6..37b68877b08 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -195,28 +195,30 @@ static void applyRotationValue(TransInfo *t, static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; - - float final; - - final = t->values[0]; - - transform_snap_increment(t, &final); - float axis_final[3]; - /* Use the negative axis to match the default Z axis of the view matrix. */ - negate_v3_v3(axis_final, t->spacemtx[t->orient_axis]); + float final = t->values[0]; if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, NULL); } - - applySnapping(t, &final); + else { + copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); + if (!(t->flag & T_INPUT_IS_VALUES_FINAL) && (dot_v3v3(axis_final, t->viewinv[2]) > 0.0f)) { + /* The input is obtained according to the position of the mouse. + * Flip to better match the movement. */ + final *= -1; + } + } if (applyNumInput(&t->num, &final)) { /* We have to limit the amount of turns to a reasonable number here, * to avoid things getting *very* slow, see how applyRotationValue() handles those... */ final = large_rotation_limit(final); } + else { + transform_snap_increment(t, &final); + applySnapping(t, &final); + } t->values_final[0] = final; diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 276d9381a0b..dc693bd6b15 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -616,12 +616,17 @@ const char *transform_orientations_spacename_get(TransInfo *t, const short orien void transform_orientations_current_set(TransInfo *t, const short orient_index) { + if (t->orient_curr == orient_index) { + return; + } + const short orientation = t->orient[orient_index].type; const char *spacename = transform_orientations_spacename_get(t, orientation); BLI_strncpy(t->spacename, spacename, sizeof(t->spacename)); copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix); invert_m3_m3(t->spacemtx_inv, t->spacemtx); + t->orient_curr = orient_index; } /** |